/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { level: 1, coins: 0, highScore: 0 }); /**** * Classes ****/ var GameElement = Container.expand(function () { var self = Container.call(this); self.speed = 0; self.active = true; self.type = 'none'; self.lastIntersecting = false; self.setup = function (elementType, posX, speedValue) { self.type = elementType; self.speed = speedValue; self.x = posX; self.y = -200; if (elementType === 'coin') { var coinGraphic = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); // Add shine animation self.animate = function () { tween(coinGraphic, { alpha: 0.5 }, { duration: 500, easing: tween.linear, onFinish: function onFinish() { tween(coinGraphic, { alpha: 1 }, { duration: 500, easing: tween.linear, onFinish: self.animate }); } }); }; self.animate(); } else if (elementType === 'obstacle') { self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); } else if (elementType === 'enemyCar') { self.attachAsset('enemyCar', { anchorX: 0.5, anchorY: 0.5 }); } }; self.update = function () { if (!self.active) return; self.y += self.speed; // Remove when off-screen if (self.y > 2732 + 100) { self.active = false; } // Rotate coins slightly for visual appeal if (self.type === 'coin') { self.rotation += 0.02; } }; return self; }); var GameUI = Container.expand(function () { var self = Container.call(this); // Create score text self.scoreText = new Text2('SCORE: 0', { size: 60, fill: 0xFFFFFF }); self.scoreText.anchor.set(0, 0); self.addChild(self.scoreText); // Create coins text self.coinsText = new Text2('COINS: 0', { size: 60, fill: 0xF1C40F }); self.coinsText.anchor.set(0, 0); self.coinsText.y = 70; self.addChild(self.coinsText); // Create level text self.levelText = new Text2('LEVEL: 1', { size: 60, fill: 0x2ECC71 }); self.levelText.anchor.set(0, 0); self.levelText.y = 140; self.addChild(self.levelText); // Create HP bar background self.hpBarBg = new Container(); self.hpBarBg.x = 0; self.hpBarBg.y = 210; self.addChild(self.hpBarBg); var hpBarBgGraphic = LK.getAsset('road', { anchorX: 0, anchorY: 0, width: 300, height: 30, tint: 0x555555 }); self.hpBarBg.addChild(hpBarBgGraphic); // Create HP bar fill self.hpBarFill = new Container(); self.hpBarFill.x = 0; self.hpBarFill.y = 210; self.addChild(self.hpBarFill); var hpBarFillGraphic = LK.getAsset('road', { anchorX: 0, anchorY: 0, width: 300, height: 30, tint: 0x27ae60 }); self.hpBarFill.addChild(hpBarFillGraphic); // Create HP text self.hpText = new Text2('HP: 100%', { size: 40, fill: 0xFFFFFF }); self.hpText.anchor.set(0, 0.5); self.hpText.x = 10; self.hpText.y = 225; self.addChild(self.hpText); // Update UI elements self.update = function (score, coins, level, hp) { self.scoreText.setText('SCORE: ' + score); self.coinsText.setText('COINS: ' + coins); self.levelText.setText('LEVEL: ' + level); if (hp !== undefined) { // Update HP bar var hpPercent = Math.max(0, Math.min(100, hp)); self.hpBarFill.children[0].width = 3 * hpPercent; self.hpText.setText('HP: ' + hpPercent + '%'); // Change color based on HP level if (hpPercent > 60) { self.hpBarFill.children[0].tint = 0x27ae60; // Green } else if (hpPercent > 30) { self.hpBarFill.children[0].tint = 0xf39c12; // Orange } else { self.hpBarFill.children[0].tint = 0xe74c3c; // Red } } }; return self; }); // Game variables var PlayerCar = Container.expand(function () { var self = Container.call(this); // Create car graphics var carGraphics = self.attachAsset('playerCar', { anchorX: 0.5, anchorY: 0.5 }); // Car properties self.speed = 0; self.maxSpeed = 40; // Increased from 25 self.acceleration = 0.5; // Increased from 0.3 self.deceleration = 0.1; self.handling = 10; self.isAccelerating = true; self.hp = 100; self.level = 1; self.upgradePoints = 0; // Track last positions for collision detection self.lastX = 0; self.lastY = 0; // Control methods self.moveLeft = function () { if (self.x > roadLeftEdge + self.width / 2 + 10) { self.x -= self.handling; } }; self.moveRight = function () { if (self.x < roadRightEdge - self.width / 2 - 10) { self.x += self.handling; } }; self.update = function () { // Store last position self.lastX = self.x; self.lastY = self.y; // Update speed if (self.isAccelerating && self.speed < self.maxSpeed) { self.speed += self.acceleration; } else if (!self.isAccelerating && self.speed > 0) { self.speed -= self.deceleration; } if (self.speed < 0) self.speed = 0; // Apply visual effects based on speed var speedRatio = self.speed / self.maxSpeed; carGraphics.scaleX = 1 + speedRatio * 0.1; carGraphics.scaleY = 1 - speedRatio * 0.05; }; self.crash = function () { self.isAccelerating = false; self.speed = Math.max(0, self.speed * 0.5); // Reduce HP self.hp = Math.max(0, self.hp - 20); // Visual feedback for crash LK.effects.flashObject(self, 0xff0000, 500); LK.getSound('crash').play(); }; self.upgrade = function (type, amount) { if (type === 'speed') { self.maxSpeed += amount; } else if (type === 'handling') { self.handling += amount; } else if (type === 'acceleration') { self.acceleration += amount * 0.05; } else if (type === 'hp') { self.hp = Math.min(100, self.hp + amount); } else if (type === 'levelUp') { self.level++; self.maxSpeed += 2; self.handling += 1; self.acceleration += 0.05; self.hp = 100; // Visual feedback for car level up LK.effects.flashObject(self, 0x3498db, 1000); // Fire projectiles when car levels up fireProjectiles(self.x, self.y); } }; return self; }); var Projectile = Container.expand(function () { var self = Container.call(this); // Projectile properties self.speed = 0; self.active = true; self.lastY = 0; // Create projectile graphics var projectileGraphic = self.attachAsset('playerCar', { anchorX: 0.5, anchorY: 0.5, width: 20, height: 40, tint: 0x3498db }); // Initialize projectile self.setup = function (posX, posY, speedValue) { self.x = posX; self.y = posY; self.lastY = posY; self.speed = speedValue; self.rotation = -Math.PI / 2; // Point upward }; // Update projectile position self.update = function () { if (!self.active) return; self.lastY = self.y; self.y -= self.speed; // Remove when off-screen if (self.y < -100) { self.active = false; } }; return self; }); var RoadElement = Container.expand(function () { var self = Container.call(this); self.speed = 0; self.type = 'none'; self.setup = function (elementType, speedValue) { self.type = elementType; self.speed = speedValue; if (elementType === 'road') { self.roadGraphic = self.attachAsset('road', { anchorX: 0.5, anchorY: 0 }); } else if (elementType === 'line') { self.lineGraphic = self.attachAsset('roadLine', { anchorX: 0.5, anchorY: 0.5 }); } }; self.update = function () { self.y += self.speed; // Loop road elements if (self.type === 'road' && self.y > 2732) { self.y = -self.roadGraphic.height + 10; } // Loop road lines if (self.type === 'line' && self.y > 2732) { self.y = -100; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Initialize sound effects // Initialize car assets //Storage library for persistent game data //Minimalistic tween library for animations // Game variables var score = 0; var coins = storage.coins || 0; var level = storage.level || 1; var highScore = storage.highScore || 0; var gameSpeed = 5 + level * 0.5; var roadWidth = 600; var roadLeftEdge = (2048 - roadWidth) / 2; var roadRightEdge = roadLeftEdge + roadWidth; var spawnTimer = 0; var gameActive = true; var levelProgress = 0; var pointsToNextLevel = 1000; // Game elements var playerCar; var roadElements = []; var gameElements = []; var projectiles = []; var gameUI; // Create game UI and add to GUI layer gameUI = new GameUI(); gameUI.x = 50; gameUI.y = 50; LK.gui.topLeft.addChild(gameUI); // Create road function setupRoad() { // Create main road for (var i = 0; i < 2; i++) { var road = new RoadElement(); road.setup('road', gameSpeed); road.x = 2048 / 2; road.y = i * road.roadGraphic.height - (i > 0 ? 10 : 0); roadElements.push(road); game.addChild(road); } // Create road lines var lineSpacing = 200; for (var j = 0; j < 15; j++) { var line = new RoadElement(); line.setup('line', gameSpeed); line.x = 2048 / 2; line.y = j * lineSpacing; roadElements.push(line); game.addChild(line); } } // Create player car function setupPlayer() { playerCar = new PlayerCar(); playerCar.x = 2048 / 2; playerCar.y = 2732 - 300; game.addChild(playerCar); } // Spawn game elements (coins, obstacles, enemy cars) function spawnGameElement() { if (!gameActive) return; // Determine what to spawn based on random chance var rand = Math.random(); var type, lanePosition; // Calculate available lanes var laneWidth = roadWidth / 3; var lanes = [roadLeftEdge + laneWidth / 2, roadLeftEdge + laneWidth + laneWidth / 2, roadLeftEdge + laneWidth * 2 + laneWidth / 2]; // Choose random lane lanePosition = lanes[Math.floor(Math.random() * lanes.length)]; // Determine element type if (rand < 0.4) { type = 'coin'; } else if (rand < 0.7) { type = 'obstacle'; } else { type = 'enemyCar'; } var element = new GameElement(); element.setup(type, lanePosition, gameSpeed); gameElements.push(element); game.addChild(element); // Add some variation to spawn rate spawnTimer = 60 + Math.floor(Math.random() * 60); } // Initialize game function initGame() { // Reset game state score = 0; levelProgress = 0; gameSpeed = 5 + level * 0.5; gameActive = true; // Clear existing elements for (var i = 0; i < roadElements.length; i++) { roadElements[i].destroy(); } roadElements = []; for (var j = 0; j < gameElements.length; j++) { gameElements[j].destroy(); } gameElements = []; // Clear projectiles for (var k = 0; k < projectiles.length; k++) { projectiles[k].destroy(); } projectiles = []; clearProjectileInterval(); // Setup game elements setupRoad(); setupPlayer(); // Update UI gameUI.update(score, coins, level, playerCar.hp); } // Update score and check for level up function updateScore(points) { score += points; levelProgress += points; // Level up when enough points are collected if (levelProgress >= pointsToNextLevel) { levelUp(); } // Update high score if (score > highScore) { highScore = score; storage.highScore = highScore; } // Update UI gameUI.update(score, coins, level); } // Handle level up function levelUp() { level++; storage.level = level; levelProgress = 0; gameSpeed += 0.5; // Increase points needed for next level pointsToNextLevel = 1000 + level * 500; // Visual feedback LK.effects.flashScreen(0x2ecc71, 500); LK.getSound('levelUp').play(); // Update road and element speeds for (var i = 0; i < roadElements.length; i++) { roadElements[i].speed = gameSpeed; } // Update UI gameUI.update(score, coins, level); } // Handle coin collection function collectCoin(element) { coins++; storage.coins = coins; updateScore(50); // Restore some HP playerCar.upgrade('hp', 5); // Visual feedback LK.effects.flashObject(element, 0xf1c40f, 300); LK.getSound('coinCollect').play(); // Remove coin element.active = false; game.removeChild(element); // Check if player can level up car if (coins >= playerCar.level * 10) { coins -= playerCar.level * 10; storage.coins = coins; playerCar.upgrade('levelUp'); LK.effects.flashScreen(0x3498db, 500); } // Update UI with new HP gameUI.update(score, coins, level, playerCar.hp); } // Handle collision with obstacle or enemy car function handleCollision(element) { playerCar.crash(); updateScore(-100); // Visual feedback LK.effects.flashObject(element, 0xff0000, 300); // Remove obstacle element.active = false; game.removeChild(element); // Update HP display gameUI.update(score, coins, level, playerCar.hp); // Check if game over if (score <= 0 || playerCar.hp <= 0) { gameOver(); } } // Fire projectiles when car levels up var projectileInterval = null; function fireProjectiles(startX, startY) { // Fire multiple projectiles in different patterns based on car level var count = Math.min(playerCar.level, 5); // Max 5 projectiles for (var i = 0; i < count; i++) { var projectile = new Projectile(); var offset = (i - (count - 1) / 2) * 50; // Spread projectiles horizontally projectile.setup(startX + offset, startY - 50, 20); projectiles.push(projectile); game.addChild(projectile); } // Play sound effect LK.getSound('levelUp').play(); // Start continuous firing if not already started if (!projectileInterval) { projectileInterval = LK.setInterval(function () { if (!gameActive) return; // Only fire if playerCar is still in game and leveled up at least once if (playerCar && playerCar.level > 1) { var count = Math.min(playerCar.level, 5); for (var i = 0; i < count; i++) { var projectile = new Projectile(); var offset = (i - (count - 1) / 2) * 50; projectile.setup(playerCar.x + offset, playerCar.y - 50, 20); projectiles.push(projectile); game.addChild(projectile); } } }, 300); // Fire every 300ms } } // Clear projectile interval on game over or reset function clearProjectileInterval() { if (projectileInterval) { LK.clearInterval(projectileInterval); projectileInterval = null; } } // Game over function gameOver() { gameActive = false; clearProjectileInterval(); LK.effects.flashScreen(0xe74c3c, 1000); LK.showGameOver(); } // Initialize the game initGame(); // Game update loop game.update = function () { if (!gameActive) return; // Update player car playerCar.update(); // Update road elements for (var i = 0; i < roadElements.length; i++) { roadElements[i].update(); } // Update game elements and check collisions for (var j = gameElements.length - 1; j >= 0; j--) { var element = gameElements[j]; element.update(); // Remove inactive elements if (!element.active) { gameElements.splice(j, 1); continue; } // Check for collisions var wasIntersecting = element.lastIntersecting; var isIntersecting = element.intersects(playerCar); element.lastIntersecting = isIntersecting; // Handle new intersections if (!wasIntersecting && isIntersecting) { if (element.type === 'coin') { collectCoin(element); } else { handleCollision(element); } } } // Update projectiles and check for collisions for (var p = projectiles.length - 1; p >= 0; p--) { var projectile = projectiles[p]; projectile.update(); // Remove inactive projectiles if (!projectile.active) { game.removeChild(projectile); projectiles.splice(p, 1); continue; } // Check for collisions with game elements for (var e = gameElements.length - 1; e >= 0; e--) { var element = gameElements[e]; if (element.type !== 'coin' && projectile.intersects(element)) { // Remove the element element.active = false; game.removeChild(element); gameElements.splice(e, 1); // Give points for destroying obstacles with projectiles updateScore(25); // Create visual effect LK.effects.flashObject(projectile, 0xffffff, 200); // Remove the projectile projectile.active = false; game.removeChild(projectile); projectiles.splice(p, 1); break; } } } // Increment score based on speed if (LK.ticks % 10 === 0) { updateScore(Math.floor(playerCar.speed)); gameUI.update(score, coins, level, playerCar.hp); } // Spawn new game elements if (spawnTimer <= 0) { spawnGameElement(); } else { spawnTimer--; } // Add points for progress if (LK.ticks % 60 === 0) { updateScore(1); } }; // Touch controls game.down = function (x, y, obj) { if (!gameActive) return; // Determine which side of the screen was touched if (x < 2048 / 2) { playerCar.moveLeft(); } else { playerCar.moveRight(); } }; game.move = function (x, y, obj) { if (!gameActive) return; // Determine which side of the screen is being touched if (x < 2048 / 2) { playerCar.moveLeft(); } else { playerCar.moveRight(); } }; // Set game background color game.setBackgroundColor(0x1a1a2e);
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
level: 1,
coins: 0,
highScore: 0
});
/****
* Classes
****/
var GameElement = Container.expand(function () {
var self = Container.call(this);
self.speed = 0;
self.active = true;
self.type = 'none';
self.lastIntersecting = false;
self.setup = function (elementType, posX, speedValue) {
self.type = elementType;
self.speed = speedValue;
self.x = posX;
self.y = -200;
if (elementType === 'coin') {
var coinGraphic = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
// Add shine animation
self.animate = function () {
tween(coinGraphic, {
alpha: 0.5
}, {
duration: 500,
easing: tween.linear,
onFinish: function onFinish() {
tween(coinGraphic, {
alpha: 1
}, {
duration: 500,
easing: tween.linear,
onFinish: self.animate
});
}
});
};
self.animate();
} else if (elementType === 'obstacle') {
self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
} else if (elementType === 'enemyCar') {
self.attachAsset('enemyCar', {
anchorX: 0.5,
anchorY: 0.5
});
}
};
self.update = function () {
if (!self.active) return;
self.y += self.speed;
// Remove when off-screen
if (self.y > 2732 + 100) {
self.active = false;
}
// Rotate coins slightly for visual appeal
if (self.type === 'coin') {
self.rotation += 0.02;
}
};
return self;
});
var GameUI = Container.expand(function () {
var self = Container.call(this);
// Create score text
self.scoreText = new Text2('SCORE: 0', {
size: 60,
fill: 0xFFFFFF
});
self.scoreText.anchor.set(0, 0);
self.addChild(self.scoreText);
// Create coins text
self.coinsText = new Text2('COINS: 0', {
size: 60,
fill: 0xF1C40F
});
self.coinsText.anchor.set(0, 0);
self.coinsText.y = 70;
self.addChild(self.coinsText);
// Create level text
self.levelText = new Text2('LEVEL: 1', {
size: 60,
fill: 0x2ECC71
});
self.levelText.anchor.set(0, 0);
self.levelText.y = 140;
self.addChild(self.levelText);
// Create HP bar background
self.hpBarBg = new Container();
self.hpBarBg.x = 0;
self.hpBarBg.y = 210;
self.addChild(self.hpBarBg);
var hpBarBgGraphic = LK.getAsset('road', {
anchorX: 0,
anchorY: 0,
width: 300,
height: 30,
tint: 0x555555
});
self.hpBarBg.addChild(hpBarBgGraphic);
// Create HP bar fill
self.hpBarFill = new Container();
self.hpBarFill.x = 0;
self.hpBarFill.y = 210;
self.addChild(self.hpBarFill);
var hpBarFillGraphic = LK.getAsset('road', {
anchorX: 0,
anchorY: 0,
width: 300,
height: 30,
tint: 0x27ae60
});
self.hpBarFill.addChild(hpBarFillGraphic);
// Create HP text
self.hpText = new Text2('HP: 100%', {
size: 40,
fill: 0xFFFFFF
});
self.hpText.anchor.set(0, 0.5);
self.hpText.x = 10;
self.hpText.y = 225;
self.addChild(self.hpText);
// Update UI elements
self.update = function (score, coins, level, hp) {
self.scoreText.setText('SCORE: ' + score);
self.coinsText.setText('COINS: ' + coins);
self.levelText.setText('LEVEL: ' + level);
if (hp !== undefined) {
// Update HP bar
var hpPercent = Math.max(0, Math.min(100, hp));
self.hpBarFill.children[0].width = 3 * hpPercent;
self.hpText.setText('HP: ' + hpPercent + '%');
// Change color based on HP level
if (hpPercent > 60) {
self.hpBarFill.children[0].tint = 0x27ae60; // Green
} else if (hpPercent > 30) {
self.hpBarFill.children[0].tint = 0xf39c12; // Orange
} else {
self.hpBarFill.children[0].tint = 0xe74c3c; // Red
}
}
};
return self;
});
// Game variables
var PlayerCar = Container.expand(function () {
var self = Container.call(this);
// Create car graphics
var carGraphics = self.attachAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5
});
// Car properties
self.speed = 0;
self.maxSpeed = 40; // Increased from 25
self.acceleration = 0.5; // Increased from 0.3
self.deceleration = 0.1;
self.handling = 10;
self.isAccelerating = true;
self.hp = 100;
self.level = 1;
self.upgradePoints = 0;
// Track last positions for collision detection
self.lastX = 0;
self.lastY = 0;
// Control methods
self.moveLeft = function () {
if (self.x > roadLeftEdge + self.width / 2 + 10) {
self.x -= self.handling;
}
};
self.moveRight = function () {
if (self.x < roadRightEdge - self.width / 2 - 10) {
self.x += self.handling;
}
};
self.update = function () {
// Store last position
self.lastX = self.x;
self.lastY = self.y;
// Update speed
if (self.isAccelerating && self.speed < self.maxSpeed) {
self.speed += self.acceleration;
} else if (!self.isAccelerating && self.speed > 0) {
self.speed -= self.deceleration;
}
if (self.speed < 0) self.speed = 0;
// Apply visual effects based on speed
var speedRatio = self.speed / self.maxSpeed;
carGraphics.scaleX = 1 + speedRatio * 0.1;
carGraphics.scaleY = 1 - speedRatio * 0.05;
};
self.crash = function () {
self.isAccelerating = false;
self.speed = Math.max(0, self.speed * 0.5);
// Reduce HP
self.hp = Math.max(0, self.hp - 20);
// Visual feedback for crash
LK.effects.flashObject(self, 0xff0000, 500);
LK.getSound('crash').play();
};
self.upgrade = function (type, amount) {
if (type === 'speed') {
self.maxSpeed += amount;
} else if (type === 'handling') {
self.handling += amount;
} else if (type === 'acceleration') {
self.acceleration += amount * 0.05;
} else if (type === 'hp') {
self.hp = Math.min(100, self.hp + amount);
} else if (type === 'levelUp') {
self.level++;
self.maxSpeed += 2;
self.handling += 1;
self.acceleration += 0.05;
self.hp = 100;
// Visual feedback for car level up
LK.effects.flashObject(self, 0x3498db, 1000);
// Fire projectiles when car levels up
fireProjectiles(self.x, self.y);
}
};
return self;
});
var Projectile = Container.expand(function () {
var self = Container.call(this);
// Projectile properties
self.speed = 0;
self.active = true;
self.lastY = 0;
// Create projectile graphics
var projectileGraphic = self.attachAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5,
width: 20,
height: 40,
tint: 0x3498db
});
// Initialize projectile
self.setup = function (posX, posY, speedValue) {
self.x = posX;
self.y = posY;
self.lastY = posY;
self.speed = speedValue;
self.rotation = -Math.PI / 2; // Point upward
};
// Update projectile position
self.update = function () {
if (!self.active) return;
self.lastY = self.y;
self.y -= self.speed;
// Remove when off-screen
if (self.y < -100) {
self.active = false;
}
};
return self;
});
var RoadElement = Container.expand(function () {
var self = Container.call(this);
self.speed = 0;
self.type = 'none';
self.setup = function (elementType, speedValue) {
self.type = elementType;
self.speed = speedValue;
if (elementType === 'road') {
self.roadGraphic = self.attachAsset('road', {
anchorX: 0.5,
anchorY: 0
});
} else if (elementType === 'line') {
self.lineGraphic = self.attachAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5
});
}
};
self.update = function () {
self.y += self.speed;
// Loop road elements
if (self.type === 'road' && self.y > 2732) {
self.y = -self.roadGraphic.height + 10;
}
// Loop road lines
if (self.type === 'line' && self.y > 2732) {
self.y = -100;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Initialize sound effects
// Initialize car assets
//Storage library for persistent game data
//Minimalistic tween library for animations
// Game variables
var score = 0;
var coins = storage.coins || 0;
var level = storage.level || 1;
var highScore = storage.highScore || 0;
var gameSpeed = 5 + level * 0.5;
var roadWidth = 600;
var roadLeftEdge = (2048 - roadWidth) / 2;
var roadRightEdge = roadLeftEdge + roadWidth;
var spawnTimer = 0;
var gameActive = true;
var levelProgress = 0;
var pointsToNextLevel = 1000;
// Game elements
var playerCar;
var roadElements = [];
var gameElements = [];
var projectiles = [];
var gameUI;
// Create game UI and add to GUI layer
gameUI = new GameUI();
gameUI.x = 50;
gameUI.y = 50;
LK.gui.topLeft.addChild(gameUI);
// Create road
function setupRoad() {
// Create main road
for (var i = 0; i < 2; i++) {
var road = new RoadElement();
road.setup('road', gameSpeed);
road.x = 2048 / 2;
road.y = i * road.roadGraphic.height - (i > 0 ? 10 : 0);
roadElements.push(road);
game.addChild(road);
}
// Create road lines
var lineSpacing = 200;
for (var j = 0; j < 15; j++) {
var line = new RoadElement();
line.setup('line', gameSpeed);
line.x = 2048 / 2;
line.y = j * lineSpacing;
roadElements.push(line);
game.addChild(line);
}
}
// Create player car
function setupPlayer() {
playerCar = new PlayerCar();
playerCar.x = 2048 / 2;
playerCar.y = 2732 - 300;
game.addChild(playerCar);
}
// Spawn game elements (coins, obstacles, enemy cars)
function spawnGameElement() {
if (!gameActive) return;
// Determine what to spawn based on random chance
var rand = Math.random();
var type, lanePosition;
// Calculate available lanes
var laneWidth = roadWidth / 3;
var lanes = [roadLeftEdge + laneWidth / 2, roadLeftEdge + laneWidth + laneWidth / 2, roadLeftEdge + laneWidth * 2 + laneWidth / 2];
// Choose random lane
lanePosition = lanes[Math.floor(Math.random() * lanes.length)];
// Determine element type
if (rand < 0.4) {
type = 'coin';
} else if (rand < 0.7) {
type = 'obstacle';
} else {
type = 'enemyCar';
}
var element = new GameElement();
element.setup(type, lanePosition, gameSpeed);
gameElements.push(element);
game.addChild(element);
// Add some variation to spawn rate
spawnTimer = 60 + Math.floor(Math.random() * 60);
}
// Initialize game
function initGame() {
// Reset game state
score = 0;
levelProgress = 0;
gameSpeed = 5 + level * 0.5;
gameActive = true;
// Clear existing elements
for (var i = 0; i < roadElements.length; i++) {
roadElements[i].destroy();
}
roadElements = [];
for (var j = 0; j < gameElements.length; j++) {
gameElements[j].destroy();
}
gameElements = [];
// Clear projectiles
for (var k = 0; k < projectiles.length; k++) {
projectiles[k].destroy();
}
projectiles = [];
clearProjectileInterval();
// Setup game elements
setupRoad();
setupPlayer();
// Update UI
gameUI.update(score, coins, level, playerCar.hp);
}
// Update score and check for level up
function updateScore(points) {
score += points;
levelProgress += points;
// Level up when enough points are collected
if (levelProgress >= pointsToNextLevel) {
levelUp();
}
// Update high score
if (score > highScore) {
highScore = score;
storage.highScore = highScore;
}
// Update UI
gameUI.update(score, coins, level);
}
// Handle level up
function levelUp() {
level++;
storage.level = level;
levelProgress = 0;
gameSpeed += 0.5;
// Increase points needed for next level
pointsToNextLevel = 1000 + level * 500;
// Visual feedback
LK.effects.flashScreen(0x2ecc71, 500);
LK.getSound('levelUp').play();
// Update road and element speeds
for (var i = 0; i < roadElements.length; i++) {
roadElements[i].speed = gameSpeed;
}
// Update UI
gameUI.update(score, coins, level);
}
// Handle coin collection
function collectCoin(element) {
coins++;
storage.coins = coins;
updateScore(50);
// Restore some HP
playerCar.upgrade('hp', 5);
// Visual feedback
LK.effects.flashObject(element, 0xf1c40f, 300);
LK.getSound('coinCollect').play();
// Remove coin
element.active = false;
game.removeChild(element);
// Check if player can level up car
if (coins >= playerCar.level * 10) {
coins -= playerCar.level * 10;
storage.coins = coins;
playerCar.upgrade('levelUp');
LK.effects.flashScreen(0x3498db, 500);
}
// Update UI with new HP
gameUI.update(score, coins, level, playerCar.hp);
}
// Handle collision with obstacle or enemy car
function handleCollision(element) {
playerCar.crash();
updateScore(-100);
// Visual feedback
LK.effects.flashObject(element, 0xff0000, 300);
// Remove obstacle
element.active = false;
game.removeChild(element);
// Update HP display
gameUI.update(score, coins, level, playerCar.hp);
// Check if game over
if (score <= 0 || playerCar.hp <= 0) {
gameOver();
}
}
// Fire projectiles when car levels up
var projectileInterval = null;
function fireProjectiles(startX, startY) {
// Fire multiple projectiles in different patterns based on car level
var count = Math.min(playerCar.level, 5); // Max 5 projectiles
for (var i = 0; i < count; i++) {
var projectile = new Projectile();
var offset = (i - (count - 1) / 2) * 50; // Spread projectiles horizontally
projectile.setup(startX + offset, startY - 50, 20);
projectiles.push(projectile);
game.addChild(projectile);
}
// Play sound effect
LK.getSound('levelUp').play();
// Start continuous firing if not already started
if (!projectileInterval) {
projectileInterval = LK.setInterval(function () {
if (!gameActive) return;
// Only fire if playerCar is still in game and leveled up at least once
if (playerCar && playerCar.level > 1) {
var count = Math.min(playerCar.level, 5);
for (var i = 0; i < count; i++) {
var projectile = new Projectile();
var offset = (i - (count - 1) / 2) * 50;
projectile.setup(playerCar.x + offset, playerCar.y - 50, 20);
projectiles.push(projectile);
game.addChild(projectile);
}
}
}, 300); // Fire every 300ms
}
}
// Clear projectile interval on game over or reset
function clearProjectileInterval() {
if (projectileInterval) {
LK.clearInterval(projectileInterval);
projectileInterval = null;
}
}
// Game over
function gameOver() {
gameActive = false;
clearProjectileInterval();
LK.effects.flashScreen(0xe74c3c, 1000);
LK.showGameOver();
}
// Initialize the game
initGame();
// Game update loop
game.update = function () {
if (!gameActive) return;
// Update player car
playerCar.update();
// Update road elements
for (var i = 0; i < roadElements.length; i++) {
roadElements[i].update();
}
// Update game elements and check collisions
for (var j = gameElements.length - 1; j >= 0; j--) {
var element = gameElements[j];
element.update();
// Remove inactive elements
if (!element.active) {
gameElements.splice(j, 1);
continue;
}
// Check for collisions
var wasIntersecting = element.lastIntersecting;
var isIntersecting = element.intersects(playerCar);
element.lastIntersecting = isIntersecting;
// Handle new intersections
if (!wasIntersecting && isIntersecting) {
if (element.type === 'coin') {
collectCoin(element);
} else {
handleCollision(element);
}
}
}
// Update projectiles and check for collisions
for (var p = projectiles.length - 1; p >= 0; p--) {
var projectile = projectiles[p];
projectile.update();
// Remove inactive projectiles
if (!projectile.active) {
game.removeChild(projectile);
projectiles.splice(p, 1);
continue;
}
// Check for collisions with game elements
for (var e = gameElements.length - 1; e >= 0; e--) {
var element = gameElements[e];
if (element.type !== 'coin' && projectile.intersects(element)) {
// Remove the element
element.active = false;
game.removeChild(element);
gameElements.splice(e, 1);
// Give points for destroying obstacles with projectiles
updateScore(25);
// Create visual effect
LK.effects.flashObject(projectile, 0xffffff, 200);
// Remove the projectile
projectile.active = false;
game.removeChild(projectile);
projectiles.splice(p, 1);
break;
}
}
}
// Increment score based on speed
if (LK.ticks % 10 === 0) {
updateScore(Math.floor(playerCar.speed));
gameUI.update(score, coins, level, playerCar.hp);
}
// Spawn new game elements
if (spawnTimer <= 0) {
spawnGameElement();
} else {
spawnTimer--;
}
// Add points for progress
if (LK.ticks % 60 === 0) {
updateScore(1);
}
};
// Touch controls
game.down = function (x, y, obj) {
if (!gameActive) return;
// Determine which side of the screen was touched
if (x < 2048 / 2) {
playerCar.moveLeft();
} else {
playerCar.moveRight();
}
};
game.move = function (x, y, obj) {
if (!gameActive) return;
// Determine which side of the screen is being touched
if (x < 2048 / 2) {
playerCar.moveLeft();
} else {
playerCar.moveRight();
}
};
// Set game background color
game.setBackgroundColor(0x1a1a2e);