/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Bomb = Container.expand(function () { var self = Container.call(this); var bombGraphics = self.attachAsset('powerUp', { anchorX: 0.5, anchorY: 0.5 }); // Make bomb look dangerous with dark red tint and smaller size bombGraphics.tint = 0x660000; bombGraphics.scaleX = 0.6; bombGraphics.scaleY = 0.6; self.speed = 13.86; self.targetLane = 1; self.rotationSpeed = 0.3; self.pulseScale = 1; self.pulseDirection = 1; self.update = function () { self.speed = 13.86 * gameSpeed; self.y += self.speed; // Move towards target lane (player's position when thrown) var targetX = 324 + self.targetLane * 400; var diff = targetX - self.x; if (Math.abs(diff) > 10) { self.x += diff * 0.1; } // Spinning and pulsing animation for danger effect bombGraphics.rotation += self.rotationSpeed; self.pulseScale += self.pulseDirection * 0.05; if (self.pulseScale > 1.3) { self.pulseDirection = -1; } else if (self.pulseScale < 0.8) { self.pulseDirection = 1; } bombGraphics.scaleX = 0.6 * self.pulseScale; bombGraphics.scaleY = 0.6 * self.pulseScale; }; return self; }); var Bomber = Container.expand(function () { var self = Container.call(this); var bomberGraphics = self.attachAsset('bomberPerson', { anchorX: 0.5, anchorY: 0.5 }); // Make bomber distinct with darker brown color and human-like proportions bomberGraphics.scaleX = 0.8; bomberGraphics.scaleY = 0.9; self.speed = 6.93; self.lane = 0; self.throwTimer = 0; self.throwInterval = 120; // Throw bomb every 2 seconds self.hasThrown = false; self.update = function () { var difficultyMultiplier = 1 + distanceTraveled / 10000; self.speed = 6.93 * gameSpeed * difficultyMultiplier; self.y += self.speed; // Throw bomb when close to player self.throwTimer++; if (!self.hasThrown && self.throwTimer >= self.throwInterval && self.y > 500 && self.y < 1800) { self.throwBomb(); self.hasThrown = true; } // Add slight bobbing motion bomberGraphics.rotation = Math.sin(LK.ticks * 0.03) * 0.1; }; self.throwBomb = function () { var bomb = game.addChild(new Bomb()); bomb.x = self.x; bomb.y = self.y + 50; bomb.targetLane = playerCar.currentLane; bomb.speed = 13.86 * gameSpeed; bombs.push(bomb); }; return self; }); var Cup = Container.expand(function () { var self = Container.call(this); var cupGraphics = self.attachAsset('cup', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 9.24; self.rotationSpeed = 0.15; self.pulseScale = 1; self.pulseDirection = 1; self.update = function () { self.speed = 9.24 * gameSpeed; self.y += self.speed; cupGraphics.rotation += self.rotationSpeed; // Enhanced pulsing effect with sparkle self.pulseScale += self.pulseDirection * 0.04; if (self.pulseScale > 1.6) { self.pulseDirection = -1; } else if (self.pulseScale < 0.8) { self.pulseDirection = 1; } cupGraphics.scaleX = self.pulseScale; cupGraphics.scaleY = self.pulseScale; // Enhanced golden effect with sparkle animation var sparkleIntensity = 0.8 + Math.sin(LK.ticks * 0.15) * 0.2; cupGraphics.alpha = sparkleIntensity; // Alternating between bright gold and white for sparkle effect if (Math.sin(LK.ticks * 0.1) > 0.7) { cupGraphics.tint = 0xFFFFFF; // Bright white sparkle } else { cupGraphics.tint = 0xFFD700; // Rich gold } }; return self; }); var EnemyCar = Container.expand(function (carType) { var self = Container.call(this); var assetId = carType || 'enemyCar1'; var carGraphics = self.attachAsset(assetId, { anchorX: 0.5, anchorY: 0.5 }); self.speed = 9.24; self.lane = 0; self.update = function () { // Progressive speed increase with difficulty var difficultyMultiplier = 1 + distanceTraveled / 8000; // Enemies get faster over time self.speed = 9.24 * gameSpeed * difficultyMultiplier * (nitroSpeedMultiplier > 1 ? nitroSpeedMultiplier * 0.7 : 1); self.y += self.speed; // Add subtle bobbing motion for visual interest carGraphics.rotation = Math.sin(LK.ticks * 0.05) * 0.02; }; return self; }); var Explosion = Container.expand(function () { var self = Container.call(this); self.particles = []; self.lifeTime = 0; self.maxLifeTime = 60; // 1 second at 60fps // Create enhanced explosion particles with more variety for (var i = 0; i < 20; i++) { var particle = self.addChild(LK.getAsset('roadLine', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.2 + Math.random() * 0.4, scaleY: 0.2 + Math.random() * 0.4 })); // More vibrant explosion colors var colors = [0xFF1100, 0xFF4400, 0xFF6600, 0xFF8800, 0xFFAA00, 0xFFCC00, 0xFFFF00, 0xFFFFFF]; particle.tint = colors[Math.floor(Math.random() * colors.length)]; particle.vx = (Math.random() - 0.5) * 30; particle.vy = (Math.random() - 0.5) * 30; particle.gravity = 0.3 + Math.random() * 0.4; particle.friction = 0.92 + Math.random() * 0.06; particle.rotationSpeed = (Math.random() - 0.5) * 0.3; self.particles.push(particle); } self.update = function () { self.lifeTime++; // Update particles with enhanced physics for (var i = 0; i < self.particles.length; i++) { var particle = self.particles[i]; particle.x += particle.vx; particle.y += particle.vy; particle.vy += particle.gravity; particle.vx *= particle.friction; particle.vy *= particle.friction; // Add rotation to particles particle.rotation += particle.rotationSpeed; // Enhanced fade out with size reduction var fadeProgress = self.lifeTime / self.maxLifeTime; particle.alpha = 1 - fadeProgress; particle.scaleX *= 0.98; particle.scaleY *= 0.98; // Color intensity decreases over time if (fadeProgress > 0.5) { var intensity = 1 - (fadeProgress - 0.5) * 2; particle.tint = particle.tint & 0xFFFFFF * intensity; } } // Destroy explosion when done if (self.lifeTime >= self.maxLifeTime) { self.destroy(); } }; return self; }); var Nitro = Container.expand(function () { var self = Container.call(this); var nitroGraphics = self.attachAsset('nitro', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 9.24; self.rotationSpeed = 0.2; self.pulseScale = 1; self.pulseDirection = 1; self.update = function () { self.y += self.speed; nitroGraphics.rotation += self.rotationSpeed; // Enhanced pulsing effect with electric blue glow self.pulseScale += self.pulseDirection * 0.03; if (self.pulseScale > 1.5) { self.pulseDirection = -1; } else if (self.pulseScale < 0.7) { self.pulseDirection = 1; } nitroGraphics.scaleX = self.pulseScale; nitroGraphics.scaleY = self.pulseScale; // Electric blue glow effect with lightning-like intensity changes var electricIntensity = 0.6 + Math.sin(LK.ticks * 0.2) * 0.4; nitroGraphics.alpha = electricIntensity; // Bright electric blue with occasional white flashes if (Math.random() < 0.1) { nitroGraphics.tint = 0xFFFFFF; // White flash } else { nitroGraphics.tint = 0x00BFFF; // Electric blue } }; return self; }); var Pedestrian = Container.expand(function () { var self = Container.call(this); var pedestrianGraphics = self.attachAsset('pedestrian', { anchorX: 0.5, anchorY: 0.5 }); // Make pedestrian look different from bomber with varied appearances var appearances = [{ tint: 0xFF6B6B, scaleX: 0.6, scaleY: 0.9 }, // Red shirt, tall { tint: 0x4ECDC4, scaleX: 0.8, scaleY: 0.7 }, // Teal shirt, short { tint: 0xFFE66D, scaleX: 0.7, scaleY: 0.8 }, // Yellow shirt, medium { tint: 0xA8E6CF, scaleX: 0.75, scaleY: 0.85 }, // Green shirt, medium-tall { tint: 0xFF8B94, scaleX: 0.65, scaleY: 0.75 }, // Pink shirt, small { tint: 0xB4A7D6, scaleX: 0.9, scaleY: 0.6 } // Purple shirt, wide ]; var appearance = appearances[Math.floor(Math.random() * appearances.length)]; pedestrianGraphics.tint = appearance.tint; pedestrianGraphics.scaleX = appearance.scaleX; pedestrianGraphics.scaleY = appearance.scaleY; self.speed = 6.93; self.lane = 0; self.jumpPhase = 'waiting'; // 'waiting', 'jumping', 'crossing' self.jumpTimer = 0; self.jumpInterval = 180; // 3 seconds to decide to jump self.targetLane = Math.floor(Math.random() * 4); // Target lane to reach self.crossingSpeed = 3; self.update = function () { var difficultyMultiplier = 1 + distanceTraveled / 10000; self.speed = 6.93 * gameSpeed * difficultyMultiplier; self.y += self.speed; // Handle jumping behavior self.jumpTimer++; if (self.jumpPhase === 'waiting' && self.jumpTimer >= self.jumpInterval && self.y > 500 && self.y < 1800) { // Start jumping onto road self.jumpPhase = 'jumping'; self.jumpTimer = 0; } if (self.jumpPhase === 'jumping') { // Move toward target lane var targetX = 324 + self.targetLane * 400; var diff = targetX - self.x; if (Math.abs(diff) > 20) { self.x += diff * 0.08; } else { self.jumpPhase = 'crossing'; } } if (self.jumpPhase === 'crossing') { // Cross the road randomly if (Math.random() < 0.02) { self.targetLane = Math.floor(Math.random() * 4); } var targetX = 324 + self.targetLane * 400; var diff = targetX - self.x; self.x += diff * 0.05; } // Add walking animation pedestrianGraphics.rotation = Math.sin(LK.ticks * 0.1) * 0.1; }; return self; }); var PlayerCar = Container.expand(function () { var self = Container.call(this); var carGraphics = self.attachAsset('playerCar', { anchorX: 0.5, anchorY: 0.5 }); self.targetLane = 1; self.currentLane = 1; self.laneWidth = 400; self.moveSpeed = 0.35; self.update = function () { var targetX = self.getLaneX(self.targetLane); var diff = targetX - self.x; var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5); if (Math.abs(diff) > 5) { self.x += diff * adjustedMoveSpeed; } else { self.x = targetX; self.currentLane = self.targetLane; } // Handle jumping animation if (playerJumping) { var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration; if (jumpProgress >= 1) { // Jump finished playerJumping = false; jumpHeight = 0; carGraphics.y = 0; carGraphics.rotation = 0; } else { // Calculate jump arc (parabolic motion) jumpHeight = Math.sin(jumpProgress * Math.PI) * 100; carGraphics.y = -jumpHeight; // Add rotation during jump carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.2; } } }; self.getLaneX = function (lane) { return 324 + lane * self.laneWidth; }; self.switchLane = function (direction) { var newLane = self.targetLane + direction; if (newLane >= 0 && newLane <= 3) { self.targetLane = newLane; // Add drift mechanics with tween-based smooth turning animations tween(carGraphics, { rotation: direction * 0.3 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(carGraphics, { rotation: 0 }, { duration: 300, easing: tween.easeInOut }); } }); } }; return self; }); var PlayerCar2 = Container.expand(function () { var self = Container.call(this); var carGraphics = self.attachAsset('playerCar2', { anchorX: 0.5, anchorY: 0.5 }); self.targetLane = 1; self.currentLane = 1; self.laneWidth = 400; self.moveSpeed = 0.42; // Much faster lane switching speed self.update = function () { var targetX = self.getLaneX(self.targetLane); var diff = targetX - self.x; var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5); if (Math.abs(diff) > 5) { self.x += diff * adjustedMoveSpeed; } else { self.x = targetX; self.currentLane = self.targetLane; } // Handle jumping animation if (playerJumping) { var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration; if (jumpProgress >= 1) { playerJumping = false; jumpHeight = 0; carGraphics.y = 0; carGraphics.rotation = 0; } else { jumpHeight = Math.sin(jumpProgress * Math.PI) * 100; carGraphics.y = -jumpHeight; carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.25; } } }; self.getLaneX = function (lane) { return 324 + lane * self.laneWidth; }; self.switchLane = function (direction) { var newLane = self.targetLane + direction; if (newLane >= 0 && newLane <= 3) { self.targetLane = newLane; // Add drift mechanics with tween-based smooth turning animations tween(carGraphics, { rotation: direction * 0.35 }, { duration: 180, easing: tween.easeOut, onFinish: function onFinish() { tween(carGraphics, { rotation: 0 }, { duration: 280, easing: tween.easeInOut }); } }); } }; return self; }); var PlayerCar3 = Container.expand(function () { var self = Container.call(this); var carGraphics = self.attachAsset('playerCar3', { anchorX: 0.5, anchorY: 0.5 }); self.targetLane = 1; self.currentLane = 1; self.laneWidth = 400; self.moveSpeed = 0.38; // Faster lane switching speed self.update = function () { var targetX = self.getLaneX(self.targetLane); var diff = targetX - self.x; var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5); if (Math.abs(diff) > 5) { self.x += diff * adjustedMoveSpeed; } else { self.x = targetX; self.currentLane = self.targetLane; } // Handle jumping animation if (playerJumping) { var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration; if (jumpProgress >= 1) { playerJumping = false; jumpHeight = 0; carGraphics.y = 0; carGraphics.rotation = 0; } else { jumpHeight = Math.sin(jumpProgress * Math.PI) * 100; carGraphics.y = -jumpHeight; carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.15; } } }; self.getLaneX = function (lane) { return 324 + lane * self.laneWidth; }; self.switchLane = function (direction) { var newLane = self.targetLane + direction; if (newLane >= 0 && newLane <= 3) { self.targetLane = newLane; // Add drift mechanics with tween-based smooth turning animations tween(carGraphics, { rotation: direction * 0.25 }, { duration: 220, easing: tween.easeOut, onFinish: function onFinish() { tween(carGraphics, { rotation: 0 }, { duration: 320, easing: tween.easeInOut }); } }); } }; return self; }); var PlayerCar4 = Container.expand(function () { var self = Container.call(this); var carGraphics = self.attachAsset('playerCar4', { anchorX: 0.5, anchorY: 0.5 }); self.targetLane = 1; self.currentLane = 1; self.laneWidth = 400; self.moveSpeed = 0.35; // Standard lane switching speed like other cars self.update = function () { var targetX = self.getLaneX(self.targetLane); var diff = targetX - self.x; var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5); if (Math.abs(diff) > 5) { self.x += diff * adjustedMoveSpeed; } else { self.x = targetX; self.currentLane = self.targetLane; } // Handle jumping animation if (playerJumping) { var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration; if (jumpProgress >= 1) { playerJumping = false; jumpHeight = 0; carGraphics.y = 0; carGraphics.rotation = 0; } else { jumpHeight = Math.sin(jumpProgress * Math.PI) * 100; // Standard jump height carGraphics.y = -jumpHeight; carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.2; } } }; self.getLaneX = function (lane) { return 324 + lane * self.laneWidth; }; self.switchLane = function (direction) { var newLane = self.targetLane + direction; if (newLane >= 0 && newLane <= 3) { self.targetLane = newLane; // Add drift mechanics with tween-based smooth turning animations tween(carGraphics, { rotation: direction * 0.3 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(carGraphics, { rotation: 0 }, { duration: 300, easing: tween.easeInOut }); } }); } }; return self; }); var PlayerCar5 = Container.expand(function () { var self = Container.call(this); var carGraphics = self.attachAsset('playerCar5', { anchorX: 0.5, anchorY: 0.5 }); self.targetLane = 1; self.currentLane = 1; self.laneWidth = 400; self.moveSpeed = 0.75; // Much faster lane switching speed self.update = function () { var targetX = self.getLaneX(self.targetLane); var diff = targetX - self.x; var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5); if (Math.abs(diff) > 5) { self.x += diff * adjustedMoveSpeed; } else { self.x = targetX; self.currentLane = self.targetLane; } // Handle jumping animation if (playerJumping) { var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration; if (jumpProgress >= 1) { playerJumping = false; jumpHeight = 0; carGraphics.y = 0; carGraphics.rotation = 0; } else { jumpHeight = Math.sin(jumpProgress * Math.PI) * 100; carGraphics.y = -jumpHeight; carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.3; } } }; self.getLaneX = function (lane) { return 324 + lane * self.laneWidth; }; self.switchLane = function (direction) { var newLane = self.targetLane + direction; if (newLane >= 0 && newLane <= 3) { self.targetLane = newLane; // Add drift mechanics with tween-based smooth turning animations tween(carGraphics, { rotation: direction * 0.4 }, { duration: 160, easing: tween.easeOut, onFinish: function onFinish() { tween(carGraphics, { rotation: 0 }, { duration: 250, easing: tween.easeInOut }); } }); } }; return self; }); var PlayerCar6 = Container.expand(function () { var self = Container.call(this); var carGraphics = self.attachAsset('playerCar6', { anchorX: 0.5, anchorY: 0.5 }); self.targetLane = 1; self.currentLane = 1; self.laneWidth = 400; self.moveSpeed = 0.35; // Standard lane switching speed like PlayerCar self.update = function () { var targetX = self.getLaneX(self.targetLane); var diff = targetX - self.x; var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5); if (Math.abs(diff) > 5) { self.x += diff * adjustedMoveSpeed; } else { self.x = targetX; self.currentLane = self.targetLane; } // Handle jumping animation if (playerJumping) { var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration; if (jumpProgress >= 1) { playerJumping = false; jumpHeight = 0; carGraphics.y = 0; carGraphics.rotation = 0; } else { jumpHeight = Math.sin(jumpProgress * Math.PI) * 100; // Standard jump height carGraphics.y = -jumpHeight; carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.2; } } }; self.getLaneX = function (lane) { return 324 + lane * self.laneWidth; }; self.switchLane = function (direction) { var newLane = self.targetLane + direction; if (newLane >= 0 && newLane <= 3) { self.targetLane = newLane; // Add drift mechanics with tween-based smooth turning animations tween(carGraphics, { rotation: direction * 0.3 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(carGraphics, { rotation: 0 }, { duration: 300, easing: tween.easeInOut }); } }); } }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerUpGraphics = self.attachAsset('powerUp', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 9.24; self.rotationSpeed = 0.1; self.update = function () { self.speed = 9.24 * gameSpeed * (nitroSpeedMultiplier > 1 ? nitroSpeedMultiplier * 0.8 : 1); self.y += self.speed; powerUpGraphics.rotation += self.rotationSpeed; // Enhanced visual effects with glow pulsing var glowIntensity = 0.7 + Math.sin(LK.ticks * 0.1) * 0.3; powerUpGraphics.alpha = glowIntensity; // Add rainbow tint cycling for more appealing visuals var hue = LK.ticks * 0.05 % (Math.PI * 2); var r = Math.floor(Math.sin(hue) * 127 + 128); var g = Math.floor(Math.sin(hue + Math.PI * 2 / 3) * 127 + 128); var b = Math.floor(Math.sin(hue + Math.PI * 4 / 3) * 127 + 128); powerUpGraphics.tint = r << 16 | g << 8 | b; }; return self; }); var Ramp = Container.expand(function () { var self = Container.call(this); // Create ramp visual using multiple road line assets var rampBase = self.attachAsset('roadLine', { anchorX: 0.5, anchorY: 0.5, scaleX: 8, scaleY: 2 }); rampBase.tint = 0x888888; var rampTop = self.attachAsset('roadLine', { anchorX: 0.5, anchorY: 0.5, scaleX: 6, scaleY: 1, y: -20 }); rampTop.tint = 0xAAAAA; self.speed = 9.24; self.lane = 0; self.update = function () { self.speed = 9.24 * gameSpeed; self.y += self.speed; // Add slight glow effect rampBase.alpha = 0.8 + Math.sin(LK.ticks * 0.1) * 0.2; }; 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 = 9.24; self.update = function () { self.speed = 9.24 * gameSpeed; self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2c3e50 }); /**** * Game Code ****/ // Game state management var gameState = 'splash'; // 'splash', 'menu', 'playing', 'gameOver' var menuElements = []; var bestDistance = 0; // Load best score from storage function loadBestScore() { var saved = storage.bestDistance; if (saved !== undefined) { bestDistance = saved; } } // Save best score to storage function saveBestScore() { storage.bestDistance = bestDistance; } // Start menu creation function createStartMenu() { // Simple road background - just a few lines for context for (var i = 0; i < 8; i++) { for (var lane = 0; lane < 4; lane++) { var menuLine = LK.getAsset('roadLine', { anchorX: 0.5, anchorY: 0.5, x: 624 + lane * 400, y: i * 250 + 300 }); menuLine.alpha = 0.2; game.addChild(menuLine); menuElements.push(menuLine); } } // Clean title - big and centered var titleText = new Text2('HIGHWAY RUSH', { size: 160, fill: '#FFD700', stroke: '#000000', strokeThickness: 6 }); titleText.anchor.set(0.5, 0.5); titleText.x = 1024; titleText.y = 600; game.addChild(titleText); menuElements.push(titleText); // Best score display - simple and clear var bestScoreText = new Text2('Best: ' + bestDistance + 'm', { size: 70, fill: '#FFFFFF', stroke: '#000000', strokeThickness: 4 }); bestScoreText.anchor.set(0.5, 0.5); bestScoreText.x = 1024; bestScoreText.y = 750; game.addChild(bestScoreText); menuElements.push(bestScoreText); // Car selection section - clean and organized var carSelectionText = new Text2('Choose Car:', { size: 60, fill: '#FFFFFF', stroke: '#000000', strokeThickness: 3 }); carSelectionText.anchor.set(0.5, 0.5); carSelectionText.x = 1024; carSelectionText.y = 950; game.addChild(carSelectionText); menuElements.push(carSelectionText); // Car selection buttons - properly centered for mobile var car1Button = LK.getAsset('playerCar', { anchorX: 0.5, anchorY: 0.5, x: 341, y: 1150, scaleX: 0.8, scaleY: 0.8 }); game.addChild(car1Button); menuElements.push(car1Button); var car2Button = LK.getAsset('playerCar2', { anchorX: 0.5, anchorY: 0.5, x: 574, y: 1150, scaleX: 0.8, scaleY: 0.8 }); game.addChild(car2Button); menuElements.push(car2Button); var car3Button = LK.getAsset('playerCar3', { anchorX: 0.5, anchorY: 0.5, x: 807, y: 1150, scaleX: 0.8, scaleY: 0.8 }); game.addChild(car3Button); menuElements.push(car3Button); // Add playerCar4 button var car4Button = LK.getAsset('playerCar4', { anchorX: 0.5, anchorY: 0.5, x: 1040, y: 1150, scaleX: 0.8, scaleY: 0.8 }); game.addChild(car4Button); menuElements.push(car4Button); // Add playerCar5 button var car5Button = LK.getAsset('playerCar5', { anchorX: 0.5, anchorY: 0.5, x: 1273, y: 1150, scaleX: 0.8, scaleY: 0.8 }); game.addChild(car5Button); menuElements.push(car5Button); // Add playerCar6 button var car6Button = LK.getAsset('playerCar6', { anchorX: 0.5, anchorY: 0.5, x: 1506, y: 1150, scaleX: 0.8, scaleY: 0.8 }); game.addChild(car6Button); menuElements.push(car6Button); // Selection indicator selectionIndicator = LK.getAsset('roadLine', { anchorX: 0.5, anchorY: 0.5, scaleX: 6, scaleY: 0.6, x: selectedCarType === 0 ? 341 : selectedCarType === 1 ? 574 : selectedCarType === 2 ? 807 : selectedCarType === 3 ? 1040 : selectedCarType === 4 ? 1273 : 1506, y: 1280 }); selectionIndicator.tint = 0xFFD700; game.addChild(selectionIndicator); menuElements.push(selectionIndicator); // Instructions - simple and clear var instructionsText = new Text2('Swipe to change lanes • Avoid traffic • Collect power-ups', { size: 50, fill: '#CCCCCC', stroke: '#000000', strokeThickness: 2 }); instructionsText.anchor.set(0.5, 0.5); instructionsText.x = 1024; instructionsText.y = 1450; game.addChild(instructionsText); menuElements.push(instructionsText); // Simple START BUTTON at bottom var startButton = LK.getAsset('roadLine', { anchorX: 0.5, anchorY: 0.5, scaleX: 25, scaleY: 4, x: 1024, y: 2200 }); startButton.tint = 0x00BB00; game.addChild(startButton); menuElements.push(startButton); // START text var startButtonText = new Text2('START GAME', { size: 120, fill: '#FFFFFF', stroke: '#000000', strokeThickness: 6 }); startButtonText.anchor.set(0.5, 0.5); startButtonText.x = 1024; startButtonText.y = 2200; game.addChild(startButtonText); menuElements.push(startButtonText); // Stats Chart button removed // Store button references for animations var buttonElements = { button: startButton, text: startButtonText }; // Initialize selection visual state updateCarSelection(); // Start menu music LK.playMusic('menumusic', { volume: 0.7 }); // Stylish fluid animations with enhanced effects // Title pulsing with glow effect tween(titleText, { scaleX: 1.15, scaleY: 1.15 }, { duration: 1800, yoyo: true, repeat: 50, easing: tween.easeInOut }); // Add floating animation to title tween(titleText, { y: 580 }, { duration: 3000, yoyo: true, repeat: 30, easing: tween.easeInOut }); // Remove swinging animation - title stays in center position // Car selection buttons - keep cars stationary (no movement animations) // Cars will remain in their fixed positions without floating or rotation effects // Enhanced button animations with elastic effect tween(buttonElements.button, { scaleX: 22, scaleY: 3.5 }, { duration: 2000, yoyo: true, repeat: 50, easing: tween.elasticInOut }); tween(buttonElements.text, { scaleX: 1.1, scaleY: 1.1 }, { duration: 2000, yoyo: true, repeat: 50, easing: tween.bounceInOut }); // Add color transition to start button tween(buttonElements.button, { tint: 0x00FF00 }, { duration: 1000, yoyo: true, repeat: 100, easing: tween.easeInOut }); // Stats button animations removed } function removeStartMenu() { // Stop all ongoing tweens to prevent memory leaks and performance issues for (var i = 0; i < menuElements.length; i++) { tween.stop(menuElements[i]); // Stop all tweens on this element menuElements[i].destroy(); } menuElements = []; } function startGame() { gameState = 'playing'; // Stop all menu tweens before removing menu if (menuElements.length > 0) { for (var i = 0; i < menuElements.length; i++) { tween.stop(menuElements[i]); } } removeStartMenu(); loadBestScore(); initializeGameplay(); // Reset tap counter after starting game car1TapCount = 0; car2TapCount = 0; car3TapCount = 0; car6TapCount = 0; // Initialize combo system for new game comboCount = 0; comboMultiplier = 1; lastComboTime = 0; // Statistics updates removed } // Camera shake system var cameraShake = { intensity: 0, duration: 0, originalX: 0, originalY: 0 }; function addCameraShake(intensity, duration) { if (cameraShake.intensity < intensity) { cameraShake.intensity = intensity; cameraShake.duration = duration; cameraShake.originalX = game.x; cameraShake.originalY = game.y; } } function updateCameraShake() { if (cameraShake.duration > 0) { var shakeX = (Math.random() - 0.5) * cameraShake.intensity; var shakeY = (Math.random() - 0.5) * cameraShake.intensity; game.x = cameraShake.originalX + shakeX; game.y = cameraShake.originalY + shakeY; cameraShake.duration--; cameraShake.intensity *= 0.95; // Fade out shake if (cameraShake.duration <= 0) { game.x = cameraShake.originalX; game.y = cameraShake.originalY; cameraShake.intensity = 0; } } } function initializeGameplay() { // Initialize all game variables gameSpeed = 1; baseGameSpeed = 1; gasPressed = false; gasAcceleration = 1; // Reset combo system variables comboCount = 0; comboMultiplier = 1; lastComboTime = 0; spawnTimer = 0; spawnRate = 120; lineSpawnTimer = 0; powerUpSpawnTimer = 0; nitroSpawnTimer = 0; cupSpawnTimer = 0; bomberSpawnTimer = 0; rampSpawnTimer = 0; pedestrianSpawnTimer = 0; playerJumping = false; jumpStartTime = 0; jumpHeight = 0; // Check if car1 was tapped 10 times for secret unlock if (selectedCarType === 0 && car1TapCount >= 10) { distanceTraveled = 2000; gameSpeed = 1 + distanceTraveled / 7000 + Math.pow(distanceTraveled / 15000, 1.5); gameSpeed = Math.min(gameSpeed, 4); // Flash screen to indicate secret unlock LK.effects.flashScreen(0x00ff00, 500); } else if (selectedCarType === 1 && car2TapCount >= 10) { // Trophy road mode - start with lots of trophies distanceTraveled = 0; // Flash screen golden to indicate trophy road LK.effects.flashScreen(0xFFD700, 1000); // Set flag for trophy road mode trophyRoadMode = true; } else if (selectedCarType === 5 && car6TapCount >= 31) { // PlayerCar6 ultra speed mode - 11x faster than normal distanceTraveled = 0; gameSpeed = 11; // 11 times faster than normal // Flash screen with bright cyan to indicate ultra speed LK.effects.flashScreen(0x00FFFF, 1500); // Add pulsing effect to player car for ultra speed mode tween(playerCar, { scaleX: 1.5, scaleY: 1.5 }, { duration: 500, yoyo: true, repeat: 3, easing: tween.easeInOut }); } else { distanceTraveled = 0; } nitroEffect = false; nitroEndTime = 0; hasShield = false; trophyRoadMode = false; rapModeActive = false; rapModeTimer = 0; playerCar4Unlocked = true; fastMusicPlaying = false; // Reset score LK.setScore(0); // Add enhanced road background var roadBackground = game.addChild(LK.getAsset('roadCenter', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366 })); roadBackground.alpha = 0.8; // Add road side markers var leftSide = game.addChild(LK.getAsset('roadSide', { anchorX: 0.5, anchorY: 0.5, x: 200, y: 1366 })); var rightSide = game.addChild(LK.getAsset('roadSide', { anchorX: 0.5, anchorY: 0.5, x: 1848, y: 1366 })); // Update UI texts with English scoreTxt.setText('Distance: ' + Math.floor(distanceTraveled)); bestScoreTxt.setText('Best: ' + bestDistance); speedTxt.setText('Speed: ' + gameSpeed.toFixed(1) + 'x'); // Add combo display comboTxt = new Text2('', { size: 70, fill: '#FF6B00', stroke: '#000000', strokeThickness: 3 }); comboTxt.anchor.set(0.5, 0); comboTxt.y = 160; LK.gui.top.addChild(comboTxt); // Reinitialize player car to ensure it's properly set up initializePlayerCar(); // Gas pedal completely removed from play - no longer visible or interactive gasButton = null; // Remove gas button reference // Stop menu music and start gameplay music LK.stopMusic(); LK.playMusic('bgmusic', { volume: 0.7 }); } // Initialize best score system loadBestScore(); // Define combo system variables var comboTimeWindow = 180; // 3 seconds at 60fps for combo window var comboCount = 0; var comboMultiplier = 1; var lastComboTime = 0; var comboTxt; // Player statistics system removed // Chart display system removed // Achievement system var achievements = { speedDemon: storage.achievementSpeedDemon || false, // Reach 3x speed jumpMaster: storage.achievementJumpMaster || false, // Jump 50 times collector: storage.achievementCollector || false, // Collect 100 power-ups survivor: storage.achievementSurvivor || false, // Travel 10000m in one game nitroAddict: storage.achievementNitroAddict || false // Collect 25 nitros }; function saveAchievements() { storage.achievementSpeedDemon = achievements.speedDemon; storage.achievementJumpMaster = achievements.jumpMaster; storage.achievementCollector = achievements.collector; storage.achievementSurvivor = achievements.survivor; storage.achievementNitroAddict = achievements.nitroAddict; } function checkAchievements() { // Speed Demon achievement if (!achievements.speedDemon && gameSpeed >= 3.0) { achievements.speedDemon = true; showAchievement("SPEED DEMON!", "Reached 3x speed!"); saveAchievements(); } // Jump Master achievement - removed since playerStats no longer exists // Collector achievement - removed since playerStats no longer exists // Survivor achievement if (!achievements.survivor && distanceTraveled >= 10000) { achievements.survivor = true; showAchievement("SURVIVOR!", "Traveled 10,000m!"); saveAchievements(); } // Nitro Addict achievement - removed since playerStats no longer exists } function showAchievement(title, description) { var achievementBg = LK.getAsset('roadLine', { anchorX: 0.5, anchorY: 0.5, scaleX: 25, scaleY: 4, x: 1024, y: 400 }); achievementBg.tint = 0xFFD700; achievementBg.alpha = 0; game.addChild(achievementBg); var achievementTitle = new Text2(title, { size: 80, fill: '#000000', stroke: '#FFFFFF', strokeThickness: 3 }); achievementTitle.anchor.set(0.5, 0.5); achievementTitle.x = 1024; achievementTitle.y = 370; achievementTitle.alpha = 0; game.addChild(achievementTitle); var achievementDesc = new Text2(description, { size: 50, fill: '#000000', stroke: '#FFFFFF', strokeThickness: 2 }); achievementDesc.anchor.set(0.5, 0.5); achievementDesc.x = 1024; achievementDesc.y = 430; achievementDesc.alpha = 0; game.addChild(achievementDesc); // Animate achievement popup tween(achievementBg, { alpha: 0.9 }, { duration: 500, easing: tween.easeOut }); tween(achievementTitle, { alpha: 1 }, { duration: 500, easing: tween.easeOut }); tween(achievementDesc, { alpha: 1 }, { duration: 500, easing: tween.easeOut }); // Auto-hide after 3 seconds LK.setTimeout(function () { tween(achievementBg, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { achievementBg.destroy(); } }); tween(achievementTitle, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { achievementTitle.destroy(); } }); tween(achievementDesc, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { achievementDesc.destroy(); } }); }, 3000); LK.effects.flashScreen(0xFFD700, 800); } // Show KEMALDEV splash screen first function showKemaldevSplash() { // Set game state to splash to prevent other interactions gameState = 'splash'; // Create black background covering full screen var splashBg = LK.getAsset('roadCenter', { anchorX: 0.5, anchorY: 0.5, x: 1024, y: 1366, scaleX: 2, scaleY: 2, tint: 0x000000 }); game.addChild(splashBg); // Create KEMALDEV text var kemaldevText = new Text2('KEMALDEV', { size: 200, fill: '#FFFFFF', stroke: '#FFD700', strokeThickness: 8 }); kemaldevText.anchor.set(0.5, 0.5); kemaldevText.x = 1024; kemaldevText.y = 1366; kemaldevText.alpha = 0; game.addChild(kemaldevText); // Fade in animation tween(kemaldevText, { alpha: 1 }, { duration: 800, easing: tween.easeOut }); // Add pulsing effect tween(kemaldevText, { scaleX: 1.1, scaleY: 1.1 }, { duration: 1000, yoyo: true, repeat: 2, easing: tween.easeInOut }); // Hide after 3 seconds and show main menu LK.setTimeout(function () { tween(kemaldevText, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { kemaldevText.destroy(); splashBg.destroy(); gameState = 'menu'; createStartMenu(); } }); }, 3000); } // Show KEMALDEV splash screen first, then create start menu showKemaldevSplash(); // Car selection variable var selectedCarType = 0; // 0 for PlayerCar, 1 for PlayerCar2, 2 for PlayerCar3 var playerCar; var selectionIndicator; var car1TapCount = 0; // Track taps on playercar1 for secret unlock var car2TapCount = 0; // Track taps on playercar2 for trophy road var car3TapCount = 0; // Track taps on playercar3 for secret message var car6TapCount = 0; // Track taps on playercar6 for speed boost // Update car selection visual state function updateCarSelection() { if (selectionIndicator) { var targetX = selectedCarType === 0 ? 341 : selectedCarType === 1 ? 574 : selectedCarType === 2 ? 807 : selectedCarType === 3 ? 1040 : selectedCarType === 4 ? 1273 : 1506; // Smooth fluid transition for selection indicator tween(selectionIndicator, { x: targetX }, { duration: 400, easing: tween.elasticOut }); // Add selection pulse effect tween(selectionIndicator, { scaleY: 1.2, tint: 0xFFD700 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(selectionIndicator, { scaleY: 0.6, tint: 0xFFFFFF }, { duration: 300, easing: tween.bounceOut }); } }); } // Check if car 3 is unlocked var car3Unlocked = bestDistance >= 2000; // Update car button tints if they exist if (menuElements.length > 0) { for (var i = 0; i < menuElements.length; i++) { var element = menuElements[i]; if (element.x === 624 && element.y === 1650) { element.tint = selectedCarType === 0 ? 0xFFD700 : 0xFFFFFF; } else if (element.x === 1024 && element.y === 1650) { element.tint = selectedCarType === 1 ? 0xFFD700 : 0xFFFFFF; } else if (element.x === 1424 && element.y === 1650) { if (car3Unlocked) { element.tint = selectedCarType === 2 ? 0xFFD700 : 0xFFFFFF; } else { element.tint = 0x666666; // Gray out locked car element.alpha = 0.5; } } } } } // Initialize player car based on selection function initializePlayerCar() { if (playerCar) { playerCar.destroy(); } if (selectedCarType === 0) { playerCar = game.addChild(new PlayerCar()); } else if (selectedCarType === 1) { playerCar = game.addChild(new PlayerCar2()); } else if (selectedCarType === 2) { playerCar = game.addChild(new PlayerCar3()); } else if (selectedCarType === 3) { playerCar = game.addChild(new PlayerCar4()); } else if (selectedCarType === 4) { playerCar = game.addChild(new PlayerCar5()); } else if (selectedCarType === 5) { playerCar = game.addChild(new PlayerCar6()); } playerCar.x = 324 + 400; // Lane 1 playerCar.y = 2200; } // Initialize the first car initializePlayerCar(); var enemyCars = []; var powerUps = []; var roadLines = []; var nitros = []; var cups = []; var bombers = []; var bombs = []; var ramps = []; var pedestrians = []; var playerJumping = false; var jumpStartTime = 0; var jumpDuration = 60; // 1 second at 60fps var jumpHeight = 0; var gameSpeed = 1; var spawnTimer = 0; var spawnRate = 120; var lineSpawnTimer = 0; var powerUpSpawnTimer = 0; var nitroSpawnTimer = 0; var cupSpawnTimer = 0; var bomberSpawnTimer = 0; var rampSpawnTimer = 0; var pedestrianSpawnTimer = 0; var distanceTraveled = 0; var nitroEffect = false; var nitroEndTime = 0; var nitroSpeedMultiplier = 1; var nitroAcceleration = 1; var hasShield = false; var gasPressed = false; var baseGameSpeed = 1; var gasAcceleration = 1; var maxGasMultiplier = 2.5; var gasDecelerationRate = 0.98; var gasAccelerationRate = 1.05; var trophyRoadMode = false; var rapModeActive = false; var rapModeTimer = 0; var rapModeCheckInterval = 600; // Check every 10 seconds (600 ticks at 60fps) var playerCar4Unlocked = true; // Create initial road lines for (var i = 0; i < 20; i++) { for (var lane = 0; lane < 4; lane++) { var line = game.addChild(new RoadLine()); line.x = 524 + lane * 400; // Between lanes line.y = i * 150 - 200; roadLines.push(line); } } // UI Elements var scoreTxt = new Text2('Distance: 0', { size: 80, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 4 }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var bestScoreTxt = new Text2('Best: ' + bestDistance, { size: 60, fill: 0xFFD700, stroke: 0x000000, strokeThickness: 3 }); bestScoreTxt.anchor.set(0.5, 0); bestScoreTxt.y = 90; LK.gui.top.addChild(bestScoreTxt); var speedTxt = new Text2('Speed: 1x', { size: 60, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 3 }); speedTxt.anchor.set(1, 1); speedTxt.x = -20; speedTxt.y = -20; LK.gui.bottomRight.addChild(speedTxt); // Touch controls var touchStartX = 0; var touchStartY = 0; var touchStartTime = 0; // Gas button element var gasButton; game.down = function (x, y, obj) { if (gameState === 'splash') { // Skip splash screen on tap tween.stop(); LK.clearTimeout(); gameState = 'menu'; // Clean up splash elements for (var i = game.children.length - 1; i >= 0; i--) { var child = game.children[i]; if (child) { child.destroy(); } } createStartMenu(); return; } if (gameState === 'menu') { // Check car selection buttons if (y >= 1050 && y <= 1250) { if (x >= 241 && x <= 441) { // Car 1 selected selectedCarType = 0; car1TapCount++; // Increment tap counter updateCarSelection(); initializePlayerCar(); return; } else if (x >= 474 && x <= 674) { // Car 2 selected selectedCarType = 1; car2TapCount++; // Increment tap counter for car2 updateCarSelection(); initializePlayerCar(); return; } else if (x >= 707 && x <= 907) { // Car 3 selected - check if unlocked if (bestDistance >= 2000) { selectedCarType = 2; car3TapCount++; // Increment tap counter for car3 // Check if tapped 10 times for secret message if (car3TapCount >= 10) { // Display "Thank you Yavuz Abi" in score area scoreTxt.setText('Thank you Yavuz Abi'); // Flash screen to indicate special message LK.effects.flashScreen(0xFFD700, 1000); } updateCarSelection(); initializePlayerCar(); } else { // Car 3 is locked, flash red to indicate requirement LK.effects.flashScreen(0xff0000, 300); } return; } else if (x >= 940 && x <= 1140) { // Car 4 selected - check if unlocked if (playerCar4Unlocked) { selectedCarType = 3; updateCarSelection(); initializePlayerCar(); } else { // Car 4 is locked, flash purple to indicate requirement LK.effects.flashScreen(0x9932CC, 300); } return; } else if (x >= 1173 && x <= 1373) { // Car 5 selected selectedCarType = 4; updateCarSelection(); initializePlayerCar(); return; } else if (x >= 1406 && x <= 1606) { // Car 6 selected selectedCarType = 5; car6TapCount++; // Increment tap counter for car6 updateCarSelection(); initializePlayerCar(); return; } } // Stats button interaction removed // Check for start button tap at bottom - expanded touch area for better UX if (y >= 2050 && y <= 2350 && x >= 300 && x <= 1748) { startGame(); return; } } if (gameState === 'playing') { // Gas button interaction removed - no longer functional } touchStartX = x; touchStartY = y; touchStartTime = LK.ticks; }; game.up = function (x, y, obj) { if (gameState !== 'playing') return; var touchEndX = x; var swipeDistance = touchEndX - touchStartX; var touchDuration = LK.ticks - touchStartTime; // Gas button release interaction removed - no longer functional // Detect swipe or tap for lane changing if (Math.abs(swipeDistance) > 100 && touchDuration < 30) { // Swipe detected if (swipeDistance > 0) { playerCar.switchLane(1); // Swipe right } else { playerCar.switchLane(-1); // Swipe left } } else if (touchDuration < 15) { // Gas button area check removed - full screen available for lane changes if (x > 1024) { playerCar.switchLane(1); // Right side tap } else { playerCar.switchLane(-1); // Left side tap } } }; function spawnEnemyCar() { var lane = Math.floor(Math.random() * 4); var enemy; var carTypes = ['enemyCar1', 'enemyCar2', 'enemyCar3']; var carType = carTypes[Math.floor(Math.random() * carTypes.length)]; enemy = game.addChild(new EnemyCar(carType)); enemy.x = 324 + lane * 400; enemy.y = -100; enemy.lane = lane; enemy.speed = 9.24 * gameSpeed; enemyCars.push(enemy); } function spawnPowerUp() { // Reduce spawn chance as difficulty increases var spawnChance = Math.max(0.1, 0.3 - distanceTraveled / 25000); // Decreases from 30% to 10% if (Math.random() < spawnChance) { var lane = Math.floor(Math.random() * 4); var powerUp = game.addChild(new PowerUp()); powerUp.x = 324 + lane * 400; powerUp.y = -100; powerUp.speed = 9.24 * gameSpeed; powerUps.push(powerUp); } } function spawnNitro() { // Significantly reduce spawn chance as difficulty increases var spawnChance = Math.max(0.05, 0.2 - distanceTraveled / 20000); // Decreases from 20% to 5% if (Math.random() < spawnChance) { var lane = Math.floor(Math.random() * 4); var nitro = game.addChild(new Nitro()); nitro.x = 324 + lane * 400; nitro.y = -100; nitro.speed = 9.24 * gameSpeed; nitros.push(nitro); } } function spawnCup() { // Check if trophy road mode is active if (trophyRoadMode) { // In trophy road mode, spawn many cups (trophies) var spawnChance = 0.8; // Very high spawn chance for trophies if (Math.random() < spawnChance) { // Spawn multiple cups across different lanes for (var trophyLane = 0; trophyLane < 4; trophyLane++) { if (Math.random() < 0.7) { // 70% chance per lane var cup = game.addChild(new Cup()); cup.x = 324 + trophyLane * 400; cup.y = -100 - trophyLane * 150; // Stagger them vertically cup.speed = 9.24 * gameSpeed; cups.push(cup); } } } } else { // Normal spawn chance for cups var spawnChance = Math.max(0.03, 0.15 - distanceTraveled / 30000); // Decreases from 15% to 3% if (Math.random() < spawnChance) { var lane = Math.floor(Math.random() * 4); var cup = game.addChild(new Cup()); cup.x = 324 + lane * 400; cup.y = -100; cup.speed = 9.24 * gameSpeed; cups.push(cup); } } } function spawnRamp() { // Spawn ramps occasionally to help player jump over obstacles var spawnChance = Math.max(0.05, 0.15 - distanceTraveled / 20000); // Decreases from 15% to 5% if (Math.random() < spawnChance) { var lane = Math.floor(Math.random() * 4); var ramp = game.addChild(new Ramp()); ramp.x = 324 + lane * 400; ramp.y = -100; ramp.lane = lane; ramp.speed = 9.24 * gameSpeed; ramps.push(ramp); } } function spawnPedestrian() { // Increased spawn chance for pedestrians by 80% more (from 25.92% to 46.66%) var spawnChance = Math.max(0.1555, 0.4666 - distanceTraveled / 30000); // Decreases from 46.66% to 15.55% if (Math.random() < spawnChance) { // Spawn from sides of the road var startSide = Math.random() < 0.5 ? 0 : 1; // 0 = left, 1 = right var pedestrian = game.addChild(new Pedestrian()); pedestrian.x = startSide === 0 ? 124 : 1924; // Start from road sides pedestrian.y = -100; pedestrian.lane = startSide === 0 ? 0 : 3; // Start lane pedestrian.speed = 6.93 * gameSpeed; pedestrians.push(pedestrian); } } function spawnBomber() { // Moderate spawn chance for bombers var spawnChance = Math.max(0.08, 0.25 - distanceTraveled / 25000); // Decreases from 25% to 8% if (Math.random() < spawnChance) { var lane = Math.floor(Math.random() * 4); var bomber = game.addChild(new Bomber()); bomber.x = 324 + lane * 400; bomber.y = -100; bomber.lane = lane; bomber.speed = 6.93 * gameSpeed; bombers.push(bomber); } } game.update = function () { // Only update game logic when playing if (gameState !== 'playing') return; // Update camera shake updateCameraShake(); // Update combo system if (LK.ticks - lastComboTime > comboTimeWindow && comboCount > 0) { comboCount = 0; comboMultiplier = 1; if (comboTxt) { tween(comboTxt, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { comboTxt.setText(''); comboTxt.alpha = 1; } }); } } // Player statistics updates removed // Check achievements checkAchievements(); // PlayerCar4 is now available from the start - no unlock required // Check for rap mode activation rapModeTimer++; if (rapModeTimer >= rapModeCheckInterval) { // 80% chance to activate rap mode every 10 seconds - rap appears frequently now! if (Math.random() < 0.8 && !rapModeActive) { rapModeActive = true; // Flash screen with hip-hop colors (purple/gold) LK.effects.flashScreen(0x9932CC, 800); // Change UI text to rap style scoreTxt.setText('Yo Distance: ' + Math.floor(distanceTraveled) + ' meters!'); speedTxt.setText('Speed Flow: ' + gameSpeed.toFixed(1) + 'x'); // Rap mode lasts for 5 seconds LK.setTimeout(function () { rapModeActive = false; // Reset UI text to normal scoreTxt.setText('Distance: ' + Math.floor(distanceTraveled)); speedTxt.setText('Speed: ' + gameSpeed.toFixed(1) + 'x'); LK.effects.flashScreen(0x00FFFF, 400); }, 5000); } rapModeTimer = 0; } // Update gas acceleration system with accelerator pedal physics if (gasPressed) { // Accelerate when stepping on the gas pedal gasAcceleration = Math.min(gasAcceleration * gasAccelerationRate, maxGasMultiplier); // Enhanced visual feedback for stepping on accelerator if (LK.ticks % 15 === 0) { LK.effects.flashObject(playerCar, 0xFFFF00, 150); } // Add speed lines effect when accelerating hard if (gasAcceleration > 1.8 && LK.ticks % 8 === 0) { LK.effects.flashScreen(0x004488, 30); } // Pedal vibration effect if (gasButton && gasAcceleration > 2.0) { gasButton.x = 1024 + (Math.random() - 0.5) * 4; gasButton.y = 2500 + (Math.random() - 0.5) * 4; } } else { // Decelerate when lifting foot off gas pedal gasAcceleration = Math.max(gasAcceleration * gasDecelerationRate, 1); // Reset pedal position when not pressed if (gasButton) { gasButton.x = 1024; gasButton.y = 2500; } } // Update base game speed with progression - increased by 11% baseGameSpeed = 1 + distanceTraveled / 7000 + Math.pow(distanceTraveled / 15000, 1.5); baseGameSpeed = Math.min(baseGameSpeed, 4); // Cap maximum base speed baseGameSpeed = baseGameSpeed * 1.11; // Increase speed by 11 percent // Apply gas acceleration to game speed gameSpeed = baseGameSpeed * gasAcceleration; // Update distance and speed with accelerated progression and nitro boost var effectiveSpeed = gameSpeed * nitroSpeedMultiplier * nitroAcceleration; distanceTraveled += effectiveSpeed; var lastGameSpeed = gameSpeed; // Switch to faster music at high speeds (based on base speed to prevent flickering) if (baseGameSpeed > 2.5 && !fastMusicPlaying) { LK.playMusic('fastmusic', { volume: 0.8 }); fastMusicPlaying = true; } else if (baseGameSpeed <= 2.5 && fastMusicPlaying) { LK.playMusic('bgmusic', { volume: 0.7 }); fastMusicPlaying = false; } // Update UI text based on rap mode if (rapModeActive) { scoreTxt.setText('Yo Distance: ' + Math.floor(distanceTraveled) + ' meters!'); bestScoreTxt.setText('Best Flow: ' + bestDistance); speedTxt.setText('Speed Flow: ' + gameSpeed.toFixed(1) + 'x' + (gasPressed ? ' ⚡' : '')); } else { scoreTxt.setText('Distance: ' + Math.floor(distanceTraveled)); bestScoreTxt.setText('Best: ' + bestDistance); speedTxt.setText('Speed: ' + gameSpeed.toFixed(1) + 'x' + (gasPressed ? ' ⚡' : '')); } // Add pulsing effect when speed increases if (gameSpeed > lastGameSpeed + 0.1) { tween(speedTxt, { scaleX: 1.2, scaleY: 1.2 }, { duration: 200, easing: tween.easeOut, onFinish: function onFinish() { tween(speedTxt, { scaleX: 1, scaleY: 1 }, { duration: 200, easing: tween.easeIn }); } }); } // Enhanced continuous nitro visual effects with fluid animations if (nitroEffect) { // Dynamic pulsing glow effect during nitro if (LK.ticks % 8 === 0) { var glowColor = Math.random() < 0.3 ? 0x00FFFF : Math.random() < 0.6 ? 0xFFFFFF : 0xFF00FF; LK.effects.flashObject(playerCar, glowColor, 150); } // Enhanced speed lines effect with gradient if (LK.ticks % 4 === 0) { var speedColor = Math.random() < 0.5 ? 0x0066BB : 0x004488; LK.effects.flashScreen(speedColor, 30); } // Add nitro trail effects with tween if (LK.ticks % 12 === 0) { // Create temporary trail effect var trailEffect = LK.getAsset('roadLine', { anchorX: 0.5, anchorY: 0.5, x: playerCar.x + (Math.random() - 0.5) * 100, y: playerCar.y + 50, tint: 0x00FFFF, alpha: 0.8 }); game.addChild(trailEffect); tween(trailEffect, { alpha: 0, scaleX: 3, scaleY: 0.2, y: trailEffect.y + 200 }, { duration: 600, easing: tween.easeOut, onFinish: function onFinish() { trailEffect.destroy(); } }); } } // Spawn enemies with progressive difficulty spawnTimer++; var adjustedSpawnRate = Math.max(30, spawnRate - Math.floor(distanceTraveled / 500)); // More aggressive spawn rate reduction if (spawnTimer >= adjustedSpawnRate / gameSpeed) { spawnEnemyCar(); spawnTimer = 0; // Multiple enemy spawning at higher difficulty if (distanceTraveled > 5000 && Math.random() < 0.3) { spawnEnemyCar(); // 30% chance for double spawn after 5000 distance } if (distanceTraveled > 10000 && Math.random() < 0.2) { spawnEnemyCar(); // Additional spawn chance after 10000 distance } } // Spawn power-ups with reduced frequency at higher difficulty powerUpSpawnTimer++; var powerUpInterval = Math.max(200, 300 + Math.floor(distanceTraveled / 200)); // Longer intervals as distance increases if (powerUpSpawnTimer >= powerUpInterval / gameSpeed) { spawnPowerUp(); powerUpSpawnTimer = 0; } // Spawn nitro with increased rarity at higher difficulty nitroSpawnTimer++; var nitroInterval = Math.max(400, 600 + Math.floor(distanceTraveled / 150)); // Much longer intervals as distance increases if (nitroSpawnTimer >= nitroInterval / gameSpeed) { spawnNitro(); nitroSpawnTimer = 0; } // Spawn cups with very rare frequency cupSpawnTimer++; var cupInterval = Math.max(800, 1200 + Math.floor(distanceTraveled / 100)); // Very long intervals if (cupSpawnTimer >= cupInterval / gameSpeed) { spawnCup(); cupSpawnTimer = 0; } // Spawn bombers periodically bomberSpawnTimer++; var bomberInterval = Math.max(300, 500 + Math.floor(distanceTraveled / 200)); // Moderate intervals if (bomberSpawnTimer >= bomberInterval / gameSpeed) { spawnBomber(); bomberSpawnTimer = 0; } // Spawn ramps periodically rampSpawnTimer++; var rampInterval = Math.max(600, 800 + Math.floor(distanceTraveled / 300)); // Long intervals for ramps if (rampSpawnTimer >= rampInterval / gameSpeed) { spawnRamp(); rampSpawnTimer = 0; } // Spawn pedestrians occasionally pedestrianSpawnTimer++; var pedestrianInterval = Math.max(700, 1000 + Math.floor(distanceTraveled / 250)); // Moderate intervals if (pedestrianSpawnTimer >= pedestrianInterval / gameSpeed) { spawnPedestrian(); pedestrianSpawnTimer = 0; } // Check nitro effect end if (nitroEffect && LK.ticks >= nitroEndTime) { nitroEffect = false; // Smooth transition back to normal speed tween(playerCar, { scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.easeOut }); // Reset speed multipliers gradually tween({ value: nitroSpeedMultiplier }, { value: 1 }, { duration: 800, easing: tween.easeOut, onUpdate: function onUpdate(obj) { nitroSpeedMultiplier = obj.value; } }); tween({ value: nitroAcceleration }, { value: 1 }, { duration: 800, easing: tween.easeOut, onUpdate: function onUpdate(obj) { nitroAcceleration = obj.value; } }); // Reset player car movement speed if (playerCar.originalMoveSpeed) { tween(playerCar, { moveSpeed: playerCar.originalMoveSpeed }, { duration: 500, easing: tween.easeOut }); } // Flash to indicate nitro ending LK.effects.flashScreen(0xFF4400, 300); } // Spawn road lines lineSpawnTimer++; if (lineSpawnTimer >= 25) { for (var lane = 0; lane < 4; lane++) { var line = game.addChild(new RoadLine()); line.x = 524 + lane * 400; line.y = -100; line.speed = 9.24 * gameSpeed * nitroSpeedMultiplier; roadLines.push(line); } lineSpawnTimer = 0; } // Update and check power-ups for (var j = powerUps.length - 1; j >= 0; j--) { var powerUp = powerUps[j]; // Remove off-screen power-ups if (powerUp.y > 2800) { powerUp.destroy(); powerUps.splice(j, 1); continue; } // Check collection if (powerUp.intersects(playerCar)) { // Update combo system comboCount++; lastComboTime = LK.ticks; comboMultiplier = Math.min(1 + comboCount * 0.2, 3); // Max 3x multiplier var baseScore = 50; var finalScore = Math.floor(baseScore * comboMultiplier); LK.setScore(LK.getScore() + finalScore); // Update combo display if (comboCount > 1) { comboTxt.setText('COMBO x' + comboCount + ' (' + comboMultiplier.toFixed(1) + 'x)'); tween(comboTxt, { scaleX: 1.3, scaleY: 1.3 }, { duration: 200, onFinish: function onFinish() { tween(comboTxt, { scaleX: 1, scaleY: 1 }, { duration: 200 }); } }); } LK.getSound('collect').play(); LK.effects.flashObject(powerUp, 0xffffff, 200); addCameraShake(3, 10); // Add smooth scale-out effect before destroying tween(powerUp, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 200, onFinish: function onFinish() { powerUp.destroy(); } }); powerUps.splice(j, 1); } } // Update and check nitros for (var n = nitros.length - 1; n >= 0; n--) { var nitro = nitros[n]; // Remove off-screen nitros if (nitro.y > 2800) { nitro.destroy(); nitros.splice(n, 1); continue; } // Check collection if (nitro.intersects(playerCar)) { // Statistics update removed comboCount++; lastComboTime = LK.ticks; comboMultiplier = Math.min(1 + comboCount * 0.2, 3); var baseScore = 100; var finalScore = Math.floor(baseScore * comboMultiplier); LK.setScore(LK.getScore() + finalScore); // Update combo display if (comboCount > 1 && comboTxt) { comboTxt.setText('COMBO x' + comboCount + ' (' + comboMultiplier.toFixed(1) + 'x)'); tween(comboTxt, { scaleX: 1.3, scaleY: 1.3 }, { duration: 200, onFinish: function onFinish() { tween(comboTxt, { scaleX: 1, scaleY: 1 }, { duration: 200 }); } }); } LK.getSound('collect').play(); addCameraShake(8, 20); // Activate nitro effect with massive speed boost nitroEffect = true; nitroEndTime = LK.ticks + 450; // 7.5 seconds at 60fps // Dramatic speed boost - 3x multiplier nitroSpeedMultiplier = 3.0; nitroAcceleration = 2.5; // Enhanced visual effects for nitro activation if (playerCar) { tween(playerCar, { scaleX: 1.5, scaleY: 1.5 }, { duration: 200, easing: tween.easeOut }); // Add pulsing effect during nitro tween(playerCar, { tint: 0x00FFFF }, { duration: 100, onFinish: function onFinish() { tween(playerCar, { tint: 0xFFFFFF }, { duration: 100 }); } }); // Enhanced player car movement speed during nitro if (playerCar.moveSpeed !== undefined) { playerCar.originalMoveSpeed = playerCar.moveSpeed; tween(playerCar, { moveSpeed: playerCar.moveSpeed * 2.5 }, { duration: 200, easing: tween.easeOut }); } } // Screen flash for nitro activation LK.effects.flashScreen(0x00FFFF, 800); // Add smooth scale-out effect for nitro tween(nitro, { scaleX: 4, scaleY: 4, alpha: 0 }, { duration: 600, easing: tween.elasticOut, onFinish: function onFinish() { nitro.destroy(); } }); nitros.splice(n, 1); } } // Update and check cups for (var c = cups.length - 1; c >= 0; c--) { var cup = cups[c]; // Remove off-screen cups if (cup.y > 2800) { cup.destroy(); cups.splice(c, 1); continue; } // Check collection if (cup.intersects(playerCar)) { hasShield = true; // Statistics update removed comboCount++; lastComboTime = LK.ticks; comboMultiplier = Math.min(1 + comboCount * 0.2, 3); var baseScore = 150; var finalScore = Math.floor(baseScore * comboMultiplier); LK.setScore(LK.getScore() + finalScore); // Update combo display if (comboCount > 1) { comboTxt.setText('COMBO x' + comboCount + ' (' + comboMultiplier.toFixed(1) + 'x)'); tween(comboTxt, { scaleX: 1.3, scaleY: 1.3 }, { duration: 200, onFinish: function onFinish() { tween(comboTxt, { scaleX: 1, scaleY: 1 }, { duration: 200 }); } }); } LK.getSound('collect').play(); addCameraShake(5, 15); LK.effects.flashScreen(0xFFD700, 400); // Visual feedback for shield activation tween(playerCar, { tint: 0xFFD700 }, { duration: 200, onFinish: function onFinish() { tween(playerCar, { tint: 0xFFFFFF }, { duration: 200 }); } }); // Add smooth scale-out effect for cup tween(cup, { scaleX: 3, scaleY: 3, alpha: 0 }, { duration: 300, easing: tween.elasticOut, onFinish: function onFinish() { cup.destroy(); } }); cups.splice(c, 1); } } // Update and check bombers for (var b = bombers.length - 1; b >= 0; b--) { var bomber = bombers[b]; // Remove off-screen bombers if (bomber.y > 2800) { bomber.destroy(); bombers.splice(b, 1); continue; } // Check collision with player if (bomber.intersects(playerCar)) { // Always crush/kill the bomber person on collision LK.setScore(LK.getScore() + 300); LK.getSound('collect').play(); LK.effects.flashScreen(0x00ff00, 300); // Create explosion at bomber position var explosion = game.addChild(new Explosion()); explosion.x = bomber.x; explosion.y = bomber.y; // Destroy the bomber bomber.destroy(); bombers.splice(b, 1); continue; } } // Update and check bombs for (var bomb = bombs.length - 1; bomb >= 0; bomb--) { var bombObj = bombs[bomb]; // Remove off-screen bombs if (bombObj.y > 2800) { bombObj.destroy(); bombs.splice(bomb, 1); continue; } // Check collision with player if (bombObj.intersects(playerCar)) { if (hasShield) { // Player has shield from cup - destroy bomb instead hasShield = false; LK.setScore(LK.getScore() + 200); LK.getSound('collect').play(); LK.effects.flashScreen(0x00ff00, 300); // Create explosion at bomb position var explosion = game.addChild(new Explosion()); explosion.x = bombObj.x; explosion.y = bombObj.y; // Destroy the bomb bombObj.destroy(); bombs.splice(bomb, 1); continue; } else { // Normal collision - game over with bigger explosion var explosion = game.addChild(new Explosion()); explosion.x = playerCar.x; explosion.y = playerCar.y; // Crash statistics updates removed // Intense camera shake for crash addCameraShake(25, 60); // Create additional explosion for bomb impact var bombExplosion = game.addChild(new Explosion()); bombExplosion.x = bombObj.x; bombExplosion.y = bombObj.y; tween(playerCar, { scaleX: 0, scaleY: 0, rotation: Math.PI * 2, alpha: 0 }, { duration: 500, easing: tween.easeOut }); if (distanceTraveled > bestDistance) { bestDistance = Math.floor(distanceTraveled); bestScoreTxt.setText('Best: ' + bestDistance); saveBestScore(); } LK.effects.flashScreen(0xff0000, 1000); LK.playMusic('gameovermusic', { volume: 0.6, loop: false }); LK.showGameOver(); return; } } } // Update and check ramps for (var r = ramps.length - 1; r >= 0; r--) { var ramp = ramps[r]; // Remove off-screen ramps if (ramp.y > 2800) { ramp.destroy(); ramps.splice(r, 1); continue; } // Check if player hits ramp to initiate jump if (ramp.intersects(playerCar) && !playerJumping) { playerJumping = true; jumpStartTime = LK.ticks; // Statistics update removed var baseScore = 75; var finalScore = Math.floor(baseScore * comboMultiplier); LK.setScore(LK.getScore() + finalScore); // Bonus for using ramp LK.getSound('collect').play(); addCameraShake(4, 12); // Flash effect for ramp activation LK.effects.flashScreen(0x00AAFF, 300); // Scale out ramp effect tween(ramp, { scaleX: 2, scaleY: 2, alpha: 0 }, { duration: 400, onFinish: function onFinish() { ramp.destroy(); } }); ramps.splice(r, 1); continue; } } // Update and check pedestrians for (var p = pedestrians.length - 1; p >= 0; p--) { var pedestrian = pedestrians[p]; // Remove off-screen pedestrians if (pedestrian.y > 2800) { pedestrian.destroy(); pedestrians.splice(p, 1); continue; } // Check collision with player if (pedestrian.intersects(playerCar)) { if (hasShield) { // Player has shield - save pedestrian and get bonus hasShield = false; LK.setScore(LK.getScore() + 250); LK.getSound('collect').play(); LK.effects.flashScreen(0x00ff00, 300); // Create sparkle effect for saving pedestrian var explosion = game.addChild(new Explosion()); explosion.x = pedestrian.x; explosion.y = pedestrian.y; // Destroy the pedestrian (saved) pedestrian.destroy(); pedestrians.splice(p, 1); continue; } else { // Normal collision - game over var explosion = game.addChild(new Explosion()); explosion.x = playerCar.x; explosion.y = playerCar.y; // Crash statistics updates removed // Heavy camera shake for pedestrian collision addCameraShake(30, 80); tween(playerCar, { scaleX: 0, scaleY: 0, rotation: Math.PI * 2, alpha: 0 }, { duration: 500, easing: tween.easeOut }); if (distanceTraveled > bestDistance) { bestDistance = Math.floor(distanceTraveled); bestScoreTxt.setText('Best: ' + bestDistance); saveBestScore(); } LK.effects.flashScreen(0xff0000, 1000); LK.playMusic('gameovermusic', { volume: 0.6, loop: false }); LK.showGameOver(); return; } } } // Collision detection with enemies - skip if jumping high enough for (var i = enemyCars.length - 1; i >= 0; i--) { var enemy = enemyCars[i]; if (enemy.lastY === undefined) enemy.lastY = enemy.y; // Remove off-screen enemies if (enemy.lastY < 2800 && enemy.y >= 2800) { enemy.destroy(); enemyCars.splice(i, 1); continue; } // Check collision with player - but not if jumping high enough if (enemy.intersects(playerCar) && (!playerJumping || jumpHeight < 50)) { if (hasShield) { // Player has shield from cup - destroy enemy instead hasShield = false; LK.setScore(LK.getScore() + 200); LK.getSound('collect').play(); LK.effects.flashScreen(0x00ff00, 300); // Create explosion at enemy position var explosion = game.addChild(new Explosion()); explosion.x = enemy.x; explosion.y = enemy.y; // Destroy the enemy enemy.destroy(); enemyCars.splice(i, 1); continue; } else { // Normal collision - game over // Create explosion at collision point var explosion = game.addChild(new Explosion()); explosion.x = playerCar.x; explosion.y = playerCar.y; // Crash statistics updates removed // Strong camera shake for car collision addCameraShake(20, 50); // Make player car explode with tween effect tween(playerCar, { scaleX: 0, scaleY: 0, rotation: Math.PI * 2, alpha: 0 }, { duration: 500, easing: tween.easeOut }); // Update best score if needed if (distanceTraveled > bestDistance) { bestDistance = Math.floor(distanceTraveled); bestScoreTxt.setText('Best: ' + bestDistance); saveBestScore(); } LK.effects.flashScreen(0xff0000, 1000); LK.playMusic('gameovermusic', { volume: 0.6, loop: false }); LK.showGameOver(); return; } } else if (playerJumping && jumpHeight >= 50) { // Player jumped over enemy - bonus points! if (!enemy.jumpedOver) { LK.setScore(LK.getScore() + 150); LK.getSound('dodge').play(); enemy.jumpedOver = true; // Mark to prevent multiple bonuses } } // Check for near miss (score bonus) var distanceFromPlayer = Math.abs(enemy.x - playerCar.x); if (enemy.y > playerCar.y - 150 && enemy.y < playerCar.y + 150 && distanceFromPlayer < 200 && distanceFromPlayer > 150) { if (!enemy.nearMissScored) { LK.setScore(LK.getScore() + 10); LK.getSound('dodge').play(); enemy.nearMissScored = true; } } enemy.lastY = enemy.y; } // Update road lines for (var k = roadLines.length - 1; k >= 0; k--) { var line = roadLines[k]; // Remove off-screen lines if (line.y > 2800) { line.destroy(); roadLines.splice(k, 1); } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
// Make bomb look dangerous with dark red tint and smaller size
bombGraphics.tint = 0x660000;
bombGraphics.scaleX = 0.6;
bombGraphics.scaleY = 0.6;
self.speed = 13.86;
self.targetLane = 1;
self.rotationSpeed = 0.3;
self.pulseScale = 1;
self.pulseDirection = 1;
self.update = function () {
self.speed = 13.86 * gameSpeed;
self.y += self.speed;
// Move towards target lane (player's position when thrown)
var targetX = 324 + self.targetLane * 400;
var diff = targetX - self.x;
if (Math.abs(diff) > 10) {
self.x += diff * 0.1;
}
// Spinning and pulsing animation for danger effect
bombGraphics.rotation += self.rotationSpeed;
self.pulseScale += self.pulseDirection * 0.05;
if (self.pulseScale > 1.3) {
self.pulseDirection = -1;
} else if (self.pulseScale < 0.8) {
self.pulseDirection = 1;
}
bombGraphics.scaleX = 0.6 * self.pulseScale;
bombGraphics.scaleY = 0.6 * self.pulseScale;
};
return self;
});
var Bomber = Container.expand(function () {
var self = Container.call(this);
var bomberGraphics = self.attachAsset('bomberPerson', {
anchorX: 0.5,
anchorY: 0.5
});
// Make bomber distinct with darker brown color and human-like proportions
bomberGraphics.scaleX = 0.8;
bomberGraphics.scaleY = 0.9;
self.speed = 6.93;
self.lane = 0;
self.throwTimer = 0;
self.throwInterval = 120; // Throw bomb every 2 seconds
self.hasThrown = false;
self.update = function () {
var difficultyMultiplier = 1 + distanceTraveled / 10000;
self.speed = 6.93 * gameSpeed * difficultyMultiplier;
self.y += self.speed;
// Throw bomb when close to player
self.throwTimer++;
if (!self.hasThrown && self.throwTimer >= self.throwInterval && self.y > 500 && self.y < 1800) {
self.throwBomb();
self.hasThrown = true;
}
// Add slight bobbing motion
bomberGraphics.rotation = Math.sin(LK.ticks * 0.03) * 0.1;
};
self.throwBomb = function () {
var bomb = game.addChild(new Bomb());
bomb.x = self.x;
bomb.y = self.y + 50;
bomb.targetLane = playerCar.currentLane;
bomb.speed = 13.86 * gameSpeed;
bombs.push(bomb);
};
return self;
});
var Cup = Container.expand(function () {
var self = Container.call(this);
var cupGraphics = self.attachAsset('cup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 9.24;
self.rotationSpeed = 0.15;
self.pulseScale = 1;
self.pulseDirection = 1;
self.update = function () {
self.speed = 9.24 * gameSpeed;
self.y += self.speed;
cupGraphics.rotation += self.rotationSpeed;
// Enhanced pulsing effect with sparkle
self.pulseScale += self.pulseDirection * 0.04;
if (self.pulseScale > 1.6) {
self.pulseDirection = -1;
} else if (self.pulseScale < 0.8) {
self.pulseDirection = 1;
}
cupGraphics.scaleX = self.pulseScale;
cupGraphics.scaleY = self.pulseScale;
// Enhanced golden effect with sparkle animation
var sparkleIntensity = 0.8 + Math.sin(LK.ticks * 0.15) * 0.2;
cupGraphics.alpha = sparkleIntensity;
// Alternating between bright gold and white for sparkle effect
if (Math.sin(LK.ticks * 0.1) > 0.7) {
cupGraphics.tint = 0xFFFFFF; // Bright white sparkle
} else {
cupGraphics.tint = 0xFFD700; // Rich gold
}
};
return self;
});
var EnemyCar = Container.expand(function (carType) {
var self = Container.call(this);
var assetId = carType || 'enemyCar1';
var carGraphics = self.attachAsset(assetId, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 9.24;
self.lane = 0;
self.update = function () {
// Progressive speed increase with difficulty
var difficultyMultiplier = 1 + distanceTraveled / 8000; // Enemies get faster over time
self.speed = 9.24 * gameSpeed * difficultyMultiplier * (nitroSpeedMultiplier > 1 ? nitroSpeedMultiplier * 0.7 : 1);
self.y += self.speed;
// Add subtle bobbing motion for visual interest
carGraphics.rotation = Math.sin(LK.ticks * 0.05) * 0.02;
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
self.particles = [];
self.lifeTime = 0;
self.maxLifeTime = 60; // 1 second at 60fps
// Create enhanced explosion particles with more variety
for (var i = 0; i < 20; i++) {
var particle = self.addChild(LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.2 + Math.random() * 0.4,
scaleY: 0.2 + Math.random() * 0.4
}));
// More vibrant explosion colors
var colors = [0xFF1100, 0xFF4400, 0xFF6600, 0xFF8800, 0xFFAA00, 0xFFCC00, 0xFFFF00, 0xFFFFFF];
particle.tint = colors[Math.floor(Math.random() * colors.length)];
particle.vx = (Math.random() - 0.5) * 30;
particle.vy = (Math.random() - 0.5) * 30;
particle.gravity = 0.3 + Math.random() * 0.4;
particle.friction = 0.92 + Math.random() * 0.06;
particle.rotationSpeed = (Math.random() - 0.5) * 0.3;
self.particles.push(particle);
}
self.update = function () {
self.lifeTime++;
// Update particles with enhanced physics
for (var i = 0; i < self.particles.length; i++) {
var particle = self.particles[i];
particle.x += particle.vx;
particle.y += particle.vy;
particle.vy += particle.gravity;
particle.vx *= particle.friction;
particle.vy *= particle.friction;
// Add rotation to particles
particle.rotation += particle.rotationSpeed;
// Enhanced fade out with size reduction
var fadeProgress = self.lifeTime / self.maxLifeTime;
particle.alpha = 1 - fadeProgress;
particle.scaleX *= 0.98;
particle.scaleY *= 0.98;
// Color intensity decreases over time
if (fadeProgress > 0.5) {
var intensity = 1 - (fadeProgress - 0.5) * 2;
particle.tint = particle.tint & 0xFFFFFF * intensity;
}
}
// Destroy explosion when done
if (self.lifeTime >= self.maxLifeTime) {
self.destroy();
}
};
return self;
});
var Nitro = Container.expand(function () {
var self = Container.call(this);
var nitroGraphics = self.attachAsset('nitro', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 9.24;
self.rotationSpeed = 0.2;
self.pulseScale = 1;
self.pulseDirection = 1;
self.update = function () {
self.y += self.speed;
nitroGraphics.rotation += self.rotationSpeed;
// Enhanced pulsing effect with electric blue glow
self.pulseScale += self.pulseDirection * 0.03;
if (self.pulseScale > 1.5) {
self.pulseDirection = -1;
} else if (self.pulseScale < 0.7) {
self.pulseDirection = 1;
}
nitroGraphics.scaleX = self.pulseScale;
nitroGraphics.scaleY = self.pulseScale;
// Electric blue glow effect with lightning-like intensity changes
var electricIntensity = 0.6 + Math.sin(LK.ticks * 0.2) * 0.4;
nitroGraphics.alpha = electricIntensity;
// Bright electric blue with occasional white flashes
if (Math.random() < 0.1) {
nitroGraphics.tint = 0xFFFFFF; // White flash
} else {
nitroGraphics.tint = 0x00BFFF; // Electric blue
}
};
return self;
});
var Pedestrian = Container.expand(function () {
var self = Container.call(this);
var pedestrianGraphics = self.attachAsset('pedestrian', {
anchorX: 0.5,
anchorY: 0.5
});
// Make pedestrian look different from bomber with varied appearances
var appearances = [{
tint: 0xFF6B6B,
scaleX: 0.6,
scaleY: 0.9
},
// Red shirt, tall
{
tint: 0x4ECDC4,
scaleX: 0.8,
scaleY: 0.7
},
// Teal shirt, short
{
tint: 0xFFE66D,
scaleX: 0.7,
scaleY: 0.8
},
// Yellow shirt, medium
{
tint: 0xA8E6CF,
scaleX: 0.75,
scaleY: 0.85
},
// Green shirt, medium-tall
{
tint: 0xFF8B94,
scaleX: 0.65,
scaleY: 0.75
},
// Pink shirt, small
{
tint: 0xB4A7D6,
scaleX: 0.9,
scaleY: 0.6
} // Purple shirt, wide
];
var appearance = appearances[Math.floor(Math.random() * appearances.length)];
pedestrianGraphics.tint = appearance.tint;
pedestrianGraphics.scaleX = appearance.scaleX;
pedestrianGraphics.scaleY = appearance.scaleY;
self.speed = 6.93;
self.lane = 0;
self.jumpPhase = 'waiting'; // 'waiting', 'jumping', 'crossing'
self.jumpTimer = 0;
self.jumpInterval = 180; // 3 seconds to decide to jump
self.targetLane = Math.floor(Math.random() * 4); // Target lane to reach
self.crossingSpeed = 3;
self.update = function () {
var difficultyMultiplier = 1 + distanceTraveled / 10000;
self.speed = 6.93 * gameSpeed * difficultyMultiplier;
self.y += self.speed;
// Handle jumping behavior
self.jumpTimer++;
if (self.jumpPhase === 'waiting' && self.jumpTimer >= self.jumpInterval && self.y > 500 && self.y < 1800) {
// Start jumping onto road
self.jumpPhase = 'jumping';
self.jumpTimer = 0;
}
if (self.jumpPhase === 'jumping') {
// Move toward target lane
var targetX = 324 + self.targetLane * 400;
var diff = targetX - self.x;
if (Math.abs(diff) > 20) {
self.x += diff * 0.08;
} else {
self.jumpPhase = 'crossing';
}
}
if (self.jumpPhase === 'crossing') {
// Cross the road randomly
if (Math.random() < 0.02) {
self.targetLane = Math.floor(Math.random() * 4);
}
var targetX = 324 + self.targetLane * 400;
var diff = targetX - self.x;
self.x += diff * 0.05;
}
// Add walking animation
pedestrianGraphics.rotation = Math.sin(LK.ticks * 0.1) * 0.1;
};
return self;
});
var PlayerCar = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.35;
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
// Jump finished
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
// Calculate jump arc (parabolic motion)
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100;
carGraphics.y = -jumpHeight;
// Add rotation during jump
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.2;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PlayerCar2 = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar2', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.42; // Much faster lane switching speed
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100;
carGraphics.y = -jumpHeight;
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.25;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.35
}, {
duration: 180,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 280,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PlayerCar3 = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar3', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.38; // Faster lane switching speed
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100;
carGraphics.y = -jumpHeight;
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.15;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.25
}, {
duration: 220,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 320,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PlayerCar4 = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar4', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.35; // Standard lane switching speed like other cars
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100; // Standard jump height
carGraphics.y = -jumpHeight;
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.2;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PlayerCar5 = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar5', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.75; // Much faster lane switching speed
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100;
carGraphics.y = -jumpHeight;
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.3;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.4
}, {
duration: 160,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 250,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PlayerCar6 = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar6', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetLane = 1;
self.currentLane = 1;
self.laneWidth = 400;
self.moveSpeed = 0.35; // Standard lane switching speed like PlayerCar
self.update = function () {
var targetX = self.getLaneX(self.targetLane);
var diff = targetX - self.x;
var adjustedMoveSpeed = self.moveSpeed * (1 + (gameSpeed - 1) * 0.5);
if (Math.abs(diff) > 5) {
self.x += diff * adjustedMoveSpeed;
} else {
self.x = targetX;
self.currentLane = self.targetLane;
}
// Handle jumping animation
if (playerJumping) {
var jumpProgress = (LK.ticks - jumpStartTime) / jumpDuration;
if (jumpProgress >= 1) {
playerJumping = false;
jumpHeight = 0;
carGraphics.y = 0;
carGraphics.rotation = 0;
} else {
jumpHeight = Math.sin(jumpProgress * Math.PI) * 100; // Standard jump height
carGraphics.y = -jumpHeight;
carGraphics.rotation = Math.sin(jumpProgress * Math.PI) * 0.2;
}
}
};
self.getLaneX = function (lane) {
return 324 + lane * self.laneWidth;
};
self.switchLane = function (direction) {
var newLane = self.targetLane + direction;
if (newLane >= 0 && newLane <= 3) {
self.targetLane = newLane;
// Add drift mechanics with tween-based smooth turning animations
tween(carGraphics, {
rotation: direction * 0.3
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(carGraphics, {
rotation: 0
}, {
duration: 300,
easing: tween.easeInOut
});
}
});
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 9.24;
self.rotationSpeed = 0.1;
self.update = function () {
self.speed = 9.24 * gameSpeed * (nitroSpeedMultiplier > 1 ? nitroSpeedMultiplier * 0.8 : 1);
self.y += self.speed;
powerUpGraphics.rotation += self.rotationSpeed;
// Enhanced visual effects with glow pulsing
var glowIntensity = 0.7 + Math.sin(LK.ticks * 0.1) * 0.3;
powerUpGraphics.alpha = glowIntensity;
// Add rainbow tint cycling for more appealing visuals
var hue = LK.ticks * 0.05 % (Math.PI * 2);
var r = Math.floor(Math.sin(hue) * 127 + 128);
var g = Math.floor(Math.sin(hue + Math.PI * 2 / 3) * 127 + 128);
var b = Math.floor(Math.sin(hue + Math.PI * 4 / 3) * 127 + 128);
powerUpGraphics.tint = r << 16 | g << 8 | b;
};
return self;
});
var Ramp = Container.expand(function () {
var self = Container.call(this);
// Create ramp visual using multiple road line assets
var rampBase = self.attachAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 8,
scaleY: 2
});
rampBase.tint = 0x888888;
var rampTop = self.attachAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6,
scaleY: 1,
y: -20
});
rampTop.tint = 0xAAAAA;
self.speed = 9.24;
self.lane = 0;
self.update = function () {
self.speed = 9.24 * gameSpeed;
self.y += self.speed;
// Add slight glow effect
rampBase.alpha = 0.8 + Math.sin(LK.ticks * 0.1) * 0.2;
};
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 = 9.24;
self.update = function () {
self.speed = 9.24 * gameSpeed;
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2c3e50
});
/****
* Game Code
****/
// Game state management
var gameState = 'splash'; // 'splash', 'menu', 'playing', 'gameOver'
var menuElements = [];
var bestDistance = 0;
// Load best score from storage
function loadBestScore() {
var saved = storage.bestDistance;
if (saved !== undefined) {
bestDistance = saved;
}
}
// Save best score to storage
function saveBestScore() {
storage.bestDistance = bestDistance;
}
// Start menu creation
function createStartMenu() {
// Simple road background - just a few lines for context
for (var i = 0; i < 8; i++) {
for (var lane = 0; lane < 4; lane++) {
var menuLine = LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
x: 624 + lane * 400,
y: i * 250 + 300
});
menuLine.alpha = 0.2;
game.addChild(menuLine);
menuElements.push(menuLine);
}
}
// Clean title - big and centered
var titleText = new Text2('HIGHWAY RUSH', {
size: 160,
fill: '#FFD700',
stroke: '#000000',
strokeThickness: 6
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 600;
game.addChild(titleText);
menuElements.push(titleText);
// Best score display - simple and clear
var bestScoreText = new Text2('Best: ' + bestDistance + 'm', {
size: 70,
fill: '#FFFFFF',
stroke: '#000000',
strokeThickness: 4
});
bestScoreText.anchor.set(0.5, 0.5);
bestScoreText.x = 1024;
bestScoreText.y = 750;
game.addChild(bestScoreText);
menuElements.push(bestScoreText);
// Car selection section - clean and organized
var carSelectionText = new Text2('Choose Car:', {
size: 60,
fill: '#FFFFFF',
stroke: '#000000',
strokeThickness: 3
});
carSelectionText.anchor.set(0.5, 0.5);
carSelectionText.x = 1024;
carSelectionText.y = 950;
game.addChild(carSelectionText);
menuElements.push(carSelectionText);
// Car selection buttons - properly centered for mobile
var car1Button = LK.getAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5,
x: 341,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car1Button);
menuElements.push(car1Button);
var car2Button = LK.getAsset('playerCar2', {
anchorX: 0.5,
anchorY: 0.5,
x: 574,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car2Button);
menuElements.push(car2Button);
var car3Button = LK.getAsset('playerCar3', {
anchorX: 0.5,
anchorY: 0.5,
x: 807,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car3Button);
menuElements.push(car3Button);
// Add playerCar4 button
var car4Button = LK.getAsset('playerCar4', {
anchorX: 0.5,
anchorY: 0.5,
x: 1040,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car4Button);
menuElements.push(car4Button);
// Add playerCar5 button
var car5Button = LK.getAsset('playerCar5', {
anchorX: 0.5,
anchorY: 0.5,
x: 1273,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car5Button);
menuElements.push(car5Button);
// Add playerCar6 button
var car6Button = LK.getAsset('playerCar6', {
anchorX: 0.5,
anchorY: 0.5,
x: 1506,
y: 1150,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(car6Button);
menuElements.push(car6Button);
// Selection indicator
selectionIndicator = LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 6,
scaleY: 0.6,
x: selectedCarType === 0 ? 341 : selectedCarType === 1 ? 574 : selectedCarType === 2 ? 807 : selectedCarType === 3 ? 1040 : selectedCarType === 4 ? 1273 : 1506,
y: 1280
});
selectionIndicator.tint = 0xFFD700;
game.addChild(selectionIndicator);
menuElements.push(selectionIndicator);
// Instructions - simple and clear
var instructionsText = new Text2('Swipe to change lanes • Avoid traffic • Collect power-ups', {
size: 50,
fill: '#CCCCCC',
stroke: '#000000',
strokeThickness: 2
});
instructionsText.anchor.set(0.5, 0.5);
instructionsText.x = 1024;
instructionsText.y = 1450;
game.addChild(instructionsText);
menuElements.push(instructionsText);
// Simple START BUTTON at bottom
var startButton = LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 25,
scaleY: 4,
x: 1024,
y: 2200
});
startButton.tint = 0x00BB00;
game.addChild(startButton);
menuElements.push(startButton);
// START text
var startButtonText = new Text2('START GAME', {
size: 120,
fill: '#FFFFFF',
stroke: '#000000',
strokeThickness: 6
});
startButtonText.anchor.set(0.5, 0.5);
startButtonText.x = 1024;
startButtonText.y = 2200;
game.addChild(startButtonText);
menuElements.push(startButtonText);
// Stats Chart button removed
// Store button references for animations
var buttonElements = {
button: startButton,
text: startButtonText
};
// Initialize selection visual state
updateCarSelection();
// Start menu music
LK.playMusic('menumusic', {
volume: 0.7
});
// Stylish fluid animations with enhanced effects
// Title pulsing with glow effect
tween(titleText, {
scaleX: 1.15,
scaleY: 1.15
}, {
duration: 1800,
yoyo: true,
repeat: 50,
easing: tween.easeInOut
});
// Add floating animation to title
tween(titleText, {
y: 580
}, {
duration: 3000,
yoyo: true,
repeat: 30,
easing: tween.easeInOut
});
// Remove swinging animation - title stays in center position
// Car selection buttons - keep cars stationary (no movement animations)
// Cars will remain in their fixed positions without floating or rotation effects
// Enhanced button animations with elastic effect
tween(buttonElements.button, {
scaleX: 22,
scaleY: 3.5
}, {
duration: 2000,
yoyo: true,
repeat: 50,
easing: tween.elasticInOut
});
tween(buttonElements.text, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 2000,
yoyo: true,
repeat: 50,
easing: tween.bounceInOut
});
// Add color transition to start button
tween(buttonElements.button, {
tint: 0x00FF00
}, {
duration: 1000,
yoyo: true,
repeat: 100,
easing: tween.easeInOut
});
// Stats button animations removed
}
function removeStartMenu() {
// Stop all ongoing tweens to prevent memory leaks and performance issues
for (var i = 0; i < menuElements.length; i++) {
tween.stop(menuElements[i]); // Stop all tweens on this element
menuElements[i].destroy();
}
menuElements = [];
}
function startGame() {
gameState = 'playing';
// Stop all menu tweens before removing menu
if (menuElements.length > 0) {
for (var i = 0; i < menuElements.length; i++) {
tween.stop(menuElements[i]);
}
}
removeStartMenu();
loadBestScore();
initializeGameplay();
// Reset tap counter after starting game
car1TapCount = 0;
car2TapCount = 0;
car3TapCount = 0;
car6TapCount = 0;
// Initialize combo system for new game
comboCount = 0;
comboMultiplier = 1;
lastComboTime = 0;
// Statistics updates removed
}
// Camera shake system
var cameraShake = {
intensity: 0,
duration: 0,
originalX: 0,
originalY: 0
};
function addCameraShake(intensity, duration) {
if (cameraShake.intensity < intensity) {
cameraShake.intensity = intensity;
cameraShake.duration = duration;
cameraShake.originalX = game.x;
cameraShake.originalY = game.y;
}
}
function updateCameraShake() {
if (cameraShake.duration > 0) {
var shakeX = (Math.random() - 0.5) * cameraShake.intensity;
var shakeY = (Math.random() - 0.5) * cameraShake.intensity;
game.x = cameraShake.originalX + shakeX;
game.y = cameraShake.originalY + shakeY;
cameraShake.duration--;
cameraShake.intensity *= 0.95; // Fade out shake
if (cameraShake.duration <= 0) {
game.x = cameraShake.originalX;
game.y = cameraShake.originalY;
cameraShake.intensity = 0;
}
}
}
function initializeGameplay() {
// Initialize all game variables
gameSpeed = 1;
baseGameSpeed = 1;
gasPressed = false;
gasAcceleration = 1;
// Reset combo system variables
comboCount = 0;
comboMultiplier = 1;
lastComboTime = 0;
spawnTimer = 0;
spawnRate = 120;
lineSpawnTimer = 0;
powerUpSpawnTimer = 0;
nitroSpawnTimer = 0;
cupSpawnTimer = 0;
bomberSpawnTimer = 0;
rampSpawnTimer = 0;
pedestrianSpawnTimer = 0;
playerJumping = false;
jumpStartTime = 0;
jumpHeight = 0;
// Check if car1 was tapped 10 times for secret unlock
if (selectedCarType === 0 && car1TapCount >= 10) {
distanceTraveled = 2000;
gameSpeed = 1 + distanceTraveled / 7000 + Math.pow(distanceTraveled / 15000, 1.5);
gameSpeed = Math.min(gameSpeed, 4);
// Flash screen to indicate secret unlock
LK.effects.flashScreen(0x00ff00, 500);
} else if (selectedCarType === 1 && car2TapCount >= 10) {
// Trophy road mode - start with lots of trophies
distanceTraveled = 0;
// Flash screen golden to indicate trophy road
LK.effects.flashScreen(0xFFD700, 1000);
// Set flag for trophy road mode
trophyRoadMode = true;
} else if (selectedCarType === 5 && car6TapCount >= 31) {
// PlayerCar6 ultra speed mode - 11x faster than normal
distanceTraveled = 0;
gameSpeed = 11; // 11 times faster than normal
// Flash screen with bright cyan to indicate ultra speed
LK.effects.flashScreen(0x00FFFF, 1500);
// Add pulsing effect to player car for ultra speed mode
tween(playerCar, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 500,
yoyo: true,
repeat: 3,
easing: tween.easeInOut
});
} else {
distanceTraveled = 0;
}
nitroEffect = false;
nitroEndTime = 0;
hasShield = false;
trophyRoadMode = false;
rapModeActive = false;
rapModeTimer = 0;
playerCar4Unlocked = true;
fastMusicPlaying = false;
// Reset score
LK.setScore(0);
// Add enhanced road background
var roadBackground = game.addChild(LK.getAsset('roadCenter', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
}));
roadBackground.alpha = 0.8;
// Add road side markers
var leftSide = game.addChild(LK.getAsset('roadSide', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: 1366
}));
var rightSide = game.addChild(LK.getAsset('roadSide', {
anchorX: 0.5,
anchorY: 0.5,
x: 1848,
y: 1366
}));
// Update UI texts with English
scoreTxt.setText('Distance: ' + Math.floor(distanceTraveled));
bestScoreTxt.setText('Best: ' + bestDistance);
speedTxt.setText('Speed: ' + gameSpeed.toFixed(1) + 'x');
// Add combo display
comboTxt = new Text2('', {
size: 70,
fill: '#FF6B00',
stroke: '#000000',
strokeThickness: 3
});
comboTxt.anchor.set(0.5, 0);
comboTxt.y = 160;
LK.gui.top.addChild(comboTxt);
// Reinitialize player car to ensure it's properly set up
initializePlayerCar();
// Gas pedal completely removed from play - no longer visible or interactive
gasButton = null; // Remove gas button reference
// Stop menu music and start gameplay music
LK.stopMusic();
LK.playMusic('bgmusic', {
volume: 0.7
});
}
// Initialize best score system
loadBestScore();
// Define combo system variables
var comboTimeWindow = 180; // 3 seconds at 60fps for combo window
var comboCount = 0;
var comboMultiplier = 1;
var lastComboTime = 0;
var comboTxt;
// Player statistics system removed
// Chart display system removed
// Achievement system
var achievements = {
speedDemon: storage.achievementSpeedDemon || false,
// Reach 3x speed
jumpMaster: storage.achievementJumpMaster || false,
// Jump 50 times
collector: storage.achievementCollector || false,
// Collect 100 power-ups
survivor: storage.achievementSurvivor || false,
// Travel 10000m in one game
nitroAddict: storage.achievementNitroAddict || false // Collect 25 nitros
};
function saveAchievements() {
storage.achievementSpeedDemon = achievements.speedDemon;
storage.achievementJumpMaster = achievements.jumpMaster;
storage.achievementCollector = achievements.collector;
storage.achievementSurvivor = achievements.survivor;
storage.achievementNitroAddict = achievements.nitroAddict;
}
function checkAchievements() {
// Speed Demon achievement
if (!achievements.speedDemon && gameSpeed >= 3.0) {
achievements.speedDemon = true;
showAchievement("SPEED DEMON!", "Reached 3x speed!");
saveAchievements();
}
// Jump Master achievement - removed since playerStats no longer exists
// Collector achievement - removed since playerStats no longer exists
// Survivor achievement
if (!achievements.survivor && distanceTraveled >= 10000) {
achievements.survivor = true;
showAchievement("SURVIVOR!", "Traveled 10,000m!");
saveAchievements();
}
// Nitro Addict achievement - removed since playerStats no longer exists
}
function showAchievement(title, description) {
var achievementBg = LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 25,
scaleY: 4,
x: 1024,
y: 400
});
achievementBg.tint = 0xFFD700;
achievementBg.alpha = 0;
game.addChild(achievementBg);
var achievementTitle = new Text2(title, {
size: 80,
fill: '#000000',
stroke: '#FFFFFF',
strokeThickness: 3
});
achievementTitle.anchor.set(0.5, 0.5);
achievementTitle.x = 1024;
achievementTitle.y = 370;
achievementTitle.alpha = 0;
game.addChild(achievementTitle);
var achievementDesc = new Text2(description, {
size: 50,
fill: '#000000',
stroke: '#FFFFFF',
strokeThickness: 2
});
achievementDesc.anchor.set(0.5, 0.5);
achievementDesc.x = 1024;
achievementDesc.y = 430;
achievementDesc.alpha = 0;
game.addChild(achievementDesc);
// Animate achievement popup
tween(achievementBg, {
alpha: 0.9
}, {
duration: 500,
easing: tween.easeOut
});
tween(achievementTitle, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
tween(achievementDesc, {
alpha: 1
}, {
duration: 500,
easing: tween.easeOut
});
// Auto-hide after 3 seconds
LK.setTimeout(function () {
tween(achievementBg, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
achievementBg.destroy();
}
});
tween(achievementTitle, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
achievementTitle.destroy();
}
});
tween(achievementDesc, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
achievementDesc.destroy();
}
});
}, 3000);
LK.effects.flashScreen(0xFFD700, 800);
}
// Show KEMALDEV splash screen first
function showKemaldevSplash() {
// Set game state to splash to prevent other interactions
gameState = 'splash';
// Create black background covering full screen
var splashBg = LK.getAsset('roadCenter', {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366,
scaleX: 2,
scaleY: 2,
tint: 0x000000
});
game.addChild(splashBg);
// Create KEMALDEV text
var kemaldevText = new Text2('KEMALDEV', {
size: 200,
fill: '#FFFFFF',
stroke: '#FFD700',
strokeThickness: 8
});
kemaldevText.anchor.set(0.5, 0.5);
kemaldevText.x = 1024;
kemaldevText.y = 1366;
kemaldevText.alpha = 0;
game.addChild(kemaldevText);
// Fade in animation
tween(kemaldevText, {
alpha: 1
}, {
duration: 800,
easing: tween.easeOut
});
// Add pulsing effect
tween(kemaldevText, {
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 1000,
yoyo: true,
repeat: 2,
easing: tween.easeInOut
});
// Hide after 3 seconds and show main menu
LK.setTimeout(function () {
tween(kemaldevText, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
kemaldevText.destroy();
splashBg.destroy();
gameState = 'menu';
createStartMenu();
}
});
}, 3000);
}
// Show KEMALDEV splash screen first, then create start menu
showKemaldevSplash();
// Car selection variable
var selectedCarType = 0; // 0 for PlayerCar, 1 for PlayerCar2, 2 for PlayerCar3
var playerCar;
var selectionIndicator;
var car1TapCount = 0; // Track taps on playercar1 for secret unlock
var car2TapCount = 0; // Track taps on playercar2 for trophy road
var car3TapCount = 0; // Track taps on playercar3 for secret message
var car6TapCount = 0; // Track taps on playercar6 for speed boost
// Update car selection visual state
function updateCarSelection() {
if (selectionIndicator) {
var targetX = selectedCarType === 0 ? 341 : selectedCarType === 1 ? 574 : selectedCarType === 2 ? 807 : selectedCarType === 3 ? 1040 : selectedCarType === 4 ? 1273 : 1506;
// Smooth fluid transition for selection indicator
tween(selectionIndicator, {
x: targetX
}, {
duration: 400,
easing: tween.elasticOut
});
// Add selection pulse effect
tween(selectionIndicator, {
scaleY: 1.2,
tint: 0xFFD700
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(selectionIndicator, {
scaleY: 0.6,
tint: 0xFFFFFF
}, {
duration: 300,
easing: tween.bounceOut
});
}
});
}
// Check if car 3 is unlocked
var car3Unlocked = bestDistance >= 2000;
// Update car button tints if they exist
if (menuElements.length > 0) {
for (var i = 0; i < menuElements.length; i++) {
var element = menuElements[i];
if (element.x === 624 && element.y === 1650) {
element.tint = selectedCarType === 0 ? 0xFFD700 : 0xFFFFFF;
} else if (element.x === 1024 && element.y === 1650) {
element.tint = selectedCarType === 1 ? 0xFFD700 : 0xFFFFFF;
} else if (element.x === 1424 && element.y === 1650) {
if (car3Unlocked) {
element.tint = selectedCarType === 2 ? 0xFFD700 : 0xFFFFFF;
} else {
element.tint = 0x666666; // Gray out locked car
element.alpha = 0.5;
}
}
}
}
}
// Initialize player car based on selection
function initializePlayerCar() {
if (playerCar) {
playerCar.destroy();
}
if (selectedCarType === 0) {
playerCar = game.addChild(new PlayerCar());
} else if (selectedCarType === 1) {
playerCar = game.addChild(new PlayerCar2());
} else if (selectedCarType === 2) {
playerCar = game.addChild(new PlayerCar3());
} else if (selectedCarType === 3) {
playerCar = game.addChild(new PlayerCar4());
} else if (selectedCarType === 4) {
playerCar = game.addChild(new PlayerCar5());
} else if (selectedCarType === 5) {
playerCar = game.addChild(new PlayerCar6());
}
playerCar.x = 324 + 400; // Lane 1
playerCar.y = 2200;
}
// Initialize the first car
initializePlayerCar();
var enemyCars = [];
var powerUps = [];
var roadLines = [];
var nitros = [];
var cups = [];
var bombers = [];
var bombs = [];
var ramps = [];
var pedestrians = [];
var playerJumping = false;
var jumpStartTime = 0;
var jumpDuration = 60; // 1 second at 60fps
var jumpHeight = 0;
var gameSpeed = 1;
var spawnTimer = 0;
var spawnRate = 120;
var lineSpawnTimer = 0;
var powerUpSpawnTimer = 0;
var nitroSpawnTimer = 0;
var cupSpawnTimer = 0;
var bomberSpawnTimer = 0;
var rampSpawnTimer = 0;
var pedestrianSpawnTimer = 0;
var distanceTraveled = 0;
var nitroEffect = false;
var nitroEndTime = 0;
var nitroSpeedMultiplier = 1;
var nitroAcceleration = 1;
var hasShield = false;
var gasPressed = false;
var baseGameSpeed = 1;
var gasAcceleration = 1;
var maxGasMultiplier = 2.5;
var gasDecelerationRate = 0.98;
var gasAccelerationRate = 1.05;
var trophyRoadMode = false;
var rapModeActive = false;
var rapModeTimer = 0;
var rapModeCheckInterval = 600; // Check every 10 seconds (600 ticks at 60fps)
var playerCar4Unlocked = true;
// Create initial road lines
for (var i = 0; i < 20; i++) {
for (var lane = 0; lane < 4; lane++) {
var line = game.addChild(new RoadLine());
line.x = 524 + lane * 400; // Between lanes
line.y = i * 150 - 200;
roadLines.push(line);
}
}
// UI Elements
var scoreTxt = new Text2('Distance: 0', {
size: 80,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var bestScoreTxt = new Text2('Best: ' + bestDistance, {
size: 60,
fill: 0xFFD700,
stroke: 0x000000,
strokeThickness: 3
});
bestScoreTxt.anchor.set(0.5, 0);
bestScoreTxt.y = 90;
LK.gui.top.addChild(bestScoreTxt);
var speedTxt = new Text2('Speed: 1x', {
size: 60,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 3
});
speedTxt.anchor.set(1, 1);
speedTxt.x = -20;
speedTxt.y = -20;
LK.gui.bottomRight.addChild(speedTxt);
// Touch controls
var touchStartX = 0;
var touchStartY = 0;
var touchStartTime = 0;
// Gas button element
var gasButton;
game.down = function (x, y, obj) {
if (gameState === 'splash') {
// Skip splash screen on tap
tween.stop();
LK.clearTimeout();
gameState = 'menu';
// Clean up splash elements
for (var i = game.children.length - 1; i >= 0; i--) {
var child = game.children[i];
if (child) {
child.destroy();
}
}
createStartMenu();
return;
}
if (gameState === 'menu') {
// Check car selection buttons
if (y >= 1050 && y <= 1250) {
if (x >= 241 && x <= 441) {
// Car 1 selected
selectedCarType = 0;
car1TapCount++; // Increment tap counter
updateCarSelection();
initializePlayerCar();
return;
} else if (x >= 474 && x <= 674) {
// Car 2 selected
selectedCarType = 1;
car2TapCount++; // Increment tap counter for car2
updateCarSelection();
initializePlayerCar();
return;
} else if (x >= 707 && x <= 907) {
// Car 3 selected - check if unlocked
if (bestDistance >= 2000) {
selectedCarType = 2;
car3TapCount++; // Increment tap counter for car3
// Check if tapped 10 times for secret message
if (car3TapCount >= 10) {
// Display "Thank you Yavuz Abi" in score area
scoreTxt.setText('Thank you Yavuz Abi');
// Flash screen to indicate special message
LK.effects.flashScreen(0xFFD700, 1000);
}
updateCarSelection();
initializePlayerCar();
} else {
// Car 3 is locked, flash red to indicate requirement
LK.effects.flashScreen(0xff0000, 300);
}
return;
} else if (x >= 940 && x <= 1140) {
// Car 4 selected - check if unlocked
if (playerCar4Unlocked) {
selectedCarType = 3;
updateCarSelection();
initializePlayerCar();
} else {
// Car 4 is locked, flash purple to indicate requirement
LK.effects.flashScreen(0x9932CC, 300);
}
return;
} else if (x >= 1173 && x <= 1373) {
// Car 5 selected
selectedCarType = 4;
updateCarSelection();
initializePlayerCar();
return;
} else if (x >= 1406 && x <= 1606) {
// Car 6 selected
selectedCarType = 5;
car6TapCount++; // Increment tap counter for car6
updateCarSelection();
initializePlayerCar();
return;
}
}
// Stats button interaction removed
// Check for start button tap at bottom - expanded touch area for better UX
if (y >= 2050 && y <= 2350 && x >= 300 && x <= 1748) {
startGame();
return;
}
}
if (gameState === 'playing') {
// Gas button interaction removed - no longer functional
}
touchStartX = x;
touchStartY = y;
touchStartTime = LK.ticks;
};
game.up = function (x, y, obj) {
if (gameState !== 'playing') return;
var touchEndX = x;
var swipeDistance = touchEndX - touchStartX;
var touchDuration = LK.ticks - touchStartTime;
// Gas button release interaction removed - no longer functional
// Detect swipe or tap for lane changing
if (Math.abs(swipeDistance) > 100 && touchDuration < 30) {
// Swipe detected
if (swipeDistance > 0) {
playerCar.switchLane(1); // Swipe right
} else {
playerCar.switchLane(-1); // Swipe left
}
} else if (touchDuration < 15) {
// Gas button area check removed - full screen available for lane changes
if (x > 1024) {
playerCar.switchLane(1); // Right side tap
} else {
playerCar.switchLane(-1); // Left side tap
}
}
};
function spawnEnemyCar() {
var lane = Math.floor(Math.random() * 4);
var enemy;
var carTypes = ['enemyCar1', 'enemyCar2', 'enemyCar3'];
var carType = carTypes[Math.floor(Math.random() * carTypes.length)];
enemy = game.addChild(new EnemyCar(carType));
enemy.x = 324 + lane * 400;
enemy.y = -100;
enemy.lane = lane;
enemy.speed = 9.24 * gameSpeed;
enemyCars.push(enemy);
}
function spawnPowerUp() {
// Reduce spawn chance as difficulty increases
var spawnChance = Math.max(0.1, 0.3 - distanceTraveled / 25000); // Decreases from 30% to 10%
if (Math.random() < spawnChance) {
var lane = Math.floor(Math.random() * 4);
var powerUp = game.addChild(new PowerUp());
powerUp.x = 324 + lane * 400;
powerUp.y = -100;
powerUp.speed = 9.24 * gameSpeed;
powerUps.push(powerUp);
}
}
function spawnNitro() {
// Significantly reduce spawn chance as difficulty increases
var spawnChance = Math.max(0.05, 0.2 - distanceTraveled / 20000); // Decreases from 20% to 5%
if (Math.random() < spawnChance) {
var lane = Math.floor(Math.random() * 4);
var nitro = game.addChild(new Nitro());
nitro.x = 324 + lane * 400;
nitro.y = -100;
nitro.speed = 9.24 * gameSpeed;
nitros.push(nitro);
}
}
function spawnCup() {
// Check if trophy road mode is active
if (trophyRoadMode) {
// In trophy road mode, spawn many cups (trophies)
var spawnChance = 0.8; // Very high spawn chance for trophies
if (Math.random() < spawnChance) {
// Spawn multiple cups across different lanes
for (var trophyLane = 0; trophyLane < 4; trophyLane++) {
if (Math.random() < 0.7) {
// 70% chance per lane
var cup = game.addChild(new Cup());
cup.x = 324 + trophyLane * 400;
cup.y = -100 - trophyLane * 150; // Stagger them vertically
cup.speed = 9.24 * gameSpeed;
cups.push(cup);
}
}
}
} else {
// Normal spawn chance for cups
var spawnChance = Math.max(0.03, 0.15 - distanceTraveled / 30000); // Decreases from 15% to 3%
if (Math.random() < spawnChance) {
var lane = Math.floor(Math.random() * 4);
var cup = game.addChild(new Cup());
cup.x = 324 + lane * 400;
cup.y = -100;
cup.speed = 9.24 * gameSpeed;
cups.push(cup);
}
}
}
function spawnRamp() {
// Spawn ramps occasionally to help player jump over obstacles
var spawnChance = Math.max(0.05, 0.15 - distanceTraveled / 20000); // Decreases from 15% to 5%
if (Math.random() < spawnChance) {
var lane = Math.floor(Math.random() * 4);
var ramp = game.addChild(new Ramp());
ramp.x = 324 + lane * 400;
ramp.y = -100;
ramp.lane = lane;
ramp.speed = 9.24 * gameSpeed;
ramps.push(ramp);
}
}
function spawnPedestrian() {
// Increased spawn chance for pedestrians by 80% more (from 25.92% to 46.66%)
var spawnChance = Math.max(0.1555, 0.4666 - distanceTraveled / 30000); // Decreases from 46.66% to 15.55%
if (Math.random() < spawnChance) {
// Spawn from sides of the road
var startSide = Math.random() < 0.5 ? 0 : 1; // 0 = left, 1 = right
var pedestrian = game.addChild(new Pedestrian());
pedestrian.x = startSide === 0 ? 124 : 1924; // Start from road sides
pedestrian.y = -100;
pedestrian.lane = startSide === 0 ? 0 : 3; // Start lane
pedestrian.speed = 6.93 * gameSpeed;
pedestrians.push(pedestrian);
}
}
function spawnBomber() {
// Moderate spawn chance for bombers
var spawnChance = Math.max(0.08, 0.25 - distanceTraveled / 25000); // Decreases from 25% to 8%
if (Math.random() < spawnChance) {
var lane = Math.floor(Math.random() * 4);
var bomber = game.addChild(new Bomber());
bomber.x = 324 + lane * 400;
bomber.y = -100;
bomber.lane = lane;
bomber.speed = 6.93 * gameSpeed;
bombers.push(bomber);
}
}
game.update = function () {
// Only update game logic when playing
if (gameState !== 'playing') return;
// Update camera shake
updateCameraShake();
// Update combo system
if (LK.ticks - lastComboTime > comboTimeWindow && comboCount > 0) {
comboCount = 0;
comboMultiplier = 1;
if (comboTxt) {
tween(comboTxt, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
comboTxt.setText('');
comboTxt.alpha = 1;
}
});
}
}
// Player statistics updates removed
// Check achievements
checkAchievements();
// PlayerCar4 is now available from the start - no unlock required
// Check for rap mode activation
rapModeTimer++;
if (rapModeTimer >= rapModeCheckInterval) {
// 80% chance to activate rap mode every 10 seconds - rap appears frequently now!
if (Math.random() < 0.8 && !rapModeActive) {
rapModeActive = true;
// Flash screen with hip-hop colors (purple/gold)
LK.effects.flashScreen(0x9932CC, 800);
// Change UI text to rap style
scoreTxt.setText('Yo Distance: ' + Math.floor(distanceTraveled) + ' meters!');
speedTxt.setText('Speed Flow: ' + gameSpeed.toFixed(1) + 'x');
// Rap mode lasts for 5 seconds
LK.setTimeout(function () {
rapModeActive = false;
// Reset UI text to normal
scoreTxt.setText('Distance: ' + Math.floor(distanceTraveled));
speedTxt.setText('Speed: ' + gameSpeed.toFixed(1) + 'x');
LK.effects.flashScreen(0x00FFFF, 400);
}, 5000);
}
rapModeTimer = 0;
}
// Update gas acceleration system with accelerator pedal physics
if (gasPressed) {
// Accelerate when stepping on the gas pedal
gasAcceleration = Math.min(gasAcceleration * gasAccelerationRate, maxGasMultiplier);
// Enhanced visual feedback for stepping on accelerator
if (LK.ticks % 15 === 0) {
LK.effects.flashObject(playerCar, 0xFFFF00, 150);
}
// Add speed lines effect when accelerating hard
if (gasAcceleration > 1.8 && LK.ticks % 8 === 0) {
LK.effects.flashScreen(0x004488, 30);
}
// Pedal vibration effect
if (gasButton && gasAcceleration > 2.0) {
gasButton.x = 1024 + (Math.random() - 0.5) * 4;
gasButton.y = 2500 + (Math.random() - 0.5) * 4;
}
} else {
// Decelerate when lifting foot off gas pedal
gasAcceleration = Math.max(gasAcceleration * gasDecelerationRate, 1);
// Reset pedal position when not pressed
if (gasButton) {
gasButton.x = 1024;
gasButton.y = 2500;
}
}
// Update base game speed with progression - increased by 11%
baseGameSpeed = 1 + distanceTraveled / 7000 + Math.pow(distanceTraveled / 15000, 1.5);
baseGameSpeed = Math.min(baseGameSpeed, 4); // Cap maximum base speed
baseGameSpeed = baseGameSpeed * 1.11; // Increase speed by 11 percent
// Apply gas acceleration to game speed
gameSpeed = baseGameSpeed * gasAcceleration;
// Update distance and speed with accelerated progression and nitro boost
var effectiveSpeed = gameSpeed * nitroSpeedMultiplier * nitroAcceleration;
distanceTraveled += effectiveSpeed;
var lastGameSpeed = gameSpeed;
// Switch to faster music at high speeds (based on base speed to prevent flickering)
if (baseGameSpeed > 2.5 && !fastMusicPlaying) {
LK.playMusic('fastmusic', {
volume: 0.8
});
fastMusicPlaying = true;
} else if (baseGameSpeed <= 2.5 && fastMusicPlaying) {
LK.playMusic('bgmusic', {
volume: 0.7
});
fastMusicPlaying = false;
}
// Update UI text based on rap mode
if (rapModeActive) {
scoreTxt.setText('Yo Distance: ' + Math.floor(distanceTraveled) + ' meters!');
bestScoreTxt.setText('Best Flow: ' + bestDistance);
speedTxt.setText('Speed Flow: ' + gameSpeed.toFixed(1) + 'x' + (gasPressed ? ' ⚡' : ''));
} else {
scoreTxt.setText('Distance: ' + Math.floor(distanceTraveled));
bestScoreTxt.setText('Best: ' + bestDistance);
speedTxt.setText('Speed: ' + gameSpeed.toFixed(1) + 'x' + (gasPressed ? ' ⚡' : ''));
}
// Add pulsing effect when speed increases
if (gameSpeed > lastGameSpeed + 0.1) {
tween(speedTxt, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(speedTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
}
// Enhanced continuous nitro visual effects with fluid animations
if (nitroEffect) {
// Dynamic pulsing glow effect during nitro
if (LK.ticks % 8 === 0) {
var glowColor = Math.random() < 0.3 ? 0x00FFFF : Math.random() < 0.6 ? 0xFFFFFF : 0xFF00FF;
LK.effects.flashObject(playerCar, glowColor, 150);
}
// Enhanced speed lines effect with gradient
if (LK.ticks % 4 === 0) {
var speedColor = Math.random() < 0.5 ? 0x0066BB : 0x004488;
LK.effects.flashScreen(speedColor, 30);
}
// Add nitro trail effects with tween
if (LK.ticks % 12 === 0) {
// Create temporary trail effect
var trailEffect = LK.getAsset('roadLine', {
anchorX: 0.5,
anchorY: 0.5,
x: playerCar.x + (Math.random() - 0.5) * 100,
y: playerCar.y + 50,
tint: 0x00FFFF,
alpha: 0.8
});
game.addChild(trailEffect);
tween(trailEffect, {
alpha: 0,
scaleX: 3,
scaleY: 0.2,
y: trailEffect.y + 200
}, {
duration: 600,
easing: tween.easeOut,
onFinish: function onFinish() {
trailEffect.destroy();
}
});
}
}
// Spawn enemies with progressive difficulty
spawnTimer++;
var adjustedSpawnRate = Math.max(30, spawnRate - Math.floor(distanceTraveled / 500)); // More aggressive spawn rate reduction
if (spawnTimer >= adjustedSpawnRate / gameSpeed) {
spawnEnemyCar();
spawnTimer = 0;
// Multiple enemy spawning at higher difficulty
if (distanceTraveled > 5000 && Math.random() < 0.3) {
spawnEnemyCar(); // 30% chance for double spawn after 5000 distance
}
if (distanceTraveled > 10000 && Math.random() < 0.2) {
spawnEnemyCar(); // Additional spawn chance after 10000 distance
}
}
// Spawn power-ups with reduced frequency at higher difficulty
powerUpSpawnTimer++;
var powerUpInterval = Math.max(200, 300 + Math.floor(distanceTraveled / 200)); // Longer intervals as distance increases
if (powerUpSpawnTimer >= powerUpInterval / gameSpeed) {
spawnPowerUp();
powerUpSpawnTimer = 0;
}
// Spawn nitro with increased rarity at higher difficulty
nitroSpawnTimer++;
var nitroInterval = Math.max(400, 600 + Math.floor(distanceTraveled / 150)); // Much longer intervals as distance increases
if (nitroSpawnTimer >= nitroInterval / gameSpeed) {
spawnNitro();
nitroSpawnTimer = 0;
}
// Spawn cups with very rare frequency
cupSpawnTimer++;
var cupInterval = Math.max(800, 1200 + Math.floor(distanceTraveled / 100)); // Very long intervals
if (cupSpawnTimer >= cupInterval / gameSpeed) {
spawnCup();
cupSpawnTimer = 0;
}
// Spawn bombers periodically
bomberSpawnTimer++;
var bomberInterval = Math.max(300, 500 + Math.floor(distanceTraveled / 200)); // Moderate intervals
if (bomberSpawnTimer >= bomberInterval / gameSpeed) {
spawnBomber();
bomberSpawnTimer = 0;
}
// Spawn ramps periodically
rampSpawnTimer++;
var rampInterval = Math.max(600, 800 + Math.floor(distanceTraveled / 300)); // Long intervals for ramps
if (rampSpawnTimer >= rampInterval / gameSpeed) {
spawnRamp();
rampSpawnTimer = 0;
}
// Spawn pedestrians occasionally
pedestrianSpawnTimer++;
var pedestrianInterval = Math.max(700, 1000 + Math.floor(distanceTraveled / 250)); // Moderate intervals
if (pedestrianSpawnTimer >= pedestrianInterval / gameSpeed) {
spawnPedestrian();
pedestrianSpawnTimer = 0;
}
// Check nitro effect end
if (nitroEffect && LK.ticks >= nitroEndTime) {
nitroEffect = false;
// Smooth transition back to normal speed
tween(playerCar, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeOut
});
// Reset speed multipliers gradually
tween({
value: nitroSpeedMultiplier
}, {
value: 1
}, {
duration: 800,
easing: tween.easeOut,
onUpdate: function onUpdate(obj) {
nitroSpeedMultiplier = obj.value;
}
});
tween({
value: nitroAcceleration
}, {
value: 1
}, {
duration: 800,
easing: tween.easeOut,
onUpdate: function onUpdate(obj) {
nitroAcceleration = obj.value;
}
});
// Reset player car movement speed
if (playerCar.originalMoveSpeed) {
tween(playerCar, {
moveSpeed: playerCar.originalMoveSpeed
}, {
duration: 500,
easing: tween.easeOut
});
}
// Flash to indicate nitro ending
LK.effects.flashScreen(0xFF4400, 300);
}
// Spawn road lines
lineSpawnTimer++;
if (lineSpawnTimer >= 25) {
for (var lane = 0; lane < 4; lane++) {
var line = game.addChild(new RoadLine());
line.x = 524 + lane * 400;
line.y = -100;
line.speed = 9.24 * gameSpeed * nitroSpeedMultiplier;
roadLines.push(line);
}
lineSpawnTimer = 0;
}
// Update and check power-ups
for (var j = powerUps.length - 1; j >= 0; j--) {
var powerUp = powerUps[j];
// Remove off-screen power-ups
if (powerUp.y > 2800) {
powerUp.destroy();
powerUps.splice(j, 1);
continue;
}
// Check collection
if (powerUp.intersects(playerCar)) {
// Update combo system
comboCount++;
lastComboTime = LK.ticks;
comboMultiplier = Math.min(1 + comboCount * 0.2, 3); // Max 3x multiplier
var baseScore = 50;
var finalScore = Math.floor(baseScore * comboMultiplier);
LK.setScore(LK.getScore() + finalScore);
// Update combo display
if (comboCount > 1) {
comboTxt.setText('COMBO x' + comboCount + ' (' + comboMultiplier.toFixed(1) + 'x)');
tween(comboTxt, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
}
LK.getSound('collect').play();
LK.effects.flashObject(powerUp, 0xffffff, 200);
addCameraShake(3, 10);
// Add smooth scale-out effect before destroying
tween(powerUp, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
powerUp.destroy();
}
});
powerUps.splice(j, 1);
}
}
// Update and check nitros
for (var n = nitros.length - 1; n >= 0; n--) {
var nitro = nitros[n];
// Remove off-screen nitros
if (nitro.y > 2800) {
nitro.destroy();
nitros.splice(n, 1);
continue;
}
// Check collection
if (nitro.intersects(playerCar)) {
// Statistics update removed
comboCount++;
lastComboTime = LK.ticks;
comboMultiplier = Math.min(1 + comboCount * 0.2, 3);
var baseScore = 100;
var finalScore = Math.floor(baseScore * comboMultiplier);
LK.setScore(LK.getScore() + finalScore);
// Update combo display
if (comboCount > 1 && comboTxt) {
comboTxt.setText('COMBO x' + comboCount + ' (' + comboMultiplier.toFixed(1) + 'x)');
tween(comboTxt, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
}
LK.getSound('collect').play();
addCameraShake(8, 20);
// Activate nitro effect with massive speed boost
nitroEffect = true;
nitroEndTime = LK.ticks + 450; // 7.5 seconds at 60fps
// Dramatic speed boost - 3x multiplier
nitroSpeedMultiplier = 3.0;
nitroAcceleration = 2.5;
// Enhanced visual effects for nitro activation
if (playerCar) {
tween(playerCar, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
easing: tween.easeOut
});
// Add pulsing effect during nitro
tween(playerCar, {
tint: 0x00FFFF
}, {
duration: 100,
onFinish: function onFinish() {
tween(playerCar, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
});
// Enhanced player car movement speed during nitro
if (playerCar.moveSpeed !== undefined) {
playerCar.originalMoveSpeed = playerCar.moveSpeed;
tween(playerCar, {
moveSpeed: playerCar.moveSpeed * 2.5
}, {
duration: 200,
easing: tween.easeOut
});
}
}
// Screen flash for nitro activation
LK.effects.flashScreen(0x00FFFF, 800);
// Add smooth scale-out effect for nitro
tween(nitro, {
scaleX: 4,
scaleY: 4,
alpha: 0
}, {
duration: 600,
easing: tween.elasticOut,
onFinish: function onFinish() {
nitro.destroy();
}
});
nitros.splice(n, 1);
}
}
// Update and check cups
for (var c = cups.length - 1; c >= 0; c--) {
var cup = cups[c];
// Remove off-screen cups
if (cup.y > 2800) {
cup.destroy();
cups.splice(c, 1);
continue;
}
// Check collection
if (cup.intersects(playerCar)) {
hasShield = true;
// Statistics update removed
comboCount++;
lastComboTime = LK.ticks;
comboMultiplier = Math.min(1 + comboCount * 0.2, 3);
var baseScore = 150;
var finalScore = Math.floor(baseScore * comboMultiplier);
LK.setScore(LK.getScore() + finalScore);
// Update combo display
if (comboCount > 1) {
comboTxt.setText('COMBO x' + comboCount + ' (' + comboMultiplier.toFixed(1) + 'x)');
tween(comboTxt, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 200,
onFinish: function onFinish() {
tween(comboTxt, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
}
});
}
LK.getSound('collect').play();
addCameraShake(5, 15);
LK.effects.flashScreen(0xFFD700, 400);
// Visual feedback for shield activation
tween(playerCar, {
tint: 0xFFD700
}, {
duration: 200,
onFinish: function onFinish() {
tween(playerCar, {
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
// Add smooth scale-out effect for cup
tween(cup, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 300,
easing: tween.elasticOut,
onFinish: function onFinish() {
cup.destroy();
}
});
cups.splice(c, 1);
}
}
// Update and check bombers
for (var b = bombers.length - 1; b >= 0; b--) {
var bomber = bombers[b];
// Remove off-screen bombers
if (bomber.y > 2800) {
bomber.destroy();
bombers.splice(b, 1);
continue;
}
// Check collision with player
if (bomber.intersects(playerCar)) {
// Always crush/kill the bomber person on collision
LK.setScore(LK.getScore() + 300);
LK.getSound('collect').play();
LK.effects.flashScreen(0x00ff00, 300);
// Create explosion at bomber position
var explosion = game.addChild(new Explosion());
explosion.x = bomber.x;
explosion.y = bomber.y;
// Destroy the bomber
bomber.destroy();
bombers.splice(b, 1);
continue;
}
}
// Update and check bombs
for (var bomb = bombs.length - 1; bomb >= 0; bomb--) {
var bombObj = bombs[bomb];
// Remove off-screen bombs
if (bombObj.y > 2800) {
bombObj.destroy();
bombs.splice(bomb, 1);
continue;
}
// Check collision with player
if (bombObj.intersects(playerCar)) {
if (hasShield) {
// Player has shield from cup - destroy bomb instead
hasShield = false;
LK.setScore(LK.getScore() + 200);
LK.getSound('collect').play();
LK.effects.flashScreen(0x00ff00, 300);
// Create explosion at bomb position
var explosion = game.addChild(new Explosion());
explosion.x = bombObj.x;
explosion.y = bombObj.y;
// Destroy the bomb
bombObj.destroy();
bombs.splice(bomb, 1);
continue;
} else {
// Normal collision - game over with bigger explosion
var explosion = game.addChild(new Explosion());
explosion.x = playerCar.x;
explosion.y = playerCar.y;
// Crash statistics updates removed
// Intense camera shake for crash
addCameraShake(25, 60);
// Create additional explosion for bomb impact
var bombExplosion = game.addChild(new Explosion());
bombExplosion.x = bombObj.x;
bombExplosion.y = bombObj.y;
tween(playerCar, {
scaleX: 0,
scaleY: 0,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut
});
if (distanceTraveled > bestDistance) {
bestDistance = Math.floor(distanceTraveled);
bestScoreTxt.setText('Best: ' + bestDistance);
saveBestScore();
}
LK.effects.flashScreen(0xff0000, 1000);
LK.playMusic('gameovermusic', {
volume: 0.6,
loop: false
});
LK.showGameOver();
return;
}
}
}
// Update and check ramps
for (var r = ramps.length - 1; r >= 0; r--) {
var ramp = ramps[r];
// Remove off-screen ramps
if (ramp.y > 2800) {
ramp.destroy();
ramps.splice(r, 1);
continue;
}
// Check if player hits ramp to initiate jump
if (ramp.intersects(playerCar) && !playerJumping) {
playerJumping = true;
jumpStartTime = LK.ticks;
// Statistics update removed
var baseScore = 75;
var finalScore = Math.floor(baseScore * comboMultiplier);
LK.setScore(LK.getScore() + finalScore); // Bonus for using ramp
LK.getSound('collect').play();
addCameraShake(4, 12);
// Flash effect for ramp activation
LK.effects.flashScreen(0x00AAFF, 300);
// Scale out ramp effect
tween(ramp, {
scaleX: 2,
scaleY: 2,
alpha: 0
}, {
duration: 400,
onFinish: function onFinish() {
ramp.destroy();
}
});
ramps.splice(r, 1);
continue;
}
}
// Update and check pedestrians
for (var p = pedestrians.length - 1; p >= 0; p--) {
var pedestrian = pedestrians[p];
// Remove off-screen pedestrians
if (pedestrian.y > 2800) {
pedestrian.destroy();
pedestrians.splice(p, 1);
continue;
}
// Check collision with player
if (pedestrian.intersects(playerCar)) {
if (hasShield) {
// Player has shield - save pedestrian and get bonus
hasShield = false;
LK.setScore(LK.getScore() + 250);
LK.getSound('collect').play();
LK.effects.flashScreen(0x00ff00, 300);
// Create sparkle effect for saving pedestrian
var explosion = game.addChild(new Explosion());
explosion.x = pedestrian.x;
explosion.y = pedestrian.y;
// Destroy the pedestrian (saved)
pedestrian.destroy();
pedestrians.splice(p, 1);
continue;
} else {
// Normal collision - game over
var explosion = game.addChild(new Explosion());
explosion.x = playerCar.x;
explosion.y = playerCar.y;
// Crash statistics updates removed
// Heavy camera shake for pedestrian collision
addCameraShake(30, 80);
tween(playerCar, {
scaleX: 0,
scaleY: 0,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut
});
if (distanceTraveled > bestDistance) {
bestDistance = Math.floor(distanceTraveled);
bestScoreTxt.setText('Best: ' + bestDistance);
saveBestScore();
}
LK.effects.flashScreen(0xff0000, 1000);
LK.playMusic('gameovermusic', {
volume: 0.6,
loop: false
});
LK.showGameOver();
return;
}
}
}
// Collision detection with enemies - skip if jumping high enough
for (var i = enemyCars.length - 1; i >= 0; i--) {
var enemy = enemyCars[i];
if (enemy.lastY === undefined) enemy.lastY = enemy.y;
// Remove off-screen enemies
if (enemy.lastY < 2800 && enemy.y >= 2800) {
enemy.destroy();
enemyCars.splice(i, 1);
continue;
}
// Check collision with player - but not if jumping high enough
if (enemy.intersects(playerCar) && (!playerJumping || jumpHeight < 50)) {
if (hasShield) {
// Player has shield from cup - destroy enemy instead
hasShield = false;
LK.setScore(LK.getScore() + 200);
LK.getSound('collect').play();
LK.effects.flashScreen(0x00ff00, 300);
// Create explosion at enemy position
var explosion = game.addChild(new Explosion());
explosion.x = enemy.x;
explosion.y = enemy.y;
// Destroy the enemy
enemy.destroy();
enemyCars.splice(i, 1);
continue;
} else {
// Normal collision - game over
// Create explosion at collision point
var explosion = game.addChild(new Explosion());
explosion.x = playerCar.x;
explosion.y = playerCar.y;
// Crash statistics updates removed
// Strong camera shake for car collision
addCameraShake(20, 50);
// Make player car explode with tween effect
tween(playerCar, {
scaleX: 0,
scaleY: 0,
rotation: Math.PI * 2,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut
});
// Update best score if needed
if (distanceTraveled > bestDistance) {
bestDistance = Math.floor(distanceTraveled);
bestScoreTxt.setText('Best: ' + bestDistance);
saveBestScore();
}
LK.effects.flashScreen(0xff0000, 1000);
LK.playMusic('gameovermusic', {
volume: 0.6,
loop: false
});
LK.showGameOver();
return;
}
} else if (playerJumping && jumpHeight >= 50) {
// Player jumped over enemy - bonus points!
if (!enemy.jumpedOver) {
LK.setScore(LK.getScore() + 150);
LK.getSound('dodge').play();
enemy.jumpedOver = true; // Mark to prevent multiple bonuses
}
}
// Check for near miss (score bonus)
var distanceFromPlayer = Math.abs(enemy.x - playerCar.x);
if (enemy.y > playerCar.y - 150 && enemy.y < playerCar.y + 150 && distanceFromPlayer < 200 && distanceFromPlayer > 150) {
if (!enemy.nearMissScored) {
LK.setScore(LK.getScore() + 10);
LK.getSound('dodge').play();
enemy.nearMissScored = true;
}
}
enemy.lastY = enemy.y;
}
// Update road lines
for (var k = roadLines.length - 1; k >= 0; k--) {
var line = roadLines[k];
// Remove off-screen lines
if (line.y > 2800) {
line.destroy();
roadLines.splice(k, 1);
}
}
};
pixel art ferrari bird's eye view. In-Game asset. 2d. High contrast. No shadows
pixel art tofaş bird's eye view. In-Game asset. 2d. High contrast. No shadows
pixel art Togg bird's eye view. In-Game asset. 2d. High contrast. No shadows
pixel art gas pedal bird's eye view. In-Game asset. 2d. High contrast. No shadows
pixel art nitro. In-Game asset. 2d. High contrast. No shadows
pixel art fantasy car bird's eye view. In-Game asset. 2d. High contrast. No shadows
pixel art straight line,. In-Game asset. 2d. High contrast. No shadows
Gold and Glory pixel art cup. In-Game asset. 2d. High contrast. No shadows
bugatti bolide pixel art bird's eye view. In-Game asset. 2d. High contrast. No shadows
BMW X6 pixel art bird's eye view. In-Game asset. 2d. High contrast. No shadows
pixel art joker. In-Game asset. 2d. High contrast. No shadows
düz sarı çizgi. In-Game asset. 2d. High contrast. No shadows
pixel art peter parker. In-Game asset. 2d. High contrast. No shadows
bird's eye pixel art motorcycle suzuki. In-Game asset. 2d. High contrast. No shadows