User prompt
There are some bugs in the game, like the player suddenly dying, also make the menu and buttons customizable with images
User prompt
Add a menu for the play button and options, add a small text saying "This game may contain bugs, if so, please restart."
User prompt
make the trees not so crowded
User prompt
Add a forest background with collision trees
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'batteryText.style.fill = "#44ff44";' Line Number: 344
Code edit (1 edits merged)
Please save this source code
User prompt
Shadow Hunt
Initial prompt
Quieto hacer un juego de terror
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Collectible = Container.expand(function () { var self = Container.call(this); var collectibleGraphics = self.attachAsset('collectible', { anchorX: 0.5, anchorY: 0.5 }); self.collected = false; return self; }); var Flashlight = Container.expand(function () { var self = Container.call(this); var flashlightGraphics = self.attachAsset('flashlightBeam', { anchorX: 0.5, anchorY: 0.5 }); flashlightGraphics.alpha = 0.6; self.battery = 100; self.maxBattery = 100; self.update = function () { self.battery -= 0.1; if (self.battery <= 0) { self.battery = 0; flashlightGraphics.alpha = 0; } else { var batteryRatio = self.battery / self.maxBattery; flashlightGraphics.alpha = 0.3 + 0.3 * batteryRatio; // Flickering effect when battery is low if (batteryRatio < 0.3) { if (Math.random() < 0.1) { flashlightGraphics.alpha *= 0.3; } } } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; self.health = 3; return self; }); var ShadowCreature = Container.expand(function () { var self = Container.call(this); var shadowGraphics = self.attachAsset('shadowCreature', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 2; self.patrolDirection = Math.random() * Math.PI * 2; self.isInLight = false; self.isChasing = false; self.patrolTimer = 0; self.update = function () { // Store original position for collision detection var originalX = self.x; var originalY = self.y; if (self.isInLight) { // Shadow retreats when in light var dx = self.x - flashlight.x; var dy = self.y - flashlight.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed * 2; self.y += dy / distance * self.speed * 2; } self.isChasing = false; } else if (self.isChasing) { // Chase player var dx = player.x - self.x; var dy = player.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed * 1.5; self.y += dy / distance * self.speed * 1.5; } } else { // Patrol behavior self.patrolTimer++; if (self.patrolTimer > 120) { self.patrolDirection = Math.random() * Math.PI * 2; self.patrolTimer = 0; } self.x += Math.cos(self.patrolDirection) * self.speed * 0.5; self.y += Math.sin(self.patrolDirection) * self.speed * 0.5; } // Check collision with trees var collisionDetected = false; for (var i = 0; i < trees.length; i++) { if (self.intersects(trees[i])) { collisionDetected = true; break; } } // If collision detected, revert movement and change patrol direction if (collisionDetected) { self.x = originalX; self.y = originalY; self.patrolDirection = Math.random() * Math.PI * 2; } // Keep within bounds and change direction if hitting boundary if (self.x < 50) { self.x = 50; self.patrolDirection = Math.random() * Math.PI * 2; } if (self.x > 1998) { self.x = 1998; self.patrolDirection = Math.random() * Math.PI * 2; } if (self.y < 50) { self.y = 50; self.patrolDirection = Math.random() * Math.PI * 2; } if (self.y > 2682) { self.y = 2682; self.patrolDirection = Math.random() * Math.PI * 2; } }; return self; }); var Tree = Container.expand(function () { var self = Container.call(this); var treeGraphics = self.attachAsset('tree', { anchorX: 0.5, anchorY: 1.0 }); return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x0a0a0a }); /**** * Game Code ****/ // Add forest background var forestBg = game.addChild(LK.getAsset('forestBackground', { anchorX: 0, anchorY: 0 })); forestBg.x = 0; forestBg.y = 0; var player = game.addChild(new Player()); var flashlight = game.addChild(new Flashlight()); var shadowCreatures = []; var collectibles = []; var trees = []; var exitPoint = null; // Game state variables var gameStarted = false; var gameOver = false; var itemsCollected = 0; var totalItems = 6; var flashlightX = 1024; var flashlightY = 1366; var showMenu = true; // Create menu elements var menuContainer = game.addChild(new Container()); menuContainer.x = 1024; menuContainer.y = 1366; // Menu background var menuBg = menuContainer.addChild(LK.getAsset('menuBackground', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.5, scaleY: 4.5 })); menuBg.alpha = 0.9; // Game title var titleText = new Text2('SHADOW HUNT', { size: 120, fill: 0xFF4444 }); titleText.anchor.set(0.5, 0.5); titleText.x = 0; titleText.y = -400; menuContainer.addChild(titleText); // Play button var playButton = menuContainer.addChild(LK.getAsset('menuButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1 })); playButton.x = 0; playButton.y = -100; var playText = new Text2('PLAY', { size: 80, fill: 0xFFFFFF }); playText.anchor.set(0.5, 0.5); playText.x = 0; playText.y = -100; menuContainer.addChild(playText); // Options button var optionsButton = menuContainer.addChild(LK.getAsset('menuButton', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, scaleY: 1 })); optionsButton.x = 0; optionsButton.y = 100; var optionsText = new Text2('OPTIONS', { size: 80, fill: 0xFFFFFF }); optionsText.anchor.set(0.5, 0.5); optionsText.x = 0; optionsText.y = 100; menuContainer.addChild(optionsText); // Bug warning text var bugWarningText = new Text2('This game may contain bugs, if so, please restart.', { size: 40, fill: 0xFFAA44 }); bugWarningText.anchor.set(0.5, 0.5); bugWarningText.x = 0; bugWarningText.y = 300; menuContainer.addChild(bugWarningText); // Menu button event handlers with visual feedback playButton.down = function (x, y, obj) { playButton.alpha = 0.7; LK.setTimeout(function () { showMenu = false; menuContainer.visible = false; gameStarted = true; LK.playMusic('ambientHorror'); }, 100); }; playButton.move = function (x, y, obj) { playButton.alpha = 0.8; }; playButton.up = function (x, y, obj) { playButton.alpha = 1.0; }; optionsButton.down = function (x, y, obj) { optionsButton.alpha = 0.7; // Simple options toggle - could expand later var optionsMenu = new Text2('Audio: ON\nDifficulty: Normal\n\nTap anywhere to close', { size: 60, fill: 0xFFFFFF }); optionsMenu.anchor.set(0.5, 0.5); optionsMenu.x = 0; optionsMenu.y = 0; var optionsOverlay = menuContainer.addChild(LK.getAsset('menuBackground', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2 })); optionsOverlay.alpha = 0.95; optionsOverlay.x = 0; optionsOverlay.y = 0; menuContainer.addChild(optionsMenu); optionsOverlay.down = function (x, y, obj) { menuContainer.removeChild(optionsOverlay); menuContainer.removeChild(optionsMenu); optionsButton.alpha = 1.0; }; }; optionsButton.move = function (x, y, obj) { optionsButton.alpha = 0.8; }; optionsButton.up = function (x, y, obj) { optionsButton.alpha = 1.0; }; // Create collision trees scattered around the forest for (var i = 0; i < 12; i++) { var tree = game.addChild(new Tree()); tree.x = Math.random() * 1800 + 100; tree.y = Math.random() * 2400 + 200; trees.push(tree); } // Initialize player position player.x = 1024; player.y = 2400; // Create shadow creatures for (var i = 0; i < 4; i++) { var shadow = game.addChild(new ShadowCreature()); shadow.x = Math.random() * 1800 + 100; shadow.y = Math.random() * 2000 + 100; shadowCreatures.push(shadow); } // Create collectibles for (var i = 0; i < totalItems; i++) { var collectible = game.addChild(new Collectible()); collectible.x = Math.random() * 1800 + 100; collectible.y = Math.random() * 2000 + 100; collectibles.push(collectible); } // Create exit point (initially hidden) exitPoint = game.addChild(LK.getAsset('exitPoint', { anchorX: 0.5, anchorY: 0.5 })); exitPoint.x = 1024; exitPoint.y = 100; exitPoint.alpha = 0; // UI Elements var healthText = new Text2('Health: 3', { size: 80, fill: 0xFF4444 }); healthText.anchor.set(0, 0); LK.gui.topRight.addChild(healthText); var itemsText = new Text2('Items: 0/' + totalItems, { size: 80, fill: 0xFFFF44 }); itemsText.anchor.set(0, 0); LK.gui.top.addChild(itemsText); var batteryText = new Text2('Battery: 100%', { size: 60, fill: 0x44FF44 }); batteryText.anchor.set(1, 0); LK.gui.bottomRight.addChild(batteryText); // Game controls game.move = function (x, y, obj) { if (gameOver || showMenu) return; flashlightX = x; flashlightY = y; flashlight.x = x; flashlight.y = y; }; game.down = function (x, y, obj) { if (gameOver || showMenu) return; if (!gameStarted) { gameStarted = true; LK.playMusic('ambientHorror'); } flashlightX = x; flashlightY = y; flashlight.x = x; flashlight.y = y; }; function checkFlashlightCollision(target) { var dx = target.x - flashlight.x; var dy = target.y - flashlight.y; var distance = Math.sqrt(dx * dx + dy * dy); return distance < 150; } function movePlayerTowardsFlashlight() { var dx = flashlightX - player.x; var dy = flashlightY - player.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 5) { var moveX = dx / distance * player.speed; var moveY = dy / distance * player.speed; // Store original position var originalX = player.x; var originalY = player.y; // Try to move player.x += moveX; player.y += moveY; // Check collision with trees var collisionDetected = false; for (var i = 0; i < trees.length; i++) { if (player.intersects(trees[i])) { collisionDetected = true; break; } } // If collision detected, revert movement if (collisionDetected) { player.x = originalX; player.y = originalY; } // Keep player within bounds if (player.x < 30) player.x = 30; if (player.x > 2018) player.x = 2018; if (player.y < 30) player.y = 30; if (player.y > 2702) player.y = 2702; } } function checkShadowDetection() { for (var i = 0; i < shadowCreatures.length; i++) { var shadow = shadowCreatures[i]; // Check if shadow is in light shadow.isInLight = checkFlashlightCollision(shadow); // Check if shadow can see player (not in light and close enough) if (!shadow.isInLight) { var dx = player.x - shadow.x; var dy = player.y - shadow.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 200) { shadow.isChasing = true; LK.getSound('shadowMove').play(); } else if (distance > 400) { shadow.isChasing = false; } } } } // Add collision tracking to prevent rapid multiple hits var lastHitTime = 0; var hitCooldown = 2000; // 2 seconds between hits function checkPlayerCaught() { var currentTime = Date.now(); for (var i = 0; i < shadowCreatures.length; i++) { var shadow = shadowCreatures[i]; if (player.intersects(shadow) && !shadow.isInLight && currentTime - lastHitTime > hitCooldown) { player.health--; lastHitTime = currentTime; healthText.setText('Health: ' + player.health); LK.getSound('caught').play(); LK.effects.flashScreen(0xff0000, 500); // Push player away from shadow var dx = player.x - shadow.x; var dy = player.y - shadow.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { player.x += dx / distance * 150; player.y += dy / distance * 150; } if (player.health <= 0) { gameOver = true; LK.showGameOver(); return; } break; } } } function checkCollectibles() { for (var i = collectibles.length - 1; i >= 0; i--) { var collectible = collectibles[i]; if (!collectible.collected && player.intersects(collectible)) { collectible.collected = true; collectible.alpha = 0; itemsCollected++; LK.getSound('collect').play(); itemsText.setText('Items: ' + itemsCollected + '/' + totalItems); if (itemsCollected >= totalItems) { exitPoint.alpha = 1; tween(exitPoint, { scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.easeInOut }); } } } } function checkWinCondition() { if (itemsCollected >= totalItems && player.intersects(exitPoint)) { gameOver = true; LK.getSound('victory').play(); LK.showYouWin(); } } function checkBatteryDeath() { if (flashlight.battery <= 0) { gameOver = true; LK.showGameOver(); } } game.update = function () { if (gameOver || !gameStarted || showMenu) return; movePlayerTowardsFlashlight(); checkShadowDetection(); checkPlayerCaught(); checkCollectibles(); checkWinCondition(); checkBatteryDeath(); // Update battery display var batteryPercent = Math.floor(flashlight.battery); batteryText.setText('Battery: ' + batteryPercent + '%'); // Change battery text color based on level if (flashlight.battery < 30) { batteryText.fill = "#ff4444"; } else if (flashlight.battery < 60) { batteryText.fill = "#ffaa44"; } else { batteryText.fill = "#44ff44"; } };
===================================================================
--- original.js
+++ change.js
@@ -109,13 +109,25 @@
self.x = originalX;
self.y = originalY;
self.patrolDirection = Math.random() * Math.PI * 2;
}
- // Keep within bounds
- if (self.x < 50) self.x = 50;
- if (self.x > 1998) self.x = 1998;
- if (self.y < 50) self.y = 50;
- if (self.y > 2682) self.y = 2682;
+ // Keep within bounds and change direction if hitting boundary
+ if (self.x < 50) {
+ self.x = 50;
+ self.patrolDirection = Math.random() * Math.PI * 2;
+ }
+ if (self.x > 1998) {
+ self.x = 1998;
+ self.patrolDirection = Math.random() * Math.PI * 2;
+ }
+ if (self.y < 50) {
+ self.y = 50;
+ self.patrolDirection = Math.random() * Math.PI * 2;
+ }
+ if (self.y > 2682) {
+ self.y = 2682;
+ self.patrolDirection = Math.random() * Math.PI * 2;
+ }
};
return self;
});
var Tree = Container.expand(function () {
@@ -162,16 +174,15 @@
var menuContainer = game.addChild(new Container());
menuContainer.x = 1024;
menuContainer.y = 1366;
// Menu background
-var menuBg = menuContainer.addChild(LK.getAsset('exitPoint', {
+var menuBg = menuContainer.addChild(LK.getAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5,
- scaleX: 15,
- scaleY: 25,
- color: 0x000000
+ scaleX: 2.5,
+ scaleY: 4.5
}));
-menuBg.alpha = 0.8;
+menuBg.alpha = 0.9;
// Game title
var titleText = new Text2('SHADOW HUNT', {
size: 120,
fill: 0xFF4444
@@ -180,13 +191,13 @@
titleText.x = 0;
titleText.y = -400;
menuContainer.addChild(titleText);
// Play button
-var playButton = menuContainer.addChild(LK.getAsset('exitPoint', {
+var playButton = menuContainer.addChild(LK.getAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5,
- scaleX: 4,
- scaleY: 2
+ scaleX: 1,
+ scaleY: 1
}));
playButton.x = 0;
playButton.y = -100;
var playText = new Text2('PLAY', {
@@ -197,13 +208,13 @@
playText.x = 0;
playText.y = -100;
menuContainer.addChild(playText);
// Options button
-var optionsButton = menuContainer.addChild(LK.getAsset('exitPoint', {
+var optionsButton = menuContainer.addChild(LK.getAsset('menuButton', {
anchorX: 0.5,
anchorY: 0.5,
- scaleX: 4,
- scaleY: 2
+ scaleX: 1,
+ scaleY: 1
}));
optionsButton.x = 0;
optionsButton.y = 100;
var optionsText = new Text2('OPTIONS', {
@@ -222,39 +233,56 @@
bugWarningText.anchor.set(0.5, 0.5);
bugWarningText.x = 0;
bugWarningText.y = 300;
menuContainer.addChild(bugWarningText);
-// Menu button event handlers
+// Menu button event handlers with visual feedback
playButton.down = function (x, y, obj) {
- showMenu = false;
- menuContainer.visible = false;
- gameStarted = true;
- LK.playMusic('ambientHorror');
+ playButton.alpha = 0.7;
+ LK.setTimeout(function () {
+ showMenu = false;
+ menuContainer.visible = false;
+ gameStarted = true;
+ LK.playMusic('ambientHorror');
+ }, 100);
};
+playButton.move = function (x, y, obj) {
+ playButton.alpha = 0.8;
+};
+playButton.up = function (x, y, obj) {
+ playButton.alpha = 1.0;
+};
optionsButton.down = function (x, y, obj) {
+ optionsButton.alpha = 0.7;
// Simple options toggle - could expand later
var optionsMenu = new Text2('Audio: ON\nDifficulty: Normal\n\nTap anywhere to close', {
size: 60,
fill: 0xFFFFFF
});
optionsMenu.anchor.set(0.5, 0.5);
optionsMenu.x = 0;
optionsMenu.y = 0;
- var optionsOverlay = menuContainer.addChild(LK.getAsset('exitPoint', {
+ var optionsOverlay = menuContainer.addChild(LK.getAsset('menuBackground', {
anchorX: 0.5,
anchorY: 0.5,
- scaleX: 10,
- scaleY: 8
+ scaleX: 2,
+ scaleY: 2
}));
- optionsOverlay.alpha = 0.9;
+ optionsOverlay.alpha = 0.95;
optionsOverlay.x = 0;
optionsOverlay.y = 0;
menuContainer.addChild(optionsMenu);
optionsOverlay.down = function (x, y, obj) {
menuContainer.removeChild(optionsOverlay);
menuContainer.removeChild(optionsMenu);
+ optionsButton.alpha = 1.0;
};
};
+optionsButton.move = function (x, y, obj) {
+ optionsButton.alpha = 0.8;
+};
+optionsButton.up = function (x, y, obj) {
+ optionsButton.alpha = 1.0;
+};
// Create collision trees scattered around the forest
for (var i = 0; i < 12; i++) {
var tree = game.addChild(new Tree());
tree.x = Math.random() * 1800 + 100;
@@ -381,23 +409,28 @@
}
}
}
}
+// Add collision tracking to prevent rapid multiple hits
+var lastHitTime = 0;
+var hitCooldown = 2000; // 2 seconds between hits
function checkPlayerCaught() {
+ var currentTime = Date.now();
for (var i = 0; i < shadowCreatures.length; i++) {
var shadow = shadowCreatures[i];
- if (player.intersects(shadow) && !shadow.isInLight) {
+ if (player.intersects(shadow) && !shadow.isInLight && currentTime - lastHitTime > hitCooldown) {
player.health--;
+ lastHitTime = currentTime;
healthText.setText('Health: ' + player.health);
LK.getSound('caught').play();
LK.effects.flashScreen(0xff0000, 500);
// Push player away from shadow
var dx = player.x - shadow.x;
var dy = player.y - shadow.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
- player.x += dx / distance * 100;
- player.y += dy / distance * 100;
+ player.x += dx / distance * 150;
+ player.y += dy / distance * 150;
}
if (player.health <= 0) {
gameOver = true;
LK.showGameOver();
a scared pixel art kid with a flashlight. In-Game asset. High contrast. No shadows
a large black beast with fangs sharpened with blood pixel art style. In-Game asset. High contrast. No shadows
an open book with blood, terrifying pixel art. In-Game asset. 2d. High contrast. No shadows
a terrifying but illuminating exit. In-Game asset. 2d. High contrast. No shadows
Tree pixel art. In-Game asset. 2d. High contrast. No shadows
a dark forest with bloodthirsty black wolves. In-Game asset. 2d. High contrast. No shadows
Button terror. In-Game asset. 2d. High contrast. No shadows