/**** * 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