User prompt
Every time your enemy car spawns randomly, the color is different
User prompt
Let the shield effect rotate around itself ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
The animations of the car are broken and the health bar is not visible, fix them ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Fix it when the car slipped up
User prompt
Let the car have animations ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Don't let the shield effect rotate too much
User prompt
Add rotation effect to shield
User prompt
Slow down the speed from 250 points to 400 points, then decrease the speed
User prompt
After 250 points, it accelerates a little more up to 400 points, and at 400 points it returns to normal speed.
User prompt
Remove speed inscription
User prompt
Put an inscription showing how fast the car is and place it somewhere on the screen
User prompt
Let the fireball pass through the car while there is a shield
User prompt
Let's get the hellbox while there's a shield
User prompt
Don't let hellbox come out after 70 points
User prompt
After 200 points, only the barriers come out. Let the barriers spawn at the same time in 2 lanes after 200 points
User prompt
Add points to the fireball as enemies, and the points increase when you pass by the fireballs
User prompt
After 70 points, the score will continue to increase. Let fireballs earn points
User prompt
Let's get points from fireballs
User prompt
Don't let there be a fireball before 60 points
User prompt
After 70 points, the game will return to its normal speed
User prompt
After 70 points, only the fireball will come out
User prompt
GameLet the acceleration of the game start at 20 points, but not too much until 70 points
User prompt
When we say Hellboxa, let the car health increase a little
User prompt
Let the Hellbox spawn in random places, like a spell bottle
User prompt
Update and handle HellBox collisions in main game update loop
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // Enemy Car Class var EnemyCar = Container.expand(function () { var self = Container.call(this); var car = self.attachAsset('enemyCar', { anchorX: 0.5, anchorY: 0.5 }); self.lane = 1; self.speed = 18; self.update = function () { self.y += self.speed * gameSpeed; }; return self; }); // Fireball Class var Fireball = Container.expand(function () { var self = Container.call(this); var fireball = self.attachAsset('Fireball', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 28; self.lane = 1; // --- Health bar for Fireball (ace) --- self.maxLife = 3; self.life = self.maxLife; // Health bar background self.lifeBarBg = self.attachAsset('lifeBarBg', { anchorX: 0.5, anchorY: 0.5, width: 220, height: 220, y: -90, alpha: 0.92 }); // Health bar border self.lifeBarBorder = self.attachAsset('lifeBarBorder', { anchorX: 0.5, anchorY: 0.5, width: 260, height: 260, y: -90, alpha: 1 }); // Health bar fill self.lifeBar = self.attachAsset('lifeBar', { anchorX: 0.0, anchorY: 0.5, width: 180, height: 60, x: -90, y: -90, alpha: 1 }); // Heart icon self.lifeBarHeart = self.attachAsset('heartIcon', { anchorX: 0.5, anchorY: 0.5, width: 70, height: 70, x: -130, y: -90, alpha: 1 }); // Helper to update fireball health bar UI self.updateLifeBar = function () { // Show only if not full and not dead var show = self.life < self.maxLife && self.life > 0; self.lifeBarBg.visible = show; self.lifeBar.visible = show; self.lifeBarBorder.visible = show; self.lifeBarHeart.visible = show; // Set width proportional to life var minWidth = 24; var w = self.life > 0 ? Math.max(minWidth, Math.round(180 * (self.life / self.maxLife))) : 0; self.lifeBar.width = w; // Hide if dead if (self.life <= 0) { self.lifeBarBg.visible = false; self.lifeBar.visible = false; self.lifeBarBorder.visible = false; self.lifeBarHeart.visible = false; } }; // Initialize bar state self.updateLifeBar(); self.update = function () { // Move fireball down the screen self.y += self.speed * gameSpeed; // Keep health bar above fireball self.lifeBarBg.y = -90; self.lifeBarBorder.y = -90; self.lifeBar.y = -90; self.lifeBarHeart.y = -90; self.lifeBar.x = -90; self.lifeBarHeart.x = -130; self.updateLifeBar(); }; return self; }); // Lane Divider Class var LaneDivider = Container.expand(function () { var self = Container.call(this); var div = self.attachAsset('laneDivider', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 18; self.update = function () { self.y += self.speed * gameSpeed; }; return self; }); // Obstacle Class var Obstacle = Container.expand(function () { var self = Container.call(this); var obs = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); self.lane = 1; self.speed = 18; self.update = function () { self.y += self.speed * gameSpeed; }; return self; }); // Player Car Class var PlayerCar = Container.expand(function () { var self = Container.call(this); var car = self.attachAsset('playerCar', { anchorX: 0.5, anchorY: 0.5 }); self.lane = 1; // 0: left, 1: center, 2: right self.life = playerMaxLife; // Add life property to player car self.setLane = function (laneIdx) { self.lane = laneIdx; // Animate to new lane position var targetX = lanes[self.lane]; tween(self, { x: targetX }, { duration: 120, easing: tween.cubicOut, onUpdate: function onUpdate() { updateLifeBar(); } }); updateLifeBar(); }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Use spellBottle as heart // Health bar assets // Spell bottle asset (example: blue bottle, 120x180) // When the player picks up the magic bottle, the car bursts into flames (flame burst effect) // Lane positions (3 lanes) // Car (player) // Enemy car // Obstacle (barrier) // Road lane divider // Sound for crash // Sound for lane change // Music (background) var laneCount = 3; var laneWidth = 520; // Increased lane width for more space between lanes var lanes = [2048 / 2 - laneWidth, // left 2048 / 2, // center 2048 / 2 + laneWidth // right ]; // Game variables var playerCar; var enemyCars = []; var obstacles = []; var laneDividers = []; var score = 0; var highScore = storage.highScore || 0; var scoreTxt; var highScoreTxt; var gameSpeed = 1; var ticksSinceStart = 0; var swipeStartX = null; var swipeStartY = null; var swipeActive = false; var lastLane = 1; var spawnTick = 0; var dividerSpacing = 320; var dragNode = null; // --- LIFE SYSTEM --- var playerMaxLife = 5; var playerLife = playerMaxLife; // Health bar UI will be handled by a new, clear, and consistent system below // Score display scoreTxt = new Text2('0', { size: 120, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0.5); LK.gui.top.addChild(scoreTxt); // Shield timer display var shieldTxt = new Text2('', { size: 80, fill: 0x2BD5E6 }); shieldTxt.anchor.set(0.5, 0.5); LK.gui.top.addChild(shieldTxt); // High Score display highScoreTxt = new Text2('HI: ' + highScore, { size: 60, fill: 0xFFFF00 }); highScoreTxt.anchor.set(0.5, 0.5); LK.gui.top.addChild(highScoreTxt); // Add swipe left gesture to high score text var hiSwipeStartX = null; var hiSwipeStartY = null; var hiSwipeActive = false; highScoreTxt.down = function (x, y, obj) { hiSwipeStartX = x; hiSwipeStartY = y; hiSwipeActive = true; }; highScoreTxt.move = function (x, y, obj) { if (!hiSwipeActive) return; var dx = x - hiSwipeStartX; var dy = y - hiSwipeStartY; // Only consider horizontal swipes, ignore vertical if (Math.abs(dx) > 60 && Math.abs(dx) > Math.abs(dy)) { if (dx < 0) { // Swipe left detected on high score text // Flash the high score text white for feedback tween(highScoreTxt, { tint: 0xffffff }, { duration: 80, yoyo: true, repeat: 1, onComplete: function onComplete() { highScoreTxt.tint = 0xFFFF00; } }); hiSwipeActive = false; } } }; highScoreTxt.up = function (x, y, obj) { hiSwipeActive = false; }; // Start music LK.playMusic('bgmusic'); // Create player car playerCar = new PlayerCar(); playerCar.x = lanes[1]; playerCar.y = 2732 - 500; playerCar.setLane(1); // Shield properties playerCar.shieldActive = false; playerCar.shieldTicks = 0; // Add shield effect asset (invisible by default) var shieldEffect = LK.getAsset('centerCircle', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.2, scaleY: 1.2, x: playerCar.x, y: playerCar.y, alpha: 0.5, tint: 0xffffff }); shieldEffect.visible = false; game.addChild(shieldEffect); game.addChild(playerCar); // Add two vertical side stripes (left and right) to the play area var sideStripeWidth = 60; var sideStripeHeight = 2732; var leftStripe = LK.getAsset('laneDivider', { anchorX: 0.5, anchorY: 0, width: sideStripeWidth, height: sideStripeHeight, x: sideStripeWidth / 2, y: 0 }); var rightStripe = LK.getAsset('laneDivider', { anchorX: 0.5, anchorY: 0, width: sideStripeWidth, height: sideStripeHeight, x: 2048 - sideStripeWidth / 2, y: 0 }); game.addChild(leftStripe); game.addChild(rightStripe); // Create lane dividers (vertical lines for each lane) // For 3 lanes, we want to copy the center lane divider and place it to the right and left of the center stripe, without adding extra lines // The center divider is between lane 0 and lane 1, and between lane 1 and lane 2 // So, for 3 lanes, we want to draw the two dividers: one between lane 0 and 1, and one between lane 1 and 2 var dividerOffsets = []; // Find the X positions for the two dividers (between lanes) for (var l = 1; l < laneCount; l++) { dividerOffsets.push((lanes[l - 1] + lanes[l]) / 2); } // Now, for each divider, draw a set of stripes down the screen for (var d = 0; d < dividerOffsets.length; d++) { for (var i = 0; i < 10; i++) { // Center LaneDivider var divider = new LaneDivider(); divider.x = dividerOffsets[d]; divider.y = i * dividerSpacing; laneDividers.push(divider); game.addChild(divider); // Left copy var dividerLeft = new LaneDivider(); dividerLeft.x = dividerOffsets[d] - laneWidth; dividerLeft.y = i * dividerSpacing; laneDividers.push(dividerLeft); game.addChild(dividerLeft); // Right copy var dividerRight = new LaneDivider(); dividerRight.x = dividerOffsets[d] + laneWidth; dividerRight.y = i * dividerSpacing; laneDividers.push(dividerRight); game.addChild(dividerRight); } } // Prepare for dynamic spell bottle spawning var spellBottle = null; var spellBottleActive = false; var spellBottleLane = 1; // Add: track last spell bottle spawn tick to limit spawn rate var lastSpellBottleSpawnTick = -1000; // Helper: spawn enemy car, obstacle, or fireball function spawnObstacleOrEnemy() { var laneIdx = Math.floor(Math.random() * laneCount); var y = -300; if (score >= 70) { // Only spawn fireballs after 70 points if (!window.fireballs) window.fireballs = []; if (window.fireballs.length < 2) { var fireball = new Fireball(); fireball.lane = laneIdx; fireball.x = lanes[laneIdx]; fireball.y = y; window.fireballs.push(fireball); game.addChild(fireball); } } else { // Randomly decide: 60% enemy car, 25% obstacle, 15% fireball var rand = Math.random(); if (rand < 0.6) { var enemy = new EnemyCar(); enemy.lane = laneIdx; enemy.x = lanes[laneIdx]; enemy.y = y; enemyCars.push(enemy); game.addChild(enemy); } else if (rand < 0.85) { var obs = new Obstacle(); obs.lane = laneIdx; obs.x = lanes[laneIdx]; obs.y = y; obstacles.push(obs); game.addChild(obs); } else { // Limit fireballs: only spawn if fewer than 2 are on screen if (!window.fireballs) window.fireballs = []; if (window.fireballs.length < 2) { var fireball = new Fireball(); fireball.lane = laneIdx; fireball.x = lanes[laneIdx]; fireball.y = y; window.fireballs.push(fireball); game.addChild(fireball); } } } } // Helper: update score function updateScore(val) { score = val; scoreTxt.setText(score); if (score > highScore) { highScore = score; highScoreTxt.setText('HI: ' + highScore); storage.highScore = highScore; } } // Helper: update player health bar UI (global, for use in PlayerCar.setLane and elsewhere) function updateLifeBar() { // Always show the health bar unless dead var showBar = playerLife > 0; if (window.playerHealthBarBg) window.playerHealthBarBg.visible = showBar; if (window.playerHealthBarFill) window.playerHealthBarFill.visible = showBar; if (window.playerHealthBarBorder) window.playerHealthBarBorder.visible = showBar; // Removed: if (window.playerHealthBarHeart) window.playerHealthBarHeart.visible = showBar; // Position above player car if (playerCar && window.playerHealthBarBg && window.playerHealthBarFill && window.playerHealthBarBorder) { var barY = playerCar.y - 140; var barX = playerCar.x; window.playerHealthBarBg.x = barX; window.playerHealthBarBg.y = barY; window.playerHealthBarFill.x = barX - 240; window.playerHealthBarFill.y = barY; window.playerHealthBarBorder.x = barX; window.playerHealthBarBorder.y = barY; // Removed: window.playerHealthBarHeart.x = barX - 320; // Removed: window.playerHealthBarHeart.y = barY; // Set width proportional to life, always show a minimum width if not dead var minWidth = 38; var fillW = playerLife > 0 ? Math.max(minWidth, Math.round(480 * (playerLife / playerMaxLife))) : 0; window.playerHealthBarFill.width = fillW; } // Hide if dead if (playerLife <= 0) { if (window.playerHealthBarBg) window.playerHealthBarBg.visible = false; if (window.playerHealthBarFill) window.playerHealthBarFill.visible = false; if (window.playerHealthBarBorder) window.playerHealthBarBorder.visible = false; // Removed: if (window.playerHealthBarHeart) window.playerHealthBarHeart.visible = false; } } // Touch/drag/swipe handling game.down = function (x, y, obj) { swipeStartX = x; swipeStartY = y; swipeActive = true; dragNode = playerCar; }; game.move = function (x, y, obj) { // Only handle swipe if active if (!swipeActive) return; if (!dragNode) return; var dx = x - swipeStartX; var dy = y - swipeStartY; // Only consider horizontal swipes, ignore vertical if (Math.abs(dx) > 80 && Math.abs(dx) > Math.abs(dy)) { var newLane = playerCar.lane; if (dx < 0 && playerCar.lane > 0) { newLane = playerCar.lane - 1; } else if (dx > 0 && playerCar.lane < laneCount - 1) { newLane = playerCar.lane + 1; } if (newLane !== playerCar.lane) { playerCar.setLane(newLane); LK.getSound('swipe').play(); swipeActive = false; dragNode = null; } } }; game.up = function (x, y, obj) { swipeActive = false; dragNode = null; }; // Main game update loop game.update = function () { ticksSinceStart++; // Adjust acceleration: start at 20 points, increase slowly until 70 points, then ramp up if (score >= 70) { if (ticksSinceStart % 60 === 0 && gameSpeed < 4) { // After 70, ramp up faster if (gameSpeed < 2) { gameSpeed += 0.10; } else if (gameSpeed < 3) { gameSpeed += 0.16; } else { gameSpeed += 0.22; } if (gameSpeed > 4) gameSpeed = 4; } } else if (score >= 20) { // Between 20 and 70, increase very slowly if (ticksSinceStart % 90 === 0 && gameSpeed < 2) { gameSpeed += 0.04; if (gameSpeed > 2) gameSpeed = 2; } } else { gameSpeed = 1; } // Move lane dividers, loop to top for (var i = 0; i < laneDividers.length; i++) { var div = laneDividers[i]; div.update(); if (div.y > 2732 + 60) { div.y -= dividerSpacing * 10; } } // Spawn or move spell bottle if (!spellBottleActive) { // Determine spawn cooldown and chance based on score var bottleCooldown = score >= 50 ? 300 : 600; // 5s if score>=50, else 10s var bottleChance = score >= 50 ? 1 / 60 : 1 / 120; // 1/60 per frame if score>=50, else 1/120 // Only allow spawn if enough time has passed since last spawn if (ticksSinceStart - lastSpellBottleSpawnTick > bottleCooldown) { // Try to spawn with the appropriate chance if (Math.random() < bottleChance) { spellBottleLane = Math.floor(Math.random() * laneCount); var bottleX = lanes[spellBottleLane]; // Place the bottle at a fixed Y position (e.g., 900px from the top) var bottleY = 900; spellBottle = LK.getAsset('spellBottle', { anchorX: 0.5, anchorY: 1.0, x: bottleX, y: bottleY }); game.addChild(spellBottle); spellBottleActive = true; lastSpellBottleSpawnTick = ticksSinceStart; } } } else if (spellBottle) { // Move the spell bottle down the screen spellBottle.y += 18 * gameSpeed; // Off screen? Remove (if it has scrolled above the visible area) if (spellBottle.y < -200 || spellBottle.y > 2732 + 200) { spellBottle.destroy(); spellBottle = null; spellBottleActive = false; } // Check collision with playerCar for shield pickup if (spellBottle && !playerCar.shieldActive && spellBottle.intersects(playerCar)) { // Grant shield for 3 seconds playerCar.shieldActive = true; playerCar.shieldTicks = 180; // 3 seconds at 60fps // Add flame burst effect: flashObject with orange/yellow color, then white // Growing fire effect: overlay a fire image that grows in scale for 1s, then fades out var fireMagic = LK.getAsset('spellBottle', { anchorX: 0.5, anchorY: 0.5, x: playerCar.x, y: playerCar.y, scaleX: 1, scaleY: 1, alpha: 0.85, tint: 0xff6600 }); game.addChild(fireMagic); // Animate fire to grow and fade out tween(fireMagic, { scaleX: 2.2, scaleY: 2.2, alpha: 0 }, { duration: 1000, easing: tween.cubicOut, onUpdate: function onUpdate() { fireMagic.x = playerCar.x; fireMagic.y = playerCar.y; }, onComplete: function onComplete() { fireMagic.destroy(); } }); // Also flash the car for extra effect LK.effects.flashObject(playerCar, 0xffa500, 350); LK.setTimeout(function () { LK.effects.flashObject(playerCar, 0xffff00, 350); }, 350); spellBottle.destroy(); spellBottle = null; spellBottleActive = false; } } // Spawn enemies/obstacles every 40-60 ticks, randomize spawnTick++; var spawnInterval = 40 + Math.floor(Math.random() * 20); if (spawnTick > spawnInterval) { spawnObstacleOrEnemy(); spawnTick = 0; } // Update enemy cars for (var i = enemyCars.length - 1; i >= 0; i--) { var enemy = enemyCars[i]; enemy.update(); // Off screen if (enemy.y > 2732 + 300) { enemy.destroy(); enemyCars.splice(i, 1); updateScore(score + 1); continue; } // Collision with spell bottle if (spellBottle && enemy.intersects(spellBottle)) { spellBottle.destroy(); spellBottle = null; spellBottleActive = false; } // Collision with player if (enemy.intersects(playerCar)) { if (playerCar.shieldActive) { // Ignore collision, let player pass through enemy car while shield is active continue; } else { // --- LIFE SYSTEM: lose 1 life, give 1 to enemy, show bar --- if (playerLife > 0) { playerLife--; playerCar.life = playerLife; // Give 1 life to enemy (could be used for enemy powerup, here just for demo) if (!enemy.life) enemy.life = 0; enemy.life++; // If enemy is a fireball, update its health bar if (typeof enemy.updateLifeBar === "function") { enemy.updateLifeBar(); } updateLifeBar(); LK.effects.flashObject(playerCar, 0xff0000, 400); if (playerLife <= 0) { LK.getSound('crash').play(); LK.effects.flashScreen(0xff0000, 800); // Explosion effect at player car position LK.effects.flashObject(playerCar, 0xffffff, 700); LK.showGameOver(); return; } // Remove enemy on hit enemy.destroy(); enemyCars.splice(i, 1); continue; } else { LK.getSound('crash').play(); LK.effects.flashScreen(0xff0000, 800); // Explosion effect at player car position LK.effects.flashObject(playerCar, 0xffffff, 700); LK.showGameOver(); return; } } } } // Update obstacles for (var j = obstacles.length - 1; j >= 0; j--) { var obs = obstacles[j]; obs.update(); // Off screen if (obs.y > 2732 + 200) { obs.destroy(); obstacles.splice(j, 1); updateScore(score + 1); continue; } // Collision with player if (obs.intersects(playerCar)) { if (playerCar.shieldActive) { // Ignore collision, let player pass through obstacle while shield is active continue; } else { LK.getSound('crash').play(); LK.effects.flashScreen(0xff0000, 800); // Explosion effect at player car position LK.effects.flashObject(playerCar, 0xffffff, 700); LK.showGameOver(); return; } } } // Update fireballs if (!window.fireballs) window.fireballs = []; for (var f = window.fireballs.length - 1; f >= 0; f--) { var fireball = window.fireballs[f]; fireball.update(); // Off screen if (fireball.y > 2732 + 200) { fireball.destroy(); window.fireballs.splice(f, 1); continue; } // Collision with player if (fireball.intersects(playerCar)) { if (playerCar.shieldActive) { // Ignore collision, let player pass through fireball while shield is active fireball.destroy(); window.fireballs.splice(f, 1); continue; } else { LK.getSound('crash').play(); LK.effects.flashScreen(0xff3300, 900); LK.effects.flashObject(playerCar, 0xff6600, 700); LK.showGameOver(); return; } } } // --- HELLBOX SPAWNING & COLLISION HANDLING --- // Find all HellBoxes in the game (if any) if (!window.hellBoxes) window.hellBoxes = []; if (typeof window.lastHellBoxSpawnTick === "undefined") window.lastHellBoxSpawnTick = -1000; if (typeof window.hellBoxActive === "undefined") window.hellBoxActive = false; if (typeof window.hellBoxObj === "undefined") window.hellBoxObj = null; // HellBox spawn logic (like spell bottle) if (!window.hellBoxActive) { // Only allow spawn if enough time has passed since last spawn var hellBoxCooldown = score >= 50 ? 400 : 800; // 6.6s if score>=50, else 13s var hellBoxChance = score >= 50 ? 1 / 90 : 1 / 180; // 1/90 per frame if score>=50, else 1/180 if (ticksSinceStart - window.lastHellBoxSpawnTick > hellBoxCooldown) { if (Math.random() < hellBoxChance) { var hellBoxLane = Math.floor(Math.random() * laneCount); var hellBoxX = lanes[hellBoxLane]; // Place the HellBox at a random Y between 700 and 1200 var hellBoxY = 700 + Math.floor(Math.random() * 500); var hellBox = LK.getAsset('HellBox', { anchorX: 0.5, anchorY: 1.0, x: hellBoxX, y: hellBoxY }); game.addChild(hellBox); window.hellBoxes.push(hellBox); window.hellBoxActive = true; window.hellBoxObj = hellBox; window.lastHellBoxSpawnTick = ticksSinceStart; } } } else if (window.hellBoxObj) { // Move the HellBox down the screen window.hellBoxObj.y += 18 * gameSpeed; // Off screen? Remove if (window.hellBoxObj.y < -200 || window.hellBoxObj.y > 2732 + 200) { window.hellBoxObj.destroy(); var idx = window.hellBoxes.indexOf(window.hellBoxObj); if (idx !== -1) window.hellBoxes.splice(idx, 1); window.hellBoxObj = null; window.hellBoxActive = false; } } // HellBox collision and cleanup for (var h = window.hellBoxes.length - 1; h >= 0; h--) { var hellBox = window.hellBoxes[h]; if (!hellBox) continue; // Update position if needed (if HellBox has .update) if (typeof hellBox.update === "function") hellBox.update(); // Off screen? Remove if (hellBox.y > 2732 + 200) { hellBox.destroy(); window.hellBoxes.splice(h, 1); if (window.hellBoxObj === hellBox) { window.hellBoxObj = null; window.hellBoxActive = false; } continue; } // Collision with player if (hellBox.intersects(playerCar)) { if (playerCar.shieldActive) { // Ignore collision, let player pass through HellBox while shield is active hellBox.destroy(); window.hellBoxes.splice(h, 1); if (window.hellBoxObj === hellBox) { window.hellBoxObj = null; window.hellBoxActive = false; } continue; } else { // Player hit by HellBoxa: increase car health a little var healAmount = 1; if (playerLife < playerMaxLife) { playerLife = Math.min(playerLife + healAmount, playerMaxLife); playerCar.life = playerLife; updateLifeBar(); LK.effects.flashObject(playerCar, 0x00ff00, 400); } hellBox.destroy(); window.hellBoxes.splice(h, 1); if (window.hellBoxObj === hellBox) { window.hellBoxObj = null; window.hellBoxActive = false; } continue; } } } ; // Shield timer logic if (playerCar.shieldActive) { playerCar.shieldTicks--; // Show shield seconds left (rounded up) var shieldSeconds = Math.ceil(playerCar.shieldTicks / 60); shieldTxt.setText("Shield: " + shieldSeconds + "s"); // Show shield effect shieldEffect.visible = true; // Keep shield effect centered on playerCar shieldEffect.x = playerCar.x; shieldEffect.y = playerCar.y; if (playerCar.shieldTicks <= 0) { playerCar.shieldActive = false; playerCar.shieldTicks = 0; shieldTxt.setText(''); shieldEffect.visible = false; } } else { shieldTxt.setText(''); shieldEffect.visible = false; } // --- LIFE BAR UI update --- // Draw a simple, always-visible horizontal health bar above the player car if (!window.playerHealthBar) { // Bar background (expanded, taller) window.playerHealthBarBg = LK.getAsset('lifeBarBg', { anchorX: 0.5, anchorY: 0.5, width: 520, height: 120, //{4H} // Increased height for taller bar alpha: 0.85 }); // Bar fill (expanded, taller) window.playerHealthBarFill = LK.getAsset('lifeBar', { anchorX: 0.0, anchorY: 0.5, width: 480, height: 90, // Increased height for taller bar x: -240, alpha: 1 }); // Bar border (expanded, taller) window.playerHealthBarBorder = LK.getAsset('lifeBarBorder', { anchorX: 0.5, anchorY: 0.5, width: 560, height: 130, // Increased height for taller border alpha: 1 }); // Heart icon (expanded) // Removed the magic thing (spell bottle) to the left of the health bar by not adding any extra icon here window.playerHealthBarHeart = LK.getAsset('heartIcon', { anchorX: 0.5, anchorY: 0.5, width: 80, height: 80, x: -320, alpha: 1 }); // Add to game game.addChild(window.playerHealthBarBg); game.addChild(window.playerHealthBarFill); game.addChild(window.playerHealthBarBorder); // Removed: game.addChild(window.playerHealthBarHeart); window.playerHealthBar = true; } // Always show the health bar unless dead var showBar = playerLife > 0; window.playerHealthBarBg.visible = showBar; window.playerHealthBarFill.visible = showBar; window.playerHealthBarBorder.visible = showBar; // Removed: window.playerHealthBarHeart.visible = showBar; // Position above player car if (playerCar) { var barY = playerCar.y - 140; var barX = playerCar.x; window.playerHealthBarBg.x = barX; window.playerHealthBarBg.y = barY; window.playerHealthBarFill.x = barX - 240; window.playerHealthBarFill.y = barY; window.playerHealthBarBorder.x = barX; window.playerHealthBarBorder.y = barY; // Removed: window.playerHealthBarHeart.x = barX - 320; // Removed: window.playerHealthBarHeart.y = barY; // Set width proportional to life, always show a minimum width if not dead var minWidth = 38; var fillW = playerLife > 0 ? Math.max(minWidth, Math.round(480 * (playerLife / playerMaxLife))) : 0; window.playerHealthBarFill.width = fillW; } // Hide if dead if (playerLife <= 0) { window.playerHealthBarBg.visible = false; window.playerHealthBarFill.visible = false; window.playerHealthBarBorder.visible = false; // Removed: window.playerHealthBarHeart.visible = false; } }; // Place high score text to the left of the score text, both horizontally aligned highScoreTxt.x = LK.gui.top.width / 2 - 220; highScoreTxt.y = scoreTxt.height / 2 + 10; scoreTxt.x = LK.gui.top.width / 2 - 60; scoreTxt.y = scoreTxt.height / 2 + 10; // Position shield timer text directly below score, moved a little to the left shieldTxt.x = LK.gui.top.width / 2 - 80; shieldTxt.y = scoreTxt.y + scoreTxt.height / 2 + shieldTxt.height / 2 + 10; ;
===================================================================
--- original.js
+++ change.js
@@ -353,28 +353,12 @@
// Add: track last spell bottle spawn tick to limit spawn rate
var lastSpellBottleSpawnTick = -1000;
// Helper: spawn enemy car, obstacle, or fireball
function spawnObstacleOrEnemy() {
- // Randomly decide: 60% enemy car, 25% obstacle, 15% fireball
- var rand = Math.random();
var laneIdx = Math.floor(Math.random() * laneCount);
var y = -300;
- if (rand < 0.6) {
- var enemy = new EnemyCar();
- enemy.lane = laneIdx;
- enemy.x = lanes[laneIdx];
- enemy.y = y;
- enemyCars.push(enemy);
- game.addChild(enemy);
- } else if (rand < 0.85) {
- var obs = new Obstacle();
- obs.lane = laneIdx;
- obs.x = lanes[laneIdx];
- obs.y = y;
- obstacles.push(obs);
- game.addChild(obs);
- } else {
- // Limit fireballs: only spawn if fewer than 2 are on screen
+ if (score >= 70) {
+ // Only spawn fireballs after 70 points
if (!window.fireballs) window.fireballs = [];
if (window.fireballs.length < 2) {
var fireball = new Fireball();
fireball.lane = laneIdx;
@@ -382,8 +366,37 @@
fireball.y = y;
window.fireballs.push(fireball);
game.addChild(fireball);
}
+ } else {
+ // Randomly decide: 60% enemy car, 25% obstacle, 15% fireball
+ var rand = Math.random();
+ if (rand < 0.6) {
+ var enemy = new EnemyCar();
+ enemy.lane = laneIdx;
+ enemy.x = lanes[laneIdx];
+ enemy.y = y;
+ enemyCars.push(enemy);
+ game.addChild(enemy);
+ } else if (rand < 0.85) {
+ var obs = new Obstacle();
+ obs.lane = laneIdx;
+ obs.x = lanes[laneIdx];
+ obs.y = y;
+ obstacles.push(obs);
+ game.addChild(obs);
+ } else {
+ // Limit fireballs: only spawn if fewer than 2 are on screen
+ if (!window.fireballs) window.fireballs = [];
+ if (window.fireballs.length < 2) {
+ var fireball = new Fireball();
+ fireball.lane = laneIdx;
+ fireball.x = lanes[laneIdx];
+ fireball.y = y;
+ window.fireballs.push(fireball);
+ game.addChild(fireball);
+ }
+ }
}
}
// Helper: update score
function updateScore(val) {