/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Define a class for scrolling backgrounds var Background = Container.expand(function () { var self = Container.call(this); self.speed = 3; self.asset = null; self.init = function (assetName, startX) { self.asset = self.attachAsset(assetName, { anchorX: 0, anchorY: 0 }); self.x = startX; self.y = 0; }; self.update = function () { self.x -= gameSpeed; // If background has moved completely off screen to the left, reposition it to the right if (self.x <= -1366) { self.x = 1366 * 2; } }; return self; }); // Define a class for bombs dropped by player var Bomb = Container.expand(function () { var self = Container.call(this); // Create bomb graphic var bombGraphics = self.attachAsset('bomb', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.8, scaleY: 1.8 }); // Track last position and explosion state self.lastY = 0; self.hasExploded = false; self.velocityY = 4; // Reduced further to make bombs drop even slower // Update bomb position and check for ground collision self.update = function () { // Store last position before updating self.lastY = self.y; // Apply gravity self.velocityY += 0.2; // Reduced from 0.5 for even slower falling self.y += self.velocityY; // Make bomb pulse in size and rotate as it falls bombGraphics.rotation += 0.05; // Rotate the bomb // Pulse size between 1.0 and 1.4 based on sine wave with faster frequency var pulseScale = 1.0 + 0.2 * Math.sin(LK.ticks * 0.25); // Increased from 0.1 to 0.25 for faster pulse bombGraphics.scale.set(pulseScale, pulseScale); // Check for collision with missiles var children = game.children.slice(); for (var i = 0; i < children.length; i++) { if (children[i] instanceof Missile && self.intersects(children[i])) { // Create individual missile explosion at the hit missile's position var hitMissile = children[i]; var missileExplosion = new Container(); var missileExplosionGraphic = missileExplosion.attachAsset('explosion', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9, scaleX: 0.1, scaleY: 0.1 }); missileExplosion.x = hitMissile.x; missileExplosion.y = hitMissile.y; missileExplosion.scrollSpeed = gameSpeed; missileExplosion.update = function () { missileExplosion.x -= missileExplosion.scrollSpeed; }; game.addChild(missileExplosion); // Animate explosion tween(missileExplosionGraphic, { alpha: 0, scaleX: 1.8, scaleY: 1.8 }, { duration: 1000, onFinish: function onFinish() { game.removeChild(missileExplosion); } }); LK.effects.flashScreen(0xFFA500, 500); // Orange flash for 500ms player.lives = Math.min(3, player.lives + 1); player.setHeartStatus(player.lives, true); // Remove the specific missile that was hit game.removeChild(hitMissile); // Give the player 1000 points LK.setScore(LK.getScore() + 1000); self.explode(); return; } } // Check if bomb hits the ground if (self.lastY < floorLevel && self.y >= floorLevel) { self.explode(); } }; // Handle explosion effect and enemy destruction self.explode = function () { if (self.hasExploded) { return; } self.hasExploded = true; // Play explosion sound LK.getSound('explosion').play(); // Create explosion graphic var explosion = LK.getAsset('explosion', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); explosion.x = self.x; explosion.y = self.y; game.addChild(explosion); // Check for enemies and missiles in explosion radius var enemyHit = false; var missileHit = false; var children = game.children.slice(); var missilesToRemove = []; var enemiesToRemove = []; for (var i = 0; i < children.length; i++) { // Check for enemy hits if (children[i] instanceof Enemy) { var enemy = children[i]; // Simple distance check for explosion radius var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < 150) { // Explosion radius // Create player hit explosion at enemy's position using playerHitExplosion asset var enemyExplosion = new Container(); var enemyExplosionGraphic = enemyExplosion.attachAsset('playerHitExplosion', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9, scaleX: 0.1, scaleY: 0.1 }); enemyExplosion.x = enemy.x; enemyExplosion.y = enemy.y; enemyExplosion.scrollSpeed = gameSpeed; // Store the current game speed enemyExplosion.update = function () { // Make explosion scroll with background enemyExplosion.x -= enemyExplosion.scrollSpeed; }; game.addChild(enemyExplosion); // Animate explosion growing and fading out tween(enemyExplosionGraphic, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, onFinish: function onFinish() { game.removeChild(enemyExplosion); } }); // Add enemy to removal list enemiesToRemove.push(enemy); enemyHit = true; } } else if (children[i] instanceof Missile) { var missile = children[i]; // Check if missile is in explosion radius var mDx = missile.x - self.x; var mDy = missile.y - self.y; var mDistance = Math.sqrt(mDx * mDx + mDy * mDy); if (mDistance < 150) { // Create explosion at missile position var missileExplosion = new Container(); var missileExplosionGraphic = missileExplosion.attachAsset('explosion', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9, scaleX: 0.1, scaleY: 0.1 }); missileExplosion.x = missile.x; missileExplosion.y = missile.y; missileExplosion.scrollSpeed = gameSpeed; missileExplosion.update = function () { missileExplosion.x -= missileExplosion.scrollSpeed; }; game.addChild(missileExplosion); // Animate explosion tween(missileExplosionGraphic, { alpha: 0, scaleX: 1.8, scaleY: 1.8 }, { duration: 1000, onFinish: function onFinish() { game.removeChild(missileExplosion); } }); // Restore heart using setHeartStatus function player.setHeartStatus(player.lives, true); // Flash the heart to highlight it was restored LK.effects.flashObject(player.hearts[player.lives - 1], 0x00FF00, 500); // Add missile to removal list missilesToRemove.push(missile); } } } if (enemyHit) { // If no missile was hit but an enemy was, give normal points // Play enemy hit sound when enemy is destroyed LK.getSound('enemyHit').play(); // Add 500 points for destroying enemy with bomb LK.setScore(LK.getScore() + 500); // Score text is updated in game.update animation } // Remove all collected enemies and missiles for (var k = 0; k < enemiesToRemove.length; k++) { game.removeChild(enemiesToRemove[k]); } for (var l = 0; l < missilesToRemove.length; l++) { game.removeChild(missilesToRemove[l]); } // Remove bomb game.removeChild(self); // Fade out and remove explosion after 500ms tween(explosion, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 500, onFinish: function onFinish() { game.removeChild(explosion); } }); }; return self; }); // Define a class for enemies var Enemy = Container.expand(function () { var self = Container.call(this); // Create enemy using proper enemy sprite var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5, scaleX: 0.5, scaleY: 0.5 }); // Track last position and collision state self.lastX = 0; self.lastCollided = false; self.update = function () { // Store last position before updating self.lastX = self.x; // Move at the same speed as background self.x -= gameSpeed; // Check if enemy hits left edge of screen if (self.lastX > 0 && self.x <= 0) { // Add 100 to score LK.setScore(LK.getScore() + 100); // Score text is updated in game.update animation // Remove this enemy self.parent.removeChild(self); } // Check collision with player if not previously collided if (!self.lastCollided && self.intersects(player)) { // Set collision flag to prevent multiple hits self.lastCollided = true; // Create player hit explosion at enemy's position using different asset var explosion = new Container(); var explosionGraphic = explosion.attachAsset('playerHitExplosion', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9, scaleX: 0.1, scaleY: 0.1 }); explosion.x = self.x; explosion.y = self.y; explosion.scrollSpeed = gameSpeed; // Store the current game speed explosion.update = function () { // Make explosion scroll with background explosion.x -= explosion.scrollSpeed; }; game.addChild(explosion); // Play explosion sound when player is hit LK.getSound('explosion').play(); // Animate explosion growing and fading out tween(explosionGraphic, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, onFinish: function onFinish() { game.removeChild(explosion); } }); // Remove enemy from game self.parent.removeChild(self); // Reduce player lives if (player.lives > 0) { player.lives--; // Play sound when life is lost LK.getSound('lifeLost').play(); // Update heart display if (player.hearts.length > 0) { // Make the heart 10% opacity instead of removing it player.setHeartStatus(player.lives, false); } // Flash player to indicate damage LK.effects.flashObject(player, 0xFF0000, 500); // Game over if no lives left if (player.lives <= 0) { // Hide player player.visible = false; // Create explosion where player was var finalExplosion = new Container(); var finalExplosionGraphic = finalExplosion.attachAsset('playerExplosion', { anchorX: 0.5, anchorY: 0.5, alpha: 1.0, scaleX: 1.0, scaleY: 1.0 }); finalExplosion.x = player.x; finalExplosion.y = player.y; game.addChild(finalExplosion); // Stop game scrolling gameSpeed = 0; // Animate explosion growing and fading out over 1.5 seconds tween(finalExplosionGraphic, { alpha: 0, scaleX: 3.0, scaleY: 3.0 }, { duration: 1500, onFinish: function onFinish() { game.removeChild(finalExplosion); LK.showGameOver(); } }); } } } }; return self; }); // Define a class for missiles that launch at player var Missile = Container.expand(function () { var self = Container.call(this); // Create missile graphic using dedicated missile asset var missileGraphics = self.attachAsset('missile', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.5, scaleY: 2.2 }); // Track missile properties self.warningTime = 60; // 1 second warning at 60fps self.isWarning = true; // Start in warning state self.scrollSpeed = 0; // Will be set when missile is created // Create warning indicator self.warningIndicator = new Container(); var warningGraphic = self.warningIndicator.attachAsset('missile', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.0, tint: 0xFF0000 // Red color for warning }); // Add warning text self.warningText = new Text2('!', { size: 60, fill: 0xFFFFFF, stroke: 0x000000, strokeThickness: 3 }); self.warningText.anchor.set(0.5, 0.5); self.warningIndicator.addChild(self.warningText); // Update method for missile behavior self.update = function () { if (self.isWarning) { // During warning phase, just count down self.warningTime--; // Make warning indicator blink self.warningIndicator.alpha = Math.floor(self.warningTime / 10) % 2 === 0 ? 1.0 : 0.3; // When warning time ends, start moving missile if (self.warningTime <= 0) { self.isWarning = false; game.removeChild(self.warningIndicator); // Flash missile red-white-red-white when it first launches LK.effects.flashObject(missileGraphics, 0xFF0000, 500, 4); // Play whoosh sound when missile starts moving LK.getSound('whoosh').play(); } } else { // Move missile from right to left at 1.5x scroll speed self.x -= self.scrollSpeed; // Check if missile is off screen if (self.x < -50) { if (self.parent) { // Add 50 points when missile reaches left edge LK.setScore(LK.getScore() + 50); self.parent.removeChild(self); } return; } // Check for collision with player if (self.intersects(player) && player.lives > 0) { // Create explosion var explosion = new Container(); var explosionGraphic = explosion.attachAsset('playerHitExplosion', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9, scaleX: 0.1, scaleY: 0.1 }); explosion.x = self.x; explosion.y = self.y; explosion.scrollSpeed = gameSpeed; explosion.update = function () { explosion.x -= explosion.scrollSpeed; }; game.addChild(explosion); // Play explosion sound when player is hit by missile LK.getSound('explosion').play(); // Animate explosion tween(explosionGraphic, { alpha: 0, scaleX: 1.5, scaleY: 1.5 }, { duration: 1000, onFinish: function onFinish() { game.removeChild(explosion); } }); // Reduce player lives player.lives--; // Play sound when life is lost LK.getSound('lifeLost').play(); // Update heart display if (player.hearts.length > 0) { // Make the heart 10% opacity instead of removing it player.setHeartStatus(player.lives, false); } // Flash player to indicate damage LK.effects.flashObject(player, 0xFF0000, 500); // Game over if no lives left if (player.lives <= 0) { // Hide player player.visible = false; // Create explosion where player was var finalExplosion = new Container(); var finalExplosionGraphic = finalExplosion.attachAsset('playerExplosion', { anchorX: 0.5, anchorY: 0.5, alpha: 1.0, scaleX: 1.0, scaleY: 1.0 }); finalExplosion.x = player.x; finalExplosion.y = player.y; game.addChild(finalExplosion); // Stop game scrolling gameSpeed = 0; // Animate explosion growing and fading out over 1.5 seconds tween(finalExplosionGraphic, { alpha: 0, scaleX: 3.0, scaleY: 3.0 }, { duration: 1500, onFinish: function onFinish() { game.removeChild(finalExplosion); LK.showGameOver(); } }); } // Remove missile if (self.parent) { self.parent.removeChild(self); } } } }; // Initialize missile with warning at the specified position self.init = function (yPosition) { // Position missile at right edge of screen self.x = 2048; self.y = yPosition; // Set missile speed to 1.5x the current game speed self.scrollSpeed = gameSpeed * 1.5; // Position warning indicator at the right edge self.warningIndicator.x = 2048; self.warningIndicator.y = yPosition; // Add warning indicator to game game.addChild(self.warningIndicator); }; return self; }); //<Assets used in the game will automatically appear here> // Define a class for the player character var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); self.speed = 5; self.jumpHeight = 40; self.isJumping = false; self.velocityY = 0; self.lives = 3; // Initialize player with 3 lives self.hearts = []; // Array to store heart icons // Function to set heart visibility self.setHeartStatus = function (livesCount, active) { // Loop through all hearts for (var i = 0; i < self.hearts.length; i++) { // If lives count is less than or equal to the heart index, set to inactive // Otherwise set to active if (i < livesCount) { self.hearts[i].alpha = 1.0; } else { self.hearts[i].alpha = 0.2; } } }; self.canDropBomb = false; // Start with bomb unready self.activeBomb = null; // Reference to current active bomb self.bombCooldown = 240; // Start with full cooldown self.bombReloadTime = 240; // 4 seconds at 60fps self.createHearts = function () { // Always create three hearts in the middle of the screen near the bottom for (var i = 0; i < 3; i++) { var heart = new Container(); // Create a heart shape using heart asset var heartShape = heart.attachAsset('heart', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); // Calculate position in the middle of the screen heart.x = 2048 / 2 + (i - 1) * 200; // Center horizontally with even wider spacing heart.y = 2582; // Position 50 pixels up from previous position // Set inactive hearts to 10% opacity if beyond current lives if (i >= self.lives) { heart.alpha = 0.1; } // Add heart to array and game so it stays fixed self.hearts.push(heart); game.addChild(heart); } }; // Initialize hearts when player is created self.createHearts(); // Create bomb indicator self.bombIndicator = new Container(); var bombGraphic = self.bombIndicator.attachAsset('bomb', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.7, scaleY: 1.7 }); // No cooldown overlay needed // Add text to show reload progress self.bombReadyText = new Text2('READY', { size: 12, // Smaller text size fill: 0x4B0082, // Dark purple stroke: 0x000000, strokeThickness: 2 }); // Initialize style explicitly to avoid "Cannot set properties of undefined" error self.bombReadyText.style = { fill: 0x4B0082 // Dark purple }; self.bombReadyText.anchor.set(0.5, 0.5); // Center it on the bomb self.bombReadyText.y = 0; // Center it on the bomb self.bombIndicator.addChild(self.bombReadyText); // Position bomb indicator at bottom of screen, doubled in size self.bombIndicator.x = 2048 / 2; self.bombIndicator.y = 2732 - 375; // Position 50 pixels up from previous position self.bombIndicator.scale.set(2, 2); // Double the size game.addChild(self.bombIndicator); self.update = function () { if (self.isJumping) { // If there's an active bomb, hover in place until bomb explodes if (self.activeBomb && self.activeBomb.parent) { // Apply very slight hover effect self.y += Math.sin(LK.ticks * 0.1) * 0.5; // Remove any upward momentum if (self.velocityY < 0) { self.velocityY = 0; } } else { self.y += self.velocityY; self.velocityY += 0.7; // Decreased gravity effect by 30% if (self.y >= floorLevel) { // Return to floor level self.y = floorLevel; self.isJumping = false; self.velocityY = 0; self.activeBomb = null; // Clear reference to active bomb } } } // Handle bomb cooldown if (self.bombCooldown > 0) { self.bombCooldown--; // Calculate progress for new animation var progress = self.bombCooldown / self.bombReloadTime; // If it's the first frame of cooldown, set up initial state if (self.bombCooldown === self.bombReloadTime - 1) { // Stop any existing tweens tween.stop(bombGraphic); // Reset to 50% scale and transparent bombGraphic.scale.set(0.5, 0.5); bombGraphic.alpha = 0; // Start tween to scale up and increase opacity tween(bombGraphic, { alpha: 1.0, scaleX: 1.0, scaleY: 1.0 }, { duration: self.bombReloadTime * (1000 / 60), easing: tween.easeInOut }); } // Update text to show progress if (self.bombCooldown <= 0) { self.canDropBomb = true; self.bombReadyText.setText('READY'); self.bombReadyText.style.fill = 0x00FF00; // Play bomb ready sound when bomb becomes available LK.getSound('bombReady').play(); } else { var secondsLeft = Math.ceil(self.bombCooldown / 60); self.bombReadyText.setText(secondsLeft + 's'); self.bombReadyText.style.fill = 0xFF0000; } } }; self.jump = function () { if (!self.isJumping) { self.isJumping = true; self.velocityY = -self.jumpHeight; // Play jump sound when player jumps LK.getSound('jump').play(); } else if (self.canDropBomb) { // Drop a bomb if in mid-air and haven't dropped one yet self.canDropBomb = false; self.bombCooldown = self.bombReloadTime; // Start cooldown timer (4 seconds) // Reset bomb graphic to 50% size and transparent bombGraphic.scale.set(0.5, 0.5); bombGraphic.alpha = 0; // Create new bomb var bomb = new Bomb(); bomb.x = self.x; bomb.y = self.y + 50; // Position slightly below player bomb.lastY = bomb.y; // Add bomb to game game.addChild(bomb); self.activeBomb = bomb; } }; }); // Define a class for street backgrounds (bottom part) var StreetBackground = Container.expand(function () { var self = Container.call(this); self.speed = 3; self.asset = null; self.init = function (assetName, startX) { self.asset = self.attachAsset(assetName, { anchorX: 0, anchorY: 0, scaleY: 0.5 // Make the background half height }); self.x = startX; self.y = 2732 * 0.5; // Position in the bottom half of the screen }; self.update = function () { self.x -= gameSpeed; // If background has moved completely off screen to the left, reposition it to the right if (self.x <= -2048) { self.x = 2048 * 2 - gameSpeed; } }; return self; }); // UI Panel class var UIPanel = Container.expand(function () { var self = Container.call(this); // Create a panel using a brand new UI panel image var panel = self.attachAsset('uiPanelBackground', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9 }); // Method to update panel content (kept for compatibility) self.updateContent = function (status) { // No text to update anymore }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1A0933 // Dark purple background }); /**** * Game Code ****/ // Game speed control variable var gameSpeed = 5; // Floor level variable (Y position for player and enemies) var floorLevel = 2732 * 0.55 + 400; // 55% of screen height + 400px down // Track enemies var enemies = []; // Create three scrolling backgrounds for the top part var backgrounds = []; // Create three scrolling backgrounds for the bottom part (street) var streetBackgrounds = []; // Create each background and position them for (var i = 0; i < 3; i++) { var bg = new Background(); bg.init('background' + (i + 1), i * 1366); backgrounds.push(bg); game.addChild(bg); // Create street backgrounds using different assets var streetBg = new StreetBackground(); streetBg.init('street' + (i + 1), i * 2048); streetBackgrounds.push(streetBg); game.addChild(streetBg); } // Initialize player var player = game.addChild(new Player()); player.x = 2048 / 2 - 500; // Move player back 500 pixels player.y = floorLevel; // Position player at the floor level // Create and position UI panel var uiPanel = new UIPanel(); uiPanel.x = 2048 / 2; // Center horizontally uiPanel.y = 2732 - 250; // Position 50 pixels up from previous position uiPanel.scale.set(1.2, 1.2); // Make the UI panel 20% bigger // Make sure UI panel is at the right display level (moved up six levels) game.addChildAt(uiPanel, 6); // Create a new Text2 object to display the score with cyberpunk styling var scoreText = new Text2('0', { size: 120, fill: 0x00FFFF, // Cyan color for cyberpunk neon effect stroke: 0xFF00FF, // Magenta stroke for contrast strokeThickness: 5, // Thick stroke for glow effect dropShadow: true, dropShadowColor: 0x00FFFF, // Cyan shadow dropShadowBlur: 10, dropShadowAngle: Math.PI / 4, dropShadowDistance: 6, letterSpacing: 3 // Spacing between letters for futuristic look }); // Add the score text to the game GUI at the top center of the screen LK.gui.top.addChild(scoreText); // Center the text scoreText.anchor.set(0.5, 0); // Add padding from the top scoreText.y = 80; // Lives text has been removed // Keep track of displayed score for animation var displayedScore = 0; // Create a pulsating glow effect for the cyberpunk score display function pulseScoreText() { tween(scoreText, { strokeThickness: 8, dropShadowBlur: 15 }, { duration: 800, onFinish: function onFinish() { tween(scoreText, { strokeThickness: 5, dropShadowBlur: 10 }, { duration: 800, onFinish: pulseScoreText }); } }); } pulseScoreText(); // Handle game updates game.update = function () { // Increase game speed as score increases for difficulty progression gameSpeed = 5 + Math.min(LK.getScore() / 10, 5); // Cap at max 10 speed // Check if score reaches 3000, increase game speed and missile spawn rate if (LK.getScore() >= 20000) { // Boost speed significantly at 20000 points gameSpeed = 5 + Math.min(LK.getScore() / 10, 12); // Cap at max 17 speed } else if (LK.getScore() >= 3000) { // Boost speed further when score hits 3000 gameSpeed = 5 + Math.min(LK.getScore() / 10, 8); // Cap at max 13 speed } // Update scrolling backgrounds for (var i = 0; i < backgrounds.length; i++) { backgrounds[i].update(); } // Update street backgrounds for (var i = 0; i < streetBackgrounds.length; i++) { streetBackgrounds[i].update(); } player.update(); // Spawn enemies (wait 5 seconds at the start - 300 frames at 60fps) if (LK.ticks > 300) { // Determine enemy spawn interval based on score var enemySpawnInterval = 180; // Default: every 3 seconds if (LK.getScore() >= 20000) { enemySpawnInterval = 90; // Every 1.5 seconds at 20000+ } else if (LK.getScore() >= 3000) { enemySpawnInterval = 150; // Every 2.5 seconds at 3000+ } if (LK.ticks % enemySpawnInterval === 0) { // Spawn enemy var enemy = new Enemy(); enemy.x = 2048; // Start at right edge of screen enemy.y = floorLevel; // Position at floor level enemy.lastX = enemy.x; // Initialize lastX game.addChild(enemy); } } // Spawn missiles when player score reaches 1500 if (LK.getScore() >= 1500) { // Determine spawn interval based on score thresholds var missileSpawnInterval = 120; // Default interval if (LK.getScore() >= 20000) { missileSpawnInterval = 30; // Four times as often at 20000+ } else if (LK.getScore() >= 3000) { missileSpawnInterval = 60; // Twice as often at 3000+ } if (LK.ticks % missileSpawnInterval === 0) { // Calculate a y-position for the missile // Should be at least 500px above player but no higher than max jump height var playerMaxHeight = floorLevel - player.jumpHeight * 6; // Approximate max jump height var minMissileHeight = floorLevel - 2800; // At least 500px above player (increased from 300px) var maxMissileHeight = floorLevel - 800; // Don't go too high // Calculate the valid range for missile spawn positions var validRangeMin = Math.max(maxMissileHeight, minMissileHeight); var validRangeMax = floorLevel - 50; // Generate a random position within this range var missileY = validRangeMin + Math.random() * (validRangeMax - validRangeMin); // Ensure missile is within screen bounds missileY = Math.max(100, Math.min(missileY, floorLevel - 50)); // Create missile with warning var missile = new Missile(); missile.init(missileY); game.addChild(missile); } } // Update all enemies and bombs var children = game.children.slice(); for (var i = 0; i < children.length; i++) { if (children[i] instanceof Enemy) { children[i].update(); } else if (children[i] instanceof Bomb) { children[i].update(); } else if (children[i] instanceof Missile) { children[i].update(); } else if (children[i].update && children[i].scrollSpeed !== undefined) { // Update any container with scrollSpeed (like our player hit explosions) children[i].update(); } } // Animate score count up var actualScore = LK.getScore(); if (displayedScore < actualScore) { // Increment displayed score by a percentage of the difference displayedScore = Math.min(displayedScore + Math.ceil((actualScore - displayedScore) * 0.1), actualScore); scoreText.setText(displayedScore.toString()); } // Lives text display has been removed // Update UI panel is no longer needed - using player's bomb display }; // Handle player jump game.down = function (x, y, obj) { player.jump(); };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Define a class for scrolling backgrounds
var Background = Container.expand(function () {
var self = Container.call(this);
self.speed = 3;
self.asset = null;
self.init = function (assetName, startX) {
self.asset = self.attachAsset(assetName, {
anchorX: 0,
anchorY: 0
});
self.x = startX;
self.y = 0;
};
self.update = function () {
self.x -= gameSpeed;
// If background has moved completely off screen to the left, reposition it to the right
if (self.x <= -1366) {
self.x = 1366 * 2;
}
};
return self;
});
// Define a class for bombs dropped by player
var Bomb = Container.expand(function () {
var self = Container.call(this);
// Create bomb graphic
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8
});
// Track last position and explosion state
self.lastY = 0;
self.hasExploded = false;
self.velocityY = 4; // Reduced further to make bombs drop even slower
// Update bomb position and check for ground collision
self.update = function () {
// Store last position before updating
self.lastY = self.y;
// Apply gravity
self.velocityY += 0.2; // Reduced from 0.5 for even slower falling
self.y += self.velocityY;
// Make bomb pulse in size and rotate as it falls
bombGraphics.rotation += 0.05; // Rotate the bomb
// Pulse size between 1.0 and 1.4 based on sine wave with faster frequency
var pulseScale = 1.0 + 0.2 * Math.sin(LK.ticks * 0.25); // Increased from 0.1 to 0.25 for faster pulse
bombGraphics.scale.set(pulseScale, pulseScale);
// Check for collision with missiles
var children = game.children.slice();
for (var i = 0; i < children.length; i++) {
if (children[i] instanceof Missile && self.intersects(children[i])) {
// Create individual missile explosion at the hit missile's position
var hitMissile = children[i];
var missileExplosion = new Container();
var missileExplosionGraphic = missileExplosion.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9,
scaleX: 0.1,
scaleY: 0.1
});
missileExplosion.x = hitMissile.x;
missileExplosion.y = hitMissile.y;
missileExplosion.scrollSpeed = gameSpeed;
missileExplosion.update = function () {
missileExplosion.x -= missileExplosion.scrollSpeed;
};
game.addChild(missileExplosion);
// Animate explosion
tween(missileExplosionGraphic, {
alpha: 0,
scaleX: 1.8,
scaleY: 1.8
}, {
duration: 1000,
onFinish: function onFinish() {
game.removeChild(missileExplosion);
}
});
LK.effects.flashScreen(0xFFA500, 500); // Orange flash for 500ms
player.lives = Math.min(3, player.lives + 1);
player.setHeartStatus(player.lives, true);
// Remove the specific missile that was hit
game.removeChild(hitMissile);
// Give the player 1000 points
LK.setScore(LK.getScore() + 1000);
self.explode();
return;
}
}
// Check if bomb hits the ground
if (self.lastY < floorLevel && self.y >= floorLevel) {
self.explode();
}
};
// Handle explosion effect and enemy destruction
self.explode = function () {
if (self.hasExploded) {
return;
}
self.hasExploded = true;
// Play explosion sound
LK.getSound('explosion').play();
// Create explosion graphic
var explosion = LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
explosion.x = self.x;
explosion.y = self.y;
game.addChild(explosion);
// Check for enemies and missiles in explosion radius
var enemyHit = false;
var missileHit = false;
var children = game.children.slice();
var missilesToRemove = [];
var enemiesToRemove = [];
for (var i = 0; i < children.length; i++) {
// Check for enemy hits
if (children[i] instanceof Enemy) {
var enemy = children[i];
// Simple distance check for explosion radius
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 150) {
// Explosion radius
// Create player hit explosion at enemy's position using playerHitExplosion asset
var enemyExplosion = new Container();
var enemyExplosionGraphic = enemyExplosion.attachAsset('playerHitExplosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9,
scaleX: 0.1,
scaleY: 0.1
});
enemyExplosion.x = enemy.x;
enemyExplosion.y = enemy.y;
enemyExplosion.scrollSpeed = gameSpeed; // Store the current game speed
enemyExplosion.update = function () {
// Make explosion scroll with background
enemyExplosion.x -= enemyExplosion.scrollSpeed;
};
game.addChild(enemyExplosion);
// Animate explosion growing and fading out
tween(enemyExplosionGraphic, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1000,
onFinish: function onFinish() {
game.removeChild(enemyExplosion);
}
});
// Add enemy to removal list
enemiesToRemove.push(enemy);
enemyHit = true;
}
} else if (children[i] instanceof Missile) {
var missile = children[i];
// Check if missile is in explosion radius
var mDx = missile.x - self.x;
var mDy = missile.y - self.y;
var mDistance = Math.sqrt(mDx * mDx + mDy * mDy);
if (mDistance < 150) {
// Create explosion at missile position
var missileExplosion = new Container();
var missileExplosionGraphic = missileExplosion.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9,
scaleX: 0.1,
scaleY: 0.1
});
missileExplosion.x = missile.x;
missileExplosion.y = missile.y;
missileExplosion.scrollSpeed = gameSpeed;
missileExplosion.update = function () {
missileExplosion.x -= missileExplosion.scrollSpeed;
};
game.addChild(missileExplosion);
// Animate explosion
tween(missileExplosionGraphic, {
alpha: 0,
scaleX: 1.8,
scaleY: 1.8
}, {
duration: 1000,
onFinish: function onFinish() {
game.removeChild(missileExplosion);
}
});
// Restore heart using setHeartStatus function
player.setHeartStatus(player.lives, true);
// Flash the heart to highlight it was restored
LK.effects.flashObject(player.hearts[player.lives - 1], 0x00FF00, 500);
// Add missile to removal list
missilesToRemove.push(missile);
}
}
}
if (enemyHit) {
// If no missile was hit but an enemy was, give normal points
// Play enemy hit sound when enemy is destroyed
LK.getSound('enemyHit').play();
// Add 500 points for destroying enemy with bomb
LK.setScore(LK.getScore() + 500);
// Score text is updated in game.update animation
}
// Remove all collected enemies and missiles
for (var k = 0; k < enemiesToRemove.length; k++) {
game.removeChild(enemiesToRemove[k]);
}
for (var l = 0; l < missilesToRemove.length; l++) {
game.removeChild(missilesToRemove[l]);
}
// Remove bomb
game.removeChild(self);
// Fade out and remove explosion after 500ms
tween(explosion, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 500,
onFinish: function onFinish() {
game.removeChild(explosion);
}
});
};
return self;
});
// Define a class for enemies
var Enemy = Container.expand(function () {
var self = Container.call(this);
// Create enemy using proper enemy sprite
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.5
});
// Track last position and collision state
self.lastX = 0;
self.lastCollided = false;
self.update = function () {
// Store last position before updating
self.lastX = self.x;
// Move at the same speed as background
self.x -= gameSpeed;
// Check if enemy hits left edge of screen
if (self.lastX > 0 && self.x <= 0) {
// Add 100 to score
LK.setScore(LK.getScore() + 100);
// Score text is updated in game.update animation
// Remove this enemy
self.parent.removeChild(self);
}
// Check collision with player if not previously collided
if (!self.lastCollided && self.intersects(player)) {
// Set collision flag to prevent multiple hits
self.lastCollided = true;
// Create player hit explosion at enemy's position using different asset
var explosion = new Container();
var explosionGraphic = explosion.attachAsset('playerHitExplosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9,
scaleX: 0.1,
scaleY: 0.1
});
explosion.x = self.x;
explosion.y = self.y;
explosion.scrollSpeed = gameSpeed; // Store the current game speed
explosion.update = function () {
// Make explosion scroll with background
explosion.x -= explosion.scrollSpeed;
};
game.addChild(explosion);
// Play explosion sound when player is hit
LK.getSound('explosion').play();
// Animate explosion growing and fading out
tween(explosionGraphic, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1000,
onFinish: function onFinish() {
game.removeChild(explosion);
}
});
// Remove enemy from game
self.parent.removeChild(self);
// Reduce player lives
if (player.lives > 0) {
player.lives--;
// Play sound when life is lost
LK.getSound('lifeLost').play();
// Update heart display
if (player.hearts.length > 0) {
// Make the heart 10% opacity instead of removing it
player.setHeartStatus(player.lives, false);
}
// Flash player to indicate damage
LK.effects.flashObject(player, 0xFF0000, 500);
// Game over if no lives left
if (player.lives <= 0) {
// Hide player
player.visible = false;
// Create explosion where player was
var finalExplosion = new Container();
var finalExplosionGraphic = finalExplosion.attachAsset('playerExplosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1.0,
scaleX: 1.0,
scaleY: 1.0
});
finalExplosion.x = player.x;
finalExplosion.y = player.y;
game.addChild(finalExplosion);
// Stop game scrolling
gameSpeed = 0;
// Animate explosion growing and fading out over 1.5 seconds
tween(finalExplosionGraphic, {
alpha: 0,
scaleX: 3.0,
scaleY: 3.0
}, {
duration: 1500,
onFinish: function onFinish() {
game.removeChild(finalExplosion);
LK.showGameOver();
}
});
}
}
}
};
return self;
});
// Define a class for missiles that launch at player
var Missile = Container.expand(function () {
var self = Container.call(this);
// Create missile graphic using dedicated missile asset
var missileGraphics = self.attachAsset('missile', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 2.2
});
// Track missile properties
self.warningTime = 60; // 1 second warning at 60fps
self.isWarning = true; // Start in warning state
self.scrollSpeed = 0; // Will be set when missile is created
// Create warning indicator
self.warningIndicator = new Container();
var warningGraphic = self.warningIndicator.attachAsset('missile', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.0,
tint: 0xFF0000 // Red color for warning
});
// Add warning text
self.warningText = new Text2('!', {
size: 60,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 3
});
self.warningText.anchor.set(0.5, 0.5);
self.warningIndicator.addChild(self.warningText);
// Update method for missile behavior
self.update = function () {
if (self.isWarning) {
// During warning phase, just count down
self.warningTime--;
// Make warning indicator blink
self.warningIndicator.alpha = Math.floor(self.warningTime / 10) % 2 === 0 ? 1.0 : 0.3;
// When warning time ends, start moving missile
if (self.warningTime <= 0) {
self.isWarning = false;
game.removeChild(self.warningIndicator);
// Flash missile red-white-red-white when it first launches
LK.effects.flashObject(missileGraphics, 0xFF0000, 500, 4);
// Play whoosh sound when missile starts moving
LK.getSound('whoosh').play();
}
} else {
// Move missile from right to left at 1.5x scroll speed
self.x -= self.scrollSpeed;
// Check if missile is off screen
if (self.x < -50) {
if (self.parent) {
// Add 50 points when missile reaches left edge
LK.setScore(LK.getScore() + 50);
self.parent.removeChild(self);
}
return;
}
// Check for collision with player
if (self.intersects(player) && player.lives > 0) {
// Create explosion
var explosion = new Container();
var explosionGraphic = explosion.attachAsset('playerHitExplosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9,
scaleX: 0.1,
scaleY: 0.1
});
explosion.x = self.x;
explosion.y = self.y;
explosion.scrollSpeed = gameSpeed;
explosion.update = function () {
explosion.x -= explosion.scrollSpeed;
};
game.addChild(explosion);
// Play explosion sound when player is hit by missile
LK.getSound('explosion').play();
// Animate explosion
tween(explosionGraphic, {
alpha: 0,
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 1000,
onFinish: function onFinish() {
game.removeChild(explosion);
}
});
// Reduce player lives
player.lives--;
// Play sound when life is lost
LK.getSound('lifeLost').play();
// Update heart display
if (player.hearts.length > 0) {
// Make the heart 10% opacity instead of removing it
player.setHeartStatus(player.lives, false);
}
// Flash player to indicate damage
LK.effects.flashObject(player, 0xFF0000, 500);
// Game over if no lives left
if (player.lives <= 0) {
// Hide player
player.visible = false;
// Create explosion where player was
var finalExplosion = new Container();
var finalExplosionGraphic = finalExplosion.attachAsset('playerExplosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 1.0,
scaleX: 1.0,
scaleY: 1.0
});
finalExplosion.x = player.x;
finalExplosion.y = player.y;
game.addChild(finalExplosion);
// Stop game scrolling
gameSpeed = 0;
// Animate explosion growing and fading out over 1.5 seconds
tween(finalExplosionGraphic, {
alpha: 0,
scaleX: 3.0,
scaleY: 3.0
}, {
duration: 1500,
onFinish: function onFinish() {
game.removeChild(finalExplosion);
LK.showGameOver();
}
});
}
// Remove missile
if (self.parent) {
self.parent.removeChild(self);
}
}
}
};
// Initialize missile with warning at the specified position
self.init = function (yPosition) {
// Position missile at right edge of screen
self.x = 2048;
self.y = yPosition;
// Set missile speed to 1.5x the current game speed
self.scrollSpeed = gameSpeed * 1.5;
// Position warning indicator at the right edge
self.warningIndicator.x = 2048;
self.warningIndicator.y = yPosition;
// Add warning indicator to game
game.addChild(self.warningIndicator);
};
return self;
});
//<Assets used in the game will automatically appear here>
// Define a class for the player character
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
self.speed = 5;
self.jumpHeight = 40;
self.isJumping = false;
self.velocityY = 0;
self.lives = 3; // Initialize player with 3 lives
self.hearts = []; // Array to store heart icons
// Function to set heart visibility
self.setHeartStatus = function (livesCount, active) {
// Loop through all hearts
for (var i = 0; i < self.hearts.length; i++) {
// If lives count is less than or equal to the heart index, set to inactive
// Otherwise set to active
if (i < livesCount) {
self.hearts[i].alpha = 1.0;
} else {
self.hearts[i].alpha = 0.2;
}
}
};
self.canDropBomb = false; // Start with bomb unready
self.activeBomb = null; // Reference to current active bomb
self.bombCooldown = 240; // Start with full cooldown
self.bombReloadTime = 240; // 4 seconds at 60fps
self.createHearts = function () {
// Always create three hearts in the middle of the screen near the bottom
for (var i = 0; i < 3; i++) {
var heart = new Container();
// Create a heart shape using heart asset
var heartShape = heart.attachAsset('heart', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
// Calculate position in the middle of the screen
heart.x = 2048 / 2 + (i - 1) * 200; // Center horizontally with even wider spacing
heart.y = 2582; // Position 50 pixels up from previous position
// Set inactive hearts to 10% opacity if beyond current lives
if (i >= self.lives) {
heart.alpha = 0.1;
}
// Add heart to array and game so it stays fixed
self.hearts.push(heart);
game.addChild(heart);
}
};
// Initialize hearts when player is created
self.createHearts();
// Create bomb indicator
self.bombIndicator = new Container();
var bombGraphic = self.bombIndicator.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.7,
scaleY: 1.7
});
// No cooldown overlay needed
// Add text to show reload progress
self.bombReadyText = new Text2('READY', {
size: 12,
// Smaller text size
fill: 0x4B0082,
// Dark purple
stroke: 0x000000,
strokeThickness: 2
});
// Initialize style explicitly to avoid "Cannot set properties of undefined" error
self.bombReadyText.style = {
fill: 0x4B0082 // Dark purple
};
self.bombReadyText.anchor.set(0.5, 0.5); // Center it on the bomb
self.bombReadyText.y = 0; // Center it on the bomb
self.bombIndicator.addChild(self.bombReadyText);
// Position bomb indicator at bottom of screen, doubled in size
self.bombIndicator.x = 2048 / 2;
self.bombIndicator.y = 2732 - 375; // Position 50 pixels up from previous position
self.bombIndicator.scale.set(2, 2); // Double the size
game.addChild(self.bombIndicator);
self.update = function () {
if (self.isJumping) {
// If there's an active bomb, hover in place until bomb explodes
if (self.activeBomb && self.activeBomb.parent) {
// Apply very slight hover effect
self.y += Math.sin(LK.ticks * 0.1) * 0.5;
// Remove any upward momentum
if (self.velocityY < 0) {
self.velocityY = 0;
}
} else {
self.y += self.velocityY;
self.velocityY += 0.7; // Decreased gravity effect by 30%
if (self.y >= floorLevel) {
// Return to floor level
self.y = floorLevel;
self.isJumping = false;
self.velocityY = 0;
self.activeBomb = null; // Clear reference to active bomb
}
}
}
// Handle bomb cooldown
if (self.bombCooldown > 0) {
self.bombCooldown--;
// Calculate progress for new animation
var progress = self.bombCooldown / self.bombReloadTime;
// If it's the first frame of cooldown, set up initial state
if (self.bombCooldown === self.bombReloadTime - 1) {
// Stop any existing tweens
tween.stop(bombGraphic);
// Reset to 50% scale and transparent
bombGraphic.scale.set(0.5, 0.5);
bombGraphic.alpha = 0;
// Start tween to scale up and increase opacity
tween(bombGraphic, {
alpha: 1.0,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: self.bombReloadTime * (1000 / 60),
easing: tween.easeInOut
});
}
// Update text to show progress
if (self.bombCooldown <= 0) {
self.canDropBomb = true;
self.bombReadyText.setText('READY');
self.bombReadyText.style.fill = 0x00FF00;
// Play bomb ready sound when bomb becomes available
LK.getSound('bombReady').play();
} else {
var secondsLeft = Math.ceil(self.bombCooldown / 60);
self.bombReadyText.setText(secondsLeft + 's');
self.bombReadyText.style.fill = 0xFF0000;
}
}
};
self.jump = function () {
if (!self.isJumping) {
self.isJumping = true;
self.velocityY = -self.jumpHeight;
// Play jump sound when player jumps
LK.getSound('jump').play();
} else if (self.canDropBomb) {
// Drop a bomb if in mid-air and haven't dropped one yet
self.canDropBomb = false;
self.bombCooldown = self.bombReloadTime; // Start cooldown timer (4 seconds)
// Reset bomb graphic to 50% size and transparent
bombGraphic.scale.set(0.5, 0.5);
bombGraphic.alpha = 0;
// Create new bomb
var bomb = new Bomb();
bomb.x = self.x;
bomb.y = self.y + 50; // Position slightly below player
bomb.lastY = bomb.y;
// Add bomb to game
game.addChild(bomb);
self.activeBomb = bomb;
}
};
});
// Define a class for street backgrounds (bottom part)
var StreetBackground = Container.expand(function () {
var self = Container.call(this);
self.speed = 3;
self.asset = null;
self.init = function (assetName, startX) {
self.asset = self.attachAsset(assetName, {
anchorX: 0,
anchorY: 0,
scaleY: 0.5 // Make the background half height
});
self.x = startX;
self.y = 2732 * 0.5; // Position in the bottom half of the screen
};
self.update = function () {
self.x -= gameSpeed;
// If background has moved completely off screen to the left, reposition it to the right
if (self.x <= -2048) {
self.x = 2048 * 2 - gameSpeed;
}
};
return self;
});
// UI Panel class
var UIPanel = Container.expand(function () {
var self = Container.call(this);
// Create a panel using a brand new UI panel image
var panel = self.attachAsset('uiPanelBackground', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9
});
// Method to update panel content (kept for compatibility)
self.updateContent = function (status) {
// No text to update anymore
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1A0933 // Dark purple background
});
/****
* Game Code
****/
// Game speed control variable
var gameSpeed = 5;
// Floor level variable (Y position for player and enemies)
var floorLevel = 2732 * 0.55 + 400; // 55% of screen height + 400px down
// Track enemies
var enemies = [];
// Create three scrolling backgrounds for the top part
var backgrounds = [];
// Create three scrolling backgrounds for the bottom part (street)
var streetBackgrounds = [];
// Create each background and position them
for (var i = 0; i < 3; i++) {
var bg = new Background();
bg.init('background' + (i + 1), i * 1366);
backgrounds.push(bg);
game.addChild(bg);
// Create street backgrounds using different assets
var streetBg = new StreetBackground();
streetBg.init('street' + (i + 1), i * 2048);
streetBackgrounds.push(streetBg);
game.addChild(streetBg);
}
// Initialize player
var player = game.addChild(new Player());
player.x = 2048 / 2 - 500; // Move player back 500 pixels
player.y = floorLevel; // Position player at the floor level
// Create and position UI panel
var uiPanel = new UIPanel();
uiPanel.x = 2048 / 2; // Center horizontally
uiPanel.y = 2732 - 250; // Position 50 pixels up from previous position
uiPanel.scale.set(1.2, 1.2); // Make the UI panel 20% bigger
// Make sure UI panel is at the right display level (moved up six levels)
game.addChildAt(uiPanel, 6);
// Create a new Text2 object to display the score with cyberpunk styling
var scoreText = new Text2('0', {
size: 120,
fill: 0x00FFFF,
// Cyan color for cyberpunk neon effect
stroke: 0xFF00FF,
// Magenta stroke for contrast
strokeThickness: 5,
// Thick stroke for glow effect
dropShadow: true,
dropShadowColor: 0x00FFFF,
// Cyan shadow
dropShadowBlur: 10,
dropShadowAngle: Math.PI / 4,
dropShadowDistance: 6,
letterSpacing: 3 // Spacing between letters for futuristic look
});
// Add the score text to the game GUI at the top center of the screen
LK.gui.top.addChild(scoreText);
// Center the text
scoreText.anchor.set(0.5, 0);
// Add padding from the top
scoreText.y = 80;
// Lives text has been removed
// Keep track of displayed score for animation
var displayedScore = 0;
// Create a pulsating glow effect for the cyberpunk score display
function pulseScoreText() {
tween(scoreText, {
strokeThickness: 8,
dropShadowBlur: 15
}, {
duration: 800,
onFinish: function onFinish() {
tween(scoreText, {
strokeThickness: 5,
dropShadowBlur: 10
}, {
duration: 800,
onFinish: pulseScoreText
});
}
});
}
pulseScoreText();
// Handle game updates
game.update = function () {
// Increase game speed as score increases for difficulty progression
gameSpeed = 5 + Math.min(LK.getScore() / 10, 5); // Cap at max 10 speed
// Check if score reaches 3000, increase game speed and missile spawn rate
if (LK.getScore() >= 20000) {
// Boost speed significantly at 20000 points
gameSpeed = 5 + Math.min(LK.getScore() / 10, 12); // Cap at max 17 speed
} else if (LK.getScore() >= 3000) {
// Boost speed further when score hits 3000
gameSpeed = 5 + Math.min(LK.getScore() / 10, 8); // Cap at max 13 speed
}
// Update scrolling backgrounds
for (var i = 0; i < backgrounds.length; i++) {
backgrounds[i].update();
}
// Update street backgrounds
for (var i = 0; i < streetBackgrounds.length; i++) {
streetBackgrounds[i].update();
}
player.update();
// Spawn enemies (wait 5 seconds at the start - 300 frames at 60fps)
if (LK.ticks > 300) {
// Determine enemy spawn interval based on score
var enemySpawnInterval = 180; // Default: every 3 seconds
if (LK.getScore() >= 20000) {
enemySpawnInterval = 90; // Every 1.5 seconds at 20000+
} else if (LK.getScore() >= 3000) {
enemySpawnInterval = 150; // Every 2.5 seconds at 3000+
}
if (LK.ticks % enemySpawnInterval === 0) {
// Spawn enemy
var enemy = new Enemy();
enemy.x = 2048; // Start at right edge of screen
enemy.y = floorLevel; // Position at floor level
enemy.lastX = enemy.x; // Initialize lastX
game.addChild(enemy);
}
}
// Spawn missiles when player score reaches 1500
if (LK.getScore() >= 1500) {
// Determine spawn interval based on score thresholds
var missileSpawnInterval = 120; // Default interval
if (LK.getScore() >= 20000) {
missileSpawnInterval = 30; // Four times as often at 20000+
} else if (LK.getScore() >= 3000) {
missileSpawnInterval = 60; // Twice as often at 3000+
}
if (LK.ticks % missileSpawnInterval === 0) {
// Calculate a y-position for the missile
// Should be at least 500px above player but no higher than max jump height
var playerMaxHeight = floorLevel - player.jumpHeight * 6; // Approximate max jump height
var minMissileHeight = floorLevel - 2800; // At least 500px above player (increased from 300px)
var maxMissileHeight = floorLevel - 800; // Don't go too high
// Calculate the valid range for missile spawn positions
var validRangeMin = Math.max(maxMissileHeight, minMissileHeight);
var validRangeMax = floorLevel - 50;
// Generate a random position within this range
var missileY = validRangeMin + Math.random() * (validRangeMax - validRangeMin);
// Ensure missile is within screen bounds
missileY = Math.max(100, Math.min(missileY, floorLevel - 50));
// Create missile with warning
var missile = new Missile();
missile.init(missileY);
game.addChild(missile);
}
}
// Update all enemies and bombs
var children = game.children.slice();
for (var i = 0; i < children.length; i++) {
if (children[i] instanceof Enemy) {
children[i].update();
} else if (children[i] instanceof Bomb) {
children[i].update();
} else if (children[i] instanceof Missile) {
children[i].update();
} else if (children[i].update && children[i].scrollSpeed !== undefined) {
// Update any container with scrollSpeed (like our player hit explosions)
children[i].update();
}
}
// Animate score count up
var actualScore = LK.getScore();
if (displayedScore < actualScore) {
// Increment displayed score by a percentage of the difference
displayedScore = Math.min(displayedScore + Math.ceil((actualScore - displayedScore) * 0.1), actualScore);
scoreText.setText(displayedScore.toString());
}
// Lives text display has been removed
// Update UI panel is no longer needed - using player's bomb display
};
// Handle player jump
game.down = function (x, y, obj) {
player.jump();
};
cyberpunk pixel art asphalt street. In-Game asset. 2d. High contrast. No shadows, street debris
cyberpunk pixel art asphalt street. In-Game asset. 2d. High contrast. No shadows, street debris
Neon pink techno heart. In-Game asset. 2d. High contrast. No shadows
Side view, angry cyberpunk robot, looking left. full body, cute but aggro In-Game asset. 2d. High contrast. No shadows
Side view, cute female cyberpunk robot, looking right, full body, chibi, riding in a hover sphere with energy glow at bottom, hands on controls In-Game asset. 2d. High contrast. No shadows
cyberpunk explosion with the word "ouch" in the middle. sparks. In-Game asset. 2d. High contrast. No shadows
Glowing energy sphere. Spherical. Yellow and blue. In-Game asset. 2d. High contrast. No shadows
digital explosion, burnt orange neon blue, pixels, sparks. In-Game asset. 2d. High contrast. No shadows
digital explosion. squares. pixels. chaos. neon. sparks. In-Game asset. 2d. High contrast. No shadows