User prompt
Has una animacion cuando player se mueve ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Quita queco toco el object green light gano has que cuando el player toca la linea gana
User prompt
Has que los asest green light y red light esten en el centro
User prompt
Al principio se mostrara player idle cuando no player y la linea no aparece todavia
User prompt
Y el asest finish line donde esta y has que en el principio aparesca player idle no player
User prompt
Mejor 0.5 segundos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Recuerda cuando se mueva y se vuelva a poner el player idle se espere 1 segundo ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Que se espere 1 segundo cuando se ponga el player ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Usa el asest player idle cuando el player este quieto y el asest de player cuando se mueva cua do no se este moviendo se ponga el asest player idle
User prompt
Usa el sonido eliminado para cuando queda eliminado el player
User prompt
Has un efecto cuando se ponga las luces en roja y verde. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Usa la musica redlight cuando la luz este en roja
User prompt
Cuandi está la luz en roja el persinaje tambien se puede mover pero si se mueve en luz roja se muere
User prompt
Has una musica cuando está en verde
User prompt
Y la animacion al personaje cuando se mueve ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Has una animacion cuando se muere ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Cuando se toca la pantalla da un paso a adelante con el efecto (swipe)
User prompt
Se mueve con el efecto swipe
User prompt
Cuando se hace doble tap en la pantalla se mueve
User prompt
Please fix the bug: 'Uncaught TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'instructionText.style.fill = "#ff0000";' Line Number: 97
User prompt
Crea el juegi de luz roja luz verde del juego del calamar cuando la luz está roja no te puedes mover pero si está verde puedes avanzar si pasas la cuerda del piso ganas.
User prompt
Red Light Green Light
User prompt
Crea el juegi de luz roja luz verde del juego del calamar cuando la luz está roja no te puedes mover pero si está verde puedes avanzar si pasas la cuerda del piso ganas.
User prompt
Please continue polishing my design document.
User prompt
Please continue polishing my design document.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var NPC = Container.expand(function () {
var self = Container.call(this);
var npcGraphics = self.attachAsset('Player_idle', {
anchorX: 0.5,
anchorY: 0.5
});
// Movement tracking
self.lastX = 0;
self.lastY = 0;
self.isMoving = false;
self.moveThreshold = 2;
self.isDead = false;
self.moveTimer = 0;
self.nextMoveTime = Math.random() * 40 + 20; // Random time between 0.33-1 seconds
// Enhanced bounce animation method identical to Player
self.bounceAnimation = function () {
tween(self, {
scaleX: 1.3,
scaleY: 0.8
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 0.9,
scaleY: 1.2
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeOut
});
}
});
}
});
};
// Enhanced transition animation method identical to Player
self.transitionAnimation = function () {
tween(self, {
scaleX: 1.2,
scaleY: 0.9
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.bounceOut
});
}
});
};
self.eliminateNPC = function () {
if (self.isDead) return;
self.isDead = true;
// Play elimination sound
LK.getSound('eliminate').play();
// Create blood splatter effect
for (var i = 0; i < 6; i++) {
var bloodDrop = game.addChild(LK.getAsset('redLight', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y,
scaleX: 0.1,
scaleY: 0.1
}));
var angle = i / 6 * Math.PI * 2 + (Math.random() - 0.5) * 0.5;
var distance = 80 + Math.random() * 120;
var targetX = self.x + Math.cos(angle) * distance;
var targetY = self.y + Math.sin(angle) * distance;
tween(bloodDrop, {
x: targetX,
y: targetY,
scaleX: 0.2 + Math.random() * 0.15,
scaleY: 0.2 + Math.random() * 0.15,
alpha: 0
}, {
duration: 600 + Math.random() * 300,
easing: tween.easeOut,
onFinish: function onFinish() {
if (bloodDrop.parent) {
bloodDrop.destroy();
}
}
});
}
// Hide NPC after death animation
tween(self, {
alpha: 0
}, {
duration: 1500,
easing: tween.easeOut
});
};
self.update = function () {
if (self.isDead) return;
// Check if NPC reached finish line and stop movement
if (self.y <= 370) {
// NPC reached finish line, stop all movement
self.isMoving = false;
if (!self.reachedFinish) {
self.reachedFinish = true;
self.removeChildren();
npcGraphics = self.attachAsset('Player_idle', {
anchorX: 0.5,
anchorY: 0.5
});
}
// Update last position
self.lastX = self.x;
self.lastY = self.y;
return;
}
var deltaX = Math.abs(self.x - self.lastX);
var deltaY = Math.abs(self.y - self.lastY);
var wasMoving = self.isMoving;
self.isMoving = deltaX > self.moveThreshold || deltaY > self.moveThreshold;
// Switch assets based on movement state with enhanced animations
if (wasMoving !== self.isMoving) {
if (self.isMoving) {
// Cancel any pending idle transition
if (self.idleTimeout) {
LK.clearTimeout(self.idleTimeout);
self.idleTimeout = null;
}
// Switch to moving player asset immediately
self.removeChildren();
npcGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Enhanced transition animation identical to Player
self.transitionAnimation();
self.bounceAnimation();
} else {
// Wait 40ms (0.04 seconds) before switching to idle asset
self.idleTimeout = LK.setTimeout(function () {
// Only switch to idle if still not moving
if (!self.isMoving && !self.isDead) {
self.removeChildren();
npcGraphics = self.attachAsset('Player_idle', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.idleTimeout = null;
}, 40);
}
}
// NPC movement logic
if (!isRedLight) {
// During green light, move randomly
self.moveTimer++;
if (self.moveTimer >= self.nextMoveTime) {
var stepSize = 50 + Math.random() * 20;
var newY = self.y - stepSize;
if (newY >= 100) {
self.y = newY;
// Switch to player asset when moving
self.removeChildren();
npcGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Enhanced transition animation identical to Player
self.transitionAnimation();
// Enhanced movement animation with squash and stretch identical to Player
self.bounceAnimation();
// Add additional movement effects like Player
tween(npcGraphics, {
rotation: 0.1
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(npcGraphics, {
rotation: -0.1
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(npcGraphics, {
rotation: 0
}, {
duration: 100,
easing: tween.easeOut
});
}
});
}
});
}
self.moveTimer = 0;
self.nextMoveTime = Math.random() * 40 + 20;
}
} else {
// During red light, sometimes make a mistake and move
self.moveTimer++;
var mistakeChance = 0.002; // Much lower chance per frame for NPCs to lose
if (self.moveTimer > 120 && Math.random() < mistakeChance) {
// NPC makes mistake and moves during red light
var stepSize = 40 + Math.random() * 30;
var newY = self.y - stepSize;
if (newY >= 100) {
self.y = newY;
}
// Switch to player asset when moving during mistake
self.removeChildren();
npcGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Enhanced transition animation identical to Player
self.transitionAnimation();
// Enhanced movement animation with squash and stretch identical to Player
self.bounceAnimation();
// Add dramatic mistake animation
tween(npcGraphics, {
tint: 0xff6666,
scaleX: 1.2,
scaleY: 0.8
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(npcGraphics, {
tint: 0xffffff,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut
});
}
});
// Eliminate this NPC for moving during red light
self.eliminateNPC();
}
}
// Continuous idle state checking - if NPC is not moving, ensure it uses idle asset
if (!self.isMoving && !self.isDead && !self.reachedFinish) {
// Check if current asset is not already Player_idle
var currentAsset = self.children[0];
if (currentAsset && currentAsset.texture && !currentAsset.texture.baseTexture.resource.url.includes('Player_idle')) {
// Switch to idle asset immediately
self.removeChildren();
npcGraphics = self.attachAsset('Player_idle', {
anchorX: 0.5,
anchorY: 0.5
});
}
}
// Additional check: when red light is active and NPC is not moving, switch to idle
if (isRedLight && !self.isMoving && !self.isDead && !self.reachedFinish) {
var currentAsset = self.children[0];
if (currentAsset && currentAsset.texture && !currentAsset.texture.baseTexture.resource.url.includes('Player_idle')) {
// Switch to idle asset immediately during red light
self.removeChildren();
npcGraphics = self.attachAsset('Player_idle', {
anchorX: 0.5,
anchorY: 0.5
});
}
}
// Update last position
self.lastX = self.x;
self.lastY = self.y;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('Player_idle', {
anchorX: 0.5,
anchorY: 0.5
});
// Movement tracking
self.lastX = 0;
self.lastY = 0;
self.isMoving = false;
self.moveThreshold = 2; // Minimum movement to detect
// Enhanced bounce animation method
self.bounceAnimation = function () {
tween(self, {
scaleX: 1.3,
scaleY: 0.8
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 0.9,
scaleY: 1.2
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeOut
});
}
});
}
});
};
self.update = function () {
// Check if player is moving
var deltaX = Math.abs(self.x - self.lastX);
var deltaY = Math.abs(self.y - self.lastY);
var wasMoving = self.isMoving;
self.isMoving = deltaX > self.moveThreshold || deltaY > self.moveThreshold;
// Switch assets based on movement state
if (wasMoving !== self.isMoving) {
if (self.isMoving) {
// Cancel any pending idle transition
if (self.idleTimeout) {
tween.stop(self.idleTimeout);
self.idleTimeout = null;
}
// Switch to moving player asset
self.removeChildren();
playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Enhanced transition animation
self.bounceAnimation();
} else {
// Wait 300ms before switching to idle asset
self.idleTimeout = {};
tween(self.idleTimeout, {}, {
duration: 300,
onFinish: function onFinish() {
// Only switch to idle if still not moving
if (!self.isMoving) {
self.removeChildren();
playerGraphics = self.attachAsset('Player_idle', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.idleTimeout = null;
}
});
}
}
// Update last position
self.lastX = self.x;
self.lastY = self.y;
};
return self;
});
/****
* Initialize Game
****/
// Game state variables
var game = new LK.Game({
backgroundColor: 0x2c2c2c // Dark grey background for dramatic effect
});
/****
* Game Code
****/
// Game state variables
// Traffic light states
// Player character
// Finish line
// Sound effects
var isRedLight = false;
var lightChangeTimer = 0;
var nextLightChange = 180; // 3 seconds at 60fps
var player;
var trafficLight;
var finishLine;
var isDragging = false;
var gameStarted = false;
var showingMenu = true;
var npcs = [];
var gamePaused = false;
var showingGameMenu = false;
// Swipe detection variables declared in down handler
// Create arena background
var arenaBackground = game.addChild(LK.getAsset('Arena', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 3.5,
scaleY: 4.5
}));
// Create traffic light at center
trafficLight = game.addChild(LK.getAsset('greenLight', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
}));
// Create finish line at top
finishLine = game.addChild(LK.getAsset('finishLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 350,
alpha: 1
}));
// Create main menu elements
var logoImage = game.addChild(LK.getAsset('Logo', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 900,
scaleX: 5.0,
scaleY: 5.0
}));
var playButton = game.addChild(LK.getAsset('Play', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 1600,
scaleX: 6.0,
scaleY: 6.0
}));
// Create countdown display (initially hidden)
var countdownText = new Text2('3', {
size: 600,
fill: 0xFFFFFF,
font: "'Impact', 'Arial Black', sans-serif"
});
countdownText.anchor.set(0.5, 0.5);
countdownText.x = 2048 / 2;
countdownText.y = 2732 / 2;
countdownText.alpha = 0;
game.addChild(countdownText);
// Create player at bottom with countdown delay
player = new Player();
player.x = 2048 / 2;
player.y = 2500;
player.alpha = 0; // Start invisible
game.addChild(player); // Add player to game scene immediately
// Start countdown animation
function startCountdown() {
// Show "3"
countdownText.setText('3');
countdownText.alpha = 1;
countdownText.scaleX = 0.1;
countdownText.scaleY = 0.1;
countdownText.tint = 0x00ff00; // Green for "3"
countdownText.rotation = -0.5;
tween(countdownText, {
scaleX: 1.8,
scaleY: 1.8,
rotation: 0,
alpha: 0
}, {
duration: 1000,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Show "2"
countdownText.setText('2');
countdownText.alpha = 1;
countdownText.scaleX = 0.1;
countdownText.scaleY = 0.1;
countdownText.tint = 0xff0000; // Red for "2"
countdownText.rotation = 0.5;
tween(countdownText, {
scaleX: 1.8,
scaleY: 1.8,
rotation: 0,
alpha: 0
}, {
duration: 1000,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Show "1"
countdownText.setText('1');
countdownText.alpha = 1;
countdownText.scaleX = 0.1;
countdownText.scaleY = 0.1;
countdownText.tint = 0xff69b4; // Pink for "1"
countdownText.rotation = -0.3;
tween(countdownText, {
scaleX: 1.8,
scaleY: 1.8,
rotation: 0,
alpha: 0
}, {
duration: 1000,
easing: tween.backOut,
onFinish: function onFinish() {
// Show "GO!"
countdownText.setText('GO!');
countdownText.alpha = 1;
countdownText.scaleX = 0.2;
countdownText.scaleY = 0.2;
countdownText.tint = 0x4caf50;
countdownText.rotation = 0;
tween(countdownText, {
scaleX: 2.2,
scaleY: 2.2,
alpha: 0
}, {
duration: 800,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Hide countdown and show player
countdownText.alpha = 0;
tween(player, {
alpha: 1
}, {
duration: 500,
easing: tween.easeIn
});
// Create players appearing from bottom
for (var i = 0; i < 8; i++) {
var appearingPlayer = new NPC();
// Position players at bottom of screen
appearingPlayer.x = 300 + i * 200 + Math.random() * 100;
appearingPlayer.y = 2800; // Start below screen
appearingPlayer.alpha = 1;
npcs.push(appearingPlayer);
game.addChild(appearingPlayer);
// Animate player moving up from bottom with delay
var delay = i * 200 + Math.random() * 300;
LK.setTimeout(function (targetPlayer) {
return function () {
tween(targetPlayer, {
y: 2400 + Math.random() * 200
}, {
duration: 800,
easing: tween.easeOut
});
};
}(appearingPlayer), delay);
}
}
});
}
});
}
});
}
});
}
// Add button hover effect
playButton.down = function (x, y, obj) {
if (!showingMenu) return;
// Button press animation with bounce effect
tween(playButton, {
scaleX: 5.2,
scaleY: 5.2,
rotation: 0.1
}, {
duration: 150,
easing: tween.easeOut
});
};
playButton.up = function (x, y, obj) {
if (!showingMenu) return;
showingMenu = false;
// Button release animation with elastic bounce
tween(playButton, {
scaleX: 7.0,
scaleY: 7.0,
rotation: 0
}, {
duration: 200,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Scale back down with bounce
tween(playButton, {
scaleX: 6.0,
scaleY: 6.0
}, {
duration: 300,
easing: tween.bounceOut
});
}
});
// Hide menu elements with animation
tween(logoImage, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 500,
easing: tween.easeIn
});
tween(playButton, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
// Start countdown after menu disappears
startCountdown();
// Show pause button when game starts
showPauseButton();
}
});
};
// Don't start countdown immediately - wait for menu interaction
// startCountdown();
// Create pause menu elements (initially hidden)
var pauseMenuBackground = game.addChild(LK.getAsset('Arena', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 3.5,
scaleY: 4.5,
alpha: 0
}));
var pauseMenuTitle = new Text2('PAUSED', {
size: 200,
fill: 0xFFFFFF,
font: "'Impact', 'Arial Black', sans-serif"
});
pauseMenuTitle.anchor.set(0.5, 0.5);
pauseMenuTitle.x = 2048 / 2;
pauseMenuTitle.y = 800;
pauseMenuTitle.alpha = 0;
game.addChild(pauseMenuTitle);
var resumeButton = game.addChild(LK.getAsset('greenLight', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 1400,
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}));
var resumeText = new Text2('RESUME', {
size: 100,
fill: 0x000000,
font: "'Impact', 'Arial Black', sans-serif"
});
resumeText.anchor.set(0.5, 0.5);
resumeText.x = 2048 / 2;
resumeText.y = 1400;
resumeText.alpha = 0;
game.addChild(resumeText);
var restartButton = game.addChild(LK.getAsset('redLight', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 1800,
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}));
var restartText = new Text2('RESTART', {
size: 100,
fill: 0xFFFFFF,
font: "'Impact', 'Arial Black', sans-serif"
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 2048 / 2;
restartText.y = 1800;
restartText.alpha = 0;
game.addChild(restartText);
// Pause button in top right corner
var pauseButton = game.addChild(LK.getAsset('redLight', {
anchorX: 0.5,
anchorY: 0.5,
x: 1900,
y: 150,
scaleX: 0.8,
scaleY: 0.8,
alpha: 0
}));
var pauseButtonText = new Text2('||', {
size: 80,
fill: 0xFFFFFF,
font: "'Impact', 'Arial Black', sans-serif"
});
pauseButtonText.anchor.set(0.5, 0.5);
pauseButtonText.x = 1900;
pauseButtonText.y = 150;
pauseButtonText.alpha = 0;
game.addChild(pauseButtonText);
// Pause button interactions
pauseButton.down = function (x, y, obj) {
if (!gameStarted || showingGameMenu || showingMenu) return;
tween(pauseButton, {
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 100,
easing: tween.easeOut
});
};
pauseButton.up = function (x, y, obj) {
if (!gameStarted || showingGameMenu || showingMenu) return;
tween(pauseButton, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
showPauseMenu();
}
});
};
// Resume button interactions
resumeButton.down = function (x, y, obj) {
if (!showingGameMenu) return;
tween(resumeButton, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 100,
easing: tween.easeOut
});
};
resumeButton.up = function (x, y, obj) {
if (!showingGameMenu) return;
tween(resumeButton, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
hidePauseMenu();
}
});
};
// Restart button interactions
restartButton.down = function (x, y, obj) {
if (!showingGameMenu) return;
tween(restartButton, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 100,
easing: tween.easeOut
});
};
restartButton.up = function (x, y, obj) {
if (!showingGameMenu) return;
tween(restartButton, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
// Reset game state and restart
LK.showGameOver();
}
});
};
// Show pause button when game starts
function showPauseButton() {
tween(pauseButton, {
alpha: 0.8
}, {
duration: 500,
easing: tween.easeIn
});
tween(pauseButtonText, {
alpha: 1
}, {
duration: 500,
easing: tween.easeIn
});
}
// Function to show pause menu
function showPauseMenu() {
if (showingMenu || showingGameMenu) return;
showingGameMenu = true;
gamePaused = true;
// Show all pause menu elements
tween(pauseMenuBackground, {
alpha: 0.9
}, {
duration: 300,
easing: tween.easeOut
});
tween(pauseMenuTitle, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.backOut
});
tween(resumeButton, {
alpha: 1
}, {
duration: 400,
easing: tween.easeOut
});
tween(resumeText, {
alpha: 1
}, {
duration: 400,
easing: tween.easeOut
});
tween(restartButton, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
tween(restartText, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
}
// Function to hide pause menu
function hidePauseMenu() {
if (!showingGameMenu) return;
// Hide all pause menu elements
tween(pauseMenuBackground, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn
});
tween(pauseMenuTitle, {
alpha: 0,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeIn
});
tween(resumeButton, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn
});
tween(resumeText, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn
});
tween(restartButton, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
showingGameMenu = false;
gamePaused = false;
}
});
tween(restartText, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn
});
}
// NPC spawning function removed
// NPCs removed from game start
// Score display for instructions
var instructionText = new Text2('GREEN: TAP TO MOVE\nRED: FREEZE!', {
size: 80,
fill: 0xFFFFFF,
font: "'Impact', 'Arial Black', sans-serif"
});
instructionText.anchor.set(0.5, 0);
LK.gui.top.addChild(instructionText);
// Light change function
function changeLight() {
isRedLight = !isRedLight;
if (isRedLight) {
// Switch to red light
trafficLight.removeChildren();
var redLightGraphics = trafficLight.attachAsset('redLight', {
anchorX: 0.5,
anchorY: 0.5
});
trafficLight.x = 2048 / 2;
trafficLight.y = 2732 / 2;
instructionText.setText('RED LIGHT - FREEZE!');
instructionText.tint = 0xff0000;
// Random duration for red light (1-4 seconds)
nextLightChange = 60 + Math.random() * 180;
// Play red light music during red light
LK.playMusic('redMusic');
// Enhanced red light visual effect with dramatic entrance and pulsing
trafficLight.scaleX = 0.1;
trafficLight.scaleY = 0.1;
trafficLight.rotation = Math.PI * 2;
trafficLight.alpha = 0;
// First phase: dramatic entrance with spin and flash
tween(trafficLight, {
scaleX: 1.8,
scaleY: 1.8,
rotation: 0,
alpha: 1
}, {
duration: 600,
easing: tween.backOut,
onFinish: function onFinish() {
// Second phase: settle to normal size with bounce
tween(trafficLight, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Third phase: continuous pulsing effect
function pulseRed() {
if (!isRedLight) return;
tween(trafficLight, {
scaleX: 1.15,
scaleY: 1.15
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (!isRedLight) return;
tween(trafficLight, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
pulseRed();
}
});
}
});
}
pulseRed();
}
});
}
});
// Enhanced instruction text animation
tween(instructionText, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(instructionText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeIn
});
}
});
// Flash screen red briefly
LK.effects.flashScreen(0xff0000, 500);
} else {
// Switch to green light
trafficLight.removeChildren();
var greenLightGraphics = trafficLight.attachAsset('greenLight', {
anchorX: 0.5,
anchorY: 0.5
});
trafficLight.x = 2048 / 2;
trafficLight.y = 2732 / 2;
instructionText.setText('GREEN LIGHT - TAP!');
instructionText.tint = 0x00ff00;
// Random duration for green light (2-5 seconds)
nextLightChange = 120 + Math.random() * 180;
// Play music during green light
LK.playMusic('greenMusic');
// Enhanced green light visual effect with bouncy entrance and floating
trafficLight.scaleX = 0.05;
trafficLight.scaleY = 0.05;
trafficLight.rotation = -Math.PI * 1.5;
trafficLight.alpha = 0.3;
// First phase: explosive entrance with multiple spins
tween(trafficLight, {
scaleX: 1.5,
scaleY: 1.5,
rotation: 0,
alpha: 1
}, {
duration: 700,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Second phase: settle with multiple bounces
tween(trafficLight, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Third phase: gentle floating effect
function floatGreen() {
if (isRedLight) return;
tween(trafficLight, {
y: trafficLight.y - 20,
scaleX: 1.05,
scaleY: 1.05,
rotation: 0.1
}, {
duration: 1200,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (isRedLight) return;
tween(trafficLight, {
y: trafficLight.y + 20,
scaleX: 1.0,
scaleY: 1.0,
rotation: -0.1
}, {
duration: 1200,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (isRedLight) return;
tween(trafficLight, {
rotation: 0
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
floatGreen();
}
});
}
});
}
});
}
floatGreen();
}
});
}
});
// Enhanced instruction text animation
tween(instructionText, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(instructionText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut
});
}
});
// Flash screen green briefly
LK.effects.flashScreen(0x00ff00, 300);
}
LK.getSound('lightChange').play();
lightChangeTimer = 0;
}
// Tap to step movement
var stepSize = 60; // Size of each step forward
game.down = function (x, y, obj) {
if (showingMenu || showingGameMenu || gamePaused) return; // Don't allow game interaction while menu is showing
if (!gameStarted) {
gameStarted = true;
changeLight(); // Start with first light change
return;
}
// Move player one step forward (upward) regardless of light state
var newY = player.y - stepSize;
// Keep player within bounds
if (newY >= 100) {
player.y = newY;
// Enhanced movement animation with squash and stretch
player.bounceAnimation();
// If moving during red light, trigger death after movement
if (isRedLight) {
// Player moved during red light - eliminate!
LK.getSound('eliminate').play();
LK.getSound('eliminate').play();
LK.effects.flashScreen(0xff0000, 1000);
// Create blood splatter effect
var bloodParticles = [];
for (var i = 0; i < 8; i++) {
var bloodDrop = game.addChild(LK.getAsset('redLight', {
anchorX: 0.5,
anchorY: 0.5,
x: player.x,
y: player.y,
scaleX: 0.1,
scaleY: 0.1
}));
bloodParticles.push(bloodDrop);
// Random direction for each blood particle
var angle = i / 8 * Math.PI * 2 + (Math.random() - 0.5) * 0.5;
var distance = 100 + Math.random() * 150;
var targetX = player.x + Math.cos(angle) * distance;
var targetY = player.y + Math.sin(angle) * distance;
// Animate blood particle
tween(bloodDrop, {
x: targetX,
y: targetY,
scaleX: 0.3 + Math.random() * 0.2,
scaleY: 0.3 + Math.random() * 0.2,
alpha: 0
}, {
duration: 800 + Math.random() * 400,
easing: tween.easeOut,
onFinish: function onFinish() {
if (bloodDrop.parent) {
bloodDrop.destroy();
}
}
});
}
// Death animation - scale up, rotate and fade out
tween(player, {
scaleX: 2,
scaleY: 2,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
// Reset player position and properties after animation
player.x = 2048 / 2;
player.y = 2500;
player.scaleX = 1;
player.scaleY = 1;
player.rotation = 0;
player.alpha = 1;
player.lastX = player.x;
player.lastY = player.y;
// Show game over after animation completes
LK.showGameOver();
}
});
}
}
};
// Main game update
game.update = function () {
if (!gameStarted || gamePaused) return;
// Update light timer
lightChangeTimer++;
if (lightChangeTimer >= nextLightChange) {
changeLight();
}
// Check win condition - player reaches finish line
if (player.intersects(finishLine)) {
// Player reaches finish line - show menu instead of game over
LK.effects.flashScreen(0x00ff00, 1000);
// Reset to main menu instead of showing game over
showingMenu = true;
gameStarted = false;
gamePaused = false;
showingGameMenu = false;
// Reset player position
player.x = 2048 / 2;
player.y = 2500;
player.scaleX = 1;
player.scaleY = 1;
player.rotation = 0;
player.alpha = 0;
player.lastX = player.x;
player.lastY = player.y;
// Reset NPCs
for (var i = 0; i < npcs.length; i++) {
if (npcs[i].parent) {
npcs[i].destroy();
}
}
npcs = [];
// Reset light to green
isRedLight = false;
lightChangeTimer = 0;
nextLightChange = 180;
trafficLight.removeChildren();
var greenLightGraphics = trafficLight.attachAsset('greenLight', {
anchorX: 0.5,
anchorY: 0.5
});
trafficLight.x = 2048 / 2;
trafficLight.y = 2732 / 2;
trafficLight.scaleX = 1.0;
trafficLight.scaleY = 1.0;
trafficLight.rotation = 0;
trafficLight.alpha = 1;
// Show menu elements again
tween(logoImage, {
alpha: 1,
scaleX: 5.0,
scaleY: 5.0
}, {
duration: 500,
easing: tween.easeOut
});
tween(playButton, {
alpha: 1,
scaleX: 6.0,
scaleY: 6.0
}, {
duration: 500,
easing: tween.easeOut
});
// Hide pause button
tween(pauseButton, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn
});
tween(pauseButtonText, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn
});
// Reset instruction text
instructionText.setText('GREEN: TAP TO MOVE\nRED: FREEZE!');
instructionText.tint = 0xFFFFFF;
instructionText.scaleX = 1.0;
instructionText.scaleY = 1.0;
return;
}
// Keep player within bounds
if (player.x < 40) player.x = 40;
if (player.x > 2008) player.x = 2008;
if (player.y > 2600) player.y = 2600;
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var NPC = Container.expand(function () {
var self = Container.call(this);
var npcGraphics = self.attachAsset('Player_idle', {
anchorX: 0.5,
anchorY: 0.5
});
// Movement tracking
self.lastX = 0;
self.lastY = 0;
self.isMoving = false;
self.moveThreshold = 2;
self.isDead = false;
self.moveTimer = 0;
self.nextMoveTime = Math.random() * 40 + 20; // Random time between 0.33-1 seconds
// Enhanced bounce animation method identical to Player
self.bounceAnimation = function () {
tween(self, {
scaleX: 1.3,
scaleY: 0.8
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 0.9,
scaleY: 1.2
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeOut
});
}
});
}
});
};
// Enhanced transition animation method identical to Player
self.transitionAnimation = function () {
tween(self, {
scaleX: 1.2,
scaleY: 0.9
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 150,
easing: tween.bounceOut
});
}
});
};
self.eliminateNPC = function () {
if (self.isDead) return;
self.isDead = true;
// Play elimination sound
LK.getSound('eliminate').play();
// Create blood splatter effect
for (var i = 0; i < 6; i++) {
var bloodDrop = game.addChild(LK.getAsset('redLight', {
anchorX: 0.5,
anchorY: 0.5,
x: self.x,
y: self.y,
scaleX: 0.1,
scaleY: 0.1
}));
var angle = i / 6 * Math.PI * 2 + (Math.random() - 0.5) * 0.5;
var distance = 80 + Math.random() * 120;
var targetX = self.x + Math.cos(angle) * distance;
var targetY = self.y + Math.sin(angle) * distance;
tween(bloodDrop, {
x: targetX,
y: targetY,
scaleX: 0.2 + Math.random() * 0.15,
scaleY: 0.2 + Math.random() * 0.15,
alpha: 0
}, {
duration: 600 + Math.random() * 300,
easing: tween.easeOut,
onFinish: function onFinish() {
if (bloodDrop.parent) {
bloodDrop.destroy();
}
}
});
}
// Hide NPC after death animation
tween(self, {
alpha: 0
}, {
duration: 1500,
easing: tween.easeOut
});
};
self.update = function () {
if (self.isDead) return;
// Check if NPC reached finish line and stop movement
if (self.y <= 370) {
// NPC reached finish line, stop all movement
self.isMoving = false;
if (!self.reachedFinish) {
self.reachedFinish = true;
self.removeChildren();
npcGraphics = self.attachAsset('Player_idle', {
anchorX: 0.5,
anchorY: 0.5
});
}
// Update last position
self.lastX = self.x;
self.lastY = self.y;
return;
}
var deltaX = Math.abs(self.x - self.lastX);
var deltaY = Math.abs(self.y - self.lastY);
var wasMoving = self.isMoving;
self.isMoving = deltaX > self.moveThreshold || deltaY > self.moveThreshold;
// Switch assets based on movement state with enhanced animations
if (wasMoving !== self.isMoving) {
if (self.isMoving) {
// Cancel any pending idle transition
if (self.idleTimeout) {
LK.clearTimeout(self.idleTimeout);
self.idleTimeout = null;
}
// Switch to moving player asset immediately
self.removeChildren();
npcGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Enhanced transition animation identical to Player
self.transitionAnimation();
self.bounceAnimation();
} else {
// Wait 40ms (0.04 seconds) before switching to idle asset
self.idleTimeout = LK.setTimeout(function () {
// Only switch to idle if still not moving
if (!self.isMoving && !self.isDead) {
self.removeChildren();
npcGraphics = self.attachAsset('Player_idle', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.idleTimeout = null;
}, 40);
}
}
// NPC movement logic
if (!isRedLight) {
// During green light, move randomly
self.moveTimer++;
if (self.moveTimer >= self.nextMoveTime) {
var stepSize = 50 + Math.random() * 20;
var newY = self.y - stepSize;
if (newY >= 100) {
self.y = newY;
// Switch to player asset when moving
self.removeChildren();
npcGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Enhanced transition animation identical to Player
self.transitionAnimation();
// Enhanced movement animation with squash and stretch identical to Player
self.bounceAnimation();
// Add additional movement effects like Player
tween(npcGraphics, {
rotation: 0.1
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(npcGraphics, {
rotation: -0.1
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(npcGraphics, {
rotation: 0
}, {
duration: 100,
easing: tween.easeOut
});
}
});
}
});
}
self.moveTimer = 0;
self.nextMoveTime = Math.random() * 40 + 20;
}
} else {
// During red light, sometimes make a mistake and move
self.moveTimer++;
var mistakeChance = 0.002; // Much lower chance per frame for NPCs to lose
if (self.moveTimer > 120 && Math.random() < mistakeChance) {
// NPC makes mistake and moves during red light
var stepSize = 40 + Math.random() * 30;
var newY = self.y - stepSize;
if (newY >= 100) {
self.y = newY;
}
// Switch to player asset when moving during mistake
self.removeChildren();
npcGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Enhanced transition animation identical to Player
self.transitionAnimation();
// Enhanced movement animation with squash and stretch identical to Player
self.bounceAnimation();
// Add dramatic mistake animation
tween(npcGraphics, {
tint: 0xff6666,
scaleX: 1.2,
scaleY: 0.8
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(npcGraphics, {
tint: 0xffffff,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut
});
}
});
// Eliminate this NPC for moving during red light
self.eliminateNPC();
}
}
// Continuous idle state checking - if NPC is not moving, ensure it uses idle asset
if (!self.isMoving && !self.isDead && !self.reachedFinish) {
// Check if current asset is not already Player_idle
var currentAsset = self.children[0];
if (currentAsset && currentAsset.texture && !currentAsset.texture.baseTexture.resource.url.includes('Player_idle')) {
// Switch to idle asset immediately
self.removeChildren();
npcGraphics = self.attachAsset('Player_idle', {
anchorX: 0.5,
anchorY: 0.5
});
}
}
// Additional check: when red light is active and NPC is not moving, switch to idle
if (isRedLight && !self.isMoving && !self.isDead && !self.reachedFinish) {
var currentAsset = self.children[0];
if (currentAsset && currentAsset.texture && !currentAsset.texture.baseTexture.resource.url.includes('Player_idle')) {
// Switch to idle asset immediately during red light
self.removeChildren();
npcGraphics = self.attachAsset('Player_idle', {
anchorX: 0.5,
anchorY: 0.5
});
}
}
// Update last position
self.lastX = self.x;
self.lastY = self.y;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('Player_idle', {
anchorX: 0.5,
anchorY: 0.5
});
// Movement tracking
self.lastX = 0;
self.lastY = 0;
self.isMoving = false;
self.moveThreshold = 2; // Minimum movement to detect
// Enhanced bounce animation method
self.bounceAnimation = function () {
tween(self, {
scaleX: 1.3,
scaleY: 0.8
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 0.9,
scaleY: 1.2
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 100,
easing: tween.easeOut
});
}
});
}
});
};
self.update = function () {
// Check if player is moving
var deltaX = Math.abs(self.x - self.lastX);
var deltaY = Math.abs(self.y - self.lastY);
var wasMoving = self.isMoving;
self.isMoving = deltaX > self.moveThreshold || deltaY > self.moveThreshold;
// Switch assets based on movement state
if (wasMoving !== self.isMoving) {
if (self.isMoving) {
// Cancel any pending idle transition
if (self.idleTimeout) {
tween.stop(self.idleTimeout);
self.idleTimeout = null;
}
// Switch to moving player asset
self.removeChildren();
playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
// Enhanced transition animation
self.bounceAnimation();
} else {
// Wait 300ms before switching to idle asset
self.idleTimeout = {};
tween(self.idleTimeout, {}, {
duration: 300,
onFinish: function onFinish() {
// Only switch to idle if still not moving
if (!self.isMoving) {
self.removeChildren();
playerGraphics = self.attachAsset('Player_idle', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.idleTimeout = null;
}
});
}
}
// Update last position
self.lastX = self.x;
self.lastY = self.y;
};
return self;
});
/****
* Initialize Game
****/
// Game state variables
var game = new LK.Game({
backgroundColor: 0x2c2c2c // Dark grey background for dramatic effect
});
/****
* Game Code
****/
// Game state variables
// Traffic light states
// Player character
// Finish line
// Sound effects
var isRedLight = false;
var lightChangeTimer = 0;
var nextLightChange = 180; // 3 seconds at 60fps
var player;
var trafficLight;
var finishLine;
var isDragging = false;
var gameStarted = false;
var showingMenu = true;
var npcs = [];
var gamePaused = false;
var showingGameMenu = false;
// Swipe detection variables declared in down handler
// Create arena background
var arenaBackground = game.addChild(LK.getAsset('Arena', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 3.5,
scaleY: 4.5
}));
// Create traffic light at center
trafficLight = game.addChild(LK.getAsset('greenLight', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
}));
// Create finish line at top
finishLine = game.addChild(LK.getAsset('finishLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 350,
alpha: 1
}));
// Create main menu elements
var logoImage = game.addChild(LK.getAsset('Logo', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 900,
scaleX: 5.0,
scaleY: 5.0
}));
var playButton = game.addChild(LK.getAsset('Play', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 1600,
scaleX: 6.0,
scaleY: 6.0
}));
// Create countdown display (initially hidden)
var countdownText = new Text2('3', {
size: 600,
fill: 0xFFFFFF,
font: "'Impact', 'Arial Black', sans-serif"
});
countdownText.anchor.set(0.5, 0.5);
countdownText.x = 2048 / 2;
countdownText.y = 2732 / 2;
countdownText.alpha = 0;
game.addChild(countdownText);
// Create player at bottom with countdown delay
player = new Player();
player.x = 2048 / 2;
player.y = 2500;
player.alpha = 0; // Start invisible
game.addChild(player); // Add player to game scene immediately
// Start countdown animation
function startCountdown() {
// Show "3"
countdownText.setText('3');
countdownText.alpha = 1;
countdownText.scaleX = 0.1;
countdownText.scaleY = 0.1;
countdownText.tint = 0x00ff00; // Green for "3"
countdownText.rotation = -0.5;
tween(countdownText, {
scaleX: 1.8,
scaleY: 1.8,
rotation: 0,
alpha: 0
}, {
duration: 1000,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Show "2"
countdownText.setText('2');
countdownText.alpha = 1;
countdownText.scaleX = 0.1;
countdownText.scaleY = 0.1;
countdownText.tint = 0xff0000; // Red for "2"
countdownText.rotation = 0.5;
tween(countdownText, {
scaleX: 1.8,
scaleY: 1.8,
rotation: 0,
alpha: 0
}, {
duration: 1000,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Show "1"
countdownText.setText('1');
countdownText.alpha = 1;
countdownText.scaleX = 0.1;
countdownText.scaleY = 0.1;
countdownText.tint = 0xff69b4; // Pink for "1"
countdownText.rotation = -0.3;
tween(countdownText, {
scaleX: 1.8,
scaleY: 1.8,
rotation: 0,
alpha: 0
}, {
duration: 1000,
easing: tween.backOut,
onFinish: function onFinish() {
// Show "GO!"
countdownText.setText('GO!');
countdownText.alpha = 1;
countdownText.scaleX = 0.2;
countdownText.scaleY = 0.2;
countdownText.tint = 0x4caf50;
countdownText.rotation = 0;
tween(countdownText, {
scaleX: 2.2,
scaleY: 2.2,
alpha: 0
}, {
duration: 800,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Hide countdown and show player
countdownText.alpha = 0;
tween(player, {
alpha: 1
}, {
duration: 500,
easing: tween.easeIn
});
// Create players appearing from bottom
for (var i = 0; i < 8; i++) {
var appearingPlayer = new NPC();
// Position players at bottom of screen
appearingPlayer.x = 300 + i * 200 + Math.random() * 100;
appearingPlayer.y = 2800; // Start below screen
appearingPlayer.alpha = 1;
npcs.push(appearingPlayer);
game.addChild(appearingPlayer);
// Animate player moving up from bottom with delay
var delay = i * 200 + Math.random() * 300;
LK.setTimeout(function (targetPlayer) {
return function () {
tween(targetPlayer, {
y: 2400 + Math.random() * 200
}, {
duration: 800,
easing: tween.easeOut
});
};
}(appearingPlayer), delay);
}
}
});
}
});
}
});
}
});
}
// Add button hover effect
playButton.down = function (x, y, obj) {
if (!showingMenu) return;
// Button press animation with bounce effect
tween(playButton, {
scaleX: 5.2,
scaleY: 5.2,
rotation: 0.1
}, {
duration: 150,
easing: tween.easeOut
});
};
playButton.up = function (x, y, obj) {
if (!showingMenu) return;
showingMenu = false;
// Button release animation with elastic bounce
tween(playButton, {
scaleX: 7.0,
scaleY: 7.0,
rotation: 0
}, {
duration: 200,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Scale back down with bounce
tween(playButton, {
scaleX: 6.0,
scaleY: 6.0
}, {
duration: 300,
easing: tween.bounceOut
});
}
});
// Hide menu elements with animation
tween(logoImage, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 500,
easing: tween.easeIn
});
tween(playButton, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 500,
easing: tween.easeIn,
onFinish: function onFinish() {
// Start countdown after menu disappears
startCountdown();
// Show pause button when game starts
showPauseButton();
}
});
};
// Don't start countdown immediately - wait for menu interaction
// startCountdown();
// Create pause menu elements (initially hidden)
var pauseMenuBackground = game.addChild(LK.getAsset('Arena', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 3.5,
scaleY: 4.5,
alpha: 0
}));
var pauseMenuTitle = new Text2('PAUSED', {
size: 200,
fill: 0xFFFFFF,
font: "'Impact', 'Arial Black', sans-serif"
});
pauseMenuTitle.anchor.set(0.5, 0.5);
pauseMenuTitle.x = 2048 / 2;
pauseMenuTitle.y = 800;
pauseMenuTitle.alpha = 0;
game.addChild(pauseMenuTitle);
var resumeButton = game.addChild(LK.getAsset('greenLight', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 1400,
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}));
var resumeText = new Text2('RESUME', {
size: 100,
fill: 0x000000,
font: "'Impact', 'Arial Black', sans-serif"
});
resumeText.anchor.set(0.5, 0.5);
resumeText.x = 2048 / 2;
resumeText.y = 1400;
resumeText.alpha = 0;
game.addChild(resumeText);
var restartButton = game.addChild(LK.getAsset('redLight', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 1800,
scaleX: 1.5,
scaleY: 1.5,
alpha: 0
}));
var restartText = new Text2('RESTART', {
size: 100,
fill: 0xFFFFFF,
font: "'Impact', 'Arial Black', sans-serif"
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 2048 / 2;
restartText.y = 1800;
restartText.alpha = 0;
game.addChild(restartText);
// Pause button in top right corner
var pauseButton = game.addChild(LK.getAsset('redLight', {
anchorX: 0.5,
anchorY: 0.5,
x: 1900,
y: 150,
scaleX: 0.8,
scaleY: 0.8,
alpha: 0
}));
var pauseButtonText = new Text2('||', {
size: 80,
fill: 0xFFFFFF,
font: "'Impact', 'Arial Black', sans-serif"
});
pauseButtonText.anchor.set(0.5, 0.5);
pauseButtonText.x = 1900;
pauseButtonText.y = 150;
pauseButtonText.alpha = 0;
game.addChild(pauseButtonText);
// Pause button interactions
pauseButton.down = function (x, y, obj) {
if (!gameStarted || showingGameMenu || showingMenu) return;
tween(pauseButton, {
scaleX: 0.7,
scaleY: 0.7
}, {
duration: 100,
easing: tween.easeOut
});
};
pauseButton.up = function (x, y, obj) {
if (!gameStarted || showingGameMenu || showingMenu) return;
tween(pauseButton, {
scaleX: 0.8,
scaleY: 0.8
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
showPauseMenu();
}
});
};
// Resume button interactions
resumeButton.down = function (x, y, obj) {
if (!showingGameMenu) return;
tween(resumeButton, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 100,
easing: tween.easeOut
});
};
resumeButton.up = function (x, y, obj) {
if (!showingGameMenu) return;
tween(resumeButton, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
hidePauseMenu();
}
});
};
// Restart button interactions
restartButton.down = function (x, y, obj) {
if (!showingGameMenu) return;
tween(restartButton, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 100,
easing: tween.easeOut
});
};
restartButton.up = function (x, y, obj) {
if (!showingGameMenu) return;
tween(restartButton, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
// Reset game state and restart
LK.showGameOver();
}
});
};
// Show pause button when game starts
function showPauseButton() {
tween(pauseButton, {
alpha: 0.8
}, {
duration: 500,
easing: tween.easeIn
});
tween(pauseButtonText, {
alpha: 1
}, {
duration: 500,
easing: tween.easeIn
});
}
// Function to show pause menu
function showPauseMenu() {
if (showingMenu || showingGameMenu) return;
showingGameMenu = true;
gamePaused = true;
// Show all pause menu elements
tween(pauseMenuBackground, {
alpha: 0.9
}, {
duration: 300,
easing: tween.easeOut
});
tween(pauseMenuTitle, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.backOut
});
tween(resumeButton, {
alpha: 1
}, {
duration: 400,
easing: tween.easeOut
});
tween(resumeText, {
alpha: 1
}, {
duration: 400,
easing: tween.easeOut
});
tween(restartButton, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
tween(restartText, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
}
// Function to hide pause menu
function hidePauseMenu() {
if (!showingGameMenu) return;
// Hide all pause menu elements
tween(pauseMenuBackground, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn
});
tween(pauseMenuTitle, {
alpha: 0,
scaleX: 1,
scaleY: 1
}, {
duration: 300,
easing: tween.easeIn
});
tween(resumeButton, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn
});
tween(resumeText, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn
});
tween(restartButton, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
showingGameMenu = false;
gamePaused = false;
}
});
tween(restartText, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn
});
}
// NPC spawning function removed
// NPCs removed from game start
// Score display for instructions
var instructionText = new Text2('GREEN: TAP TO MOVE\nRED: FREEZE!', {
size: 80,
fill: 0xFFFFFF,
font: "'Impact', 'Arial Black', sans-serif"
});
instructionText.anchor.set(0.5, 0);
LK.gui.top.addChild(instructionText);
// Light change function
function changeLight() {
isRedLight = !isRedLight;
if (isRedLight) {
// Switch to red light
trafficLight.removeChildren();
var redLightGraphics = trafficLight.attachAsset('redLight', {
anchorX: 0.5,
anchorY: 0.5
});
trafficLight.x = 2048 / 2;
trafficLight.y = 2732 / 2;
instructionText.setText('RED LIGHT - FREEZE!');
instructionText.tint = 0xff0000;
// Random duration for red light (1-4 seconds)
nextLightChange = 60 + Math.random() * 180;
// Play red light music during red light
LK.playMusic('redMusic');
// Enhanced red light visual effect with dramatic entrance and pulsing
trafficLight.scaleX = 0.1;
trafficLight.scaleY = 0.1;
trafficLight.rotation = Math.PI * 2;
trafficLight.alpha = 0;
// First phase: dramatic entrance with spin and flash
tween(trafficLight, {
scaleX: 1.8,
scaleY: 1.8,
rotation: 0,
alpha: 1
}, {
duration: 600,
easing: tween.backOut,
onFinish: function onFinish() {
// Second phase: settle to normal size with bounce
tween(trafficLight, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 400,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Third phase: continuous pulsing effect
function pulseRed() {
if (!isRedLight) return;
tween(trafficLight, {
scaleX: 1.15,
scaleY: 1.15
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (!isRedLight) return;
tween(trafficLight, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
pulseRed();
}
});
}
});
}
pulseRed();
}
});
}
});
// Enhanced instruction text animation
tween(instructionText, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(instructionText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeIn
});
}
});
// Flash screen red briefly
LK.effects.flashScreen(0xff0000, 500);
} else {
// Switch to green light
trafficLight.removeChildren();
var greenLightGraphics = trafficLight.attachAsset('greenLight', {
anchorX: 0.5,
anchorY: 0.5
});
trafficLight.x = 2048 / 2;
trafficLight.y = 2732 / 2;
instructionText.setText('GREEN LIGHT - TAP!');
instructionText.tint = 0x00ff00;
// Random duration for green light (2-5 seconds)
nextLightChange = 120 + Math.random() * 180;
// Play music during green light
LK.playMusic('greenMusic');
// Enhanced green light visual effect with bouncy entrance and floating
trafficLight.scaleX = 0.05;
trafficLight.scaleY = 0.05;
trafficLight.rotation = -Math.PI * 1.5;
trafficLight.alpha = 0.3;
// First phase: explosive entrance with multiple spins
tween(trafficLight, {
scaleX: 1.5,
scaleY: 1.5,
rotation: 0,
alpha: 1
}, {
duration: 700,
easing: tween.elasticOut,
onFinish: function onFinish() {
// Second phase: settle with multiple bounces
tween(trafficLight, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 500,
easing: tween.bounceOut,
onFinish: function onFinish() {
// Third phase: gentle floating effect
function floatGreen() {
if (isRedLight) return;
tween(trafficLight, {
y: trafficLight.y - 20,
scaleX: 1.05,
scaleY: 1.05,
rotation: 0.1
}, {
duration: 1200,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (isRedLight) return;
tween(trafficLight, {
y: trafficLight.y + 20,
scaleX: 1.0,
scaleY: 1.0,
rotation: -0.1
}, {
duration: 1200,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (isRedLight) return;
tween(trafficLight, {
rotation: 0
}, {
duration: 600,
easing: tween.easeInOut,
onFinish: function onFinish() {
floatGreen();
}
});
}
});
}
});
}
floatGreen();
}
});
}
});
// Enhanced instruction text animation
tween(instructionText, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
easing: tween.bounceOut,
onFinish: function onFinish() {
tween(instructionText, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 200,
easing: tween.easeOut
});
}
});
// Flash screen green briefly
LK.effects.flashScreen(0x00ff00, 300);
}
LK.getSound('lightChange').play();
lightChangeTimer = 0;
}
// Tap to step movement
var stepSize = 60; // Size of each step forward
game.down = function (x, y, obj) {
if (showingMenu || showingGameMenu || gamePaused) return; // Don't allow game interaction while menu is showing
if (!gameStarted) {
gameStarted = true;
changeLight(); // Start with first light change
return;
}
// Move player one step forward (upward) regardless of light state
var newY = player.y - stepSize;
// Keep player within bounds
if (newY >= 100) {
player.y = newY;
// Enhanced movement animation with squash and stretch
player.bounceAnimation();
// If moving during red light, trigger death after movement
if (isRedLight) {
// Player moved during red light - eliminate!
LK.getSound('eliminate').play();
LK.getSound('eliminate').play();
LK.effects.flashScreen(0xff0000, 1000);
// Create blood splatter effect
var bloodParticles = [];
for (var i = 0; i < 8; i++) {
var bloodDrop = game.addChild(LK.getAsset('redLight', {
anchorX: 0.5,
anchorY: 0.5,
x: player.x,
y: player.y,
scaleX: 0.1,
scaleY: 0.1
}));
bloodParticles.push(bloodDrop);
// Random direction for each blood particle
var angle = i / 8 * Math.PI * 2 + (Math.random() - 0.5) * 0.5;
var distance = 100 + Math.random() * 150;
var targetX = player.x + Math.cos(angle) * distance;
var targetY = player.y + Math.sin(angle) * distance;
// Animate blood particle
tween(bloodDrop, {
x: targetX,
y: targetY,
scaleX: 0.3 + Math.random() * 0.2,
scaleY: 0.3 + Math.random() * 0.2,
alpha: 0
}, {
duration: 800 + Math.random() * 400,
easing: tween.easeOut,
onFinish: function onFinish() {
if (bloodDrop.parent) {
bloodDrop.destroy();
}
}
});
}
// Death animation - scale up, rotate and fade out
tween(player, {
scaleX: 2,
scaleY: 2,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
// Reset player position and properties after animation
player.x = 2048 / 2;
player.y = 2500;
player.scaleX = 1;
player.scaleY = 1;
player.rotation = 0;
player.alpha = 1;
player.lastX = player.x;
player.lastY = player.y;
// Show game over after animation completes
LK.showGameOver();
}
});
}
}
};
// Main game update
game.update = function () {
if (!gameStarted || gamePaused) return;
// Update light timer
lightChangeTimer++;
if (lightChangeTimer >= nextLightChange) {
changeLight();
}
// Check win condition - player reaches finish line
if (player.intersects(finishLine)) {
// Player reaches finish line - show menu instead of game over
LK.effects.flashScreen(0x00ff00, 1000);
// Reset to main menu instead of showing game over
showingMenu = true;
gameStarted = false;
gamePaused = false;
showingGameMenu = false;
// Reset player position
player.x = 2048 / 2;
player.y = 2500;
player.scaleX = 1;
player.scaleY = 1;
player.rotation = 0;
player.alpha = 0;
player.lastX = player.x;
player.lastY = player.y;
// Reset NPCs
for (var i = 0; i < npcs.length; i++) {
if (npcs[i].parent) {
npcs[i].destroy();
}
}
npcs = [];
// Reset light to green
isRedLight = false;
lightChangeTimer = 0;
nextLightChange = 180;
trafficLight.removeChildren();
var greenLightGraphics = trafficLight.attachAsset('greenLight', {
anchorX: 0.5,
anchorY: 0.5
});
trafficLight.x = 2048 / 2;
trafficLight.y = 2732 / 2;
trafficLight.scaleX = 1.0;
trafficLight.scaleY = 1.0;
trafficLight.rotation = 0;
trafficLight.alpha = 1;
// Show menu elements again
tween(logoImage, {
alpha: 1,
scaleX: 5.0,
scaleY: 5.0
}, {
duration: 500,
easing: tween.easeOut
});
tween(playButton, {
alpha: 1,
scaleX: 6.0,
scaleY: 6.0
}, {
duration: 500,
easing: tween.easeOut
});
// Hide pause button
tween(pauseButton, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn
});
tween(pauseButtonText, {
alpha: 0
}, {
duration: 300,
easing: tween.easeIn
});
// Reset instruction text
instructionText.setText('GREEN: TAP TO MOVE\nRED: FREEZE!');
instructionText.tint = 0xFFFFFF;
instructionText.scaleX = 1.0;
instructionText.scaleY = 1.0;
return;
}
// Keep player within bounds
if (player.x < 40) player.x = 40;
if (player.x > 2008) player.x = 2008;
if (player.y > 2600) player.y = 2600;
};
Crea al player del juego el calamar con el traja verde corriendo con el numero 456.. In-Game asset. 2d. High contrast. No shadows
Crea el player 456 del juego del calamar quieto parecido al otro que me generastes. In-Game asset. 2d. High contrast. No shadows
Arena como cielo pero arena. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Boton de play de color verde y rosa. In-Game asset. 2d. High contrast. No shadows
Logo red light green light. In-Game asset. 2d. High contrast. No shadows