User prompt
Araçların üzerinde altın belirmesine izin verme
User prompt
Polis araçları arası mesafeyi yükselt
User prompt
Araçları biraz büyüült
User prompt
Polis ışıkları olması gereken yerde degil
User prompt
Polis ışıkları ve efektleri polis aracını üzerine yapışturın ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Araçlar biraz büyütülsün fakat oyuncu engellerin arasından rahat geçebilmeli ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Yandaki yeşil alanladı daraltarak yolu araçları ve şerit çizgilerini aynı oranda genişletin
User prompt
Şerit kısa çizgileri aracın üzerinde gözükmemeli
User prompt
Şerit çizgilerini genişlet ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Olmadı
User prompt
Yol şerit çizgisini yol arka planıyla eşitle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Yol cizfilerini ayarla ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Sag ve sol alandaki yeşil alanları daralt yol büyüsün ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Yolu ve araçları biraz daha genişlet ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Yolu ve araçları biraz daha genişlet ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Yolu ve araçları büyült ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Geceleri araç farlarına ısık parçacıkları ekle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Oyuncu araç farı en öne taşı
User prompt
Altınların engel üzerinde oluşmasına izin verme
User prompt
Oyun çöktü
User prompt
Altın ve gun engel üzeründe beliriyor
User prompt
Rüzgar efektini daha belirgin yap ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Oyuncu arabasına rüzgar efeckti ekle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Ormanlık alan için kare bir varlık oluştur
User prompt
Yan taraftaki yeşil alanı degiştirmek için varlık oluştur
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -25; self.update = function () { self.y += self.speed; }; return self; }); var Bush = Container.expand(function () { var self = Container.call(this); var bushGraphics = self.attachAsset('bush', { anchorX: 0.5, anchorY: 1.0 }); self.speed = gameSpeed; self.update = function () { self.y += self.speed; }; 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 = gameSpeed; self.collected = false; self.update = function () { self.y += self.speed; self.rotation += 0.1; }; return self; }); var DebrisParticle = Container.expand(function () { var self = Container.call(this); var debrisGraphics = self.attachAsset('debrisParticle', { anchorX: 0.5, anchorY: 0.5 }); self.speedX = (Math.random() - 0.5) * 20; // Random horizontal speed self.speedY = -5 - Math.random() * 15; // Upward initial speed self.gravity = 0.8; // Gravity acceleration self.lifetime = 90 + Math.random() * 60; // 1.5-2.5 seconds self.maxLifetime = self.lifetime; self.rotationSpeed = (Math.random() - 0.5) * 0.3; // Random colors for debris (metal, glass, etc.) var debrisColors = [0x666666, 0x888888, 0x444444, 0x999999, 0x333333]; debrisGraphics.tint = debrisColors[Math.floor(Math.random() * debrisColors.length)]; self.update = function () { // Apply physics self.x += self.speedX; self.y += self.speedY; self.speedY += self.gravity; // Apply gravity self.rotation += self.rotationSpeed; self.lifetime--; // Fade out over time var fadeProgress = 1 - self.lifetime / self.maxLifetime; self.alpha = Math.max(0, 1 - fadeProgress * 1.5); }; return self; }); var ExhaustParticle = Container.expand(function () { var self = Container.call(this); var particleGraphics = self.attachAsset('exhaustParticle', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3 + Math.random() * 2; self.sideSpeed = (Math.random() - 0.5) * 2; self.lifetime = 60 + Math.random() * 30; self.maxLifetime = self.lifetime; self.update = function () { self.y += self.speed; self.x += self.sideSpeed; self.lifetime--; // Fade out and scale up over time var fadeProgress = 1 - self.lifetime / self.maxLifetime; self.alpha = Math.max(0, 1 - fadeProgress * 1.5); self.scaleX = 1 + fadeProgress * 0.8; self.scaleY = 1 + fadeProgress * 0.8; }; return self; }); var Flame = Container.expand(function () { var self = Container.call(this); var flameGraphics = self.attachAsset('flame', { anchorX: 0.5, anchorY: 1.0 }); self.speed = -2 - Math.random() * 3; self.sideSpeed = (Math.random() - 0.5) * 4; self.lifetime = 30 + Math.random() * 20; self.maxLifetime = self.lifetime; self.flickerTimer = 0; self.parentCar = null; // Reference to the police car this flame belongs to self.offsetX = 0; // Offset from car position self.offsetY = 0; // Offset from car position self.update = function () { // If attached to a police car, follow its position if (self.parentCar && !self.parentCar.isDestroyed) { self.x = self.parentCar.x + self.offsetX; self.y = self.parentCar.y + self.offsetY; } self.lifetime--; // Flicker effect self.flickerTimer++; if (self.flickerTimer % 3 === 0) { var colors = [0xff4500, 0xff6600, 0xff8800, 0xffaa00]; flameGraphics.tint = colors[Math.floor(Math.random() * colors.length)]; } // Fade and scale over time var fadeProgress = 1 - self.lifetime / self.maxLifetime; self.alpha = Math.max(0, 1 - fadeProgress * 1.2); self.scaleX = 1.5 + fadeProgress * 1.2; // Increased base size from 0.5 to 1.5 self.scaleY = 2.0 + fadeProgress * 2.0; // Increased base size from 0.8 to 2.0 }; return self; }); var Flower = Container.expand(function () { var self = Container.call(this); var flowerGraphics = self.attachAsset('flower', { anchorX: 0.5, anchorY: 1.0 }); self.speed = gameSpeed; self.swayTimer = Math.random() * 100; self.originalX = 0; self.update = function () { self.y += self.speed; // Add gentle swaying motion self.swayTimer += 0.1; if (self.originalX === 0) self.originalX = self.x; self.x = self.originalX + Math.sin(self.swayTimer) * 5; }; return self; }); var LaneLine = Container.expand(function () { var self = Container.call(this); var lineGraphics = self.attachAsset('laneLine', { anchorX: 0.5, anchorY: 0.5 }); self.speed = gameSpeed; self.update = function () { self.y += self.speed; }; return self; }); var Obstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphics = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 1.0 }); self.speed = gameSpeed; // Add police lights to the obstacle (police car) var leftLight = self.attachAsset('policeLight', { anchorX: 0.5, anchorY: 0.5 }); leftLight.x = -30; leftLight.y = -60; var rightLight = self.attachAsset('policeLight', { anchorX: 0.5, anchorY: 0.5 }); rightLight.x = 30; rightLight.y = -60; rightLight.tint = 0x0000ff; // Make right light blue // Add side lights var leftSideLight = self.attachAsset('policeLight', { anchorX: 0.5, anchorY: 0.5 }); leftSideLight.x = -45; leftSideLight.y = -30; var rightSideLight = self.attachAsset('policeLight', { anchorX: 0.5, anchorY: 0.5 }); rightSideLight.x = 45; rightSideLight.y = -30; rightSideLight.tint = 0x0000ff; // Make right side light blue // Add top lights var topLeftLight = self.attachAsset('policeLight', { anchorX: 0.5, anchorY: 0.5 }); topLeftLight.x = -15; topLeftLight.y = -80; var topRightLight = self.attachAsset('policeLight', { anchorX: 0.5, anchorY: 0.5 }); topRightLight.x = 15; topRightLight.y = -80; topRightLight.tint = 0x0000ff; // Make top right light blue self.lightTimer = 0; self.isRedActive = true; // Lane changing properties self.canChangeLanes = false; self.laneChangeTimer = 0; self.laneChangeDelay = 180 + Math.random() * 240; // 3-7 seconds random delay self.targetLaneIndex = Math.floor(Math.random() * 3); // Random target lane self.isChangingLanes = false; self.originalLaneIndex = 0; // Will be set when spawned self.update = function () { self.y += self.speed; // Handle lane changing behavior - only at night if (self.canChangeLanes && !self.isChangingLanes && self.y > 200 && self.y < 2000 && !isDay) { self.laneChangeTimer++; if (self.laneChangeTimer >= self.laneChangeDelay) { // Start lane change self.isChangingLanes = true; var currentLaneIndex = self.originalLaneIndex; // Choose a different lane var availableLanes = []; for (var i = 0; i < 3; i++) { if (i !== currentLaneIndex) { availableLanes.push(i); } } if (availableLanes.length > 0) { var newLaneIndex = availableLanes[Math.floor(Math.random() * availableLanes.length)]; var targetX = player.lanes[newLaneIndex]; // Animate lane change using tween tween(self, { x: targetX }, { duration: 1000 + Math.random() * 1000, easing: tween.easeInOut, onFinish: function onFinish() { self.isChangingLanes = false; self.originalLaneIndex = newLaneIndex; // Set new delay for next potential lane change self.laneChangeTimer = 0; self.laneChangeDelay = 300 + Math.random() * 600; // 5-15 seconds } }); } } } // Police lights visible during day and night, more prominent at night var dayAlpha = isDay ? 0.6 : 1.0; // Visible during day, full at night var dayAlphaLow = isDay ? 0.3 : 0.5; // Reduced for inactive light but still visible // Animate police lights self.lightTimer++; if (self.lightTimer >= 15) { // Change every 15 frames (0.25 seconds at 60fps) self.lightTimer = 0; self.isRedActive = !self.isRedActive; if (self.isRedActive) { leftLight.alpha = dayAlpha; rightLight.alpha = dayAlphaLow; leftSideLight.alpha = dayAlpha; rightSideLight.alpha = dayAlphaLow; topLeftLight.alpha = dayAlpha; topRightLight.alpha = dayAlphaLow; } else { leftLight.alpha = dayAlphaLow; rightLight.alpha = dayAlpha; leftSideLight.alpha = dayAlphaLow; rightSideLight.alpha = dayAlpha; topLeftLight.alpha = dayAlphaLow; topRightLight.alpha = dayAlpha; } } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 1.0 }); // Add headlights to the player car var leftHeadlight = self.attachAsset('headlight', { anchorX: 0.5, anchorY: 0.5 }); leftHeadlight.x = -25; leftHeadlight.y = -120; leftHeadlight.alpha = 0; // Start invisible var rightHeadlight = self.attachAsset('headlight', { anchorX: 0.5, anchorY: 0.5 }); rightHeadlight.x = 25; rightHeadlight.y = -120; rightHeadlight.alpha = 0; // Start invisible // Store headlight references self.leftHeadlight = leftHeadlight; self.rightHeadlight = rightHeadlight; self.groundY = 2300; self.lanes = [650, 1024, 1398]; // Three lanes self.currentLane = 1; // Middle lane self.targetX = self.lanes[self.currentLane]; self.x = self.targetX; self.y = self.groundY; self.moveLeft = function () { if (self.currentLane > 0) { self.currentLane--; self.targetX = self.lanes[self.currentLane]; // Add shake effect when moving left tween(self, { rotation: -0.1 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { rotation: 0 }, { duration: 100, easing: tween.easeInOut }); } }); // Play car movement sound try { var carMoveSound = LK.getSound('carMove'); carMoveSound.volume = 0.005; carMoveSound.play(); } catch (e) { console.log('Car move sound error:', e); } } }; self.moveRight = function () { if (self.currentLane < 2) { self.currentLane++; self.targetX = self.lanes[self.currentLane]; // Add shake effect when moving right tween(self, { rotation: 0.1 }, { duration: 100, easing: tween.easeOut, onFinish: function onFinish() { tween(self, { rotation: 0 }, { duration: 100, easing: tween.easeInOut }); } }); // Play car movement sound try { var carMoveSound = LK.getSound('carMove'); carMoveSound.volume = 0.005; carMoveSound.play(); } catch (e) { console.log('Car move sound error:', e); } } }; self.update = function () { // Handle lane switching var dx = self.targetX - self.x; if (Math.abs(dx) > 2) { self.x += dx * 0.15; } else { self.x = self.targetX; } }; 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 = gameSpeed; self.collected = false; self.lifetime = 420; // 7 seconds at 60fps self.update = function () { self.y += self.speed; self.rotation += 0.15; // Decrease lifetime self.lifetime--; // Flash when about to disappear (last 3 seconds) if (self.lifetime <= 180 && self.lifetime > 0) { self.alpha = (Math.sin(self.lifetime * 0.3) + 1) * 0.5; } }; return self; }); var RainDrop = Container.expand(function () { var self = Container.call(this); var dropGraphics = self.attachAsset('rainDrop', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 15 + Math.random() * 10; // Rain falls fast self.sideSpeed = -2 + Math.random() * 4; // Slight horizontal movement self.alpha = 0.3 + Math.random() * 0.4; // Semi-transparent self.update = function () { self.y += self.speed; self.x += self.sideSpeed; }; return self; }); var Rock = Container.expand(function () { var self = Container.call(this); var rockGraphics = self.attachAsset('rock', { anchorX: 0.5, anchorY: 1.0 }); self.speed = gameSpeed; self.update = function () { self.y += self.speed; }; return self; }); var Smoke = Container.expand(function () { var self = Container.call(this); var smokeGraphics = self.attachAsset('smoke', { anchorX: 0.5, anchorY: 1.0 }); self.speed = -1 - Math.random() * 2; self.sideSpeed = (Math.random() - 0.5) * 3; self.lifetime = 60 + Math.random() * 40; self.maxLifetime = self.lifetime; self.update = function () { self.y += self.speed; self.x += self.sideSpeed; self.lifetime--; // Fade and expand over time var fadeProgress = 1 - self.lifetime / self.maxLifetime; self.alpha = Math.max(0, 0.8 - fadeProgress * 1.2); self.scaleX = 0.3 + fadeProgress * 2; self.scaleY = 0.3 + fadeProgress * 2; }; 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 = gameSpeed; self.update = function () { self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x87CEEB }); /**** * Game Code ****/ var player; var obstacles = []; var coins = []; var powerups = []; var bullets = []; var hasWeapon = false; var weaponTimer = 0; var weaponDuration = 1200; // 20 seconds at 60fps var laneLines = []; var trees = []; var bushes = []; var rocks = []; var flowers = []; var currentGreenAreaType = 'forest'; // forest, grass, dark, meadow, jungle var greenAreaChangeTimer = 0; var greenAreaChangeDuration = 1800; // 30 seconds at 60fps var gameSpeed = 8; var maxSpeed = 20; var speedIncrement = 0.005; var distance = 0; var obstacleSpawnTimer = 0; var coinSpawnTimer = 0; var powerupSpawnTimer = 0; var laneLineSpawnTimer = 0; var treeSpawnTimer = 0; var lastSwipeX = 0; var lastSwipeY = 0; var swipeStarted = false; var policeMusicPlaying = false; var policeOnScreen = false; var lives = 3; var maxLives = 3; var exhaustParticles = []; var exhaustSpawnTimer = 0; var flames = []; var smokes = []; var debrisParticles = []; var rainDrops = []; var rainSpawnTimer = 0; // Rain cycle variables var isRaining = false; var rainTimer = 0; var rainDuration = 0; // Will be set randomly var rainCooldown = 0; // Will be set randomly var nextRainEvent = 0; // Timer for next rain event var rainSoundPlaying = false; var thunderTimer = 0; var nextThunderTime = 0; // Day/night cycle variables var dayNightTimer = 0; var dayNightCycleDuration = 3600; // 60 seconds (1 minute) at 60fps var isDay = true; var isTransitioning = false; // Game timer for police lane changing feature var gameTimer = 0; var laneChangeStartTime = 7200; // 2 minutes at 60fps (2 * 60 * 60) // Night speed multiplier var nightSpeedMultiplier = 1.25; // 25% faster during night var baseGameSpeed = 8; // Store the base game speed var dayColors = { sky: 0x87CEEB, // Light blue sky forest: 0x228b22, // Forest green road: 0xffffff // Normal road color }; var nightColors = { sky: 0x191970, // Midnight blue forest: 0x0f2f0f, // Dark forest green road: 0x404040 // Darker road color }; // Create road background var roadBackground = game.addChild(LK.getAsset('roadBackground', { anchorX: 0.5, anchorY: 0.5 })); roadBackground.x = 1024; // Center of screen roadBackground.y = 1366; // Create green forest backgrounds on sides var leftForest = game.addChild(LK.getAsset('forestBackground', { anchorX: 0.5, anchorY: 0.5 })); leftForest.x = 238; // Center of left side area leftForest.y = 1366; var rightForest = game.addChild(LK.getAsset('forestBackground', { anchorX: 0.5, anchorY: 0.5 })); rightForest.x = 1810; // Center of right side area rightForest.y = 1366; // Create road borders var leftBorder = game.addChild(LK.getAsset('roadBorder', { anchorX: 0.5, anchorY: 0.5 })); leftBorder.x = 476; // Left of leftmost lane leftBorder.y = 1366; var rightBorder = game.addChild(LK.getAsset('roadBorder', { anchorX: 0.5, anchorY: 0.5 })); rightBorder.x = 1572; // Right of rightmost lane rightBorder.y = 1366; // Create player player = game.addChild(new Player()); player.scaleX = 1.9; player.scaleY = 1.9; // Create score display var scoreText = new Text2('Score: 0', { size: 60, fill: 0xFFFFFF }); scoreText.anchor.set(0.5, 0); LK.gui.top.addChild(scoreText); // Distance display removed - only counting coins for score // Create lives display as hearts in top right var healthBars = []; for (var h = 0; h < maxLives; h++) { var heart = LK.getAsset('heart', { anchorX: 0.5, anchorY: 0.5 }); heart.x = -50 - h * 50; heart.y = 80; LK.gui.topRight.addChild(heart); healthBars.push(heart); } // Touch controls game.down = function (x, y, obj) { lastSwipeX = x; lastSwipeY = y; swipeStarted = true; }; game.up = function (x, y, obj) { if (swipeStarted) { var deltaX = x - lastSwipeX; var deltaY = y - lastSwipeY; var swipeThreshold = 100; if (Math.abs(deltaX) > Math.abs(deltaY)) { // Horizontal swipe if (deltaX > swipeThreshold) { player.moveRight(); } else if (deltaX < -swipeThreshold) { player.moveLeft(); } } } swipeStarted = false; }; function spawnObstacle() { var obstacle = new Obstacle(); var laneIndex = Math.floor(Math.random() * 3); obstacle.x = player.lanes[laneIndex]; obstacle.y = -100; obstacle.speed = gameSpeed; obstacle.scaleX = 0.9; obstacle.scaleY = 0.9; // Set original lane index for lane changing obstacle.originalLaneIndex = laneIndex; // Enable lane changing after 2 minutes if game has been running long enough if (gameTimer >= laneChangeStartTime) { obstacle.canChangeLanes = Math.random() < 0.3; // 30% chance to be a lane changer } tween(obstacle, { scaleX: 1.9, scaleY: 1.9 }, { duration: 400, easing: tween.easeOut }); obstacles.push(obstacle); game.addChild(obstacle); } function spawnCoin() { var coin = new Coin(); var laneIndex = Math.floor(Math.random() * 3); var targetX = player.lanes[laneIndex]; var canSpawn = true; // Check if there's an obstacle in this lane that would conflict for (var i = 0; i < obstacles.length; i++) { var obstacle = obstacles[i]; // Check if obstacle is in the same lane and close to spawn area if (Math.abs(obstacle.x - targetX) < 50 && obstacle.y >= -300 && obstacle.y <= 200) { canSpawn = false; break; } } // Also check if there's a powerup in this lane that would conflict if (canSpawn) { for (var p = 0; p < powerups.length; p++) { var powerup = powerups[p]; // Check if powerup is in the same lane and close to spawn area if (Math.abs(powerup.x - targetX) < 50 && powerup.y >= -300 && powerup.y <= 200) { canSpawn = false; break; } } } // If we can't spawn in the selected lane, try other lanes if (!canSpawn) { var availableLanes = []; for (var lane = 0; lane < 3; lane++) { var laneX = player.lanes[lane]; var laneAvailable = true; // Check for obstacles in this lane for (var j = 0; j < obstacles.length; j++) { var obs = obstacles[j]; if (Math.abs(obs.x - laneX) < 50 && obs.y >= -300 && obs.y <= 200) { laneAvailable = false; break; } } // Also check for powerups in this lane if (laneAvailable) { for (var k = 0; k < powerups.length; k++) { var pup = powerups[k]; if (Math.abs(pup.x - laneX) < 50 && pup.y >= -300 && pup.y <= 200) { laneAvailable = false; break; } } } if (laneAvailable) { availableLanes.push(lane); } } // If no lanes are available, don't spawn coin this time if (availableLanes.length === 0) { return; } // Pick a random available lane laneIndex = availableLanes[Math.floor(Math.random() * availableLanes.length)]; targetX = player.lanes[laneIndex]; } coin.x = targetX; coin.y = -50; coin.speed = gameSpeed; coin.scaleX = 0.5; coin.scaleY = 0.5; tween(coin, { scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.easeOut }); coins.push(coin); game.addChild(coin); } function spawnPowerUp() { var powerup = new PowerUp(); var laneIndex = Math.floor(Math.random() * 3); powerup.x = player.lanes[laneIndex]; powerup.y = -50; powerup.speed = gameSpeed; powerup.scaleX = 0.3; powerup.scaleY = 0.3; tween(powerup, { scaleX: 1, scaleY: 1 }, { duration: 600, easing: tween.easeOut }); powerups.push(powerup); game.addChild(powerup); } function spawnLaneLine() { // Lane dividers between lanes var positions = [837, 1211]; // Between lanes 0-1 and 1-2 for (var i = 0; i < positions.length; i++) { var laneLine = new LaneLine(); laneLine.x = positions[i]; laneLine.y = -20; laneLine.speed = gameSpeed; laneLines.push(laneLine); game.addChild(laneLine); } } function spawnExhaustParticle() { var particle = new ExhaustParticle(); particle.x = player.x + (Math.random() - 0.5) * 40; particle.y = player.y + 20; particle.scaleX = 0.5 + Math.random() * 0.5; particle.scaleY = 0.5 + Math.random() * 0.5; particle.alpha = 0.6 + Math.random() * 0.4; exhaustParticles.push(particle); game.addChild(particle); } function createFlameEffect(x, y, parentCar) { // Create multiple flame particles for (var i = 0; i < 12; i++) { // Increased from 8 to 12 flames var flame = new Flame(); flame.x = x + (Math.random() - 0.5) * 80; // Increased spread from 60 to 80 flame.y = y + Math.random() * 40; // Increased spread from 30 to 40 flame.scaleX = 1.2 + Math.random() * 0.8; // Increased base size from 0.5 to 1.2 flame.scaleY = 1.2 + Math.random() * 0.8; // Increased base size from 0.5 to 1.2 // Attach flame to police car if provided if (parentCar) { flame.parentCar = parentCar; flame.offsetX = (Math.random() - 0.5) * 80; flame.offsetY = Math.random() * 40 - 60; // Flames above the car } flames.push(flame); game.addChild(flame); } // Create smoke particles for (var j = 0; j < 6; j++) { // Increased from 4 to 6 smoke particles var smoke = new Smoke(); smoke.x = x + (Math.random() - 0.5) * 50; // Increased spread from 40 to 50 smoke.y = y - 10 + Math.random() * 30; // Increased spread from 20 to 30 smoke.alpha = 0.4 + Math.random() * 0.3; smoke.scaleX = 1.5 + Math.random() * 0.5; // Increased smoke size smoke.scaleY = 1.5 + Math.random() * 0.5; // Increased smoke size smokes.push(smoke); game.addChild(smoke); } // Create debris particles for explosion effect for (var k = 0; k < 15; k++) { var debris = new DebrisParticle(); debris.x = x + (Math.random() - 0.5) * 40; debris.y = y + (Math.random() - 0.5) * 30; debris.scaleX = 0.5 + Math.random() * 1.0; debris.scaleY = 0.5 + Math.random() * 1.0; debrisParticles.push(debris); game.addChild(debris); } } function spawnLandscapeElements() { // Spawn bushes occasionally if (Math.random() < 0.4) { spawnBushes(); } // Spawn rocks occasionally if (Math.random() < 0.2) { spawnRocks(); } // Spawn flowers occasionally in meadow areas if (currentGreenAreaType === 'meadow' && Math.random() < 0.3) { spawnFlowers(); } } function spawnBushes() { // Spawn bushes on left side var leftPositions = [150, 250, 350]; for (var i = 0; i < leftPositions.length; i++) { if (Math.random() < 0.5) { var leftBush = new Bush(); leftBush.x = leftPositions[i]; leftBush.y = -60; leftBush.speed = gameSpeed; leftBush.scaleX = 0.7 + Math.random() * 0.6; leftBush.scaleY = 0.7 + Math.random() * 0.6; if (!isDay) leftBush.alpha = 0.7; bushes.push(leftBush); game.addChild(leftBush); } } // Spawn bushes on right side var rightPositions = [1698, 1798, 1898]; for (var j = 0; j < rightPositions.length; j++) { if (Math.random() < 0.5) { var rightBush = new Bush(); rightBush.x = rightPositions[j]; rightBush.y = -60; rightBush.speed = gameSpeed; rightBush.scaleX = 0.7 + Math.random() * 0.6; rightBush.scaleY = 0.7 + Math.random() * 0.6; if (!isDay) rightBush.alpha = 0.7; bushes.push(rightBush); game.addChild(rightBush); } } } function spawnRocks() { // Spawn rocks on left side if (Math.random() < 0.6) { var leftRock = new Rock(); leftRock.x = 120 + Math.random() * 200; leftRock.y = -40; leftRock.speed = gameSpeed; leftRock.scaleX = 0.8 + Math.random() * 0.4; leftRock.scaleY = 0.8 + Math.random() * 0.4; var grayVariation = 0.7 + Math.random() * 0.3; leftRock.tint = grayVariation * 0x808080 | 0; if (!isDay) leftRock.alpha = 0.6; rocks.push(leftRock); game.addChild(leftRock); } // Spawn rocks on right side if (Math.random() < 0.6) { var rightRock = new Rock(); rightRock.x = 1680 + Math.random() * 200; rightRock.y = -40; rightRock.speed = gameSpeed; rightRock.scaleX = 0.8 + Math.random() * 0.4; rightRock.scaleY = 0.8 + Math.random() * 0.4; var grayVariation = 0.7 + Math.random() * 0.3; rightRock.tint = grayVariation * 0x808080 | 0; if (!isDay) rightRock.alpha = 0.6; rocks.push(rightRock); game.addChild(rightRock); } } function spawnFlowers() { // Spawn flowers on left side for (var i = 0; i < 3; i++) { if (Math.random() < 0.4) { var leftFlower = new Flower(); leftFlower.x = 180 + Math.random() * 120; leftFlower.y = -20; leftFlower.speed = gameSpeed; leftFlower.scaleX = 0.8 + Math.random() * 0.4; leftFlower.scaleY = 0.8 + Math.random() * 0.4; var flowerColors = [0xff69b4, 0xff1493, 0xffd700, 0xff6347, 0x9370db]; leftFlower.tint = flowerColors[Math.floor(Math.random() * flowerColors.length)]; flowers.push(leftFlower); game.addChild(leftFlower); } } // Spawn flowers on right side for (var j = 0; j < 3; j++) { if (Math.random() < 0.4) { var rightFlower = new Flower(); rightFlower.x = 1720 + Math.random() * 120; rightFlower.y = -20; rightFlower.speed = gameSpeed; rightFlower.scaleX = 0.8 + Math.random() * 0.4; rightFlower.scaleY = 0.8 + Math.random() * 0.4; var flowerColors = [0xff69b4, 0xff1493, 0xffd700, 0xff6347, 0x9370db]; rightFlower.tint = flowerColors[Math.floor(Math.random() * flowerColors.length)]; flowers.push(rightFlower); game.addChild(rightFlower); } } } function changeGreenAreaType() { var areaTypes = ['forest', 'grass', 'dark', 'meadow', 'jungle']; var newType = areaTypes[Math.floor(Math.random() * areaTypes.length)]; if (newType !== currentGreenAreaType) { currentGreenAreaType = newType; var newAssetName = currentGreenAreaType === 'forest' ? 'forestBackground' : currentGreenAreaType === 'grass' ? 'grassField' : currentGreenAreaType === 'dark' ? 'darkForest' : currentGreenAreaType === 'meadow' ? 'meadow' : 'jungleArea'; // Create new forest backgrounds var newLeftForest = game.addChild(LK.getAsset(newAssetName, { anchorX: 0.5, anchorY: 0.5 })); newLeftForest.x = 238; newLeftForest.y = -1366; // Start above screen var newRightForest = game.addChild(LK.getAsset(newAssetName, { anchorX: 0.5, anchorY: 0.5 })); newRightForest.x = 1810; newRightForest.y = -1366; // Start above screen // Apply current day/night colors var targetColors = isDay ? dayColors : nightColors; newLeftForest.tint = targetColors.forest; newRightForest.tint = targetColors.forest; // Animate new backgrounds into view tween(newLeftForest, { y: 1366 }, { duration: 2000, easing: tween.easeInOut }); tween(newRightForest, { y: 1366 }, { duration: 2000, easing: tween.easeInOut }); // Move old backgrounds out and destroy them tween(leftForest, { y: 4098 // Move below screen }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { leftForest.destroy(); } }); tween(rightForest, { y: 4098 // Move below screen }, { duration: 2000, easing: tween.easeInOut, onFinish: function onFinish() { rightForest.destroy(); } }); // Update references leftForest = newLeftForest; rightForest = newRightForest; } } function spawnTrees() { // Spawn trees on left side of road var leftPositions = [100, 200, 300, 400]; for (var i = 0; i < leftPositions.length; i++) { if (Math.random() < 0.7) { var leftTree = new Tree(); leftTree.x = leftPositions[i]; leftTree.y = -80; leftTree.speed = gameSpeed; // Add some variation in scale leftTree.scaleX = 0.8 + Math.random() * 0.4; leftTree.scaleY = 0.8 + Math.random() * 0.4; // Add slight tint variation for natural look var tintVariation = 0.9 + Math.random() * 0.2; leftTree.tint = tintVariation * 0x90EE90 | 0; // Apply current day/night brightness if (!isDay) { leftTree.alpha = 0.6; } trees.push(leftTree); game.addChild(leftTree); } } // Spawn trees on right side of road var rightPositions = [1648, 1748, 1848, 1948]; for (var j = 0; j < rightPositions.length; j++) { if (Math.random() < 0.7) { var rightTree = new Tree(); rightTree.x = rightPositions[j]; rightTree.y = -80; rightTree.speed = gameSpeed; // Add some variation in scale rightTree.scaleX = 0.8 + Math.random() * 0.4; rightTree.scaleY = 0.8 + Math.random() * 0.4; // Add slight tint variation for natural look var tintVariation = 0.9 + Math.random() * 0.2; rightTree.tint = tintVariation * 0x90EE90 | 0; // Apply current day/night brightness if (!isDay) { rightTree.alpha = 0.6; } trees.push(rightTree); game.addChild(rightTree); } } } function spawnRain() { // Spawn multiple rain drops across the screen width for (var i = 0; i < 8; i++) { var rainDrop = new RainDrop(); rainDrop.x = Math.random() * 2048; // Random X across screen width rainDrop.y = -20 - Math.random() * 50; // Start above screen rainDrop.speed = gameSpeed + 15 + Math.random() * 10; // Rain speed based on game speed rainDrops.push(rainDrop); game.addChild(rainDrop); } } // Main game loop game.update = function () { // Update game timer gameTimer++; // Calculate current base speed with gradual increase var currentBaseSpeed = Math.min(maxSpeed, baseGameSpeed + gameTimer * speedIncrement); // Apply night speed multiplier gameSpeed = isDay ? currentBaseSpeed : currentBaseSpeed * nightSpeedMultiplier; // Distance tracking removed - only counting coins for score // Spawn obstacles - more frequent during night obstacleSpawnTimer++; var obstacleSpawnRate = isDay ? 60 + Math.random() * 60 : 30 + Math.random() * 30; // Night: 30-60 frames, Day: 60-120 frames if (obstacleSpawnTimer > obstacleSpawnRate) { spawnObstacle(); obstacleSpawnTimer = 0; } // Spawn coins - dynamically adjust spawn rate based on game speed (increased frequency) coinSpawnTimer++; var coinSpawnRate = Math.max(20, 80 - (gameSpeed - 8) * 4); // Much faster spawning as speed increases if (coinSpawnTimer > coinSpawnRate + Math.random() * 20) { spawnCoin(); coinSpawnTimer = 0; } // Spawn powerups (rare spawn - every 1 minute) powerupSpawnTimer++; if (powerupSpawnTimer > 3600) { // 1 minute (60 seconds * 60 fps) spawnPowerUp(); powerupSpawnTimer = 0; } // Spawn lane lines laneLineSpawnTimer++; if (laneLineSpawnTimer > 30) { spawnLaneLine(); laneLineSpawnTimer = 0; } // Spawn trees and landscape elements treeSpawnTimer++; if (treeSpawnTimer > 45) { spawnTrees(); spawnLandscapeElements(); treeSpawnTimer = 0; } // Change green area types periodically greenAreaChangeTimer++; if (greenAreaChangeTimer > greenAreaChangeDuration) { changeGreenAreaType(); greenAreaChangeTimer = 0; // Randomize next change duration greenAreaChangeDuration = 1200 + Math.random() * 1800; // 20-50 seconds } // Update obstacles var currentPoliceOnScreen = false; for (var i = obstacles.length - 1; i >= 0; i--) { var obstacle = obstacles[i]; obstacle.speed = gameSpeed; // Check if police car is on screen if (obstacle.y >= -200 && obstacle.y <= 2900) { currentPoliceOnScreen = true; } // Remove obstacles that are off screen if (obstacle.y > 2800) { obstacle.destroy(); obstacles.splice(i, 1); continue; } // Check collision with player (skip if obstacle is already hit) if (!obstacle.isHit && player.intersects(obstacle)) { // Play crash sound try { LK.getSound('crash').play(); } catch (e) { console.log('Crash sound error:', e); } // Reduce lives lives--; // Hide the health bar corresponding to lost life if (lives >= 0 && lives < healthBars.length) { healthBars[healthBars.length - 1 - lives].visible = false; } // Flash screen and remove obstacle LK.effects.flashScreen(0xff0000, 500); obstacle.destroy(); obstacles.splice(i, 1); // Check if game over if (lives <= 0) { // Add delay to allow crash sound to play before game over LK.setTimeout(function () { LK.showGameOver(); }, 800); // Wait 800ms for crash sound to play return; } // Make player temporarily invulnerable player.alpha = 0.5; LK.setTimeout(function () { player.alpha = 1.0; }, 1500); // 1.5 seconds of invulnerability continue; } } // Handle police music based on police presence if (currentPoliceOnScreen && !policeMusicPlaying) { // Start police siren as a sound effect that loops instead of music // This allows it to play alongside the background music try { var policeSiren = LK.getSound('policemusic'); if (policeSiren) { policeSiren.loop = true; policeSiren.play(); } } catch (e) { console.log('Police siren play error:', e); } policeMusicPlaying = true; policeOnScreen = true; } else if (!currentPoliceOnScreen && policeMusicPlaying) { // Stop police siren sound try { var policeSiren = LK.getSound('policemusic'); if (policeSiren) { policeSiren.stop(); } } catch (e) { console.log('Police siren stop error:', e); } policeMusicPlaying = false; policeOnScreen = false; } else if (currentPoliceOnScreen && policeMusicPlaying) { // Ensure police siren continues playing if it stopped try { var policeSiren = LK.getSound('policemusic'); if (policeSiren && !policeSiren.playing) { policeSiren.loop = true; policeSiren.play(); } } catch (e) { console.log('Police siren restart error:', e); } } // Update coins for (var j = coins.length - 1; j >= 0; j--) { var coin = coins[j]; coin.speed = gameSpeed; // Remove coins that are off screen if (coin.y > 2800) { coin.destroy(); coins.splice(j, 1); continue; } // Check collection if (!coin.collected && player.intersects(coin)) { coin.collected = true; LK.setScore(LK.getScore() + 1); // Each coin is worth exactly 1 point scoreText.setText('Score: ' + LK.getScore()); LK.getSound('collect').play(); // Enhanced visual effect with faster animation for higher speeds var animationDuration = Math.max(200, 400 - (gameSpeed - 8) * 10); tween(coin, { alpha: 0, scaleX: 2.5, scaleY: 2.5, y: coin.y - 50 }, { duration: animationDuration, easing: tween.easeOut, onFinish: function onFinish() { coin.destroy(); } }); coins.splice(j, 1); } } // Update powerups for (var p = powerups.length - 1; p >= 0; p--) { var powerup = powerups[p]; powerup.speed = gameSpeed; // Remove powerups that are off screen or expired if (powerup.y > 2800 || powerup.lifetime <= 0) { powerup.destroy(); powerups.splice(p, 1); continue; } // Check collection if (!powerup.collected && player.intersects(powerup)) { powerup.collected = true; hasWeapon = true; weaponTimer = weaponDuration; // 20 seconds LK.getSound('collect').play(); // Visual effect tween(powerup, { alpha: 0, scaleX: 3, scaleY: 3 }, { duration: 400, onFinish: function onFinish() { powerup.destroy(); } }); powerups.splice(p, 1); } } // Update lane lines for (var k = laneLines.length - 1; k >= 0; k--) { var laneLine = laneLines[k]; laneLine.speed = gameSpeed; // Remove lane lines that are off screen if (laneLine.y > 2800) { laneLine.destroy(); laneLines.splice(k, 1); } } // Update trees for (var t = trees.length - 1; t >= 0; t--) { var tree = trees[t]; tree.speed = gameSpeed; // Remove trees that are off screen if (tree.y > 2800) { tree.destroy(); trees.splice(t, 1); } } // Update bushes for (var bush = bushes.length - 1; bush >= 0; bush--) { var bushElement = bushes[bush]; bushElement.speed = gameSpeed; if (bushElement.y > 2800) { bushElement.destroy(); bushes.splice(bush, 1); } } // Update rocks for (var rock = rocks.length - 1; rock >= 0; rock--) { var rockElement = rocks[rock]; rockElement.speed = gameSpeed; if (rockElement.y > 2800) { rockElement.destroy(); rocks.splice(rock, 1); } } // Update flowers for (var flower = flowers.length - 1; flower >= 0; flower--) { var flowerElement = flowers[flower]; flowerElement.speed = gameSpeed; if (flowerElement.y > 2800) { flowerElement.destroy(); flowers.splice(flower, 1); } } // Handle rain cycle logic if (!isRaining) { // Check if it's time to start raining nextRainEvent++; if (nextRainEvent >= rainCooldown) { // Start rain cycle isRaining = true; rainTimer = 0; // Random rain duration: 10-60 seconds (600-3600 frames at 60fps) rainDuration = 600 + Math.random() * 3000; // 10 seconds to 1 minute nextRainEvent = 0; // Start rain music if (!rainSoundPlaying) { try { LK.playMusic('rain'); } catch (e) { console.log('Rain music play error:', e); } rainSoundPlaying = true; } // Initialize thunder timing for this rain period thunderTimer = 0; nextThunderTime = 180 + Math.random() * 600; // First thunder in 3-13 seconds console.log('Rain started for', Math.floor(rainDuration / 60), 'seconds'); } } else { // Currently raining rainTimer++; // Spawn rain particles while raining rainSpawnTimer++; if (rainSpawnTimer >= 2) { // Spawn rain every 2 frames for heavy rain effect spawnRain(); rainSpawnTimer = 0; } // Handle thunder during rain thunderTimer++; if (thunderTimer >= nextThunderTime) { // Play thunder sound try { var thunderSound = LK.getSound('thunder'); if (thunderSound) { thunderSound.play(); } } catch (e) { console.log('Thunder sound play error:', e); } // Add thunder flash effect - bright white flash LK.effects.flashScreen(0xffffff, 300); // White flash for 300ms // Set next thunder time (random between 5-20 seconds) nextThunderTime = thunderTimer + (300 + Math.random() * 900); // 5-20 seconds at 60fps } // Check if rain should stop if (rainTimer >= rainDuration) { // Stop rain cycle isRaining = false; rainTimer = 0; // Random cooldown period: 30-180 seconds (1800-10800 frames at 60fps) rainCooldown = 1800 + Math.random() * 9000; // 30 seconds to 3 minutes nextRainEvent = 0; // Reset thunder timer thunderTimer = 0; nextThunderTime = 0; // Gradually fade out existing rain drops for (var fadeRain = 0; fadeRain < rainDrops.length; fadeRain++) { var rainDrop = rainDrops[fadeRain]; tween(rainDrop, { alpha: 0, speed: rainDrop.speed * 0.3 }, { duration: 2000 + Math.random() * 1000, easing: tween.easeOut }); } console.log('Rain stopped. Next rain in', Math.floor(rainCooldown / 60), 'seconds'); } } // Stop rain music only when all rain effects are complete if (!isRaining && rainSoundPlaying && rainDrops.length === 0) { try { LK.stopMusic(); // Restart background music after rain stops LK.playMusic('bgmusic'); } catch (e) { console.log('Rain music stop error:', e); } rainSoundPlaying = false; } // Spawn exhaust particles exhaustSpawnTimer++; if (exhaustSpawnTimer >= 3) { spawnExhaustParticle(); exhaustSpawnTimer = 0; } // Update exhaust particles for (var e = exhaustParticles.length - 1; e >= 0; e--) { var particle = exhaustParticles[e]; // Remove particles that are expired or off screen if (particle.lifetime <= 0 || particle.y < -50) { particle.destroy(); exhaustParticles.splice(e, 1); } } // Update flame particles for (var f = flames.length - 1; f >= 0; f--) { var flame = flames[f]; // Remove flames that are expired or off screen if (flame.lifetime <= 0 || flame.y < -50) { flame.destroy(); flames.splice(f, 1); } } // Update smoke particles for (var s = smokes.length - 1; s >= 0; s--) { var smoke = smokes[s]; // Remove smoke that is expired or off screen if (smoke.lifetime <= 0 || smoke.y < -50) { smoke.destroy(); smokes.splice(s, 1); } } // Update debris particles for (var d = debrisParticles.length - 1; d >= 0; d--) { var debris = debrisParticles[d]; // Remove debris that is expired or off screen if (debris.lifetime <= 0 || debris.y > 2800) { debris.destroy(); debrisParticles.splice(d, 1); } } // Update rain particles for (var r = rainDrops.length - 1; r >= 0; r--) { var rain = rainDrops[r]; // Remove rain drops that are off screen if (rain.y > 2800 || rain.x < -50 || rain.x > 2098) { rain.destroy(); rainDrops.splice(r, 1); } } // Handle weapon system if (hasWeapon) { weaponTimer--; if (weaponTimer <= 0) { hasWeapon = false; } // Shoot bullets every 25 frames (increased firing rate) if (LK.ticks % 25 === 0) { var bullet = new Bullet(); bullet.x = player.x; bullet.y = player.y - 100; bullets.push(bullet); game.addChild(bullet); // Play gun sound LK.getSound('gunshot').play(); } } // Update bullets for (var b = bullets.length - 1; b >= 0; b--) { var bullet = bullets[b]; // Remove bullets that are off screen if (bullet.y < -50) { bullet.destroy(); bullets.splice(b, 1); continue; } // Check bullet collision with obstacles for (var o = obstacles.length - 1; o >= 0; o--) { var obstacle = obstacles[o]; if (!obstacle.isHit && bullet.intersects(obstacle)) { // Play police hit sound try { LK.getSound('policeHit').play(); } catch (e) { console.log('Police hit sound error:', e); } // Destroy bullet immediately bullet.destroy(); bullets.splice(b, 1); // Mark obstacle as hit to prevent further collisions obstacle.isHit = true; // Create flame effect at police car position with car reference createFlameEffect(obstacle.x, obstacle.y - 50, obstacle); // Create burning effect with flames tween(obstacle, { tint: 0x000000, alpha: 0 }, { duration: 800, easing: tween.easeOut, onFinish: function onFinish() { obstacle.isDestroyed = true; // Mark as destroyed for flame cleanup obstacle.destroy(); // Remove from obstacles array after animation completes var index = obstacles.indexOf(obstacle); if (index > -1) { obstacles.splice(index, 1); } } }); break; } } } // Update day/night cycle dayNightTimer++; if (dayNightTimer >= dayNightCycleDuration) { transitionDayNight(); dayNightTimer = 0; } // Police exhaust particles now stay in their natural layer order // Road color no longer changes automatically }; // Road color change function (kept for potential future use) function changeRoadColor(newColor) { roadBackground.tint = newColor; } // Day/night cycle transition function function transitionDayNight() { if (isTransitioning) return; isTransitioning = true; isDay = !isDay; var targetColors = isDay ? dayColors : nightColors; var transitionDuration = 2000; // 2 seconds transition // Immediately update game speed for the new cycle var currentBaseSpeed = Math.min(maxSpeed, baseGameSpeed + gameTimer * speedIncrement); gameSpeed = isDay ? currentBaseSpeed : currentBaseSpeed * nightSpeedMultiplier; // Transition background color tween(game, { backgroundColor: targetColors.sky }, { duration: transitionDuration, easing: tween.easeInOut }); // Transition forest backgrounds tween(leftForest, { tint: targetColors.forest }, { duration: transitionDuration, easing: tween.easeInOut }); tween(rightForest, { tint: targetColors.forest }, { duration: transitionDuration, easing: tween.easeInOut }); // Transition road background tween(roadBackground, { tint: targetColors.road }, { duration: transitionDuration, easing: tween.easeInOut, onFinish: function onFinish() { isTransitioning = false; } }); // Adjust trees brightness for night/day var treeBrightness = isDay ? 1.0 : 0.6; for (var i = 0; i < trees.length; i++) { var tree = trees[i]; tween(tree, { alpha: treeBrightness }, { duration: transitionDuration, easing: tween.easeInOut }); } // Adjust landscape elements brightness for night/day var elementBrightness = isDay ? 1.0 : 0.7; // Update bushes brightness for (var b = 0; b < bushes.length; b++) { var bush = bushes[b]; tween(bush, { alpha: elementBrightness }, { duration: transitionDuration, easing: tween.easeInOut }); } // Update rocks brightness for (var r = 0; r < rocks.length; r++) { var rock = rocks[r]; tween(rock, { alpha: elementBrightness }, { duration: transitionDuration, easing: tween.easeInOut }); } // Flowers stay bright during day and dim slightly at night var flowerBrightness = isDay ? 1.0 : 0.8; for (var f = 0; f < flowers.length; f++) { var flower = flowers[f]; tween(flower, { alpha: flowerBrightness }, { duration: transitionDuration, easing: tween.easeInOut }); } // Control player headlights based on day/night var headlightAlpha = isDay ? 0 : 0.8; tween(player.leftHeadlight, { alpha: headlightAlpha }, { duration: transitionDuration, easing: tween.easeInOut }); tween(player.rightHeadlight, { alpha: headlightAlpha }, { duration: transitionDuration, easing: tween.easeInOut }); } // Spawn initial powerup at game start spawnPowerUp(); // Initialize first rain cycle rainCooldown = 1800 + Math.random() * 9000; // 30 seconds to 3 minutes before first rain nextRainEvent = 0; // Start background music - this will be the base music layer LK.playMusic('bgmusic', { fade: { start: 0, end: 1, duration: 1000 } }); ;
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -25;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Bush = Container.expand(function () {
var self = Container.call(this);
var bushGraphics = self.attachAsset('bush', {
anchorX: 0.5,
anchorY: 1.0
});
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
};
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 = gameSpeed;
self.collected = false;
self.update = function () {
self.y += self.speed;
self.rotation += 0.1;
};
return self;
});
var DebrisParticle = Container.expand(function () {
var self = Container.call(this);
var debrisGraphics = self.attachAsset('debrisParticle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = (Math.random() - 0.5) * 20; // Random horizontal speed
self.speedY = -5 - Math.random() * 15; // Upward initial speed
self.gravity = 0.8; // Gravity acceleration
self.lifetime = 90 + Math.random() * 60; // 1.5-2.5 seconds
self.maxLifetime = self.lifetime;
self.rotationSpeed = (Math.random() - 0.5) * 0.3;
// Random colors for debris (metal, glass, etc.)
var debrisColors = [0x666666, 0x888888, 0x444444, 0x999999, 0x333333];
debrisGraphics.tint = debrisColors[Math.floor(Math.random() * debrisColors.length)];
self.update = function () {
// Apply physics
self.x += self.speedX;
self.y += self.speedY;
self.speedY += self.gravity; // Apply gravity
self.rotation += self.rotationSpeed;
self.lifetime--;
// Fade out over time
var fadeProgress = 1 - self.lifetime / self.maxLifetime;
self.alpha = Math.max(0, 1 - fadeProgress * 1.5);
};
return self;
});
var ExhaustParticle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('exhaustParticle', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3 + Math.random() * 2;
self.sideSpeed = (Math.random() - 0.5) * 2;
self.lifetime = 60 + Math.random() * 30;
self.maxLifetime = self.lifetime;
self.update = function () {
self.y += self.speed;
self.x += self.sideSpeed;
self.lifetime--;
// Fade out and scale up over time
var fadeProgress = 1 - self.lifetime / self.maxLifetime;
self.alpha = Math.max(0, 1 - fadeProgress * 1.5);
self.scaleX = 1 + fadeProgress * 0.8;
self.scaleY = 1 + fadeProgress * 0.8;
};
return self;
});
var Flame = Container.expand(function () {
var self = Container.call(this);
var flameGraphics = self.attachAsset('flame', {
anchorX: 0.5,
anchorY: 1.0
});
self.speed = -2 - Math.random() * 3;
self.sideSpeed = (Math.random() - 0.5) * 4;
self.lifetime = 30 + Math.random() * 20;
self.maxLifetime = self.lifetime;
self.flickerTimer = 0;
self.parentCar = null; // Reference to the police car this flame belongs to
self.offsetX = 0; // Offset from car position
self.offsetY = 0; // Offset from car position
self.update = function () {
// If attached to a police car, follow its position
if (self.parentCar && !self.parentCar.isDestroyed) {
self.x = self.parentCar.x + self.offsetX;
self.y = self.parentCar.y + self.offsetY;
}
self.lifetime--;
// Flicker effect
self.flickerTimer++;
if (self.flickerTimer % 3 === 0) {
var colors = [0xff4500, 0xff6600, 0xff8800, 0xffaa00];
flameGraphics.tint = colors[Math.floor(Math.random() * colors.length)];
}
// Fade and scale over time
var fadeProgress = 1 - self.lifetime / self.maxLifetime;
self.alpha = Math.max(0, 1 - fadeProgress * 1.2);
self.scaleX = 1.5 + fadeProgress * 1.2; // Increased base size from 0.5 to 1.5
self.scaleY = 2.0 + fadeProgress * 2.0; // Increased base size from 0.8 to 2.0
};
return self;
});
var Flower = Container.expand(function () {
var self = Container.call(this);
var flowerGraphics = self.attachAsset('flower', {
anchorX: 0.5,
anchorY: 1.0
});
self.speed = gameSpeed;
self.swayTimer = Math.random() * 100;
self.originalX = 0;
self.update = function () {
self.y += self.speed;
// Add gentle swaying motion
self.swayTimer += 0.1;
if (self.originalX === 0) self.originalX = self.x;
self.x = self.originalX + Math.sin(self.swayTimer) * 5;
};
return self;
});
var LaneLine = Container.expand(function () {
var self = Container.call(this);
var lineGraphics = self.attachAsset('laneLine', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphics = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 1.0
});
self.speed = gameSpeed;
// Add police lights to the obstacle (police car)
var leftLight = self.attachAsset('policeLight', {
anchorX: 0.5,
anchorY: 0.5
});
leftLight.x = -30;
leftLight.y = -60;
var rightLight = self.attachAsset('policeLight', {
anchorX: 0.5,
anchorY: 0.5
});
rightLight.x = 30;
rightLight.y = -60;
rightLight.tint = 0x0000ff; // Make right light blue
// Add side lights
var leftSideLight = self.attachAsset('policeLight', {
anchorX: 0.5,
anchorY: 0.5
});
leftSideLight.x = -45;
leftSideLight.y = -30;
var rightSideLight = self.attachAsset('policeLight', {
anchorX: 0.5,
anchorY: 0.5
});
rightSideLight.x = 45;
rightSideLight.y = -30;
rightSideLight.tint = 0x0000ff; // Make right side light blue
// Add top lights
var topLeftLight = self.attachAsset('policeLight', {
anchorX: 0.5,
anchorY: 0.5
});
topLeftLight.x = -15;
topLeftLight.y = -80;
var topRightLight = self.attachAsset('policeLight', {
anchorX: 0.5,
anchorY: 0.5
});
topRightLight.x = 15;
topRightLight.y = -80;
topRightLight.tint = 0x0000ff; // Make top right light blue
self.lightTimer = 0;
self.isRedActive = true;
// Lane changing properties
self.canChangeLanes = false;
self.laneChangeTimer = 0;
self.laneChangeDelay = 180 + Math.random() * 240; // 3-7 seconds random delay
self.targetLaneIndex = Math.floor(Math.random() * 3); // Random target lane
self.isChangingLanes = false;
self.originalLaneIndex = 0; // Will be set when spawned
self.update = function () {
self.y += self.speed;
// Handle lane changing behavior - only at night
if (self.canChangeLanes && !self.isChangingLanes && self.y > 200 && self.y < 2000 && !isDay) {
self.laneChangeTimer++;
if (self.laneChangeTimer >= self.laneChangeDelay) {
// Start lane change
self.isChangingLanes = true;
var currentLaneIndex = self.originalLaneIndex;
// Choose a different lane
var availableLanes = [];
for (var i = 0; i < 3; i++) {
if (i !== currentLaneIndex) {
availableLanes.push(i);
}
}
if (availableLanes.length > 0) {
var newLaneIndex = availableLanes[Math.floor(Math.random() * availableLanes.length)];
var targetX = player.lanes[newLaneIndex];
// Animate lane change using tween
tween(self, {
x: targetX
}, {
duration: 1000 + Math.random() * 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
self.isChangingLanes = false;
self.originalLaneIndex = newLaneIndex;
// Set new delay for next potential lane change
self.laneChangeTimer = 0;
self.laneChangeDelay = 300 + Math.random() * 600; // 5-15 seconds
}
});
}
}
}
// Police lights visible during day and night, more prominent at night
var dayAlpha = isDay ? 0.6 : 1.0; // Visible during day, full at night
var dayAlphaLow = isDay ? 0.3 : 0.5; // Reduced for inactive light but still visible
// Animate police lights
self.lightTimer++;
if (self.lightTimer >= 15) {
// Change every 15 frames (0.25 seconds at 60fps)
self.lightTimer = 0;
self.isRedActive = !self.isRedActive;
if (self.isRedActive) {
leftLight.alpha = dayAlpha;
rightLight.alpha = dayAlphaLow;
leftSideLight.alpha = dayAlpha;
rightSideLight.alpha = dayAlphaLow;
topLeftLight.alpha = dayAlpha;
topRightLight.alpha = dayAlphaLow;
} else {
leftLight.alpha = dayAlphaLow;
rightLight.alpha = dayAlpha;
leftSideLight.alpha = dayAlphaLow;
rightSideLight.alpha = dayAlpha;
topLeftLight.alpha = dayAlphaLow;
topRightLight.alpha = dayAlpha;
}
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 1.0
});
// Add headlights to the player car
var leftHeadlight = self.attachAsset('headlight', {
anchorX: 0.5,
anchorY: 0.5
});
leftHeadlight.x = -25;
leftHeadlight.y = -120;
leftHeadlight.alpha = 0; // Start invisible
var rightHeadlight = self.attachAsset('headlight', {
anchorX: 0.5,
anchorY: 0.5
});
rightHeadlight.x = 25;
rightHeadlight.y = -120;
rightHeadlight.alpha = 0; // Start invisible
// Store headlight references
self.leftHeadlight = leftHeadlight;
self.rightHeadlight = rightHeadlight;
self.groundY = 2300;
self.lanes = [650, 1024, 1398]; // Three lanes
self.currentLane = 1; // Middle lane
self.targetX = self.lanes[self.currentLane];
self.x = self.targetX;
self.y = self.groundY;
self.moveLeft = function () {
if (self.currentLane > 0) {
self.currentLane--;
self.targetX = self.lanes[self.currentLane];
// Add shake effect when moving left
tween(self, {
rotation: -0.1
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
rotation: 0
}, {
duration: 100,
easing: tween.easeInOut
});
}
});
// Play car movement sound
try {
var carMoveSound = LK.getSound('carMove');
carMoveSound.volume = 0.005;
carMoveSound.play();
} catch (e) {
console.log('Car move sound error:', e);
}
}
};
self.moveRight = function () {
if (self.currentLane < 2) {
self.currentLane++;
self.targetX = self.lanes[self.currentLane];
// Add shake effect when moving right
tween(self, {
rotation: 0.1
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
rotation: 0
}, {
duration: 100,
easing: tween.easeInOut
});
}
});
// Play car movement sound
try {
var carMoveSound = LK.getSound('carMove');
carMoveSound.volume = 0.005;
carMoveSound.play();
} catch (e) {
console.log('Car move sound error:', e);
}
}
};
self.update = function () {
// Handle lane switching
var dx = self.targetX - self.x;
if (Math.abs(dx) > 2) {
self.x += dx * 0.15;
} else {
self.x = self.targetX;
}
};
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 = gameSpeed;
self.collected = false;
self.lifetime = 420; // 7 seconds at 60fps
self.update = function () {
self.y += self.speed;
self.rotation += 0.15;
// Decrease lifetime
self.lifetime--;
// Flash when about to disappear (last 3 seconds)
if (self.lifetime <= 180 && self.lifetime > 0) {
self.alpha = (Math.sin(self.lifetime * 0.3) + 1) * 0.5;
}
};
return self;
});
var RainDrop = Container.expand(function () {
var self = Container.call(this);
var dropGraphics = self.attachAsset('rainDrop', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15 + Math.random() * 10; // Rain falls fast
self.sideSpeed = -2 + Math.random() * 4; // Slight horizontal movement
self.alpha = 0.3 + Math.random() * 0.4; // Semi-transparent
self.update = function () {
self.y += self.speed;
self.x += self.sideSpeed;
};
return self;
});
var Rock = Container.expand(function () {
var self = Container.call(this);
var rockGraphics = self.attachAsset('rock', {
anchorX: 0.5,
anchorY: 1.0
});
self.speed = gameSpeed;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Smoke = Container.expand(function () {
var self = Container.call(this);
var smokeGraphics = self.attachAsset('smoke', {
anchorX: 0.5,
anchorY: 1.0
});
self.speed = -1 - Math.random() * 2;
self.sideSpeed = (Math.random() - 0.5) * 3;
self.lifetime = 60 + Math.random() * 40;
self.maxLifetime = self.lifetime;
self.update = function () {
self.y += self.speed;
self.x += self.sideSpeed;
self.lifetime--;
// Fade and expand over time
var fadeProgress = 1 - self.lifetime / self.maxLifetime;
self.alpha = Math.max(0, 0.8 - fadeProgress * 1.2);
self.scaleX = 0.3 + fadeProgress * 2;
self.scaleY = 0.3 + fadeProgress * 2;
};
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 = gameSpeed;
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87CEEB
});
/****
* Game Code
****/
var player;
var obstacles = [];
var coins = [];
var powerups = [];
var bullets = [];
var hasWeapon = false;
var weaponTimer = 0;
var weaponDuration = 1200; // 20 seconds at 60fps
var laneLines = [];
var trees = [];
var bushes = [];
var rocks = [];
var flowers = [];
var currentGreenAreaType = 'forest'; // forest, grass, dark, meadow, jungle
var greenAreaChangeTimer = 0;
var greenAreaChangeDuration = 1800; // 30 seconds at 60fps
var gameSpeed = 8;
var maxSpeed = 20;
var speedIncrement = 0.005;
var distance = 0;
var obstacleSpawnTimer = 0;
var coinSpawnTimer = 0;
var powerupSpawnTimer = 0;
var laneLineSpawnTimer = 0;
var treeSpawnTimer = 0;
var lastSwipeX = 0;
var lastSwipeY = 0;
var swipeStarted = false;
var policeMusicPlaying = false;
var policeOnScreen = false;
var lives = 3;
var maxLives = 3;
var exhaustParticles = [];
var exhaustSpawnTimer = 0;
var flames = [];
var smokes = [];
var debrisParticles = [];
var rainDrops = [];
var rainSpawnTimer = 0;
// Rain cycle variables
var isRaining = false;
var rainTimer = 0;
var rainDuration = 0; // Will be set randomly
var rainCooldown = 0; // Will be set randomly
var nextRainEvent = 0; // Timer for next rain event
var rainSoundPlaying = false;
var thunderTimer = 0;
var nextThunderTime = 0;
// Day/night cycle variables
var dayNightTimer = 0;
var dayNightCycleDuration = 3600; // 60 seconds (1 minute) at 60fps
var isDay = true;
var isTransitioning = false;
// Game timer for police lane changing feature
var gameTimer = 0;
var laneChangeStartTime = 7200; // 2 minutes at 60fps (2 * 60 * 60)
// Night speed multiplier
var nightSpeedMultiplier = 1.25; // 25% faster during night
var baseGameSpeed = 8; // Store the base game speed
var dayColors = {
sky: 0x87CEEB,
// Light blue sky
forest: 0x228b22,
// Forest green
road: 0xffffff // Normal road color
};
var nightColors = {
sky: 0x191970,
// Midnight blue
forest: 0x0f2f0f,
// Dark forest green
road: 0x404040 // Darker road color
};
// Create road background
var roadBackground = game.addChild(LK.getAsset('roadBackground', {
anchorX: 0.5,
anchorY: 0.5
}));
roadBackground.x = 1024; // Center of screen
roadBackground.y = 1366;
// Create green forest backgrounds on sides
var leftForest = game.addChild(LK.getAsset('forestBackground', {
anchorX: 0.5,
anchorY: 0.5
}));
leftForest.x = 238; // Center of left side area
leftForest.y = 1366;
var rightForest = game.addChild(LK.getAsset('forestBackground', {
anchorX: 0.5,
anchorY: 0.5
}));
rightForest.x = 1810; // Center of right side area
rightForest.y = 1366;
// Create road borders
var leftBorder = game.addChild(LK.getAsset('roadBorder', {
anchorX: 0.5,
anchorY: 0.5
}));
leftBorder.x = 476; // Left of leftmost lane
leftBorder.y = 1366;
var rightBorder = game.addChild(LK.getAsset('roadBorder', {
anchorX: 0.5,
anchorY: 0.5
}));
rightBorder.x = 1572; // Right of rightmost lane
rightBorder.y = 1366;
// Create player
player = game.addChild(new Player());
player.scaleX = 1.9;
player.scaleY = 1.9;
// Create score display
var scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreText);
// Distance display removed - only counting coins for score
// Create lives display as hearts in top right
var healthBars = [];
for (var h = 0; h < maxLives; h++) {
var heart = LK.getAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
heart.x = -50 - h * 50;
heart.y = 80;
LK.gui.topRight.addChild(heart);
healthBars.push(heart);
}
// Touch controls
game.down = function (x, y, obj) {
lastSwipeX = x;
lastSwipeY = y;
swipeStarted = true;
};
game.up = function (x, y, obj) {
if (swipeStarted) {
var deltaX = x - lastSwipeX;
var deltaY = y - lastSwipeY;
var swipeThreshold = 100;
if (Math.abs(deltaX) > Math.abs(deltaY)) {
// Horizontal swipe
if (deltaX > swipeThreshold) {
player.moveRight();
} else if (deltaX < -swipeThreshold) {
player.moveLeft();
}
}
}
swipeStarted = false;
};
function spawnObstacle() {
var obstacle = new Obstacle();
var laneIndex = Math.floor(Math.random() * 3);
obstacle.x = player.lanes[laneIndex];
obstacle.y = -100;
obstacle.speed = gameSpeed;
obstacle.scaleX = 0.9;
obstacle.scaleY = 0.9;
// Set original lane index for lane changing
obstacle.originalLaneIndex = laneIndex;
// Enable lane changing after 2 minutes if game has been running long enough
if (gameTimer >= laneChangeStartTime) {
obstacle.canChangeLanes = Math.random() < 0.3; // 30% chance to be a lane changer
}
tween(obstacle, {
scaleX: 1.9,
scaleY: 1.9
}, {
duration: 400,
easing: tween.easeOut
});
obstacles.push(obstacle);
game.addChild(obstacle);
}
function spawnCoin() {
var coin = new Coin();
var laneIndex = Math.floor(Math.random() * 3);
var targetX = player.lanes[laneIndex];
var canSpawn = true;
// Check if there's an obstacle in this lane that would conflict
for (var i = 0; i < obstacles.length; i++) {
var obstacle = obstacles[i];
// Check if obstacle is in the same lane and close to spawn area
if (Math.abs(obstacle.x - targetX) < 50 && obstacle.y >= -300 && obstacle.y <= 200) {
canSpawn = false;
break;
}
}
// Also check if there's a powerup in this lane that would conflict
if (canSpawn) {
for (var p = 0; p < powerups.length; p++) {
var powerup = powerups[p];
// Check if powerup is in the same lane and close to spawn area
if (Math.abs(powerup.x - targetX) < 50 && powerup.y >= -300 && powerup.y <= 200) {
canSpawn = false;
break;
}
}
}
// If we can't spawn in the selected lane, try other lanes
if (!canSpawn) {
var availableLanes = [];
for (var lane = 0; lane < 3; lane++) {
var laneX = player.lanes[lane];
var laneAvailable = true;
// Check for obstacles in this lane
for (var j = 0; j < obstacles.length; j++) {
var obs = obstacles[j];
if (Math.abs(obs.x - laneX) < 50 && obs.y >= -300 && obs.y <= 200) {
laneAvailable = false;
break;
}
}
// Also check for powerups in this lane
if (laneAvailable) {
for (var k = 0; k < powerups.length; k++) {
var pup = powerups[k];
if (Math.abs(pup.x - laneX) < 50 && pup.y >= -300 && pup.y <= 200) {
laneAvailable = false;
break;
}
}
}
if (laneAvailable) {
availableLanes.push(lane);
}
}
// If no lanes are available, don't spawn coin this time
if (availableLanes.length === 0) {
return;
}
// Pick a random available lane
laneIndex = availableLanes[Math.floor(Math.random() * availableLanes.length)];
targetX = player.lanes[laneIndex];
}
coin.x = targetX;
coin.y = -50;
coin.speed = gameSpeed;
coin.scaleX = 0.5;
coin.scaleY = 0.5;
tween(coin, {
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeOut
});
coins.push(coin);
game.addChild(coin);
}
function spawnPowerUp() {
var powerup = new PowerUp();
var laneIndex = Math.floor(Math.random() * 3);
powerup.x = player.lanes[laneIndex];
powerup.y = -50;
powerup.speed = gameSpeed;
powerup.scaleX = 0.3;
powerup.scaleY = 0.3;
tween(powerup, {
scaleX: 1,
scaleY: 1
}, {
duration: 600,
easing: tween.easeOut
});
powerups.push(powerup);
game.addChild(powerup);
}
function spawnLaneLine() {
// Lane dividers between lanes
var positions = [837, 1211]; // Between lanes 0-1 and 1-2
for (var i = 0; i < positions.length; i++) {
var laneLine = new LaneLine();
laneLine.x = positions[i];
laneLine.y = -20;
laneLine.speed = gameSpeed;
laneLines.push(laneLine);
game.addChild(laneLine);
}
}
function spawnExhaustParticle() {
var particle = new ExhaustParticle();
particle.x = player.x + (Math.random() - 0.5) * 40;
particle.y = player.y + 20;
particle.scaleX = 0.5 + Math.random() * 0.5;
particle.scaleY = 0.5 + Math.random() * 0.5;
particle.alpha = 0.6 + Math.random() * 0.4;
exhaustParticles.push(particle);
game.addChild(particle);
}
function createFlameEffect(x, y, parentCar) {
// Create multiple flame particles
for (var i = 0; i < 12; i++) {
// Increased from 8 to 12 flames
var flame = new Flame();
flame.x = x + (Math.random() - 0.5) * 80; // Increased spread from 60 to 80
flame.y = y + Math.random() * 40; // Increased spread from 30 to 40
flame.scaleX = 1.2 + Math.random() * 0.8; // Increased base size from 0.5 to 1.2
flame.scaleY = 1.2 + Math.random() * 0.8; // Increased base size from 0.5 to 1.2
// Attach flame to police car if provided
if (parentCar) {
flame.parentCar = parentCar;
flame.offsetX = (Math.random() - 0.5) * 80;
flame.offsetY = Math.random() * 40 - 60; // Flames above the car
}
flames.push(flame);
game.addChild(flame);
}
// Create smoke particles
for (var j = 0; j < 6; j++) {
// Increased from 4 to 6 smoke particles
var smoke = new Smoke();
smoke.x = x + (Math.random() - 0.5) * 50; // Increased spread from 40 to 50
smoke.y = y - 10 + Math.random() * 30; // Increased spread from 20 to 30
smoke.alpha = 0.4 + Math.random() * 0.3;
smoke.scaleX = 1.5 + Math.random() * 0.5; // Increased smoke size
smoke.scaleY = 1.5 + Math.random() * 0.5; // Increased smoke size
smokes.push(smoke);
game.addChild(smoke);
}
// Create debris particles for explosion effect
for (var k = 0; k < 15; k++) {
var debris = new DebrisParticle();
debris.x = x + (Math.random() - 0.5) * 40;
debris.y = y + (Math.random() - 0.5) * 30;
debris.scaleX = 0.5 + Math.random() * 1.0;
debris.scaleY = 0.5 + Math.random() * 1.0;
debrisParticles.push(debris);
game.addChild(debris);
}
}
function spawnLandscapeElements() {
// Spawn bushes occasionally
if (Math.random() < 0.4) {
spawnBushes();
}
// Spawn rocks occasionally
if (Math.random() < 0.2) {
spawnRocks();
}
// Spawn flowers occasionally in meadow areas
if (currentGreenAreaType === 'meadow' && Math.random() < 0.3) {
spawnFlowers();
}
}
function spawnBushes() {
// Spawn bushes on left side
var leftPositions = [150, 250, 350];
for (var i = 0; i < leftPositions.length; i++) {
if (Math.random() < 0.5) {
var leftBush = new Bush();
leftBush.x = leftPositions[i];
leftBush.y = -60;
leftBush.speed = gameSpeed;
leftBush.scaleX = 0.7 + Math.random() * 0.6;
leftBush.scaleY = 0.7 + Math.random() * 0.6;
if (!isDay) leftBush.alpha = 0.7;
bushes.push(leftBush);
game.addChild(leftBush);
}
}
// Spawn bushes on right side
var rightPositions = [1698, 1798, 1898];
for (var j = 0; j < rightPositions.length; j++) {
if (Math.random() < 0.5) {
var rightBush = new Bush();
rightBush.x = rightPositions[j];
rightBush.y = -60;
rightBush.speed = gameSpeed;
rightBush.scaleX = 0.7 + Math.random() * 0.6;
rightBush.scaleY = 0.7 + Math.random() * 0.6;
if (!isDay) rightBush.alpha = 0.7;
bushes.push(rightBush);
game.addChild(rightBush);
}
}
}
function spawnRocks() {
// Spawn rocks on left side
if (Math.random() < 0.6) {
var leftRock = new Rock();
leftRock.x = 120 + Math.random() * 200;
leftRock.y = -40;
leftRock.speed = gameSpeed;
leftRock.scaleX = 0.8 + Math.random() * 0.4;
leftRock.scaleY = 0.8 + Math.random() * 0.4;
var grayVariation = 0.7 + Math.random() * 0.3;
leftRock.tint = grayVariation * 0x808080 | 0;
if (!isDay) leftRock.alpha = 0.6;
rocks.push(leftRock);
game.addChild(leftRock);
}
// Spawn rocks on right side
if (Math.random() < 0.6) {
var rightRock = new Rock();
rightRock.x = 1680 + Math.random() * 200;
rightRock.y = -40;
rightRock.speed = gameSpeed;
rightRock.scaleX = 0.8 + Math.random() * 0.4;
rightRock.scaleY = 0.8 + Math.random() * 0.4;
var grayVariation = 0.7 + Math.random() * 0.3;
rightRock.tint = grayVariation * 0x808080 | 0;
if (!isDay) rightRock.alpha = 0.6;
rocks.push(rightRock);
game.addChild(rightRock);
}
}
function spawnFlowers() {
// Spawn flowers on left side
for (var i = 0; i < 3; i++) {
if (Math.random() < 0.4) {
var leftFlower = new Flower();
leftFlower.x = 180 + Math.random() * 120;
leftFlower.y = -20;
leftFlower.speed = gameSpeed;
leftFlower.scaleX = 0.8 + Math.random() * 0.4;
leftFlower.scaleY = 0.8 + Math.random() * 0.4;
var flowerColors = [0xff69b4, 0xff1493, 0xffd700, 0xff6347, 0x9370db];
leftFlower.tint = flowerColors[Math.floor(Math.random() * flowerColors.length)];
flowers.push(leftFlower);
game.addChild(leftFlower);
}
}
// Spawn flowers on right side
for (var j = 0; j < 3; j++) {
if (Math.random() < 0.4) {
var rightFlower = new Flower();
rightFlower.x = 1720 + Math.random() * 120;
rightFlower.y = -20;
rightFlower.speed = gameSpeed;
rightFlower.scaleX = 0.8 + Math.random() * 0.4;
rightFlower.scaleY = 0.8 + Math.random() * 0.4;
var flowerColors = [0xff69b4, 0xff1493, 0xffd700, 0xff6347, 0x9370db];
rightFlower.tint = flowerColors[Math.floor(Math.random() * flowerColors.length)];
flowers.push(rightFlower);
game.addChild(rightFlower);
}
}
}
function changeGreenAreaType() {
var areaTypes = ['forest', 'grass', 'dark', 'meadow', 'jungle'];
var newType = areaTypes[Math.floor(Math.random() * areaTypes.length)];
if (newType !== currentGreenAreaType) {
currentGreenAreaType = newType;
var newAssetName = currentGreenAreaType === 'forest' ? 'forestBackground' : currentGreenAreaType === 'grass' ? 'grassField' : currentGreenAreaType === 'dark' ? 'darkForest' : currentGreenAreaType === 'meadow' ? 'meadow' : 'jungleArea';
// Create new forest backgrounds
var newLeftForest = game.addChild(LK.getAsset(newAssetName, {
anchorX: 0.5,
anchorY: 0.5
}));
newLeftForest.x = 238;
newLeftForest.y = -1366; // Start above screen
var newRightForest = game.addChild(LK.getAsset(newAssetName, {
anchorX: 0.5,
anchorY: 0.5
}));
newRightForest.x = 1810;
newRightForest.y = -1366; // Start above screen
// Apply current day/night colors
var targetColors = isDay ? dayColors : nightColors;
newLeftForest.tint = targetColors.forest;
newRightForest.tint = targetColors.forest;
// Animate new backgrounds into view
tween(newLeftForest, {
y: 1366
}, {
duration: 2000,
easing: tween.easeInOut
});
tween(newRightForest, {
y: 1366
}, {
duration: 2000,
easing: tween.easeInOut
});
// Move old backgrounds out and destroy them
tween(leftForest, {
y: 4098 // Move below screen
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
leftForest.destroy();
}
});
tween(rightForest, {
y: 4098 // Move below screen
}, {
duration: 2000,
easing: tween.easeInOut,
onFinish: function onFinish() {
rightForest.destroy();
}
});
// Update references
leftForest = newLeftForest;
rightForest = newRightForest;
}
}
function spawnTrees() {
// Spawn trees on left side of road
var leftPositions = [100, 200, 300, 400];
for (var i = 0; i < leftPositions.length; i++) {
if (Math.random() < 0.7) {
var leftTree = new Tree();
leftTree.x = leftPositions[i];
leftTree.y = -80;
leftTree.speed = gameSpeed;
// Add some variation in scale
leftTree.scaleX = 0.8 + Math.random() * 0.4;
leftTree.scaleY = 0.8 + Math.random() * 0.4;
// Add slight tint variation for natural look
var tintVariation = 0.9 + Math.random() * 0.2;
leftTree.tint = tintVariation * 0x90EE90 | 0;
// Apply current day/night brightness
if (!isDay) {
leftTree.alpha = 0.6;
}
trees.push(leftTree);
game.addChild(leftTree);
}
}
// Spawn trees on right side of road
var rightPositions = [1648, 1748, 1848, 1948];
for (var j = 0; j < rightPositions.length; j++) {
if (Math.random() < 0.7) {
var rightTree = new Tree();
rightTree.x = rightPositions[j];
rightTree.y = -80;
rightTree.speed = gameSpeed;
// Add some variation in scale
rightTree.scaleX = 0.8 + Math.random() * 0.4;
rightTree.scaleY = 0.8 + Math.random() * 0.4;
// Add slight tint variation for natural look
var tintVariation = 0.9 + Math.random() * 0.2;
rightTree.tint = tintVariation * 0x90EE90 | 0;
// Apply current day/night brightness
if (!isDay) {
rightTree.alpha = 0.6;
}
trees.push(rightTree);
game.addChild(rightTree);
}
}
}
function spawnRain() {
// Spawn multiple rain drops across the screen width
for (var i = 0; i < 8; i++) {
var rainDrop = new RainDrop();
rainDrop.x = Math.random() * 2048; // Random X across screen width
rainDrop.y = -20 - Math.random() * 50; // Start above screen
rainDrop.speed = gameSpeed + 15 + Math.random() * 10; // Rain speed based on game speed
rainDrops.push(rainDrop);
game.addChild(rainDrop);
}
}
// Main game loop
game.update = function () {
// Update game timer
gameTimer++;
// Calculate current base speed with gradual increase
var currentBaseSpeed = Math.min(maxSpeed, baseGameSpeed + gameTimer * speedIncrement);
// Apply night speed multiplier
gameSpeed = isDay ? currentBaseSpeed : currentBaseSpeed * nightSpeedMultiplier;
// Distance tracking removed - only counting coins for score
// Spawn obstacles - more frequent during night
obstacleSpawnTimer++;
var obstacleSpawnRate = isDay ? 60 + Math.random() * 60 : 30 + Math.random() * 30; // Night: 30-60 frames, Day: 60-120 frames
if (obstacleSpawnTimer > obstacleSpawnRate) {
spawnObstacle();
obstacleSpawnTimer = 0;
}
// Spawn coins - dynamically adjust spawn rate based on game speed (increased frequency)
coinSpawnTimer++;
var coinSpawnRate = Math.max(20, 80 - (gameSpeed - 8) * 4); // Much faster spawning as speed increases
if (coinSpawnTimer > coinSpawnRate + Math.random() * 20) {
spawnCoin();
coinSpawnTimer = 0;
}
// Spawn powerups (rare spawn - every 1 minute)
powerupSpawnTimer++;
if (powerupSpawnTimer > 3600) {
// 1 minute (60 seconds * 60 fps)
spawnPowerUp();
powerupSpawnTimer = 0;
}
// Spawn lane lines
laneLineSpawnTimer++;
if (laneLineSpawnTimer > 30) {
spawnLaneLine();
laneLineSpawnTimer = 0;
}
// Spawn trees and landscape elements
treeSpawnTimer++;
if (treeSpawnTimer > 45) {
spawnTrees();
spawnLandscapeElements();
treeSpawnTimer = 0;
}
// Change green area types periodically
greenAreaChangeTimer++;
if (greenAreaChangeTimer > greenAreaChangeDuration) {
changeGreenAreaType();
greenAreaChangeTimer = 0;
// Randomize next change duration
greenAreaChangeDuration = 1200 + Math.random() * 1800; // 20-50 seconds
}
// Update obstacles
var currentPoliceOnScreen = false;
for (var i = obstacles.length - 1; i >= 0; i--) {
var obstacle = obstacles[i];
obstacle.speed = gameSpeed;
// Check if police car is on screen
if (obstacle.y >= -200 && obstacle.y <= 2900) {
currentPoliceOnScreen = true;
}
// Remove obstacles that are off screen
if (obstacle.y > 2800) {
obstacle.destroy();
obstacles.splice(i, 1);
continue;
}
// Check collision with player (skip if obstacle is already hit)
if (!obstacle.isHit && player.intersects(obstacle)) {
// Play crash sound
try {
LK.getSound('crash').play();
} catch (e) {
console.log('Crash sound error:', e);
}
// Reduce lives
lives--;
// Hide the health bar corresponding to lost life
if (lives >= 0 && lives < healthBars.length) {
healthBars[healthBars.length - 1 - lives].visible = false;
}
// Flash screen and remove obstacle
LK.effects.flashScreen(0xff0000, 500);
obstacle.destroy();
obstacles.splice(i, 1);
// Check if game over
if (lives <= 0) {
// Add delay to allow crash sound to play before game over
LK.setTimeout(function () {
LK.showGameOver();
}, 800); // Wait 800ms for crash sound to play
return;
}
// Make player temporarily invulnerable
player.alpha = 0.5;
LK.setTimeout(function () {
player.alpha = 1.0;
}, 1500); // 1.5 seconds of invulnerability
continue;
}
}
// Handle police music based on police presence
if (currentPoliceOnScreen && !policeMusicPlaying) {
// Start police siren as a sound effect that loops instead of music
// This allows it to play alongside the background music
try {
var policeSiren = LK.getSound('policemusic');
if (policeSiren) {
policeSiren.loop = true;
policeSiren.play();
}
} catch (e) {
console.log('Police siren play error:', e);
}
policeMusicPlaying = true;
policeOnScreen = true;
} else if (!currentPoliceOnScreen && policeMusicPlaying) {
// Stop police siren sound
try {
var policeSiren = LK.getSound('policemusic');
if (policeSiren) {
policeSiren.stop();
}
} catch (e) {
console.log('Police siren stop error:', e);
}
policeMusicPlaying = false;
policeOnScreen = false;
} else if (currentPoliceOnScreen && policeMusicPlaying) {
// Ensure police siren continues playing if it stopped
try {
var policeSiren = LK.getSound('policemusic');
if (policeSiren && !policeSiren.playing) {
policeSiren.loop = true;
policeSiren.play();
}
} catch (e) {
console.log('Police siren restart error:', e);
}
}
// Update coins
for (var j = coins.length - 1; j >= 0; j--) {
var coin = coins[j];
coin.speed = gameSpeed;
// Remove coins that are off screen
if (coin.y > 2800) {
coin.destroy();
coins.splice(j, 1);
continue;
}
// Check collection
if (!coin.collected && player.intersects(coin)) {
coin.collected = true;
LK.setScore(LK.getScore() + 1); // Each coin is worth exactly 1 point
scoreText.setText('Score: ' + LK.getScore());
LK.getSound('collect').play();
// Enhanced visual effect with faster animation for higher speeds
var animationDuration = Math.max(200, 400 - (gameSpeed - 8) * 10);
tween(coin, {
alpha: 0,
scaleX: 2.5,
scaleY: 2.5,
y: coin.y - 50
}, {
duration: animationDuration,
easing: tween.easeOut,
onFinish: function onFinish() {
coin.destroy();
}
});
coins.splice(j, 1);
}
}
// Update powerups
for (var p = powerups.length - 1; p >= 0; p--) {
var powerup = powerups[p];
powerup.speed = gameSpeed;
// Remove powerups that are off screen or expired
if (powerup.y > 2800 || powerup.lifetime <= 0) {
powerup.destroy();
powerups.splice(p, 1);
continue;
}
// Check collection
if (!powerup.collected && player.intersects(powerup)) {
powerup.collected = true;
hasWeapon = true;
weaponTimer = weaponDuration; // 20 seconds
LK.getSound('collect').play();
// Visual effect
tween(powerup, {
alpha: 0,
scaleX: 3,
scaleY: 3
}, {
duration: 400,
onFinish: function onFinish() {
powerup.destroy();
}
});
powerups.splice(p, 1);
}
}
// Update lane lines
for (var k = laneLines.length - 1; k >= 0; k--) {
var laneLine = laneLines[k];
laneLine.speed = gameSpeed;
// Remove lane lines that are off screen
if (laneLine.y > 2800) {
laneLine.destroy();
laneLines.splice(k, 1);
}
}
// Update trees
for (var t = trees.length - 1; t >= 0; t--) {
var tree = trees[t];
tree.speed = gameSpeed;
// Remove trees that are off screen
if (tree.y > 2800) {
tree.destroy();
trees.splice(t, 1);
}
}
// Update bushes
for (var bush = bushes.length - 1; bush >= 0; bush--) {
var bushElement = bushes[bush];
bushElement.speed = gameSpeed;
if (bushElement.y > 2800) {
bushElement.destroy();
bushes.splice(bush, 1);
}
}
// Update rocks
for (var rock = rocks.length - 1; rock >= 0; rock--) {
var rockElement = rocks[rock];
rockElement.speed = gameSpeed;
if (rockElement.y > 2800) {
rockElement.destroy();
rocks.splice(rock, 1);
}
}
// Update flowers
for (var flower = flowers.length - 1; flower >= 0; flower--) {
var flowerElement = flowers[flower];
flowerElement.speed = gameSpeed;
if (flowerElement.y > 2800) {
flowerElement.destroy();
flowers.splice(flower, 1);
}
}
// Handle rain cycle logic
if (!isRaining) {
// Check if it's time to start raining
nextRainEvent++;
if (nextRainEvent >= rainCooldown) {
// Start rain cycle
isRaining = true;
rainTimer = 0;
// Random rain duration: 10-60 seconds (600-3600 frames at 60fps)
rainDuration = 600 + Math.random() * 3000; // 10 seconds to 1 minute
nextRainEvent = 0;
// Start rain music
if (!rainSoundPlaying) {
try {
LK.playMusic('rain');
} catch (e) {
console.log('Rain music play error:', e);
}
rainSoundPlaying = true;
}
// Initialize thunder timing for this rain period
thunderTimer = 0;
nextThunderTime = 180 + Math.random() * 600; // First thunder in 3-13 seconds
console.log('Rain started for', Math.floor(rainDuration / 60), 'seconds');
}
} else {
// Currently raining
rainTimer++;
// Spawn rain particles while raining
rainSpawnTimer++;
if (rainSpawnTimer >= 2) {
// Spawn rain every 2 frames for heavy rain effect
spawnRain();
rainSpawnTimer = 0;
}
// Handle thunder during rain
thunderTimer++;
if (thunderTimer >= nextThunderTime) {
// Play thunder sound
try {
var thunderSound = LK.getSound('thunder');
if (thunderSound) {
thunderSound.play();
}
} catch (e) {
console.log('Thunder sound play error:', e);
}
// Add thunder flash effect - bright white flash
LK.effects.flashScreen(0xffffff, 300); // White flash for 300ms
// Set next thunder time (random between 5-20 seconds)
nextThunderTime = thunderTimer + (300 + Math.random() * 900); // 5-20 seconds at 60fps
}
// Check if rain should stop
if (rainTimer >= rainDuration) {
// Stop rain cycle
isRaining = false;
rainTimer = 0;
// Random cooldown period: 30-180 seconds (1800-10800 frames at 60fps)
rainCooldown = 1800 + Math.random() * 9000; // 30 seconds to 3 minutes
nextRainEvent = 0;
// Reset thunder timer
thunderTimer = 0;
nextThunderTime = 0;
// Gradually fade out existing rain drops
for (var fadeRain = 0; fadeRain < rainDrops.length; fadeRain++) {
var rainDrop = rainDrops[fadeRain];
tween(rainDrop, {
alpha: 0,
speed: rainDrop.speed * 0.3
}, {
duration: 2000 + Math.random() * 1000,
easing: tween.easeOut
});
}
console.log('Rain stopped. Next rain in', Math.floor(rainCooldown / 60), 'seconds');
}
}
// Stop rain music only when all rain effects are complete
if (!isRaining && rainSoundPlaying && rainDrops.length === 0) {
try {
LK.stopMusic();
// Restart background music after rain stops
LK.playMusic('bgmusic');
} catch (e) {
console.log('Rain music stop error:', e);
}
rainSoundPlaying = false;
}
// Spawn exhaust particles
exhaustSpawnTimer++;
if (exhaustSpawnTimer >= 3) {
spawnExhaustParticle();
exhaustSpawnTimer = 0;
}
// Update exhaust particles
for (var e = exhaustParticles.length - 1; e >= 0; e--) {
var particle = exhaustParticles[e];
// Remove particles that are expired or off screen
if (particle.lifetime <= 0 || particle.y < -50) {
particle.destroy();
exhaustParticles.splice(e, 1);
}
}
// Update flame particles
for (var f = flames.length - 1; f >= 0; f--) {
var flame = flames[f];
// Remove flames that are expired or off screen
if (flame.lifetime <= 0 || flame.y < -50) {
flame.destroy();
flames.splice(f, 1);
}
}
// Update smoke particles
for (var s = smokes.length - 1; s >= 0; s--) {
var smoke = smokes[s];
// Remove smoke that is expired or off screen
if (smoke.lifetime <= 0 || smoke.y < -50) {
smoke.destroy();
smokes.splice(s, 1);
}
}
// Update debris particles
for (var d = debrisParticles.length - 1; d >= 0; d--) {
var debris = debrisParticles[d];
// Remove debris that is expired or off screen
if (debris.lifetime <= 0 || debris.y > 2800) {
debris.destroy();
debrisParticles.splice(d, 1);
}
}
// Update rain particles
for (var r = rainDrops.length - 1; r >= 0; r--) {
var rain = rainDrops[r];
// Remove rain drops that are off screen
if (rain.y > 2800 || rain.x < -50 || rain.x > 2098) {
rain.destroy();
rainDrops.splice(r, 1);
}
}
// Handle weapon system
if (hasWeapon) {
weaponTimer--;
if (weaponTimer <= 0) {
hasWeapon = false;
}
// Shoot bullets every 25 frames (increased firing rate)
if (LK.ticks % 25 === 0) {
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y - 100;
bullets.push(bullet);
game.addChild(bullet);
// Play gun sound
LK.getSound('gunshot').play();
}
}
// Update bullets
for (var b = bullets.length - 1; b >= 0; b--) {
var bullet = bullets[b];
// Remove bullets that are off screen
if (bullet.y < -50) {
bullet.destroy();
bullets.splice(b, 1);
continue;
}
// Check bullet collision with obstacles
for (var o = obstacles.length - 1; o >= 0; o--) {
var obstacle = obstacles[o];
if (!obstacle.isHit && bullet.intersects(obstacle)) {
// Play police hit sound
try {
LK.getSound('policeHit').play();
} catch (e) {
console.log('Police hit sound error:', e);
}
// Destroy bullet immediately
bullet.destroy();
bullets.splice(b, 1);
// Mark obstacle as hit to prevent further collisions
obstacle.isHit = true;
// Create flame effect at police car position with car reference
createFlameEffect(obstacle.x, obstacle.y - 50, obstacle);
// Create burning effect with flames
tween(obstacle, {
tint: 0x000000,
alpha: 0
}, {
duration: 800,
easing: tween.easeOut,
onFinish: function onFinish() {
obstacle.isDestroyed = true; // Mark as destroyed for flame cleanup
obstacle.destroy();
// Remove from obstacles array after animation completes
var index = obstacles.indexOf(obstacle);
if (index > -1) {
obstacles.splice(index, 1);
}
}
});
break;
}
}
}
// Update day/night cycle
dayNightTimer++;
if (dayNightTimer >= dayNightCycleDuration) {
transitionDayNight();
dayNightTimer = 0;
}
// Police exhaust particles now stay in their natural layer order
// Road color no longer changes automatically
};
// Road color change function (kept for potential future use)
function changeRoadColor(newColor) {
roadBackground.tint = newColor;
}
// Day/night cycle transition function
function transitionDayNight() {
if (isTransitioning) return;
isTransitioning = true;
isDay = !isDay;
var targetColors = isDay ? dayColors : nightColors;
var transitionDuration = 2000; // 2 seconds transition
// Immediately update game speed for the new cycle
var currentBaseSpeed = Math.min(maxSpeed, baseGameSpeed + gameTimer * speedIncrement);
gameSpeed = isDay ? currentBaseSpeed : currentBaseSpeed * nightSpeedMultiplier;
// Transition background color
tween(game, {
backgroundColor: targetColors.sky
}, {
duration: transitionDuration,
easing: tween.easeInOut
});
// Transition forest backgrounds
tween(leftForest, {
tint: targetColors.forest
}, {
duration: transitionDuration,
easing: tween.easeInOut
});
tween(rightForest, {
tint: targetColors.forest
}, {
duration: transitionDuration,
easing: tween.easeInOut
});
// Transition road background
tween(roadBackground, {
tint: targetColors.road
}, {
duration: transitionDuration,
easing: tween.easeInOut,
onFinish: function onFinish() {
isTransitioning = false;
}
});
// Adjust trees brightness for night/day
var treeBrightness = isDay ? 1.0 : 0.6;
for (var i = 0; i < trees.length; i++) {
var tree = trees[i];
tween(tree, {
alpha: treeBrightness
}, {
duration: transitionDuration,
easing: tween.easeInOut
});
}
// Adjust landscape elements brightness for night/day
var elementBrightness = isDay ? 1.0 : 0.7;
// Update bushes brightness
for (var b = 0; b < bushes.length; b++) {
var bush = bushes[b];
tween(bush, {
alpha: elementBrightness
}, {
duration: transitionDuration,
easing: tween.easeInOut
});
}
// Update rocks brightness
for (var r = 0; r < rocks.length; r++) {
var rock = rocks[r];
tween(rock, {
alpha: elementBrightness
}, {
duration: transitionDuration,
easing: tween.easeInOut
});
}
// Flowers stay bright during day and dim slightly at night
var flowerBrightness = isDay ? 1.0 : 0.8;
for (var f = 0; f < flowers.length; f++) {
var flower = flowers[f];
tween(flower, {
alpha: flowerBrightness
}, {
duration: transitionDuration,
easing: tween.easeInOut
});
}
// Control player headlights based on day/night
var headlightAlpha = isDay ? 0 : 0.8;
tween(player.leftHeadlight, {
alpha: headlightAlpha
}, {
duration: transitionDuration,
easing: tween.easeInOut
});
tween(player.rightHeadlight, {
alpha: headlightAlpha
}, {
duration: transitionDuration,
easing: tween.easeInOut
});
}
// Spawn initial powerup at game start
spawnPowerUp();
// Initialize first rain cycle
rainCooldown = 1800 + Math.random() * 9000; // 30 seconds to 3 minutes before first rain
nextRainEvent = 0;
// Start background music - this will be the base music layer
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 1,
duration: 1000
}
});
;
Polis arabası kuş bakışı. In-Game asset. 2d. High contrast. No shadows
Düz gri renk. In-Game asset. 2d. High contrast. No shadows
Kuş bakışı agaç. In-Game asset. 2d. High contrast. No shadows
Kalp 3d. In-Game asset. 2d. High contrast. No shadows
Kırmızı ve sarı gradient renk. In-Game asset. 2d. High contrast. No shadows
Çiçek kuş bakışı. In-Game asset. 2d. High contrast. No shadows
Kuş bakışı polis aracı. In-Game asset. 2d. High contrast. No shadows