/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Animal = Container.expand(function () {
var self = Container.call(this);
// Randomly choose animal type
var animalTypes = ['animal1', 'animal2', 'animal3'];
var randomType = animalTypes[Math.floor(Math.random() * animalTypes.length)];
var animalGraphics = self.attachAsset(randomType, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4 + Math.random() * 3; // Slower speed for animals between 4-7
self.lane = 0;
self.checkedForNearMiss = false;
self.update = function () {
self.y += self.speed + gameSpeed;
};
return self;
});
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6 + Math.random() * 2; // Speed between 6-8
self.lane = 0;
self.update = function () {
self.y += self.speed + gameSpeed;
};
return self;
});
var PlayerCar = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5
});
self.lane = 1; // Current lane (0-3)
self.targetX = 0;
self.speed = 8;
self.update = function () {
// Smooth movement towards target position
var diff = self.targetX - self.x;
if (Math.abs(diff) > 2) {
self.x += diff * 0.15;
} else {
self.x = self.targetX;
}
};
self.moveTo = function (lane) {
if (lane >= 0 && lane < 4) {
self.lane = lane;
self.targetX = lanePositions[lane];
}
};
return self;
});
var RoadLine = Container.expand(function () {
var self = Container.call(this);
var lineGraphics = self.attachAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.update = function () {
self.y += self.speed + gameSpeed;
if (self.y > 2732 + 50) {
self.y = -50;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x808080
});
/****
* Game Code
****/
// Game variables
// Brown bear
// Orange fox
// Green frog
var showMenu = true;
var gameStarted = false;
var countdownActive = false;
var countdownNumber = 3;
var gameSpeed = 10;
var speedIncrement = 0.01;
var maxSpeed = 15;
var speedIncreaseTimer = 0;
var speedIncreaseInterval = 120; // 2 seconds at 60 FPS
var lanePositions = [400, 650, 900, 1150]; // X positions for 4 lanes
var animals = [];
var roadLines = [];
var lastTrafficSpawn = 0;
var minSpawnDelay = 60; // Minimum ticks between spawns
var maxSpawnDelay = 120; // Maximum ticks between spawns
var nextSpawnDelay = 90;
var gameStartTime = 0;
var lastNearMissCheck = 0;
var menuAnimals = []; // Array to hold menu background animals
var bombs = [];
var lastBombSpawn = 0;
var bombSpawnInterval = 180; // 3 seconds at 60 FPS
var bombBurstTimer = 0;
var bombBurstInterval = 600; // 10 seconds at 60 FPS
// Create player car
var player = game.addChild(new PlayerCar());
player.x = lanePositions[1]; // Start in second lane
player.y = 2400; // Near bottom of screen
player.targetX = player.x;
// Create road lines for visual effect
for (var i = 0; i < 12; i++) {
var roadLine = game.addChild(new RoadLine());
roadLine.x = 525; // Between lanes 0 and 1
roadLine.y = i * 150 - 100;
roadLines.push(roadLine);
var roadLine2 = game.addChild(new RoadLine());
roadLine2.x = 775; // Between lanes 1 and 2
roadLine2.y = i * 150 - 100;
roadLines.push(roadLine2);
var roadLine3 = game.addChild(new RoadLine());
roadLine3.x = 1025; // Between lanes 2 and 3
roadLine3.y = i * 150 - 100;
roadLines.push(roadLine3);
}
function spawnBomb() {
var bomb = new Bomb();
var lane = Math.floor(Math.random() * 4);
bomb.lane = lane;
bomb.x = lanePositions[lane];
bomb.y = -100; // Start above screen
bomb.speed += gameSpeed * 0.2; // Bomb speed increases with game speed
bomb.exploded = false; // Track explosion state
bomb.spawnTime = LK.ticks; // Track when bomb was spawned
// Add slight pulsing effect to make bombs more noticeable
tween(bomb, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(bomb, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
bombs.push(bomb);
game.addChild(bomb);
}
;
// Create score display
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create points display
var pointsTxt = new Text2('Puntos: 0', {
size: 80,
fill: 0xFFFFFF
});
pointsTxt.anchor.set(0, 0);
pointsTxt.x = 20;
pointsTxt.y = 20;
LK.gui.topLeft.addChild(pointsTxt);
// Create speed display
var speedTxt = new Text2('Speed: 0', {
size: 80,
fill: 0xFFFF00
});
speedTxt.anchor.set(1, 0);
speedTxt.x = -20;
speedTxt.y = 20;
LK.gui.topRight.addChild(speedTxt);
// Create pause menu speed display
var pauseSpeedTxt = new Text2('Velocidad: 10', {
size: 100,
fill: 0xFFFFFF
});
pauseSpeedTxt.anchor.set(0.5, 0.5);
pauseSpeedTxt.y = -100;
pauseSpeedTxt.visible = false;
LK.gui.center.addChild(pauseSpeedTxt);
// Create countdown display
var countdownTxt = new Text2('3', {
size: 300,
fill: 0xFF0000
});
countdownTxt.anchor.set(0.5, 0.5);
countdownTxt.visible = false;
LK.gui.center.addChild(countdownTxt);
// Create menu elements
var menuTitle = new Text2('ENDLESS RACING', {
size: 180,
fill: 0xFFFFFF
});
menuTitle.anchor.set(0.5, 0.5);
menuTitle.y = -200;
LK.gui.center.addChild(menuTitle);
var playButton = new Text2('TAP TO PLAY', {
size: 120,
fill: 0x00FF00
});
playButton.anchor.set(0.5, 0.5);
playButton.y = 100;
LK.gui.center.addChild(playButton);
var instructionsText = new Text2('Swipe left/right to dodge traffic', {
size: 80,
fill: 0xCCCCCC
});
instructionsText.anchor.set(0.5, 0.5);
instructionsText.y = 250;
LK.gui.center.addChild(instructionsText);
// Create menu background animals
for (var i = 0; i < 8; i++) {
var menuAnimal = new Animal();
var lane = Math.floor(Math.random() * 4);
menuAnimal.x = lanePositions[lane];
menuAnimal.y = Math.random() * 2732;
menuAnimal.speed = 2 + Math.random() * 3; // Slower speed for menu
menuAnimals.push(menuAnimal);
game.addChild(menuAnimal);
}
// Create directional arrows
var leftArrow = LK.getAsset('leftArrow', {
anchorX: 0.5,
anchorY: 0.5
});
leftArrow.x = -150;
leftArrow.y = 0;
leftArrow.visible = false;
LK.gui.bottomLeft.addChild(leftArrow);
var rightArrow = LK.getAsset('rightArrow', {
anchorX: 0.5,
anchorY: 0.5
});
rightArrow.x = 150;
rightArrow.y = 0;
rightArrow.visible = false;
LK.gui.bottomRight.addChild(rightArrow);
// Arrow touch handlers
leftArrow.down = function (x, y, obj) {
if (gameStarted && !countdownActive) {
player.moveTo(Math.max(0, player.lane - 1));
}
};
rightArrow.down = function (x, y, obj) {
if (gameStarted && !countdownActive) {
player.moveTo(Math.min(3, player.lane + 1));
}
};
// Touch controls
var isDragging = false;
var dragStartX = 0;
var dragStartLane = 0;
game.down = function (x, y, obj) {
if (showMenu) {
// Start game from menu
showMenu = false;
countdownActive = true;
countdownTxt.visible = true;
menuTitle.visible = false;
playButton.visible = false;
instructionsText.visible = false;
// Hide menu animals
for (var i = 0; i < menuAnimals.length; i++) {
menuAnimals[i].destroy();
}
menuAnimals = [];
startCountdown();
return;
}
isDragging = true;
dragStartX = x;
dragStartLane = player.lane;
};
game.move = function (x, y, obj) {
if (isDragging) {
var dragDistance = x - dragStartX;
var laneChange = Math.floor(dragDistance / 150); // Sensitivity for lane changes
var targetLane = Math.max(0, Math.min(3, dragStartLane + laneChange));
player.moveTo(targetLane);
}
};
game.up = function (x, y, obj) {
isDragging = false;
};
// Main game update
game.update = function () {
// Don't update game logic if menu is showing
if (showMenu) {
// Update menu background animals
for (var i = menuAnimals.length - 1; i >= 0; i--) {
var menuAnimal = menuAnimals[i];
menuAnimal.y += menuAnimal.speed;
// Reset animal position when it goes off screen
if (menuAnimal.y > 2732 + 100) {
menuAnimal.y = -100;
var lane = Math.floor(Math.random() * 4);
menuAnimal.x = lanePositions[lane];
}
}
return;
}
// Handle countdown at game start
if (countdownActive) {
// Don't update game logic during countdown
return;
}
// Increase game speed over time
if (gameSpeed < maxSpeed) {
gameSpeed += speedIncrement;
}
// Increase speed by 1 every 2 seconds
speedIncreaseTimer++;
if (speedIncreaseTimer >= speedIncreaseInterval) {
gameSpeed += 1;
speedIncreaseTimer = 0;
}
// Update score based on time survived
var timeScore = Math.floor(LK.ticks / 10);
LK.setScore(timeScore);
scoreTxt.setText(LK.getScore());
pointsTxt.setText('Puntos: ' + LK.getScore());
speedTxt.setText('Speed: ' + Math.floor(gameSpeed));
// Update pause menu speed display (scale gameSpeed 10-15 to 10-100)
var pauseMenuSpeed = Math.floor(10 + (gameSpeed - 10) / (maxSpeed - 10) * 90);
pauseSpeedTxt.setText('Velocidad: ' + pauseMenuSpeed);
// Show/hide pause menu speed based on game state
if (LK.isPaused && LK.isPaused()) {
pauseSpeedTxt.visible = true;
} else {
pauseSpeedTxt.visible = false;
}
// Spawn animals
if (LK.ticks - lastTrafficSpawn > nextSpawnDelay) {
spawnAnimal();
lastTrafficSpawn = LK.ticks;
nextSpawnDelay = minSpawnDelay + Math.random() * (maxSpawnDelay - minSpawnDelay);
// Decrease spawn delay as speed increases
nextSpawnDelay = Math.max(30, nextSpawnDelay - gameSpeed);
}
// Spawn bombs every 3 seconds
if (LK.ticks - lastBombSpawn > bombSpawnInterval) {
spawnBomb();
lastBombSpawn = LK.ticks;
}
// Bomb burst mode - spawn multiple bombs every 10 seconds
bombBurstTimer++;
if (bombBurstTimer >= bombBurstInterval) {
// Spawn 2-3 bombs in quick succession
var burstCount = 2 + Math.floor(Math.random() * 2); // 2-3 bombs
for (var b = 0; b < burstCount; b++) {
LK.setTimeout(function () {
spawnBomb();
}, b * 200); // 200ms delay between each bomb in burst
}
bombBurstTimer = 0;
}
// Check for collisions and near misses
for (var i = animals.length - 1; i >= 0; i--) {
var animal = animals[i];
// Remove animals that are off screen
if (animal.y > 2732 + 100) {
animal.destroy();
animals.splice(i, 1);
continue;
}
// Check for collision with player
if (animal.intersects(player)) {
// Game over
LK.getSound('crash').play();
LK.showGameOver();
return;
}
// Check for near miss (bonus points)
if (!animal.checkedForNearMiss && animal.y > player.y - 100 && animal.y < player.y + 100) {
var distance = Math.abs(animal.x - player.x);
if (distance < 120 && distance > 80 && animal.lane !== player.lane) {
// Near miss! Award bonus points
LK.setScore(LK.getScore() + 10);
LK.getSound('nearMiss').play();
animal.checkedForNearMiss = true;
}
}
}
// Check bomb collisions and cleanup
for (var i = bombs.length - 1; i >= 0; i--) {
var bomb = bombs[i];
// Remove bombs that are off screen
if (bomb.y > 2732 + 100) {
bomb.destroy();
bombs.splice(i, 1);
continue;
}
// Check if bomb should explode after 2 seconds (120 ticks at 60 FPS)
if (!bomb.exploded && LK.ticks - bomb.spawnTime >= 120) {
explodeBomb(bomb);
// Check if explosion affects player
var distanceToPlayer = Math.sqrt(Math.pow(bomb.x - player.x, 2) + Math.pow(bomb.y - player.y, 2));
if (distanceToPlayer < 150) {
// Game over when bomb explodes near player
LK.getSound('crash').play();
LK.showGameOver();
return;
}
continue;
}
// Check for direct collision with player
if (bomb.intersects(player)) {
// Game over when touching bomb
LK.getSound('crash').play();
LK.showGameOver();
return;
}
}
};
// Start countdown sequence
function startCountdown() {
if (countdownNumber > 0) {
countdownTxt.setText(countdownNumber.toString());
countdownTxt.alpha = 1;
countdownTxt.scaleX = 1;
countdownTxt.scaleY = 1;
// Animate countdown number
tween(countdownTxt, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
countdownNumber--;
if (countdownNumber > 0) {
startCountdown();
} else {
// Show "GO!" message
countdownTxt.setText('GO!');
countdownTxt.fill = 0x00FF00;
countdownTxt.alpha = 1;
countdownTxt.scaleX = 1;
countdownTxt.scaleY = 1;
tween(countdownTxt, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
countdownActive = false;
gameStarted = true;
countdownTxt.visible = false;
leftArrow.visible = true;
rightArrow.visible = true;
}
});
}
}
});
}
}
// Menu is shown by default, countdown starts when user taps to play
function explodeBomb(bomb) {
if (bomb.exploded) {
return;
} // Prevent multiple explosions
bomb.exploded = true;
// Flash screen effect when bomb explodes
LK.effects.flashScreen(0xFF4500, 300);
// Create explosion effect - scale up and fade out with rotation
tween(bomb, {
scaleX: 4,
scaleY: 4,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
// Remove bomb after explosion
for (var i = bombs.length - 1; i >= 0; i--) {
if (bombs[i] === bomb) {
bomb.destroy();
bombs.splice(i, 1);
break;
}
}
}
});
// Add tint effect during explosion
tween(bomb, {
tint: 0xFF0000
}, {
duration: 200,
easing: tween.easeIn
});
}
function spawnAnimal() {
var animal = new Animal();
var lane = Math.floor(Math.random() * 4);
// Avoid spawning in same lane as player if too close
if (lane === player.lane && Math.random() < 0.3) {
lane = (lane + 1) % 4;
}
animal.lane = lane;
animal.x = lanePositions[lane];
animal.y = -100; // Start above screen
animal.speed += gameSpeed * 0.3; // Animal speed increases with game speed (slower than cars)
animals.push(animal);
game.addChild(animal);
} /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Animal = Container.expand(function () {
var self = Container.call(this);
// Randomly choose animal type
var animalTypes = ['animal1', 'animal2', 'animal3'];
var randomType = animalTypes[Math.floor(Math.random() * animalTypes.length)];
var animalGraphics = self.attachAsset(randomType, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4 + Math.random() * 3; // Slower speed for animals between 4-7
self.lane = 0;
self.checkedForNearMiss = false;
self.update = function () {
self.y += self.speed + gameSpeed;
};
return self;
});
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6 + Math.random() * 2; // Speed between 6-8
self.lane = 0;
self.update = function () {
self.y += self.speed + gameSpeed;
};
return self;
});
var PlayerCar = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5
});
self.lane = 1; // Current lane (0-3)
self.targetX = 0;
self.speed = 8;
self.update = function () {
// Smooth movement towards target position
var diff = self.targetX - self.x;
if (Math.abs(diff) > 2) {
self.x += diff * 0.15;
} else {
self.x = self.targetX;
}
};
self.moveTo = function (lane) {
if (lane >= 0 && lane < 4) {
self.lane = lane;
self.targetX = lanePositions[lane];
}
};
return self;
});
var RoadLine = Container.expand(function () {
var self = Container.call(this);
var lineGraphics = self.attachAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 5;
self.update = function () {
self.y += self.speed + gameSpeed;
if (self.y > 2732 + 50) {
self.y = -50;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x808080
});
/****
* Game Code
****/
// Game variables
// Brown bear
// Orange fox
// Green frog
var showMenu = true;
var gameStarted = false;
var countdownActive = false;
var countdownNumber = 3;
var gameSpeed = 10;
var speedIncrement = 0.01;
var maxSpeed = 15;
var speedIncreaseTimer = 0;
var speedIncreaseInterval = 120; // 2 seconds at 60 FPS
var lanePositions = [400, 650, 900, 1150]; // X positions for 4 lanes
var animals = [];
var roadLines = [];
var lastTrafficSpawn = 0;
var minSpawnDelay = 60; // Minimum ticks between spawns
var maxSpawnDelay = 120; // Maximum ticks between spawns
var nextSpawnDelay = 90;
var gameStartTime = 0;
var lastNearMissCheck = 0;
var menuAnimals = []; // Array to hold menu background animals
var bombs = [];
var lastBombSpawn = 0;
var bombSpawnInterval = 180; // 3 seconds at 60 FPS
var bombBurstTimer = 0;
var bombBurstInterval = 600; // 10 seconds at 60 FPS
// Create player car
var player = game.addChild(new PlayerCar());
player.x = lanePositions[1]; // Start in second lane
player.y = 2400; // Near bottom of screen
player.targetX = player.x;
// Create road lines for visual effect
for (var i = 0; i < 12; i++) {
var roadLine = game.addChild(new RoadLine());
roadLine.x = 525; // Between lanes 0 and 1
roadLine.y = i * 150 - 100;
roadLines.push(roadLine);
var roadLine2 = game.addChild(new RoadLine());
roadLine2.x = 775; // Between lanes 1 and 2
roadLine2.y = i * 150 - 100;
roadLines.push(roadLine2);
var roadLine3 = game.addChild(new RoadLine());
roadLine3.x = 1025; // Between lanes 2 and 3
roadLine3.y = i * 150 - 100;
roadLines.push(roadLine3);
}
function spawnBomb() {
var bomb = new Bomb();
var lane = Math.floor(Math.random() * 4);
bomb.lane = lane;
bomb.x = lanePositions[lane];
bomb.y = -100; // Start above screen
bomb.speed += gameSpeed * 0.2; // Bomb speed increases with game speed
bomb.exploded = false; // Track explosion state
bomb.spawnTime = LK.ticks; // Track when bomb was spawned
// Add slight pulsing effect to make bombs more noticeable
tween(bomb, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(bomb, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 500,
easing: tween.easeInOut
});
}
});
bombs.push(bomb);
game.addChild(bomb);
}
;
// Create score display
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create points display
var pointsTxt = new Text2('Puntos: 0', {
size: 80,
fill: 0xFFFFFF
});
pointsTxt.anchor.set(0, 0);
pointsTxt.x = 20;
pointsTxt.y = 20;
LK.gui.topLeft.addChild(pointsTxt);
// Create speed display
var speedTxt = new Text2('Speed: 0', {
size: 80,
fill: 0xFFFF00
});
speedTxt.anchor.set(1, 0);
speedTxt.x = -20;
speedTxt.y = 20;
LK.gui.topRight.addChild(speedTxt);
// Create pause menu speed display
var pauseSpeedTxt = new Text2('Velocidad: 10', {
size: 100,
fill: 0xFFFFFF
});
pauseSpeedTxt.anchor.set(0.5, 0.5);
pauseSpeedTxt.y = -100;
pauseSpeedTxt.visible = false;
LK.gui.center.addChild(pauseSpeedTxt);
// Create countdown display
var countdownTxt = new Text2('3', {
size: 300,
fill: 0xFF0000
});
countdownTxt.anchor.set(0.5, 0.5);
countdownTxt.visible = false;
LK.gui.center.addChild(countdownTxt);
// Create menu elements
var menuTitle = new Text2('ENDLESS RACING', {
size: 180,
fill: 0xFFFFFF
});
menuTitle.anchor.set(0.5, 0.5);
menuTitle.y = -200;
LK.gui.center.addChild(menuTitle);
var playButton = new Text2('TAP TO PLAY', {
size: 120,
fill: 0x00FF00
});
playButton.anchor.set(0.5, 0.5);
playButton.y = 100;
LK.gui.center.addChild(playButton);
var instructionsText = new Text2('Swipe left/right to dodge traffic', {
size: 80,
fill: 0xCCCCCC
});
instructionsText.anchor.set(0.5, 0.5);
instructionsText.y = 250;
LK.gui.center.addChild(instructionsText);
// Create menu background animals
for (var i = 0; i < 8; i++) {
var menuAnimal = new Animal();
var lane = Math.floor(Math.random() * 4);
menuAnimal.x = lanePositions[lane];
menuAnimal.y = Math.random() * 2732;
menuAnimal.speed = 2 + Math.random() * 3; // Slower speed for menu
menuAnimals.push(menuAnimal);
game.addChild(menuAnimal);
}
// Create directional arrows
var leftArrow = LK.getAsset('leftArrow', {
anchorX: 0.5,
anchorY: 0.5
});
leftArrow.x = -150;
leftArrow.y = 0;
leftArrow.visible = false;
LK.gui.bottomLeft.addChild(leftArrow);
var rightArrow = LK.getAsset('rightArrow', {
anchorX: 0.5,
anchorY: 0.5
});
rightArrow.x = 150;
rightArrow.y = 0;
rightArrow.visible = false;
LK.gui.bottomRight.addChild(rightArrow);
// Arrow touch handlers
leftArrow.down = function (x, y, obj) {
if (gameStarted && !countdownActive) {
player.moveTo(Math.max(0, player.lane - 1));
}
};
rightArrow.down = function (x, y, obj) {
if (gameStarted && !countdownActive) {
player.moveTo(Math.min(3, player.lane + 1));
}
};
// Touch controls
var isDragging = false;
var dragStartX = 0;
var dragStartLane = 0;
game.down = function (x, y, obj) {
if (showMenu) {
// Start game from menu
showMenu = false;
countdownActive = true;
countdownTxt.visible = true;
menuTitle.visible = false;
playButton.visible = false;
instructionsText.visible = false;
// Hide menu animals
for (var i = 0; i < menuAnimals.length; i++) {
menuAnimals[i].destroy();
}
menuAnimals = [];
startCountdown();
return;
}
isDragging = true;
dragStartX = x;
dragStartLane = player.lane;
};
game.move = function (x, y, obj) {
if (isDragging) {
var dragDistance = x - dragStartX;
var laneChange = Math.floor(dragDistance / 150); // Sensitivity for lane changes
var targetLane = Math.max(0, Math.min(3, dragStartLane + laneChange));
player.moveTo(targetLane);
}
};
game.up = function (x, y, obj) {
isDragging = false;
};
// Main game update
game.update = function () {
// Don't update game logic if menu is showing
if (showMenu) {
// Update menu background animals
for (var i = menuAnimals.length - 1; i >= 0; i--) {
var menuAnimal = menuAnimals[i];
menuAnimal.y += menuAnimal.speed;
// Reset animal position when it goes off screen
if (menuAnimal.y > 2732 + 100) {
menuAnimal.y = -100;
var lane = Math.floor(Math.random() * 4);
menuAnimal.x = lanePositions[lane];
}
}
return;
}
// Handle countdown at game start
if (countdownActive) {
// Don't update game logic during countdown
return;
}
// Increase game speed over time
if (gameSpeed < maxSpeed) {
gameSpeed += speedIncrement;
}
// Increase speed by 1 every 2 seconds
speedIncreaseTimer++;
if (speedIncreaseTimer >= speedIncreaseInterval) {
gameSpeed += 1;
speedIncreaseTimer = 0;
}
// Update score based on time survived
var timeScore = Math.floor(LK.ticks / 10);
LK.setScore(timeScore);
scoreTxt.setText(LK.getScore());
pointsTxt.setText('Puntos: ' + LK.getScore());
speedTxt.setText('Speed: ' + Math.floor(gameSpeed));
// Update pause menu speed display (scale gameSpeed 10-15 to 10-100)
var pauseMenuSpeed = Math.floor(10 + (gameSpeed - 10) / (maxSpeed - 10) * 90);
pauseSpeedTxt.setText('Velocidad: ' + pauseMenuSpeed);
// Show/hide pause menu speed based on game state
if (LK.isPaused && LK.isPaused()) {
pauseSpeedTxt.visible = true;
} else {
pauseSpeedTxt.visible = false;
}
// Spawn animals
if (LK.ticks - lastTrafficSpawn > nextSpawnDelay) {
spawnAnimal();
lastTrafficSpawn = LK.ticks;
nextSpawnDelay = minSpawnDelay + Math.random() * (maxSpawnDelay - minSpawnDelay);
// Decrease spawn delay as speed increases
nextSpawnDelay = Math.max(30, nextSpawnDelay - gameSpeed);
}
// Spawn bombs every 3 seconds
if (LK.ticks - lastBombSpawn > bombSpawnInterval) {
spawnBomb();
lastBombSpawn = LK.ticks;
}
// Bomb burst mode - spawn multiple bombs every 10 seconds
bombBurstTimer++;
if (bombBurstTimer >= bombBurstInterval) {
// Spawn 2-3 bombs in quick succession
var burstCount = 2 + Math.floor(Math.random() * 2); // 2-3 bombs
for (var b = 0; b < burstCount; b++) {
LK.setTimeout(function () {
spawnBomb();
}, b * 200); // 200ms delay between each bomb in burst
}
bombBurstTimer = 0;
}
// Check for collisions and near misses
for (var i = animals.length - 1; i >= 0; i--) {
var animal = animals[i];
// Remove animals that are off screen
if (animal.y > 2732 + 100) {
animal.destroy();
animals.splice(i, 1);
continue;
}
// Check for collision with player
if (animal.intersects(player)) {
// Game over
LK.getSound('crash').play();
LK.showGameOver();
return;
}
// Check for near miss (bonus points)
if (!animal.checkedForNearMiss && animal.y > player.y - 100 && animal.y < player.y + 100) {
var distance = Math.abs(animal.x - player.x);
if (distance < 120 && distance > 80 && animal.lane !== player.lane) {
// Near miss! Award bonus points
LK.setScore(LK.getScore() + 10);
LK.getSound('nearMiss').play();
animal.checkedForNearMiss = true;
}
}
}
// Check bomb collisions and cleanup
for (var i = bombs.length - 1; i >= 0; i--) {
var bomb = bombs[i];
// Remove bombs that are off screen
if (bomb.y > 2732 + 100) {
bomb.destroy();
bombs.splice(i, 1);
continue;
}
// Check if bomb should explode after 2 seconds (120 ticks at 60 FPS)
if (!bomb.exploded && LK.ticks - bomb.spawnTime >= 120) {
explodeBomb(bomb);
// Check if explosion affects player
var distanceToPlayer = Math.sqrt(Math.pow(bomb.x - player.x, 2) + Math.pow(bomb.y - player.y, 2));
if (distanceToPlayer < 150) {
// Game over when bomb explodes near player
LK.getSound('crash').play();
LK.showGameOver();
return;
}
continue;
}
// Check for direct collision with player
if (bomb.intersects(player)) {
// Game over when touching bomb
LK.getSound('crash').play();
LK.showGameOver();
return;
}
}
};
// Start countdown sequence
function startCountdown() {
if (countdownNumber > 0) {
countdownTxt.setText(countdownNumber.toString());
countdownTxt.alpha = 1;
countdownTxt.scaleX = 1;
countdownTxt.scaleY = 1;
// Animate countdown number
tween(countdownTxt, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
countdownNumber--;
if (countdownNumber > 0) {
startCountdown();
} else {
// Show "GO!" message
countdownTxt.setText('GO!');
countdownTxt.fill = 0x00FF00;
countdownTxt.alpha = 1;
countdownTxt.scaleX = 1;
countdownTxt.scaleY = 1;
tween(countdownTxt, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
countdownActive = false;
gameStarted = true;
countdownTxt.visible = false;
leftArrow.visible = true;
rightArrow.visible = true;
}
});
}
}
});
}
}
// Menu is shown by default, countdown starts when user taps to play
function explodeBomb(bomb) {
if (bomb.exploded) {
return;
} // Prevent multiple explosions
bomb.exploded = true;
// Flash screen effect when bomb explodes
LK.effects.flashScreen(0xFF4500, 300);
// Create explosion effect - scale up and fade out with rotation
tween(bomb, {
scaleX: 4,
scaleY: 4,
alpha: 0,
rotation: Math.PI * 2
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
// Remove bomb after explosion
for (var i = bombs.length - 1; i >= 0; i--) {
if (bombs[i] === bomb) {
bomb.destroy();
bombs.splice(i, 1);
break;
}
}
}
});
// Add tint effect during explosion
tween(bomb, {
tint: 0xFF0000
}, {
duration: 200,
easing: tween.easeIn
});
}
function spawnAnimal() {
var animal = new Animal();
var lane = Math.floor(Math.random() * 4);
// Avoid spawning in same lane as player if too close
if (lane === player.lane && Math.random() < 0.3) {
lane = (lane + 1) % 4;
}
animal.lane = lane;
animal.x = lanePositions[lane];
animal.y = -100; // Start above screen
animal.speed += gameSpeed * 0.3; // Animal speed increases with game speed (slower than cars)
animals.push(animal);
game.addChild(animal);
}