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 () {
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;
}
// 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;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0a0a0a
});
/****
* Game Code
****/
var player = game.addChild(new Player());
var flashlight = game.addChild(new Flashlight());
var shadowCreatures = [];
var collectibles = [];
var exitPoint = null;
// Game state variables
var gameStarted = false;
var gameOver = false;
var itemsCollected = 0;
var totalItems = 6;
var flashlightX = 1024;
var flashlightY = 1366;
// 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) return;
flashlightX = x;
flashlightY = y;
flashlight.x = x;
flashlight.y = y;
};
game.down = function (x, y, obj) {
if (gameOver) 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;
player.x += moveX;
player.y += moveY;
// 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;
}
}
}
}
function checkPlayerCaught() {
for (var i = 0; i < shadowCreatures.length; i++) {
var shadow = shadowCreatures[i];
if (player.intersects(shadow) && !shadow.isInLight) {
player.health--;
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;
}
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) 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.style.fill = "#ff4444";
} else if (flashlight.battery < 60) {
batteryText.style.fill = "#ffaa44";
} else {
batteryText.style.fill = "#44ff44";
}
}; ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,310 @@
-/****
+/****
+* 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 () {
+ 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;
+ }
+ // 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;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x0a0a0a
+});
+
+/****
+* Game Code
+****/
+var player = game.addChild(new Player());
+var flashlight = game.addChild(new Flashlight());
+var shadowCreatures = [];
+var collectibles = [];
+var exitPoint = null;
+// Game state variables
+var gameStarted = false;
+var gameOver = false;
+var itemsCollected = 0;
+var totalItems = 6;
+var flashlightX = 1024;
+var flashlightY = 1366;
+// 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) return;
+ flashlightX = x;
+ flashlightY = y;
+ flashlight.x = x;
+ flashlight.y = y;
+};
+game.down = function (x, y, obj) {
+ if (gameOver) 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;
+ player.x += moveX;
+ player.y += moveY;
+ // 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;
+ }
+ }
+ }
+}
+function checkPlayerCaught() {
+ for (var i = 0; i < shadowCreatures.length; i++) {
+ var shadow = shadowCreatures[i];
+ if (player.intersects(shadow) && !shadow.isInLight) {
+ player.health--;
+ 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;
+ }
+ 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) 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.style.fill = "#ff4444";
+ } else if (flashlight.battery < 60) {
+ batteryText.style.fill = "#ffaa44";
+ } else {
+ batteryText.style.fill = "#44ff44";
+ }
+};
\ No newline at end of file
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