/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Bush = Container.expand(function () { var self = Container.call(this); var bushGraphics = self.attachAsset('bush', { anchorX: 0.5, anchorY: 1.0 }); self.speed = 6; self.update = function () { self.y += self.speed; }; return self; }); var Car = Container.expand(function () { var self = Container.call(this); var carGraphics = self.attachAsset('playerCar', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 0; self.targetX = 0; self.lane = 1; // 0=left, 1=center, 2=right return self; }); var Coin = Container.expand(function () { var self = Container.call(this); var coinGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6; self.lastY = 0; self.lastIntersecting = false; self.update = function () { self.y += self.speed; coinGraphics.rotation += 0.1; }; return self; }); var EnemyCar = Container.expand(function () { var self = Container.call(this); var carTypes = ['enemyCar1', 'enemyCar2', 'enemyCar3']; var randomType = carTypes[Math.floor(Math.random() * carTypes.length)]; var carGraphics = self.attachAsset(randomType, { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.lastY = 0; self.lastIntersecting = false; self.update = function () { self.y += self.speed; }; return self; }); var FuelTank = Container.expand(function () { var self = Container.call(this); var fuelTankGraphics = self.attachAsset('fuelTank', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6; self.lastY = 0; self.lastIntersecting = false; self.update = function () { self.y += self.speed; fuelTankGraphics.rotation += 0.05; }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); // Random power-up type: 0=speed boost, 1=shield self.powerType = Math.floor(Math.random() * 2); var powerUpGraphics; if (self.powerType === 0) { // Speed boost power-up (blue) powerUpGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); powerUpGraphics.tint = 0x0099ff; // Blue tint } else { // Shield power-up (purple) powerUpGraphics = self.attachAsset('coin', { anchorX: 0.5, anchorY: 0.5 }); powerUpGraphics.tint = 0x9900ff; // Purple tint } self.speed = 6; self.lastY = 0; self.lastIntersecting = false; self.update = function () { self.y += self.speed; powerUpGraphics.rotation += 0.15; // Pulsing effect powerUpGraphics.scaleX = 1 + Math.sin(LK.ticks * 0.2) * 0.3; powerUpGraphics.scaleY = 1 + Math.sin(LK.ticks * 0.2) * 0.3; }; 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 = 6; self.update = function () { self.y += self.speed; }; return self; }); var SpilledBox = Container.expand(function () { var self = Container.call(this); var boxGraphics = self.attachAsset('spilledBox', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6; self.lastY = 0; self.lastIntersecting = false; self.update = function () { self.y += self.speed; }; return self; }); var SpilledFuel = Container.expand(function () { var self = Container.call(this); var spillGraphics = self.attachAsset('spilledFuel', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6; self.lastY = 0; self.lastIntersecting = false; self.update = function () { self.y += self.speed; }; return self; }); var Tree = Container.expand(function () { var self = Container.call(this); var treeGraphics = self.attachAsset('tree', { anchorX: 0.5, anchorY: 1.0 }); self.speed = 6; self.update = function () { self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ // Game variables var game = new LK.Game({ backgroundColor: 0x2c3e50 }); /**** * Game Code ****/ // Game variables var playerCar; var enemyCars = []; var coins = []; var roadLines = []; var trees = []; var bushes = []; var gameSpeed = 6; var lanes = [2048 / 4, 2048 / 2, 3 * 2048 / 4]; // Three lanes var spawnTimer = 0; var coinSpawnTimer = 0; var roadLineSpawnTimer = 0; var treeSpawnTimer = 0; var bushSpawnTimer = 0; var distanceScore = 0; var fuelTanks = []; var fuelTankSpawnTimer = 0; var currentFuel = 100; var maxFuel = 100; var fuelConsumptionRate = 0.1; var dragActive = false; var showingLeaderboard = false; var leaderboardContainer; var leaderboardScores = storage.leaderboard || []; var gameStartTime = Date.now(); var gameTime = 0; var spilledFuels = []; var spilledFuelSpawnTimer = 0; var spilledBoxes = []; var spilledBoxSpawnTimer = 0; var isSliding = false; var slideDirection = 0; var slideTimer = 0; var powerUps = []; var powerUpSpawnTimer = 0; var hasShield = false; var shieldTimer = 0; var speedBoostTimer = 0; var hasSpeedBoost = false; var comboMultiplier = 1; var comboTimer = 0; var lastCollectTime = 0; // Create score display using asset var scoreDisplay = LK.getAsset('Score', { anchorX: 0.5, anchorY: 0 }); LK.gui.top.addChild(scoreDisplay); // Create score text display var scoreTxt = new Text2('0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); scoreTxt.x = scoreDisplay.x + 60; // Position next to score image scoreTxt.y = scoreDisplay.y; LK.gui.top.addChild(scoreTxt); // Create score button to show/hide score var scoreButton = new Text2('📊', { size: 80, fill: 0x00FF00 }); scoreButton.anchor.set(0.5, 0); scoreButton.x = 2048 - 200; scoreButton.y = 20; LK.gui.top.addChild(scoreButton); // Create leaderboard button var leaderboardButton = new Text2('🏆', { size: 80, fill: 0xFFD700 }); leaderboardButton.anchor.set(0.5, 0); leaderboardButton.x = 2048 - 100; leaderboardButton.y = 20; LK.gui.top.addChild(leaderboardButton); // Score visibility state var showScore = true; // Create distance display var distanceTxt = new Text2('Distance: 0m', { size: 60, fill: 0xFFFFFF }); distanceTxt.anchor.set(0.5, 0); distanceTxt.y = 100; LK.gui.top.addChild(distanceTxt); // Create speedometer display var speedometerTxt = new Text2('Speed: 0 km/h', { size: 60, fill: 0xFFFFFF }); speedometerTxt.anchor.set(0.5, 0); speedometerTxt.y = 170; LK.gui.top.addChild(speedometerTxt); // Create fuel display var fuelTxt = new Text2('Fuel: 100%', { size: 60, fill: 0x00FF00 }); fuelTxt.anchor.set(0.5, 0); fuelTxt.y = 240; LK.gui.top.addChild(fuelTxt); // Create time display var timeTxt = new Text2('Time: 0:00', { size: 60, fill: 0xFFFFFF }); timeTxt.anchor.set(0.5, 0); timeTxt.y = 310; LK.gui.top.addChild(timeTxt); // Create shield indicator var shieldTxt = new Text2('', { size: 60, fill: 0x9900ff }); shieldTxt.anchor.set(0.5, 0); shieldTxt.y = 380; LK.gui.top.addChild(shieldTxt); // Create speed boost indicator var speedBoostTxt = new Text2('', { size: 60, fill: 0x0099ff }); speedBoostTxt.anchor.set(0.5, 0); speedBoostTxt.y = 450; LK.gui.top.addChild(speedBoostTxt); // Create combo multiplier display var comboTxt = new Text2('', { size: 70, fill: 0xFFD700 }); comboTxt.anchor.set(0.5, 0); comboTxt.y = 520; LK.gui.top.addChild(comboTxt); // Create left arrow button var leftArrow = LK.getAsset('Oktusu', { width: 300, height: 300, anchorX: 0.5, anchorY: 0.5 }); leftArrow.x = 200; leftArrow.y = 2732 - 200; game.addChild(leftArrow); // Create left arrow text var leftArrowTxt = new Text2('←', { size: 80, fill: 0xFFFFFF }); leftArrowTxt.anchor.set(0.5, 0.5); leftArrowTxt.x = leftArrow.x; leftArrowTxt.y = leftArrow.y; game.addChild(leftArrowTxt); // Create right arrow button var rightArrow = LK.getAsset('Oktusu', { width: 300, height: 300, anchorX: 0.5, anchorY: 0.5 }); rightArrow.x = 2048 - 200; rightArrow.y = 2732 - 200; game.addChild(rightArrow); // Create right arrow text var rightArrowTxt = new Text2('→', { size: 80, fill: 0xFFFFFF }); rightArrowTxt.anchor.set(0.5, 0.5); rightArrowTxt.x = rightArrow.x; rightArrowTxt.y = rightArrow.y; game.addChild(rightArrowTxt); // Gas pedal variables (keeping for boost system) var isGasPedalPressed = false; var boostMultiplier = 1.0; // Function to show leaderboard function showLeaderboard() { if (showingLeaderboard) return; showingLeaderboard = true; leaderboardContainer = new Container(); game.addChild(leaderboardContainer); // Semi-transparent background var background = LK.getAsset('highway', { width: 1800, height: 2200, anchorX: 0.5, anchorY: 0.5 }); background.x = 2048 / 2; background.y = 2732 / 2; background.alpha = 0.8; background.tint = 0x000000; leaderboardContainer.addChild(background); // Title var titleText = new Text2('🏆 TOP SCORES 🏆', { size: 100, fill: 0xFFD700 }); titleText.anchor.set(0.5, 0); titleText.x = 2048 / 2; titleText.y = 400; leaderboardContainer.addChild(titleText); // Display top 10 scores var sortedScores = leaderboardScores.slice().sort(function (a, b) { return b - a; }); for (var i = 0; i < Math.min(10, sortedScores.length); i++) { var rankText = new Text2(i + 1 + '. ' + sortedScores[i] + ' points', { size: 80, fill: i < 3 ? 0xFFD700 : 0xFFFFFF }); rankText.anchor.set(0.5, 0); rankText.x = 2048 / 2; rankText.y = 600 + i * 120; leaderboardContainer.addChild(rankText); } // Close button var closeButton = new Text2('❌ CLOSE', { size: 80, fill: 0xFF4444 }); closeButton.anchor.set(0.5, 0); closeButton.x = 2048 / 2; closeButton.y = 2200; leaderboardContainer.addChild(closeButton); } // Function to hide leaderboard function hideLeaderboard() { if (!showingLeaderboard) return; showingLeaderboard = false; if (leaderboardContainer) { leaderboardContainer.destroy(); leaderboardContainer = null; } } // Function to save score to leaderboard function saveScore(score) { leaderboardScores.push(score); leaderboardScores.sort(function (a, b) { return b - a; }); // Keep only top 20 scores if (leaderboardScores.length > 20) { leaderboardScores = leaderboardScores.slice(0, 20); } storage.leaderboard = leaderboardScores; } // Create player car playerCar = game.addChild(new Car()); playerCar.x = lanes[1]; // Start in middle lane playerCar.y = 2732 - 300; playerCar.targetX = playerCar.x; // Touch controls game.down = function (x, y, obj) { // Check if leaderboard is showing and handle close button if (showingLeaderboard) { var closeButtonBounds = { left: 2048 / 2 - 150, right: 2048 / 2 + 150, top: 2200 - 50, bottom: 2200 + 50 }; if (x >= closeButtonBounds.left && x <= closeButtonBounds.right && y >= closeButtonBounds.top && y <= closeButtonBounds.bottom) { hideLeaderboard(); return; } // Ignore other touches when leaderboard is showing return; } // Check if score button is pressed var scoreBounds = { left: scoreButton.x - 50, right: scoreButton.x + 50, top: scoreButton.y, bottom: scoreButton.y + 80 }; if (x >= scoreBounds.left && x <= scoreBounds.right && y >= scoreBounds.top && y <= scoreBounds.bottom) { showScore = !showScore; if (showScore) { scoreDisplay.alpha = 1; scoreTxt.alpha = 1; } else { scoreDisplay.alpha = 0; scoreTxt.alpha = 0; } return; } // Check if leaderboard button is pressed var leaderboardBounds = { left: leaderboardButton.x - 50, right: leaderboardButton.x + 50, top: leaderboardButton.y, bottom: leaderboardButton.y + 80 }; if (x >= leaderboardBounds.left && x <= leaderboardBounds.right && y >= leaderboardBounds.top && y <= leaderboardBounds.bottom) { showLeaderboard(); return; } // Check if left arrow is pressed var leftArrowBounds = { left: leftArrow.x - 150, right: leftArrow.x + 150, top: leftArrow.y - 150, bottom: leftArrow.y + 150 }; if (x >= leftArrowBounds.left && x <= leftArrowBounds.right && y >= leftArrowBounds.top && y <= leftArrowBounds.bottom) { // Move car to left lane if (playerCar.lane > 0) { playerCar.lane--; playerCar.targetX = lanes[playerCar.lane]; } leftArrow.tint = 0xffff00; // Yellow when pressed } // Check if right arrow is pressed var rightArrowBounds = { left: rightArrow.x - 150, right: rightArrow.x + 150, top: rightArrow.y - 150, bottom: rightArrow.y + 150 }; if (x >= rightArrowBounds.left && x <= rightArrowBounds.right && y >= rightArrowBounds.top && y <= rightArrowBounds.bottom) { // Move car to right lane if (playerCar.lane < 2) { playerCar.lane++; playerCar.targetX = lanes[playerCar.lane]; } rightArrow.tint = 0xffff00; // Yellow when pressed } }; game.move = function (x, y, obj) { // Don't allow movement when leaderboard is showing if (showingLeaderboard) return; var leftArrowBounds = { left: leftArrow.x - 150, right: leftArrow.x + 150, top: leftArrow.y - 150, bottom: leftArrow.y + 150 }; var rightArrowBounds = { left: rightArrow.x - 150, right: rightArrow.x + 150, top: rightArrow.y - 150, bottom: rightArrow.y + 150 }; }; game.up = function (x, y, obj) { // Don't process touches when leaderboard is showing if (showingLeaderboard) return; // Reset arrow button colors leftArrow.tint = 0xffffff; rightArrow.tint = 0xffffff; }; // Main game loop game.update = function () { // Don't update game when leaderboard is showing if (showingLeaderboard) return; // Update game time gameTime = Math.floor((Date.now() - gameStartTime) / 1000); var minutes = Math.floor(gameTime / 60); var seconds = gameTime % 60; var timeString = minutes + ':' + (seconds < 10 ? '0' : '') + seconds; timeTxt.setText('Time: ' + timeString); // Update power-up timers if (hasShield) { shieldTimer--; shieldTxt.setText('🛡️ Shield: ' + Math.ceil(shieldTimer / 60) + 's'); if (shieldTimer <= 0) { hasShield = false; shieldTxt.setText(''); // Remove shield visual effect playerCar.tint = 0xffffff; } } else { shieldTxt.setText(''); } if (hasSpeedBoost) { speedBoostTimer--; speedBoostTxt.setText('⚡ Boost: ' + Math.ceil(speedBoostTimer / 60) + 's'); if (speedBoostTimer <= 0) { hasSpeedBoost = false; speedBoostTxt.setText(''); } } else { speedBoostTxt.setText(''); } // Update combo system if (comboTimer > 0) { comboTimer--; comboTxt.setText('Combo x' + comboMultiplier); if (comboTimer <= 0) { comboMultiplier = 1; comboTxt.setText(''); } } else { comboTxt.setText(''); } // Reset combo if too much time passed since last collect if (Date.now() - lastCollectTime > 3000) { comboMultiplier = 1; comboTimer = 0; } // Handle sliding mechanics if (isSliding) { slideTimer--; // Apply sliding movement with tween for smooth effect var slideAmount = slideDirection * 8; playerCar.x += slideAmount; // Constrain car to stay within road bounds playerCar.x = Math.max(lanes[0] - 100, Math.min(lanes[2] + 100, playerCar.x)); // Add visual sliding effect tween(playerCar, { rotation: slideDirection * 0.3 }, { duration: 100, easing: tween.easeOut }); if (slideTimer <= 0) { isSliding = false; slideDirection = 0; // Return car to normal rotation tween(playerCar, { rotation: 0 }, { duration: 500, easing: tween.easeOut }); // Snap back to nearest lane var closestLane = 1; var minDistance = Math.abs(playerCar.x - lanes[1]); for (var i = 0; i < lanes.length; i++) { var distance = Math.abs(playerCar.x - lanes[i]); if (distance < minDistance) { minDistance = distance; closestLane = i; } } playerCar.lane = closestLane; playerCar.targetX = lanes[closestLane]; } } else { // Normal smooth car movement to target lane var moveSpeed = 15; if (Math.abs(playerCar.x - playerCar.targetX) > moveSpeed) { if (playerCar.x < playerCar.targetX) { playerCar.x += moveSpeed; } else { playerCar.x -= moveSpeed; } } else { playerCar.x = playerCar.targetX; } } // Increase game speed over time gameSpeed += 0.002; // Player car accelerates 3 units per second (3/60 = 0.05 per frame at 60fps) playerCar.speed += 0.05; // Calculate base boost from speed boost power-up only var targetBoost = 1.0; if (hasSpeedBoost) { targetBoost *= 1.5; // Additional 50% speed from power-up } // Apply boost with smooth transition if (boostMultiplier < targetBoost) { // Smoothly increase speed tween(this, { boostMultiplier: targetBoost }, { duration: 1000, easing: tween.easeOut }); } else if (boostMultiplier > targetBoost) { // Smoothly decrease speed tween(this, { boostMultiplier: targetBoost }, { duration: 500, easing: tween.easeOut }); } // Limit effective speed to prevent exceeding 150 km/h var maxEffectiveSpeed = 15; // 15 * 10 = 150 km/h display limit var effectiveSpeed = Math.min(gameSpeed * boostMultiplier, maxEffectiveSpeed); var speedLimitRatio = effectiveSpeed / (gameSpeed * boostMultiplier); // Update distance score distanceScore += effectiveSpeed * 0.1; distanceTxt.setText('Distance: ' + Math.floor(distanceScore) + 'm'); // Update speedometer display var currentSpeed = Math.floor(gameSpeed * boostMultiplier * 10); // Convert to km/h scale // Limit maximum displayed speed to 150 km/h currentSpeed = Math.min(currentSpeed, 150); speedometerTxt.setText('Speed: ' + currentSpeed + ' km/h'); // Spawn road lines roadLineSpawnTimer++; if (roadLineSpawnTimer >= 20) { roadLineSpawnTimer = 0; for (var i = 0; i < 2; i++) { var roadLine = new RoadLine(); roadLine.x = lanes[0] + i * (lanes[2] - lanes[0]); roadLine.y = -50; roadLine.speed = effectiveSpeed; roadLines.push(roadLine); game.addChild(roadLine); } } // Spawn enemy cars spawnTimer++; // Increase spawn rate based on score and distance var spawnRateBonus = Math.floor(LK.getScore() / 100) + Math.floor(distanceScore / 1000); var baseSpawnRate = Math.max(20, 90 - Math.floor(gameSpeed) - spawnRateBonus); if (spawnTimer >= baseSpawnRate) { spawnTimer = 0; var enemyCar = new EnemyCar(); var randomLane = Math.floor(Math.random() * 3); enemyCar.x = lanes[randomLane]; enemyCar.y = -100; enemyCar.speed = (gameSpeed + Math.random() * 3) * boostMultiplier; enemyCar.lastY = enemyCar.y; enemyCar.lastIntersecting = enemyCar.intersects(playerCar); enemyCars.push(enemyCar); game.addChild(enemyCar); } // Spawn trees treeSpawnTimer++; if (treeSpawnTimer >= 60) { treeSpawnTimer = 0; // Spawn trees on left side if (Math.random() < 0.8) { var leftTree = new Tree(); leftTree.x = Math.random() * (lanes[0] - 100); // Random position on left side leftTree.y = -100; leftTree.speed = effectiveSpeed; trees.push(leftTree); game.addChild(leftTree); } // Spawn trees on right side if (Math.random() < 0.8) { var rightTree = new Tree(); rightTree.x = lanes[2] + 100 + Math.random() * (2048 - lanes[2] - 200); // Random position on right side rightTree.y = -100; rightTree.speed = effectiveSpeed; trees.push(rightTree); game.addChild(rightTree); } } // Spawn bushes bushSpawnTimer++; if (bushSpawnTimer >= 40) { bushSpawnTimer = 0; // Spawn bushes on left side between trees if (Math.random() < 0.6) { var leftBush = new Bush(); leftBush.x = Math.random() * (lanes[0] - 50); // Random position on left side leftBush.y = -50; leftBush.speed = effectiveSpeed; bushes.push(leftBush); game.addChild(leftBush); } // Spawn bushes on right side between trees if (Math.random() < 0.6) { var rightBush = new Bush(); rightBush.x = lanes[2] + 50 + Math.random() * (2048 - lanes[2] - 150); // Random position on right side rightBush.y = -50; rightBush.speed = effectiveSpeed; bushes.push(rightBush); game.addChild(rightBush); } } // Spawn coins coinSpawnTimer++; if (coinSpawnTimer >= 120) { coinSpawnTimer = 0; if (Math.random() < 0.7) { var coin = new Coin(); var randomLane = Math.floor(Math.random() * 3); coin.x = lanes[randomLane]; coin.y = -50; coin.speed = effectiveSpeed; coin.lastY = coin.y; coin.lastIntersecting = coin.intersects(playerCar); coins.push(coin); game.addChild(coin); } } // Spawn fuel tanks fuelTankSpawnTimer++; if (fuelTankSpawnTimer >= 150) { fuelTankSpawnTimer = 0; if (Math.random() < 0.7) { var fuelTank = new FuelTank(); var randomLane = Math.floor(Math.random() * 3); fuelTank.x = lanes[randomLane]; fuelTank.y = -50; fuelTank.speed = effectiveSpeed; fuelTank.lastY = fuelTank.y; fuelTank.lastIntersecting = fuelTank.intersects(playerCar); fuelTanks.push(fuelTank); game.addChild(fuelTank); } } // Spawn spilled fuel spilledFuelSpawnTimer++; if (spilledFuelSpawnTimer >= 200) { spilledFuelSpawnTimer = 0; if (Math.random() < 0.4) { var spilledFuel = new SpilledFuel(); var randomLane = Math.floor(Math.random() * 3); spilledFuel.x = lanes[randomLane]; spilledFuel.y = -50; spilledFuel.speed = effectiveSpeed; spilledFuel.lastY = spilledFuel.y; spilledFuel.lastIntersecting = spilledFuel.intersects(playerCar); spilledFuels.push(spilledFuel); game.addChild(spilledFuel); } } // Spawn spilled boxes spilledBoxSpawnTimer++; if (spilledBoxSpawnTimer >= 180) { spilledBoxSpawnTimer = 0; if (Math.random() < 0.5) { var spilledBox = new SpilledBox(); var randomLane = Math.floor(Math.random() * 3); spilledBox.x = lanes[randomLane]; spilledBox.y = -50; spilledBox.speed = effectiveSpeed; spilledBox.lastY = spilledBox.y; spilledBox.lastIntersecting = spilledBox.intersects(playerCar); spilledBoxes.push(spilledBox); game.addChild(spilledBox); } } // Spawn power-ups powerUpSpawnTimer++; if (powerUpSpawnTimer >= 300) { powerUpSpawnTimer = 0; if (Math.random() < 0.6) { var powerUp = new PowerUp(); var randomLane = Math.floor(Math.random() * 3); powerUp.x = lanes[randomLane]; powerUp.y = -50; powerUp.speed = effectiveSpeed; powerUp.lastY = powerUp.y; powerUp.lastIntersecting = powerUp.intersects(playerCar); powerUps.push(powerUp); game.addChild(powerUp); } } // Update and check road lines for (var i = roadLines.length - 1; i >= 0; i--) { var roadLine = roadLines[i]; roadLine.speed = effectiveSpeed; if (roadLine.lastY === undefined) roadLine.lastY = roadLine.y; // Remove road lines that go off screen if (roadLine.lastY <= 2732 + 50 && roadLine.y > 2732 + 50) { roadLine.destroy(); roadLines.splice(i, 1); continue; } roadLine.lastY = roadLine.y; } // Update and check enemy cars for (var i = enemyCars.length - 1; i >= 0; i--) { var enemyCar = enemyCars[i]; // Increase enemy speed based on score and distance var speedBonus = Math.floor(LK.getScore() / 50) + Math.floor(distanceScore / 500); var enemyBaseSpeed = (gameSpeed + 2 + speedBonus) * boostMultiplier; enemyCar.speed = Math.min(enemyBaseSpeed, maxEffectiveSpeed + 2); // Remove cars that go off screen if (enemyCar.lastY <= 2732 + 100 && enemyCar.y > 2732 + 100) { enemyCar.destroy(); enemyCars.splice(i, 1); continue; } // Check collision with player var currentIntersecting = enemyCar.intersects(playerCar); if (!enemyCar.lastIntersecting && currentIntersecting) { if (hasShield) { // Shield protects from collision hasShield = false; shieldTimer = 0; shieldTxt.setText(''); playerCar.tint = 0xffffff; // Remove shield tint LK.effects.flashObject(playerCar, 0xffff00, 1000); // Yellow flash for shield break LK.effects.flashObject(enemyCar, 0xffff00, 500); // Push enemy car away enemyCar.y += 200; } else { // Collision detected - game over saveScore(LK.getScore()); LK.getSound('crash').play(); LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } } enemyCar.lastY = enemyCar.y; enemyCar.lastIntersecting = currentIntersecting; } // Update and check trees for (var i = trees.length - 1; i >= 0; i--) { var tree = trees[i]; tree.speed = effectiveSpeed; if (tree.lastY === undefined) tree.lastY = tree.y; // Remove trees that go off screen if (tree.lastY <= 2732 + 100 && tree.y > 2732 + 100) { tree.destroy(); trees.splice(i, 1); continue; } tree.lastY = tree.y; } // Update and check bushes for (var i = bushes.length - 1; i >= 0; i--) { var bush = bushes[i]; bush.speed = effectiveSpeed; if (bush.lastY === undefined) bush.lastY = bush.y; // Remove bushes that go off screen if (bush.lastY <= 2732 + 50 && bush.y > 2732 + 50) { bush.destroy(); bushes.splice(i, 1); continue; } bush.lastY = bush.y; } // Update and check coins for (var i = coins.length - 1; i >= 0; i--) { var coin = coins[i]; coin.speed = effectiveSpeed; // Remove coins that go off screen if (coin.lastY <= 2732 + 50 && coin.y > 2732 + 50) { coin.destroy(); coins.splice(i, 1); continue; } // Check collection by player var currentIntersecting = coin.intersects(playerCar); if (!coin.lastIntersecting && currentIntersecting) { // Coin collected lastCollectTime = Date.now(); comboTimer = 300; // 5 seconds at 60fps var pointsEarned = 10 * comboMultiplier; LK.setScore(LK.getScore() + pointsEarned); comboMultiplier = Math.min(comboMultiplier + 1, 5); // Max combo x5 scoreTxt.setText(LK.getScore().toString()); LK.getSound('collectCoin').play(); coin.destroy(); coins.splice(i, 1); continue; } coin.lastY = coin.y; coin.lastIntersecting = currentIntersecting; } // Update fuel system currentFuel -= fuelConsumptionRate * boostMultiplier; if (currentFuel <= 0) { currentFuel = 0; // Game over due to no fuel saveScore(LK.getScore()); LK.effects.flashScreen(0xff8800, 1000); LK.showGameOver(); return; } // Update fuel display with color coding var fuelPercentage = Math.floor(currentFuel / maxFuel * 100); fuelTxt.setText('Fuel: ' + fuelPercentage + '%'); if (fuelPercentage > 50) { fuelTxt.fill = 0x00FF00; // Green } else if (fuelPercentage > 25) { fuelTxt.fill = 0xFFFF00; // Yellow } else { fuelTxt.fill = 0xFF0000; // Red } // Update and check fuel tanks for (var i = fuelTanks.length - 1; i >= 0; i--) { var fuelTank = fuelTanks[i]; fuelTank.speed = effectiveSpeed; // Remove fuel tanks that go off screen if (fuelTank.lastY <= 2732 + 50 && fuelTank.y > 2732 + 50) { fuelTank.destroy(); fuelTanks.splice(i, 1); continue; } // Check collection by player var currentIntersecting = fuelTank.intersects(playerCar); if (!fuelTank.lastIntersecting && currentIntersecting) { // Fuel tank collected lastCollectTime = Date.now(); comboTimer = 300; // 5 seconds at 60fps currentFuel = Math.min(currentFuel + 30, maxFuel); var pointsEarned = 5 * comboMultiplier; LK.setScore(LK.getScore() + pointsEarned); comboMultiplier = Math.min(comboMultiplier + 1, 5); // Max combo x5 scoreTxt.setText(LK.getScore().toString()); LK.getSound('collectCoin').play(); fuelTank.destroy(); fuelTanks.splice(i, 1); continue; } fuelTank.lastY = fuelTank.y; fuelTank.lastIntersecting = currentIntersecting; } // Update and check spilled fuel for (var i = spilledFuels.length - 1; i >= 0; i--) { var spilledFuel = spilledFuels[i]; spilledFuel.speed = effectiveSpeed; // Remove spilled fuel that goes off screen if (spilledFuel.lastY <= 2732 + 50 && spilledFuel.y > 2732 + 50) { spilledFuel.destroy(); spilledFuels.splice(i, 1); continue; } // Check collision with player var currentIntersecting = spilledFuel.intersects(playerCar); if (!spilledFuel.lastIntersecting && currentIntersecting && !isSliding) { // Spilled fuel collision - make car slide isSliding = true; slideDirection = (Math.random() - 0.5) * 2; // Random slide direction slideTimer = 90; // Slide for 1.5 seconds at 60fps // Visual effect for hitting spilled fuel LK.effects.flashObject(playerCar, 0x8B4513, 500); // Add spinning rotation effect tween(playerCar, { rotation: playerCar.rotation + Math.PI * 4 // Spin 2 full rotations }, { duration: 1500, easing: tween.easeOut }); } spilledFuel.lastY = spilledFuel.y; spilledFuel.lastIntersecting = currentIntersecting; } // Update and check spilled boxes for (var i = spilledBoxes.length - 1; i >= 0; i--) { var spilledBox = spilledBoxes[i]; spilledBox.speed = effectiveSpeed; // Remove spilled boxes that go off screen if (spilledBox.lastY <= 2732 + 50 && spilledBox.y > 2732 + 50) { spilledBox.destroy(); spilledBoxes.splice(i, 1); continue; } // Check collision with player var currentIntersecting = spilledBox.intersects(playerCar); if (!spilledBox.lastIntersecting && currentIntersecting) { if (hasShield) { // Shield protects from collision hasShield = false; shieldTimer = 0; shieldTxt.setText(''); playerCar.tint = 0xffffff; // Remove shield tint LK.effects.flashObject(playerCar, 0xffff00, 1000); // Yellow flash for shield break // Destroy the box spilledBox.destroy(); spilledBoxes.splice(i, 1); continue; } else { // Spilled box collision - game over saveScore(LK.getScore()); LK.getSound('crash').play(); LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } } spilledBox.lastY = spilledBox.y; spilledBox.lastIntersecting = currentIntersecting; } // Update and check power-ups for (var i = powerUps.length - 1; i >= 0; i--) { var powerUp = powerUps[i]; powerUp.speed = effectiveSpeed; // Remove power-ups that go off screen if (powerUp.lastY <= 2732 + 50 && powerUp.y > 2732 + 50) { powerUp.destroy(); powerUps.splice(i, 1); continue; } // Check collection by player var currentIntersecting = powerUp.intersects(playerCar); if (!powerUp.lastIntersecting && currentIntersecting) { // Power-up collected lastCollectTime = Date.now(); comboTimer = 300; // 5 seconds at 60fps if (powerUp.powerType === 0) { // Speed boost power-up hasSpeedBoost = true; speedBoostTimer = 600; // 10 seconds at 60fps LK.effects.flashObject(playerCar, 0x0099ff, 500); } else { // Shield power-up hasShield = true; shieldTimer = 900; // 15 seconds at 60fps playerCar.tint = 0x9900ff; // Purple tint for shield LK.effects.flashObject(playerCar, 0x9900ff, 500); } var pointsEarned = 20 * comboMultiplier; LK.setScore(LK.getScore() + pointsEarned); comboMultiplier = Math.min(comboMultiplier + 1, 5); // Max combo x5 scoreTxt.setText(LK.getScore().toString()); LK.getSound('collectCoin').play(); powerUp.destroy(); powerUps.splice(i, 1); continue; } powerUp.lastY = powerUp.y; powerUp.lastIntersecting = currentIntersecting; } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bush = Container.expand(function () {
var self = Container.call(this);
var bushGraphics = self.attachAsset('bush', {
anchorX: 0.5,
anchorY: 1.0
});
self.speed = 6;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Car = Container.expand(function () {
var self = Container.call(this);
var carGraphics = self.attachAsset('playerCar', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0;
self.targetX = 0;
self.lane = 1; // 0=left, 1=center, 2=right
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.lastY = 0;
self.lastIntersecting = false;
self.update = function () {
self.y += self.speed;
coinGraphics.rotation += 0.1;
};
return self;
});
var EnemyCar = Container.expand(function () {
var self = Container.call(this);
var carTypes = ['enemyCar1', 'enemyCar2', 'enemyCar3'];
var randomType = carTypes[Math.floor(Math.random() * carTypes.length)];
var carGraphics = self.attachAsset(randomType, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.lastY = 0;
self.lastIntersecting = false;
self.update = function () {
self.y += self.speed;
};
return self;
});
var FuelTank = Container.expand(function () {
var self = Container.call(this);
var fuelTankGraphics = self.attachAsset('fuelTank', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.lastY = 0;
self.lastIntersecting = false;
self.update = function () {
self.y += self.speed;
fuelTankGraphics.rotation += 0.05;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
// Random power-up type: 0=speed boost, 1=shield
self.powerType = Math.floor(Math.random() * 2);
var powerUpGraphics;
if (self.powerType === 0) {
// Speed boost power-up (blue)
powerUpGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
powerUpGraphics.tint = 0x0099ff; // Blue tint
} else {
// Shield power-up (purple)
powerUpGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
powerUpGraphics.tint = 0x9900ff; // Purple tint
}
self.speed = 6;
self.lastY = 0;
self.lastIntersecting = false;
self.update = function () {
self.y += self.speed;
powerUpGraphics.rotation += 0.15;
// Pulsing effect
powerUpGraphics.scaleX = 1 + Math.sin(LK.ticks * 0.2) * 0.3;
powerUpGraphics.scaleY = 1 + Math.sin(LK.ticks * 0.2) * 0.3;
};
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 = 6;
self.update = function () {
self.y += self.speed;
};
return self;
});
var SpilledBox = Container.expand(function () {
var self = Container.call(this);
var boxGraphics = self.attachAsset('spilledBox', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.lastY = 0;
self.lastIntersecting = false;
self.update = function () {
self.y += self.speed;
};
return self;
});
var SpilledFuel = Container.expand(function () {
var self = Container.call(this);
var spillGraphics = self.attachAsset('spilledFuel', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.lastY = 0;
self.lastIntersecting = false;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Tree = Container.expand(function () {
var self = Container.call(this);
var treeGraphics = self.attachAsset('tree', {
anchorX: 0.5,
anchorY: 1.0
});
self.speed = 6;
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
// Game variables
var game = new LK.Game({
backgroundColor: 0x2c3e50
});
/****
* Game Code
****/
// Game variables
var playerCar;
var enemyCars = [];
var coins = [];
var roadLines = [];
var trees = [];
var bushes = [];
var gameSpeed = 6;
var lanes = [2048 / 4, 2048 / 2, 3 * 2048 / 4]; // Three lanes
var spawnTimer = 0;
var coinSpawnTimer = 0;
var roadLineSpawnTimer = 0;
var treeSpawnTimer = 0;
var bushSpawnTimer = 0;
var distanceScore = 0;
var fuelTanks = [];
var fuelTankSpawnTimer = 0;
var currentFuel = 100;
var maxFuel = 100;
var fuelConsumptionRate = 0.1;
var dragActive = false;
var showingLeaderboard = false;
var leaderboardContainer;
var leaderboardScores = storage.leaderboard || [];
var gameStartTime = Date.now();
var gameTime = 0;
var spilledFuels = [];
var spilledFuelSpawnTimer = 0;
var spilledBoxes = [];
var spilledBoxSpawnTimer = 0;
var isSliding = false;
var slideDirection = 0;
var slideTimer = 0;
var powerUps = [];
var powerUpSpawnTimer = 0;
var hasShield = false;
var shieldTimer = 0;
var speedBoostTimer = 0;
var hasSpeedBoost = false;
var comboMultiplier = 1;
var comboTimer = 0;
var lastCollectTime = 0;
// Create score display using asset
var scoreDisplay = LK.getAsset('Score', {
anchorX: 0.5,
anchorY: 0
});
LK.gui.top.addChild(scoreDisplay);
// Create score text display
var scoreTxt = new Text2('0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = scoreDisplay.x + 60; // Position next to score image
scoreTxt.y = scoreDisplay.y;
LK.gui.top.addChild(scoreTxt);
// Create score button to show/hide score
var scoreButton = new Text2('📊', {
size: 80,
fill: 0x00FF00
});
scoreButton.anchor.set(0.5, 0);
scoreButton.x = 2048 - 200;
scoreButton.y = 20;
LK.gui.top.addChild(scoreButton);
// Create leaderboard button
var leaderboardButton = new Text2('🏆', {
size: 80,
fill: 0xFFD700
});
leaderboardButton.anchor.set(0.5, 0);
leaderboardButton.x = 2048 - 100;
leaderboardButton.y = 20;
LK.gui.top.addChild(leaderboardButton);
// Score visibility state
var showScore = true;
// Create distance display
var distanceTxt = new Text2('Distance: 0m', {
size: 60,
fill: 0xFFFFFF
});
distanceTxt.anchor.set(0.5, 0);
distanceTxt.y = 100;
LK.gui.top.addChild(distanceTxt);
// Create speedometer display
var speedometerTxt = new Text2('Speed: 0 km/h', {
size: 60,
fill: 0xFFFFFF
});
speedometerTxt.anchor.set(0.5, 0);
speedometerTxt.y = 170;
LK.gui.top.addChild(speedometerTxt);
// Create fuel display
var fuelTxt = new Text2('Fuel: 100%', {
size: 60,
fill: 0x00FF00
});
fuelTxt.anchor.set(0.5, 0);
fuelTxt.y = 240;
LK.gui.top.addChild(fuelTxt);
// Create time display
var timeTxt = new Text2('Time: 0:00', {
size: 60,
fill: 0xFFFFFF
});
timeTxt.anchor.set(0.5, 0);
timeTxt.y = 310;
LK.gui.top.addChild(timeTxt);
// Create shield indicator
var shieldTxt = new Text2('', {
size: 60,
fill: 0x9900ff
});
shieldTxt.anchor.set(0.5, 0);
shieldTxt.y = 380;
LK.gui.top.addChild(shieldTxt);
// Create speed boost indicator
var speedBoostTxt = new Text2('', {
size: 60,
fill: 0x0099ff
});
speedBoostTxt.anchor.set(0.5, 0);
speedBoostTxt.y = 450;
LK.gui.top.addChild(speedBoostTxt);
// Create combo multiplier display
var comboTxt = new Text2('', {
size: 70,
fill: 0xFFD700
});
comboTxt.anchor.set(0.5, 0);
comboTxt.y = 520;
LK.gui.top.addChild(comboTxt);
// Create left arrow button
var leftArrow = LK.getAsset('Oktusu', {
width: 300,
height: 300,
anchorX: 0.5,
anchorY: 0.5
});
leftArrow.x = 200;
leftArrow.y = 2732 - 200;
game.addChild(leftArrow);
// Create left arrow text
var leftArrowTxt = new Text2('←', {
size: 80,
fill: 0xFFFFFF
});
leftArrowTxt.anchor.set(0.5, 0.5);
leftArrowTxt.x = leftArrow.x;
leftArrowTxt.y = leftArrow.y;
game.addChild(leftArrowTxt);
// Create right arrow button
var rightArrow = LK.getAsset('Oktusu', {
width: 300,
height: 300,
anchorX: 0.5,
anchorY: 0.5
});
rightArrow.x = 2048 - 200;
rightArrow.y = 2732 - 200;
game.addChild(rightArrow);
// Create right arrow text
var rightArrowTxt = new Text2('→', {
size: 80,
fill: 0xFFFFFF
});
rightArrowTxt.anchor.set(0.5, 0.5);
rightArrowTxt.x = rightArrow.x;
rightArrowTxt.y = rightArrow.y;
game.addChild(rightArrowTxt);
// Gas pedal variables (keeping for boost system)
var isGasPedalPressed = false;
var boostMultiplier = 1.0;
// Function to show leaderboard
function showLeaderboard() {
if (showingLeaderboard) return;
showingLeaderboard = true;
leaderboardContainer = new Container();
game.addChild(leaderboardContainer);
// Semi-transparent background
var background = LK.getAsset('highway', {
width: 1800,
height: 2200,
anchorX: 0.5,
anchorY: 0.5
});
background.x = 2048 / 2;
background.y = 2732 / 2;
background.alpha = 0.8;
background.tint = 0x000000;
leaderboardContainer.addChild(background);
// Title
var titleText = new Text2('🏆 TOP SCORES 🏆', {
size: 100,
fill: 0xFFD700
});
titleText.anchor.set(0.5, 0);
titleText.x = 2048 / 2;
titleText.y = 400;
leaderboardContainer.addChild(titleText);
// Display top 10 scores
var sortedScores = leaderboardScores.slice().sort(function (a, b) {
return b - a;
});
for (var i = 0; i < Math.min(10, sortedScores.length); i++) {
var rankText = new Text2(i + 1 + '. ' + sortedScores[i] + ' points', {
size: 80,
fill: i < 3 ? 0xFFD700 : 0xFFFFFF
});
rankText.anchor.set(0.5, 0);
rankText.x = 2048 / 2;
rankText.y = 600 + i * 120;
leaderboardContainer.addChild(rankText);
}
// Close button
var closeButton = new Text2('❌ CLOSE', {
size: 80,
fill: 0xFF4444
});
closeButton.anchor.set(0.5, 0);
closeButton.x = 2048 / 2;
closeButton.y = 2200;
leaderboardContainer.addChild(closeButton);
}
// Function to hide leaderboard
function hideLeaderboard() {
if (!showingLeaderboard) return;
showingLeaderboard = false;
if (leaderboardContainer) {
leaderboardContainer.destroy();
leaderboardContainer = null;
}
}
// Function to save score to leaderboard
function saveScore(score) {
leaderboardScores.push(score);
leaderboardScores.sort(function (a, b) {
return b - a;
});
// Keep only top 20 scores
if (leaderboardScores.length > 20) {
leaderboardScores = leaderboardScores.slice(0, 20);
}
storage.leaderboard = leaderboardScores;
}
// Create player car
playerCar = game.addChild(new Car());
playerCar.x = lanes[1]; // Start in middle lane
playerCar.y = 2732 - 300;
playerCar.targetX = playerCar.x;
// Touch controls
game.down = function (x, y, obj) {
// Check if leaderboard is showing and handle close button
if (showingLeaderboard) {
var closeButtonBounds = {
left: 2048 / 2 - 150,
right: 2048 / 2 + 150,
top: 2200 - 50,
bottom: 2200 + 50
};
if (x >= closeButtonBounds.left && x <= closeButtonBounds.right && y >= closeButtonBounds.top && y <= closeButtonBounds.bottom) {
hideLeaderboard();
return;
}
// Ignore other touches when leaderboard is showing
return;
}
// Check if score button is pressed
var scoreBounds = {
left: scoreButton.x - 50,
right: scoreButton.x + 50,
top: scoreButton.y,
bottom: scoreButton.y + 80
};
if (x >= scoreBounds.left && x <= scoreBounds.right && y >= scoreBounds.top && y <= scoreBounds.bottom) {
showScore = !showScore;
if (showScore) {
scoreDisplay.alpha = 1;
scoreTxt.alpha = 1;
} else {
scoreDisplay.alpha = 0;
scoreTxt.alpha = 0;
}
return;
}
// Check if leaderboard button is pressed
var leaderboardBounds = {
left: leaderboardButton.x - 50,
right: leaderboardButton.x + 50,
top: leaderboardButton.y,
bottom: leaderboardButton.y + 80
};
if (x >= leaderboardBounds.left && x <= leaderboardBounds.right && y >= leaderboardBounds.top && y <= leaderboardBounds.bottom) {
showLeaderboard();
return;
}
// Check if left arrow is pressed
var leftArrowBounds = {
left: leftArrow.x - 150,
right: leftArrow.x + 150,
top: leftArrow.y - 150,
bottom: leftArrow.y + 150
};
if (x >= leftArrowBounds.left && x <= leftArrowBounds.right && y >= leftArrowBounds.top && y <= leftArrowBounds.bottom) {
// Move car to left lane
if (playerCar.lane > 0) {
playerCar.lane--;
playerCar.targetX = lanes[playerCar.lane];
}
leftArrow.tint = 0xffff00; // Yellow when pressed
}
// Check if right arrow is pressed
var rightArrowBounds = {
left: rightArrow.x - 150,
right: rightArrow.x + 150,
top: rightArrow.y - 150,
bottom: rightArrow.y + 150
};
if (x >= rightArrowBounds.left && x <= rightArrowBounds.right && y >= rightArrowBounds.top && y <= rightArrowBounds.bottom) {
// Move car to right lane
if (playerCar.lane < 2) {
playerCar.lane++;
playerCar.targetX = lanes[playerCar.lane];
}
rightArrow.tint = 0xffff00; // Yellow when pressed
}
};
game.move = function (x, y, obj) {
// Don't allow movement when leaderboard is showing
if (showingLeaderboard) return;
var leftArrowBounds = {
left: leftArrow.x - 150,
right: leftArrow.x + 150,
top: leftArrow.y - 150,
bottom: leftArrow.y + 150
};
var rightArrowBounds = {
left: rightArrow.x - 150,
right: rightArrow.x + 150,
top: rightArrow.y - 150,
bottom: rightArrow.y + 150
};
};
game.up = function (x, y, obj) {
// Don't process touches when leaderboard is showing
if (showingLeaderboard) return;
// Reset arrow button colors
leftArrow.tint = 0xffffff;
rightArrow.tint = 0xffffff;
};
// Main game loop
game.update = function () {
// Don't update game when leaderboard is showing
if (showingLeaderboard) return;
// Update game time
gameTime = Math.floor((Date.now() - gameStartTime) / 1000);
var minutes = Math.floor(gameTime / 60);
var seconds = gameTime % 60;
var timeString = minutes + ':' + (seconds < 10 ? '0' : '') + seconds;
timeTxt.setText('Time: ' + timeString);
// Update power-up timers
if (hasShield) {
shieldTimer--;
shieldTxt.setText('🛡️ Shield: ' + Math.ceil(shieldTimer / 60) + 's');
if (shieldTimer <= 0) {
hasShield = false;
shieldTxt.setText('');
// Remove shield visual effect
playerCar.tint = 0xffffff;
}
} else {
shieldTxt.setText('');
}
if (hasSpeedBoost) {
speedBoostTimer--;
speedBoostTxt.setText('⚡ Boost: ' + Math.ceil(speedBoostTimer / 60) + 's');
if (speedBoostTimer <= 0) {
hasSpeedBoost = false;
speedBoostTxt.setText('');
}
} else {
speedBoostTxt.setText('');
}
// Update combo system
if (comboTimer > 0) {
comboTimer--;
comboTxt.setText('Combo x' + comboMultiplier);
if (comboTimer <= 0) {
comboMultiplier = 1;
comboTxt.setText('');
}
} else {
comboTxt.setText('');
}
// Reset combo if too much time passed since last collect
if (Date.now() - lastCollectTime > 3000) {
comboMultiplier = 1;
comboTimer = 0;
}
// Handle sliding mechanics
if (isSliding) {
slideTimer--;
// Apply sliding movement with tween for smooth effect
var slideAmount = slideDirection * 8;
playerCar.x += slideAmount;
// Constrain car to stay within road bounds
playerCar.x = Math.max(lanes[0] - 100, Math.min(lanes[2] + 100, playerCar.x));
// Add visual sliding effect
tween(playerCar, {
rotation: slideDirection * 0.3
}, {
duration: 100,
easing: tween.easeOut
});
if (slideTimer <= 0) {
isSliding = false;
slideDirection = 0;
// Return car to normal rotation
tween(playerCar, {
rotation: 0
}, {
duration: 500,
easing: tween.easeOut
});
// Snap back to nearest lane
var closestLane = 1;
var minDistance = Math.abs(playerCar.x - lanes[1]);
for (var i = 0; i < lanes.length; i++) {
var distance = Math.abs(playerCar.x - lanes[i]);
if (distance < minDistance) {
minDistance = distance;
closestLane = i;
}
}
playerCar.lane = closestLane;
playerCar.targetX = lanes[closestLane];
}
} else {
// Normal smooth car movement to target lane
var moveSpeed = 15;
if (Math.abs(playerCar.x - playerCar.targetX) > moveSpeed) {
if (playerCar.x < playerCar.targetX) {
playerCar.x += moveSpeed;
} else {
playerCar.x -= moveSpeed;
}
} else {
playerCar.x = playerCar.targetX;
}
}
// Increase game speed over time
gameSpeed += 0.002;
// Player car accelerates 3 units per second (3/60 = 0.05 per frame at 60fps)
playerCar.speed += 0.05;
// Calculate base boost from speed boost power-up only
var targetBoost = 1.0;
if (hasSpeedBoost) {
targetBoost *= 1.5; // Additional 50% speed from power-up
}
// Apply boost with smooth transition
if (boostMultiplier < targetBoost) {
// Smoothly increase speed
tween(this, {
boostMultiplier: targetBoost
}, {
duration: 1000,
easing: tween.easeOut
});
} else if (boostMultiplier > targetBoost) {
// Smoothly decrease speed
tween(this, {
boostMultiplier: targetBoost
}, {
duration: 500,
easing: tween.easeOut
});
}
// Limit effective speed to prevent exceeding 150 km/h
var maxEffectiveSpeed = 15; // 15 * 10 = 150 km/h display limit
var effectiveSpeed = Math.min(gameSpeed * boostMultiplier, maxEffectiveSpeed);
var speedLimitRatio = effectiveSpeed / (gameSpeed * boostMultiplier);
// Update distance score
distanceScore += effectiveSpeed * 0.1;
distanceTxt.setText('Distance: ' + Math.floor(distanceScore) + 'm');
// Update speedometer display
var currentSpeed = Math.floor(gameSpeed * boostMultiplier * 10); // Convert to km/h scale
// Limit maximum displayed speed to 150 km/h
currentSpeed = Math.min(currentSpeed, 150);
speedometerTxt.setText('Speed: ' + currentSpeed + ' km/h');
// Spawn road lines
roadLineSpawnTimer++;
if (roadLineSpawnTimer >= 20) {
roadLineSpawnTimer = 0;
for (var i = 0; i < 2; i++) {
var roadLine = new RoadLine();
roadLine.x = lanes[0] + i * (lanes[2] - lanes[0]);
roadLine.y = -50;
roadLine.speed = effectiveSpeed;
roadLines.push(roadLine);
game.addChild(roadLine);
}
}
// Spawn enemy cars
spawnTimer++;
// Increase spawn rate based on score and distance
var spawnRateBonus = Math.floor(LK.getScore() / 100) + Math.floor(distanceScore / 1000);
var baseSpawnRate = Math.max(20, 90 - Math.floor(gameSpeed) - spawnRateBonus);
if (spawnTimer >= baseSpawnRate) {
spawnTimer = 0;
var enemyCar = new EnemyCar();
var randomLane = Math.floor(Math.random() * 3);
enemyCar.x = lanes[randomLane];
enemyCar.y = -100;
enemyCar.speed = (gameSpeed + Math.random() * 3) * boostMultiplier;
enemyCar.lastY = enemyCar.y;
enemyCar.lastIntersecting = enemyCar.intersects(playerCar);
enemyCars.push(enemyCar);
game.addChild(enemyCar);
}
// Spawn trees
treeSpawnTimer++;
if (treeSpawnTimer >= 60) {
treeSpawnTimer = 0;
// Spawn trees on left side
if (Math.random() < 0.8) {
var leftTree = new Tree();
leftTree.x = Math.random() * (lanes[0] - 100); // Random position on left side
leftTree.y = -100;
leftTree.speed = effectiveSpeed;
trees.push(leftTree);
game.addChild(leftTree);
}
// Spawn trees on right side
if (Math.random() < 0.8) {
var rightTree = new Tree();
rightTree.x = lanes[2] + 100 + Math.random() * (2048 - lanes[2] - 200); // Random position on right side
rightTree.y = -100;
rightTree.speed = effectiveSpeed;
trees.push(rightTree);
game.addChild(rightTree);
}
}
// Spawn bushes
bushSpawnTimer++;
if (bushSpawnTimer >= 40) {
bushSpawnTimer = 0;
// Spawn bushes on left side between trees
if (Math.random() < 0.6) {
var leftBush = new Bush();
leftBush.x = Math.random() * (lanes[0] - 50); // Random position on left side
leftBush.y = -50;
leftBush.speed = effectiveSpeed;
bushes.push(leftBush);
game.addChild(leftBush);
}
// Spawn bushes on right side between trees
if (Math.random() < 0.6) {
var rightBush = new Bush();
rightBush.x = lanes[2] + 50 + Math.random() * (2048 - lanes[2] - 150); // Random position on right side
rightBush.y = -50;
rightBush.speed = effectiveSpeed;
bushes.push(rightBush);
game.addChild(rightBush);
}
}
// Spawn coins
coinSpawnTimer++;
if (coinSpawnTimer >= 120) {
coinSpawnTimer = 0;
if (Math.random() < 0.7) {
var coin = new Coin();
var randomLane = Math.floor(Math.random() * 3);
coin.x = lanes[randomLane];
coin.y = -50;
coin.speed = effectiveSpeed;
coin.lastY = coin.y;
coin.lastIntersecting = coin.intersects(playerCar);
coins.push(coin);
game.addChild(coin);
}
}
// Spawn fuel tanks
fuelTankSpawnTimer++;
if (fuelTankSpawnTimer >= 150) {
fuelTankSpawnTimer = 0;
if (Math.random() < 0.7) {
var fuelTank = new FuelTank();
var randomLane = Math.floor(Math.random() * 3);
fuelTank.x = lanes[randomLane];
fuelTank.y = -50;
fuelTank.speed = effectiveSpeed;
fuelTank.lastY = fuelTank.y;
fuelTank.lastIntersecting = fuelTank.intersects(playerCar);
fuelTanks.push(fuelTank);
game.addChild(fuelTank);
}
}
// Spawn spilled fuel
spilledFuelSpawnTimer++;
if (spilledFuelSpawnTimer >= 200) {
spilledFuelSpawnTimer = 0;
if (Math.random() < 0.4) {
var spilledFuel = new SpilledFuel();
var randomLane = Math.floor(Math.random() * 3);
spilledFuel.x = lanes[randomLane];
spilledFuel.y = -50;
spilledFuel.speed = effectiveSpeed;
spilledFuel.lastY = spilledFuel.y;
spilledFuel.lastIntersecting = spilledFuel.intersects(playerCar);
spilledFuels.push(spilledFuel);
game.addChild(spilledFuel);
}
}
// Spawn spilled boxes
spilledBoxSpawnTimer++;
if (spilledBoxSpawnTimer >= 180) {
spilledBoxSpawnTimer = 0;
if (Math.random() < 0.5) {
var spilledBox = new SpilledBox();
var randomLane = Math.floor(Math.random() * 3);
spilledBox.x = lanes[randomLane];
spilledBox.y = -50;
spilledBox.speed = effectiveSpeed;
spilledBox.lastY = spilledBox.y;
spilledBox.lastIntersecting = spilledBox.intersects(playerCar);
spilledBoxes.push(spilledBox);
game.addChild(spilledBox);
}
}
// Spawn power-ups
powerUpSpawnTimer++;
if (powerUpSpawnTimer >= 300) {
powerUpSpawnTimer = 0;
if (Math.random() < 0.6) {
var powerUp = new PowerUp();
var randomLane = Math.floor(Math.random() * 3);
powerUp.x = lanes[randomLane];
powerUp.y = -50;
powerUp.speed = effectiveSpeed;
powerUp.lastY = powerUp.y;
powerUp.lastIntersecting = powerUp.intersects(playerCar);
powerUps.push(powerUp);
game.addChild(powerUp);
}
}
// Update and check road lines
for (var i = roadLines.length - 1; i >= 0; i--) {
var roadLine = roadLines[i];
roadLine.speed = effectiveSpeed;
if (roadLine.lastY === undefined) roadLine.lastY = roadLine.y;
// Remove road lines that go off screen
if (roadLine.lastY <= 2732 + 50 && roadLine.y > 2732 + 50) {
roadLine.destroy();
roadLines.splice(i, 1);
continue;
}
roadLine.lastY = roadLine.y;
}
// Update and check enemy cars
for (var i = enemyCars.length - 1; i >= 0; i--) {
var enemyCar = enemyCars[i];
// Increase enemy speed based on score and distance
var speedBonus = Math.floor(LK.getScore() / 50) + Math.floor(distanceScore / 500);
var enemyBaseSpeed = (gameSpeed + 2 + speedBonus) * boostMultiplier;
enemyCar.speed = Math.min(enemyBaseSpeed, maxEffectiveSpeed + 2);
// Remove cars that go off screen
if (enemyCar.lastY <= 2732 + 100 && enemyCar.y > 2732 + 100) {
enemyCar.destroy();
enemyCars.splice(i, 1);
continue;
}
// Check collision with player
var currentIntersecting = enemyCar.intersects(playerCar);
if (!enemyCar.lastIntersecting && currentIntersecting) {
if (hasShield) {
// Shield protects from collision
hasShield = false;
shieldTimer = 0;
shieldTxt.setText('');
playerCar.tint = 0xffffff; // Remove shield tint
LK.effects.flashObject(playerCar, 0xffff00, 1000); // Yellow flash for shield break
LK.effects.flashObject(enemyCar, 0xffff00, 500);
// Push enemy car away
enemyCar.y += 200;
} else {
// Collision detected - game over
saveScore(LK.getScore());
LK.getSound('crash').play();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
enemyCar.lastY = enemyCar.y;
enemyCar.lastIntersecting = currentIntersecting;
}
// Update and check trees
for (var i = trees.length - 1; i >= 0; i--) {
var tree = trees[i];
tree.speed = effectiveSpeed;
if (tree.lastY === undefined) tree.lastY = tree.y;
// Remove trees that go off screen
if (tree.lastY <= 2732 + 100 && tree.y > 2732 + 100) {
tree.destroy();
trees.splice(i, 1);
continue;
}
tree.lastY = tree.y;
}
// Update and check bushes
for (var i = bushes.length - 1; i >= 0; i--) {
var bush = bushes[i];
bush.speed = effectiveSpeed;
if (bush.lastY === undefined) bush.lastY = bush.y;
// Remove bushes that go off screen
if (bush.lastY <= 2732 + 50 && bush.y > 2732 + 50) {
bush.destroy();
bushes.splice(i, 1);
continue;
}
bush.lastY = bush.y;
}
// Update and check coins
for (var i = coins.length - 1; i >= 0; i--) {
var coin = coins[i];
coin.speed = effectiveSpeed;
// Remove coins that go off screen
if (coin.lastY <= 2732 + 50 && coin.y > 2732 + 50) {
coin.destroy();
coins.splice(i, 1);
continue;
}
// Check collection by player
var currentIntersecting = coin.intersects(playerCar);
if (!coin.lastIntersecting && currentIntersecting) {
// Coin collected
lastCollectTime = Date.now();
comboTimer = 300; // 5 seconds at 60fps
var pointsEarned = 10 * comboMultiplier;
LK.setScore(LK.getScore() + pointsEarned);
comboMultiplier = Math.min(comboMultiplier + 1, 5); // Max combo x5
scoreTxt.setText(LK.getScore().toString());
LK.getSound('collectCoin').play();
coin.destroy();
coins.splice(i, 1);
continue;
}
coin.lastY = coin.y;
coin.lastIntersecting = currentIntersecting;
}
// Update fuel system
currentFuel -= fuelConsumptionRate * boostMultiplier;
if (currentFuel <= 0) {
currentFuel = 0;
// Game over due to no fuel
saveScore(LK.getScore());
LK.effects.flashScreen(0xff8800, 1000);
LK.showGameOver();
return;
}
// Update fuel display with color coding
var fuelPercentage = Math.floor(currentFuel / maxFuel * 100);
fuelTxt.setText('Fuel: ' + fuelPercentage + '%');
if (fuelPercentage > 50) {
fuelTxt.fill = 0x00FF00; // Green
} else if (fuelPercentage > 25) {
fuelTxt.fill = 0xFFFF00; // Yellow
} else {
fuelTxt.fill = 0xFF0000; // Red
}
// Update and check fuel tanks
for (var i = fuelTanks.length - 1; i >= 0; i--) {
var fuelTank = fuelTanks[i];
fuelTank.speed = effectiveSpeed;
// Remove fuel tanks that go off screen
if (fuelTank.lastY <= 2732 + 50 && fuelTank.y > 2732 + 50) {
fuelTank.destroy();
fuelTanks.splice(i, 1);
continue;
}
// Check collection by player
var currentIntersecting = fuelTank.intersects(playerCar);
if (!fuelTank.lastIntersecting && currentIntersecting) {
// Fuel tank collected
lastCollectTime = Date.now();
comboTimer = 300; // 5 seconds at 60fps
currentFuel = Math.min(currentFuel + 30, maxFuel);
var pointsEarned = 5 * comboMultiplier;
LK.setScore(LK.getScore() + pointsEarned);
comboMultiplier = Math.min(comboMultiplier + 1, 5); // Max combo x5
scoreTxt.setText(LK.getScore().toString());
LK.getSound('collectCoin').play();
fuelTank.destroy();
fuelTanks.splice(i, 1);
continue;
}
fuelTank.lastY = fuelTank.y;
fuelTank.lastIntersecting = currentIntersecting;
}
// Update and check spilled fuel
for (var i = spilledFuels.length - 1; i >= 0; i--) {
var spilledFuel = spilledFuels[i];
spilledFuel.speed = effectiveSpeed;
// Remove spilled fuel that goes off screen
if (spilledFuel.lastY <= 2732 + 50 && spilledFuel.y > 2732 + 50) {
spilledFuel.destroy();
spilledFuels.splice(i, 1);
continue;
}
// Check collision with player
var currentIntersecting = spilledFuel.intersects(playerCar);
if (!spilledFuel.lastIntersecting && currentIntersecting && !isSliding) {
// Spilled fuel collision - make car slide
isSliding = true;
slideDirection = (Math.random() - 0.5) * 2; // Random slide direction
slideTimer = 90; // Slide for 1.5 seconds at 60fps
// Visual effect for hitting spilled fuel
LK.effects.flashObject(playerCar, 0x8B4513, 500);
// Add spinning rotation effect
tween(playerCar, {
rotation: playerCar.rotation + Math.PI * 4 // Spin 2 full rotations
}, {
duration: 1500,
easing: tween.easeOut
});
}
spilledFuel.lastY = spilledFuel.y;
spilledFuel.lastIntersecting = currentIntersecting;
}
// Update and check spilled boxes
for (var i = spilledBoxes.length - 1; i >= 0; i--) {
var spilledBox = spilledBoxes[i];
spilledBox.speed = effectiveSpeed;
// Remove spilled boxes that go off screen
if (spilledBox.lastY <= 2732 + 50 && spilledBox.y > 2732 + 50) {
spilledBox.destroy();
spilledBoxes.splice(i, 1);
continue;
}
// Check collision with player
var currentIntersecting = spilledBox.intersects(playerCar);
if (!spilledBox.lastIntersecting && currentIntersecting) {
if (hasShield) {
// Shield protects from collision
hasShield = false;
shieldTimer = 0;
shieldTxt.setText('');
playerCar.tint = 0xffffff; // Remove shield tint
LK.effects.flashObject(playerCar, 0xffff00, 1000); // Yellow flash for shield break
// Destroy the box
spilledBox.destroy();
spilledBoxes.splice(i, 1);
continue;
} else {
// Spilled box collision - game over
saveScore(LK.getScore());
LK.getSound('crash').play();
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
spilledBox.lastY = spilledBox.y;
spilledBox.lastIntersecting = currentIntersecting;
}
// Update and check power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
powerUp.speed = effectiveSpeed;
// Remove power-ups that go off screen
if (powerUp.lastY <= 2732 + 50 && powerUp.y > 2732 + 50) {
powerUp.destroy();
powerUps.splice(i, 1);
continue;
}
// Check collection by player
var currentIntersecting = powerUp.intersects(playerCar);
if (!powerUp.lastIntersecting && currentIntersecting) {
// Power-up collected
lastCollectTime = Date.now();
comboTimer = 300; // 5 seconds at 60fps
if (powerUp.powerType === 0) {
// Speed boost power-up
hasSpeedBoost = true;
speedBoostTimer = 600; // 10 seconds at 60fps
LK.effects.flashObject(playerCar, 0x0099ff, 500);
} else {
// Shield power-up
hasShield = true;
shieldTimer = 900; // 15 seconds at 60fps
playerCar.tint = 0x9900ff; // Purple tint for shield
LK.effects.flashObject(playerCar, 0x9900ff, 500);
}
var pointsEarned = 20 * comboMultiplier;
LK.setScore(LK.getScore() + pointsEarned);
comboMultiplier = Math.min(comboMultiplier + 1, 5); // Max combo x5
scoreTxt.setText(LK.getScore().toString());
LK.getSound('collectCoin').play();
powerUp.destroy();
powerUps.splice(i, 1);
continue;
}
powerUp.lastY = powerUp.y;
powerUp.lastIntersecting = currentIntersecting;
}
};
Coin. In-Game asset. 2d. High contrast. No shadows
Yol hattı. In-Game asset. 2d. High contrast. No shadows
Score. In-Game asset. 2d. High contrast. No shadows
Şehir. In-Game asset. 2d. High contrast. No shadows
Gaz pedalı. In-Game asset. 2d. High contrast. No shadows
Sağ sola hareket oktuşuşlar. In-Game asset. 2d. High contrast. No shadows
Kuş bakışı ağaç. In-Game asset. 2d. High contrast. No shadows
Çalı. In-Game asset. 2d. High contrast. No shadows
Benzin kutusu. In-Game asset. 2d. High contrast. No shadows
Dökülmüş benzin. In-Game asset. 2d. High contrast. No shadows
Yola koyulmuş kutular. In-Game asset. 2d. High contrast. No shadows
Kuş bakışı Ferrari araba. In-Game asset. 2d. High contrast. No shadows
Kuş bakışı Lamborghini. In-Game asset. 2d. High contrast. No shadows
Kuş bakışı kosiegg. In-Game asset. 2d. High contrast. No shadows
Bugatti kuş bakışı. In-Game asset. 2d. High contrast. No shadows