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";
}
}; /****
* 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";
}
};
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