Code edit (1 edits merged)
Please save this source code
User prompt
Echoes of the Loop
Initial prompt
Game Title: Echoes of the Loop Genre: Puzzle / Sci-Fi / Single Player Core Concept: The player is trapped inside a time loop that resets every 60 seconds. In each loop, the player’s previous actions are recorded and replayed as “echoes” in the next loop. These echoes help solve puzzles. Gameplay Mechanics: - The world resets every 60 seconds. - Player actions are recorded each loop. - In the next loop, previous actions appear as holographic echoes. - Echoes can press buttons, hold switches, block lasers, and move objects. - The player can have up to 5 echoes at the same time. Objective: Use time loops and echoes to solve puzzles and reach the exit of each level. Progression: - Early levels focus on simple switches. - Mid levels require precise timing with multiple echoes. - Late levels include complex puzzles where the player must cooperate with past and future versions of themselves. Unique Twist: If the player dies during a loop, that death becomes an echo in the next loop and can be used as part of the solution. Art Style: Minimalist sci-fi, neon lights, dark environments. Platform: PC and Mobile
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Button = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
self.isPressed = false;
self.buttonId = 0;
self.requiredPressCount = 1;
self.currentPressCount = 0;
self.press = function () {
if (!self.isPressed) {
self.isPressed = true;
self.currentPressCount++;
LK.getSound('buttonPress').play();
buttonGraphics.attachAsset('buttonPressed', {
anchorX: 0.5,
anchorY: 0.5
});
}
};
self.reset = function () {
self.isPressed = false;
self.currentPressCount = 0;
buttonGraphics.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
};
self.isComplete = function () {
return self.currentPressCount >= self.requiredPressCount;
};
return self;
});
var Door = Container.expand(function () {
var self = Container.call(this);
var doorGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
self.isOpen = false;
self.doorId = 0;
self.open = function () {
self.isOpen = true;
doorGraphics.alpha = 0.2;
};
self.close = function () {
self.isOpen = false;
doorGraphics.alpha = 1;
};
return self;
});
var Echo = Container.expand(function () {
var self = Container.call(this);
var echoGraphics = self.attachAsset('echo', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.recordedActions = [];
self.currentActionIndex = 0;
self.loopNumber = 0;
echoGraphics.alpha = 0.6;
self.playback = function () {
if (self.currentActionIndex < self.recordedActions.length) {
var action = self.recordedActions[self.currentActionIndex];
self.x = action.x;
self.y = action.y;
self.currentActionIndex++;
}
};
self.update = function () {
self.playback();
};
return self;
});
var Exit = Container.expand(function () {
var self = Container.call(this);
var exitGraphics = self.attachAsset('exit', {
anchorX: 0.5,
anchorY: 0.5
});
self.isReachable = false;
self.makeReachable = function () {
self.isReachable = true;
tween(exitGraphics, {
alpha: 1
}, {
duration: 500
});
};
self.update = function () {
if (self.isReachable) {
exitGraphics.alpha = Math.abs(Math.sin(LK.ticks * 0.05));
} else {
exitGraphics.alpha = 0.3;
}
};
return self;
});
var Laser = Container.expand(function () {
var self = Container.call(this);
var laserGraphics = self.attachAsset('laser', {
anchorX: 0.5,
anchorY: 0.5
});
self.isActive = true;
self.damagePlayer = true;
self.deactivate = function () {
self.isActive = false;
laserGraphics.alpha = 0.3;
};
self.activate = function () {
self.isActive = true;
laserGraphics.alpha = 1;
};
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 = 8;
self.isDead = false;
self.recordedActions = [];
self.currentActionIndex = 0;
self.recordAction = function (type, x, y) {
self.recordedActions.push({
tick: LK.ticks,
type: type,
x: x,
y: y
});
};
self.reset = function () {
self.isDead = false;
self.currentActionIndex = 0;
self.recordedActions = [];
};
self.update = function () {
if (self.isDead) {
playerGraphics.alpha = 0.5;
} else {
playerGraphics.alpha = 1;
}
};
return self;
});
var Switch = Container.expand(function () {
var self = Container.call(this);
var switchGraphics = self.attachAsset('switch', {
anchorX: 0.5,
anchorY: 0.5
});
self.isActive = false;
self.switchId = 0;
self.connectedDoor = null;
self.toggle = function () {
self.isActive = !self.isActive;
LK.getSound('switchToggle').play();
if (self.isActive) {
switchGraphics.attachAsset('switchActive', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
switchGraphics.attachAsset('switch', {
anchorX: 0.5,
anchorY: 0.5
});
}
if (self.connectedDoor) {
self.connectedDoor.isOpen = self.isActive;
}
};
self.reset = function () {
self.isActive = false;
switchGraphics.attachAsset('switch', {
anchorX: 0.5,
anchorY: 0.5
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
var currentLevel = storage.currentLevel || 1;
var loopTime = 60000; // 60 seconds in milliseconds
var loopStartTime = 0;
var timeRemaining = 60;
var currentLoop = 0;
var maxLoops = 6; // Player + 5 echoes max
var echoes = [];
var buttons = [];
var switches = [];
var lasers = [];
var doors = [];
var player = null;
var exit = null;
var allPuzzlesSolved = false;
var gameOver = false;
var dragNode = null;
var playerTrail = [];
// UI Elements
var timerText = new Text2('60', {
size: 120,
fill: '#00ff00'
});
timerText.anchor.set(0.5, 0.5);
LK.gui.top.addChild(timerText);
var loopCounterText = new Text2('Loop 1/6', {
size: 80,
fill: '#00ff88'
});
loopCounterText.anchor.set(0.5, 1);
LK.gui.top.addChild(loopCounterText);
var levelText = new Text2('Level ' + currentLevel, {
size: 100,
fill: '#ffaa00'
});
levelText.anchor.set(0, 0);
levelText.x = 110;
levelText.y = 20;
LK.gui.top.addChild(levelText);
function initializeLevel() {
game.removeChildren();
echoes = [];
buttons = [];
switches = [];
lasers = [];
doors = [];
playerTrail = [];
currentLoop = 1;
allPuzzlesSolved = false;
gameOver = false;
loopStartTime = LK.ticks;
// Create player
player = game.addChild(new Player());
player.x = 200;
player.y = 300;
// Level 1: Simple button press
if (currentLevel === 1) {
var button1 = game.addChild(new Button());
button1.x = 1024;
button1.y = 400;
button1.requiredPressCount = 1;
buttons.push(button1);
var exitDoor = game.addChild(new Exit());
exitDoor.x = 1800;
exitDoor.y = 1300;
exit = exitDoor;
}
// Level 2: Two buttons
else if (currentLevel === 2) {
var button1 = game.addChild(new Button());
button1.x = 800;
button1.y = 400;
button1.requiredPressCount = 1;
buttons.push(button1);
var button2 = game.addChild(new Button());
button2.x = 1200;
button2.y = 400;
button2.requiredPressCount = 1;
buttons.push(button2);
var exitDoor = game.addChild(new Exit());
exitDoor.x = 1024;
exitDoor.y = 1300;
exit = exitDoor;
}
// Level 3: Switch and laser
else if (currentLevel === 3) {
var laserObj = game.addChild(new Laser());
laserObj.x = 1024;
laserObj.y = 600;
laserObj.rotation = 0;
lasers.push(laserObj);
var switchObj = game.addChild(new Switch());
switchObj.x = 800;
switchObj.y = 400;
switchObj.connectedDoor = null;
switches.push(switchObj);
var exitDoor = game.addChild(new Exit());
exitDoor.x = 1024;
exitDoor.y = 1300;
exit = exitDoor;
}
// Default fallback level
else {
var button1 = game.addChild(new Button());
button1.x = 1024;
button1.y = 400;
buttons.push(button1);
var exitDoor = game.addChild(new Exit());
exitDoor.x = 1024;
exitDoor.y = 1300;
exit = exitDoor;
}
}
function checkPuzzleCompletion() {
var allButtonsPressed = buttons.length === 0 || buttons.every(function (btn) {
return btn.isComplete();
});
var allSwitchesCorrect = switches.length === 0 || switches.every(function (sw) {
return sw.isActive;
});
var allLasersBlocked = lasers.length === 0 || lasers.every(function (laser) {
return !laser.isActive;
});
return allButtonsPressed && allSwitchesCorrect && allLasersBlocked;
}
function resetLevel() {
currentLoop++;
loopStartTime = LK.ticks;
// Create echo from previous loop
if (currentLoop <= maxLoops && player.recordedActions.length > 0) {
var newEcho = game.addChild(new Echo());
newEcho.x = player.x;
newEcho.y = player.y;
newEcho.recordedActions = [];
// Copy recorded actions to echo
for (var i = 0; i < player.recordedActions.length; i++) {
newEcho.recordedActions.push({
tick: player.recordedActions[i].tick,
type: player.recordedActions[i].type,
x: player.recordedActions[i].x,
y: player.recordedActions[i].y
});
}
newEcho.loopNumber = currentLoop - 1;
echoes.push(newEcho);
}
// Reset player
player.reset();
player.x = 200;
player.y = 300;
// Reset buttons
for (var i = 0; i < buttons.length; i++) {
buttons[i].reset();
}
// Reset switches
for (var i = 0; i < switches.length; i++) {
switches[i].reset();
}
// Reset lasers
for (var i = 0; i < lasers.length; i++) {
lasers[i].activate();
}
}
function handleMove(x, y, obj) {
if (gameOver || currentLoop > maxLoops) return;
if (dragNode) {
dragNode.x = x;
dragNode.y = y;
player.recordAction('move', x, y);
// Check button collisions
for (var i = 0; i < buttons.length; i++) {
if (dragNode.intersects(buttons[i])) {
buttons[i].press();
player.recordAction('buttonPress', buttons[i].x, buttons[i].y);
}
}
// Check switch collisions
for (var i = 0; i < switches.length; i++) {
if (dragNode.intersects(switches[i])) {
switches[i].toggle();
player.recordAction('switchToggle', switches[i].x, switches[i].y);
}
}
// Check laser collision
for (var i = 0; i < lasers.length; i++) {
if (lasers[i].isActive && dragNode.intersects(lasers[i])) {
LK.getSound('death').play();
LK.effects.flashScreen(0xff0000, 500);
player.isDead = true;
dragNode = null;
LK.setTimeout(function () {
resetLevel();
}, 500);
return;
}
}
// Check echo collision (they block lasers)
for (var i = 0; i < echoes.length; i++) {
if (dragNode.intersects(echoes[i])) {
// Could add echo interaction here
}
}
// Check exit collision
if (exit && dragNode.intersects(exit) && exit.isReachable) {
LK.getSound('levelComplete').play();
gameOver = true;
LK.effects.flashScreen(0x00ff00, 1000);
LK.setTimeout(function () {
storage.currentLevel = currentLevel + 1;
LK.showYouWin();
}, 1000);
}
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
if (gameOver || currentLoop > maxLoops) return;
dragNode = player;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
game.update = function () {
// Update timer
var elapsedMs = (LK.ticks - loopStartTime) * (1000 / 60); // Convert ticks to ms (60 FPS)
timeRemaining = Math.max(0, 60 - Math.floor(elapsedMs / 1000));
timerText.setText(String(timeRemaining));
// Check if loop time expired
if (elapsedMs >= loopTime) {
if (currentLoop < maxLoops) {
resetLevel();
} else {
gameOver = true;
LK.effects.flashScreen(0xff0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
return;
}
// Update loop counter
loopCounterText.setText('Loop ' + currentLoop + '/' + maxLoops);
// Update echoes
for (var i = echoes.length - 1; i >= 0; i--) {
echoes[i].update();
// Check echo button interactions
for (var j = 0; j < buttons.length; j++) {
if (echoes[i].intersects(buttons[j])) {
buttons[j].press();
}
}
// Check echo switch interactions
for (var j = 0; j < switches.length; j++) {
if (echoes[i].intersects(switches[j])) {
if (!switches[j].isActive) {
switches[j].toggle();
}
}
}
// Check if echo blocks laser
for (var j = 0; j < lasers.length; j++) {
if (echoes[i].intersects(lasers[j])) {
lasers[j].deactivate();
}
}
}
// Update player
player.update();
// Check puzzle completion
if (checkPuzzleCompletion() && exit) {
exit.makeReachable();
allPuzzlesSolved = true;
}
// Update exit
if (exit) {
exit.update();
}
};
// Initialize level and start game
initializeLevel();
LK.playMusic('loopMusic', {
loop: true
}); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Button = Container.expand(function () {
var self = Container.call(this);
var buttonGraphics = self.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
self.isPressed = false;
self.buttonId = 0;
self.requiredPressCount = 1;
self.currentPressCount = 0;
self.press = function () {
if (!self.isPressed) {
self.isPressed = true;
self.currentPressCount++;
LK.getSound('buttonPress').play();
buttonGraphics.attachAsset('buttonPressed', {
anchorX: 0.5,
anchorY: 0.5
});
}
};
self.reset = function () {
self.isPressed = false;
self.currentPressCount = 0;
buttonGraphics.attachAsset('button', {
anchorX: 0.5,
anchorY: 0.5
});
};
self.isComplete = function () {
return self.currentPressCount >= self.requiredPressCount;
};
return self;
});
var Door = Container.expand(function () {
var self = Container.call(this);
var doorGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
self.isOpen = false;
self.doorId = 0;
self.open = function () {
self.isOpen = true;
doorGraphics.alpha = 0.2;
};
self.close = function () {
self.isOpen = false;
doorGraphics.alpha = 1;
};
return self;
});
var Echo = Container.expand(function () {
var self = Container.call(this);
var echoGraphics = self.attachAsset('echo', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.recordedActions = [];
self.currentActionIndex = 0;
self.loopNumber = 0;
echoGraphics.alpha = 0.6;
self.playback = function () {
if (self.currentActionIndex < self.recordedActions.length) {
var action = self.recordedActions[self.currentActionIndex];
self.x = action.x;
self.y = action.y;
self.currentActionIndex++;
}
};
self.update = function () {
self.playback();
};
return self;
});
var Exit = Container.expand(function () {
var self = Container.call(this);
var exitGraphics = self.attachAsset('exit', {
anchorX: 0.5,
anchorY: 0.5
});
self.isReachable = false;
self.makeReachable = function () {
self.isReachable = true;
tween(exitGraphics, {
alpha: 1
}, {
duration: 500
});
};
self.update = function () {
if (self.isReachable) {
exitGraphics.alpha = Math.abs(Math.sin(LK.ticks * 0.05));
} else {
exitGraphics.alpha = 0.3;
}
};
return self;
});
var Laser = Container.expand(function () {
var self = Container.call(this);
var laserGraphics = self.attachAsset('laser', {
anchorX: 0.5,
anchorY: 0.5
});
self.isActive = true;
self.damagePlayer = true;
self.deactivate = function () {
self.isActive = false;
laserGraphics.alpha = 0.3;
};
self.activate = function () {
self.isActive = true;
laserGraphics.alpha = 1;
};
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 = 8;
self.isDead = false;
self.recordedActions = [];
self.currentActionIndex = 0;
self.recordAction = function (type, x, y) {
self.recordedActions.push({
tick: LK.ticks,
type: type,
x: x,
y: y
});
};
self.reset = function () {
self.isDead = false;
self.currentActionIndex = 0;
self.recordedActions = [];
};
self.update = function () {
if (self.isDead) {
playerGraphics.alpha = 0.5;
} else {
playerGraphics.alpha = 1;
}
};
return self;
});
var Switch = Container.expand(function () {
var self = Container.call(this);
var switchGraphics = self.attachAsset('switch', {
anchorX: 0.5,
anchorY: 0.5
});
self.isActive = false;
self.switchId = 0;
self.connectedDoor = null;
self.toggle = function () {
self.isActive = !self.isActive;
LK.getSound('switchToggle').play();
if (self.isActive) {
switchGraphics.attachAsset('switchActive', {
anchorX: 0.5,
anchorY: 0.5
});
} else {
switchGraphics.attachAsset('switch', {
anchorX: 0.5,
anchorY: 0.5
});
}
if (self.connectedDoor) {
self.connectedDoor.isOpen = self.isActive;
}
};
self.reset = function () {
self.isActive = false;
switchGraphics.attachAsset('switch', {
anchorX: 0.5,
anchorY: 0.5
});
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
var currentLevel = storage.currentLevel || 1;
var loopTime = 60000; // 60 seconds in milliseconds
var loopStartTime = 0;
var timeRemaining = 60;
var currentLoop = 0;
var maxLoops = 6; // Player + 5 echoes max
var echoes = [];
var buttons = [];
var switches = [];
var lasers = [];
var doors = [];
var player = null;
var exit = null;
var allPuzzlesSolved = false;
var gameOver = false;
var dragNode = null;
var playerTrail = [];
// UI Elements
var timerText = new Text2('60', {
size: 120,
fill: '#00ff00'
});
timerText.anchor.set(0.5, 0.5);
LK.gui.top.addChild(timerText);
var loopCounterText = new Text2('Loop 1/6', {
size: 80,
fill: '#00ff88'
});
loopCounterText.anchor.set(0.5, 1);
LK.gui.top.addChild(loopCounterText);
var levelText = new Text2('Level ' + currentLevel, {
size: 100,
fill: '#ffaa00'
});
levelText.anchor.set(0, 0);
levelText.x = 110;
levelText.y = 20;
LK.gui.top.addChild(levelText);
function initializeLevel() {
game.removeChildren();
echoes = [];
buttons = [];
switches = [];
lasers = [];
doors = [];
playerTrail = [];
currentLoop = 1;
allPuzzlesSolved = false;
gameOver = false;
loopStartTime = LK.ticks;
// Create player
player = game.addChild(new Player());
player.x = 200;
player.y = 300;
// Level 1: Simple button press
if (currentLevel === 1) {
var button1 = game.addChild(new Button());
button1.x = 1024;
button1.y = 400;
button1.requiredPressCount = 1;
buttons.push(button1);
var exitDoor = game.addChild(new Exit());
exitDoor.x = 1800;
exitDoor.y = 1300;
exit = exitDoor;
}
// Level 2: Two buttons
else if (currentLevel === 2) {
var button1 = game.addChild(new Button());
button1.x = 800;
button1.y = 400;
button1.requiredPressCount = 1;
buttons.push(button1);
var button2 = game.addChild(new Button());
button2.x = 1200;
button2.y = 400;
button2.requiredPressCount = 1;
buttons.push(button2);
var exitDoor = game.addChild(new Exit());
exitDoor.x = 1024;
exitDoor.y = 1300;
exit = exitDoor;
}
// Level 3: Switch and laser
else if (currentLevel === 3) {
var laserObj = game.addChild(new Laser());
laserObj.x = 1024;
laserObj.y = 600;
laserObj.rotation = 0;
lasers.push(laserObj);
var switchObj = game.addChild(new Switch());
switchObj.x = 800;
switchObj.y = 400;
switchObj.connectedDoor = null;
switches.push(switchObj);
var exitDoor = game.addChild(new Exit());
exitDoor.x = 1024;
exitDoor.y = 1300;
exit = exitDoor;
}
// Default fallback level
else {
var button1 = game.addChild(new Button());
button1.x = 1024;
button1.y = 400;
buttons.push(button1);
var exitDoor = game.addChild(new Exit());
exitDoor.x = 1024;
exitDoor.y = 1300;
exit = exitDoor;
}
}
function checkPuzzleCompletion() {
var allButtonsPressed = buttons.length === 0 || buttons.every(function (btn) {
return btn.isComplete();
});
var allSwitchesCorrect = switches.length === 0 || switches.every(function (sw) {
return sw.isActive;
});
var allLasersBlocked = lasers.length === 0 || lasers.every(function (laser) {
return !laser.isActive;
});
return allButtonsPressed && allSwitchesCorrect && allLasersBlocked;
}
function resetLevel() {
currentLoop++;
loopStartTime = LK.ticks;
// Create echo from previous loop
if (currentLoop <= maxLoops && player.recordedActions.length > 0) {
var newEcho = game.addChild(new Echo());
newEcho.x = player.x;
newEcho.y = player.y;
newEcho.recordedActions = [];
// Copy recorded actions to echo
for (var i = 0; i < player.recordedActions.length; i++) {
newEcho.recordedActions.push({
tick: player.recordedActions[i].tick,
type: player.recordedActions[i].type,
x: player.recordedActions[i].x,
y: player.recordedActions[i].y
});
}
newEcho.loopNumber = currentLoop - 1;
echoes.push(newEcho);
}
// Reset player
player.reset();
player.x = 200;
player.y = 300;
// Reset buttons
for (var i = 0; i < buttons.length; i++) {
buttons[i].reset();
}
// Reset switches
for (var i = 0; i < switches.length; i++) {
switches[i].reset();
}
// Reset lasers
for (var i = 0; i < lasers.length; i++) {
lasers[i].activate();
}
}
function handleMove(x, y, obj) {
if (gameOver || currentLoop > maxLoops) return;
if (dragNode) {
dragNode.x = x;
dragNode.y = y;
player.recordAction('move', x, y);
// Check button collisions
for (var i = 0; i < buttons.length; i++) {
if (dragNode.intersects(buttons[i])) {
buttons[i].press();
player.recordAction('buttonPress', buttons[i].x, buttons[i].y);
}
}
// Check switch collisions
for (var i = 0; i < switches.length; i++) {
if (dragNode.intersects(switches[i])) {
switches[i].toggle();
player.recordAction('switchToggle', switches[i].x, switches[i].y);
}
}
// Check laser collision
for (var i = 0; i < lasers.length; i++) {
if (lasers[i].isActive && dragNode.intersects(lasers[i])) {
LK.getSound('death').play();
LK.effects.flashScreen(0xff0000, 500);
player.isDead = true;
dragNode = null;
LK.setTimeout(function () {
resetLevel();
}, 500);
return;
}
}
// Check echo collision (they block lasers)
for (var i = 0; i < echoes.length; i++) {
if (dragNode.intersects(echoes[i])) {
// Could add echo interaction here
}
}
// Check exit collision
if (exit && dragNode.intersects(exit) && exit.isReachable) {
LK.getSound('levelComplete').play();
gameOver = true;
LK.effects.flashScreen(0x00ff00, 1000);
LK.setTimeout(function () {
storage.currentLevel = currentLevel + 1;
LK.showYouWin();
}, 1000);
}
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
if (gameOver || currentLoop > maxLoops) return;
dragNode = player;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
game.update = function () {
// Update timer
var elapsedMs = (LK.ticks - loopStartTime) * (1000 / 60); // Convert ticks to ms (60 FPS)
timeRemaining = Math.max(0, 60 - Math.floor(elapsedMs / 1000));
timerText.setText(String(timeRemaining));
// Check if loop time expired
if (elapsedMs >= loopTime) {
if (currentLoop < maxLoops) {
resetLevel();
} else {
gameOver = true;
LK.effects.flashScreen(0xff0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
return;
}
// Update loop counter
loopCounterText.setText('Loop ' + currentLoop + '/' + maxLoops);
// Update echoes
for (var i = echoes.length - 1; i >= 0; i--) {
echoes[i].update();
// Check echo button interactions
for (var j = 0; j < buttons.length; j++) {
if (echoes[i].intersects(buttons[j])) {
buttons[j].press();
}
}
// Check echo switch interactions
for (var j = 0; j < switches.length; j++) {
if (echoes[i].intersects(switches[j])) {
if (!switches[j].isActive) {
switches[j].toggle();
}
}
}
// Check if echo blocks laser
for (var j = 0; j < lasers.length; j++) {
if (echoes[i].intersects(lasers[j])) {
lasers[j].deactivate();
}
}
}
// Update player
player.update();
// Check puzzle completion
if (checkPuzzleCompletion() && exit) {
exit.makeReachable();
allPuzzlesSolved = true;
}
// Update exit
if (exit) {
exit.update();
}
};
// Initialize level and start game
initializeLevel();
LK.playMusic('loopMusic', {
loop: true
});