User prompt
Add an ability in which enemies can dodge your bullets every 5 seconds.
User prompt
Make the enemy ships which reach the bottom edge shoot 10 projectile before self-destructing.
User prompt
The bullets which are shot by enemy ships after reaching the bottom edge are very hard to see. Make them the same color as normal enemy bullets.
User prompt
Make it so that whenever an enemy ship reaches the bottom edge of the screen, it aims toward you and shoots with increased fire rate and bullet speed for 5 seconds before self destructing. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Does not play still, how to fix???
User prompt
Still can't hear it.
User prompt
I added a firepool sound, yet it does not play
User prompt
I accidentally deleted firepool sound asset, add again
User prompt
```javascript // Define your sounds at the beginning of your code LK.init.sound('explosion', {volume: 0.7}); LK.init.sound('shieldActivation', {volume: 0.5}); LK.init.sound('firePoolDestroy', {volume: 0.6}); LK.init.sound('bulletExplosion', {volume: 0.4}); LK.init.sound('shieldCollision', {volume: 0.5}); LK.init.sound('playerCollision', {volume: 0.6}); LK.init.sound('levelUp', {volume: 0.8}); LK.init.sound('playerHit', {volume: 0.5}); LK.init.sound('gameOver', {volume: 0.7}); LK.init.sound('winSound', {volume: 0.8}); do this it still does not play
User prompt
do this for me please in my game
User prompt
Add these sounds to assets
User prompt
I still can't hear anything how do I create these sounds
User prompt
Can you create sounds for: Add sound when enemy is destroyed by fire pool shield activation sound effect player bullet explosion sound when bullet is removed at max bounce count collision sound when enemy collides with shield collision sound when player collides with enemy level up sound sound when player gets hit by enemy bullet background music when game starts game over sound effect win sound effect
User prompt
It still hits me even though the bullet is only in the vicinity of me (player)
User prompt
make it so that when a bullet collides with the player, only then damage is dealt to the player, the bullet cannot be in the vicinity of the player and still deal damage.
User prompt
Remove all the hitbox stuff keep the hitboxes normal
User prompt
THe bullets don't hit me sometimes
User prompt
Make the bullet, player and enemy ship hitboxes to be more exact. I am able to get hit by bullets without properly hitting them.
User prompt
Add sounds to this game for all actions.
User prompt
After the explosion of enemies, the enemies inside the radius of the explosion should be destroyed.
User prompt
Remove enemy bullet destruction completely from the whole game.
User prompt
The game is lagging sometimes because of the enemy bullets destruction ability. Remove the lag please.
User prompt
Also make it that enemy bullets cannot be destroyed until 7 seconds after the quad powerup ends
User prompt
Please fix the bug: 'TypeError: tween.stopTweens is not a function. (In 'tween.stopTweens(finalLifeText)', 'tween.stopTweens' is undefined)' in or related to this line: 'tween.stopTweens(finalLifeText);' Line Number: 1007
User prompt
The game starts lagging a lot when the powerup which allows for bullets to fire from 4 sides is activated. MAke it so that during the powerup, enemy bullets cannot be destroyed.
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); // Use default hitbox // Enemy properties self.health = 1; self.speed = 2; self.scoreValue = 100; self.fireRate = 120; // Ticks between shots self.lastShot = Math.floor(Math.random() * 60); // Randomize initial shot timer self.movementPattern = Math.floor(Math.random() * 3); // 0: straight, 1: zigzag, 2: circular self.movementCounter = 0; // Initial target position (will be set during movement) self.targetX = null; self.update = function () { // Basic downward movement self.y += self.speed; // Apply movement pattern if (self.movementPattern === 1) { // Zigzag with occasional side movement self.x += Math.sin(self.movementCounter * 0.05) * 3; // Occasionally move to a different horizontal position if (self.movementCounter % 500 === 0) { // Choose a new target position on the opposite side self.targetX = self.x < GAME_WIDTH / 2 ? GAME_WIDTH * 0.7 + Math.random() * GAME_WIDTH * 0.2 : GAME_WIDTH * 0.1 + Math.random() * GAME_WIDTH * 0.2; } if (self.targetX) { var diffX = self.targetX - self.x; if (Math.abs(diffX) > 10) { self.x += diffX * 0.03; } } self.movementCounter++; } else if (self.movementPattern === 2) { // Circular with occasional repositioning self.x += Math.sin(self.movementCounter * 0.03) * 4; // Occasionally reset position to avoid grouping if (self.movementCounter % 700 === 0) { // Move to random position on screen self.targetX = Math.random() * GAME_WIDTH * 0.8 + GAME_WIDTH * 0.1; } // Move toward target if exists if (self.targetX) { var diffX = self.targetX - self.x; if (Math.abs(diffX) > 10) { self.x += diffX * 0.02; } } self.movementCounter++; } else { // Add movement for straight pattern (pattern 0) if (self.movementCounter % 900 === 0) { // Occasional side movement self.targetX = Math.random() * GAME_WIDTH * 0.8 + GAME_WIDTH * 0.1; } // Move toward target if exists if (self.targetX) { var diffX = self.targetX - self.x; if (Math.abs(diffX) > 10) { self.x += diffX * 0.01; } } self.movementCounter++; } }; // Take damage and check if destroyed self.takeDamage = function (amount) { self.health -= amount; if (self.health <= 0) { return true; // Enemy is destroyed } return false; }; // Use default intersection method return self; }); var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 7; // Moving downward self.update = function () { self.y += self.speed; }; // Use default intersection method return self; }); var Explosion = Container.expand(function () { var self = Container.call(this); var explosionGraphics = self.attachAsset('explosion', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); // Explosion duration self.duration = 30; // frames self.currentFrame = 0; // Scale explosion from small to large then fade explosionGraphics.scale.x = 0.1; explosionGraphics.scale.y = 0.1; self.update = function () { self.currentFrame++; // Expand and then fade if (self.currentFrame < 15) { explosionGraphics.scale.x += 0.1; explosionGraphics.scale.y += 0.1; } else { explosionGraphics.alpha -= 0.08; } // Remove when animation complete if (self.currentFrame >= self.duration) { self.destroy(); return true; } return false; }; return self; }); var FirePool = Container.expand(function () { var self = Container.call(this); var fireGraphics = self.attachAsset('firePool', { anchorX: 0.5, anchorY: 0.5, alpha: 0.7 }); // Fire pool duration (4 seconds at 60fps) self.duration = 240; self.currentFrame = 0; // Pulsate effect self.pulsateDirection = 1; self.pulsateAmount = 0; self.update = function () { self.currentFrame++; // Pulsate effect self.pulsateAmount += 0.02 * self.pulsateDirection; if (self.pulsateAmount > 0.2 || self.pulsateAmount < -0.2) { self.pulsateDirection *= -1; } fireGraphics.scale.x = 1 + self.pulsateAmount; fireGraphics.scale.y = 1 + self.pulsateAmount; // Fade out at the end if (self.currentFrame > 150) { fireGraphics.alpha -= 0.03; } // Check for enemies touching the fire pool for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.intersects(self)) { // Enemy is instantly destroyed by fire score += enemy.scoreValue; LK.setScore(score); updateScoreDisplay(); LK.effects.flashObject(enemy, 0xff0000, 300); // Play explosion sound when enemy is destroyed by fire pool LK.getSound('firePoolDestroy').play(); enemy.destroy(); enemies.splice(i, 1); } } // Remove when duration complete if (self.currentFrame >= self.duration) { self.destroy(); return true; } return false; }; return self; }); var HealthBar = Container.expand(function () { var self = Container.call(this); // Health bar properties self.maxHealth = 4; self.currentHealth = 4; self.width = 140; self.height = 20; // Create background bar (gray) var background = self.attachAsset('healthbar', { anchorX: 0.5, anchorY: 0.5, scaleX: 1, // Adjust to match bar width scaleY: 1, // Adjust to match bar height tint: 0x666666 // Gray color }); // Create foreground bar (health indicator - green) var foreground = self.attachAsset('healthbar', { anchorX: 0, anchorY: 0.5, scaleX: 1, // Adjust to match bar width scaleY: 1, // Adjust to match bar height tint: 0x00FF00 // Green color }); // Center the foreground bar foreground.x = -background.width / 2; // Update health bar visual based on current health self.updateHealth = function (health) { self.currentHealth = health; // Update the scale of the foreground bar based on current health var healthPercentage = Math.max(self.currentHealth / self.maxHealth, 0); // Scale should decrease as health decreases, not increase // Ensure that we don't go to 0 until health is actually 0 if (self.currentHealth > 0) { // For non-zero health, ensure we have at least a small visible portion of health bar foreground.scale.x = Math.max(healthPercentage, 0.05); } else { // Only when health is truly zero, set scale to zero foreground.scale.x = 0; } // Change color based on health level if (healthPercentage > 0.6) { foreground.tint = 0x00FF00; // Green } else if (healthPercentage > 0.3) { foreground.tint = 0xFFFF00; // Yellow } else { foreground.tint = 0xFF0000; // Red } }; return self; }); var Missile = Container.expand(function () { var self = Container.call(this); var missileGraphics = self.attachAsset('missile', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); self.speed = -10; // Moving upward self.targetX = null; self.targetY = null; // Add targetY for better homing self.turnSpeed = 0.25; // Significantly increased turn speed for better tracking self.angle = 0; // For side missiles self.update = function () { // Basic upward movement self.y += self.speed; // Enhanced target tracking if we have a target if (self.targetX && self.targetY) { // Calculate distance to target var diffX = self.targetX - self.x; var diffY = self.targetY - self.y; var dist = Math.sqrt(diffX * diffX + diffY * diffY); // Track frames since launch for initial trajectory control if (self.initialDirectionFrames === undefined) { self.initialDirectionFrames = 0; } // For the first 20 frames, maintain initial trajectory with very minimal homing // This ensures missiles start with distinctive paths if (self.initialDirectionFrames < 20) { self.initialDirectionFrames++; // Initial direction based on missile type if (self.initialDirection === 'left-up') { // Left missile veers slightly left self.x -= 2; self.y += self.speed * 0.2; // Slow vertical movement slightly } else if (self.initialDirection === 'right-up') { // Right missile veers slightly right self.x += 2; self.y += self.speed * 0.2; // Slow vertical movement slightly } else { // Center missile goes straight up // No horizontal movement, just straight up } } else { // After initial frames, apply enhanced homing behavior // Use a larger factor for more effective tracking while keeping realistic movement var homingFactor = self.turnSpeed * 0.3; // Significantly increased factor for better homing // Move more noticeably toward target x position self.x += diffX * homingFactor; // Also add vertical homing for more direct targeting self.y += diffY * (homingFactor * 0.4); // Add vertical component to homing // Apply slight angular adjustment to maintain separation // This ensures missiles maintain some of their initial trajectory if (self.angle) { self.x += Math.sin(self.angle) * 0.2; // Further reduced angular influence for better homing } } // Improved y-speed adjustment if target is far above or below if (diffY < -150) { // Increased speed adjustment for better vertical tracking self.y += self.speed * 0.06; // More aggressive speed adjustment } else if (diffY > 150) { // Increased adjustment if target is below missile self.y += self.speed * -0.04; // More noticeable slowdown } } }; // Create explosion when hitting a target or edge self.explode = function () { var explosion = new Explosion(); explosion.x = self.x; explosion.y = self.y; game.addChild(explosion); // Create fire pool after explosion var firePool = new FirePool(); firePool.x = self.x; firePool.y = self.y; game.addChild(firePool); firePools.push(firePool); // Play explosion sound LK.getSound('explosion').play(); // Damage enemies in area for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; var dx = enemy.x - self.x; var dy = enemy.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // If enemy is within explosion radius if (distance < 150) { // Enemy is destroyed by area damage score += enemy.scoreValue; LK.setScore(score); updateScoreDisplay(); LK.effects.flashObject(enemy, 0xff0000, 300); enemy.destroy(); enemies.splice(i, 1); } } return true; }; return self; }); var PlayerBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -20; // Moving upward (increased speed) self.power = 1; self.direction = 'up'; // up, down, left, right self.isPiercing = false; self.isBouncing = false; self.bounceCount = 0; self.maxBounces = 3; // Enemy bullet destruction functionality removed self.update = function () { // Move bullet based on direction if (self.direction === 'up') { self.y += self.speed; // Check for bouncing against top edge if (self.isBouncing && self.y < 0 && self.bounceCount < self.maxBounces) { self.direction = 'down'; self.bounceCount++; } } else if (self.direction === 'down') { self.y -= self.speed; // Note: speed is negative, so this is adding a positive value // Check for bouncing against bottom edge if (self.isBouncing && self.y > GAME_HEIGHT && self.bounceCount < self.maxBounces) { self.direction = 'up'; self.bounceCount++; } } else if (self.direction === 'left') { self.x += self.speed; // Check for bouncing against left edge if (self.isBouncing && self.x < 0 && self.bounceCount < self.maxBounces) { self.direction = 'right'; self.bounceCount++; } } else if (self.direction === 'right') { self.x -= self.speed; // Note: speed is negative, so this is adding a positive value // Check for bouncing against right edge if (self.isBouncing && self.x > GAME_WIDTH && self.bounceCount < self.maxBounces) { self.direction = 'left'; self.bounceCount++; } } }; // Method to create explosion when player bullet is destroyed self.explode = function () { var explosion = new Explosion(); explosion.x = self.x; explosion.y = self.y; // Make player bullet explosion slightly smaller explosion.scale.x = 0.6; explosion.scale.y = 0.6; game.addChild(explosion); explosions.push(explosion); // Play explosion sound LK.getSound('explosion').play(); }; // Use default intersection method return self; }); var PlayerShip = Container.expand(function () { var self = Container.call(this); // Visual representation var shipGraphics = self.attachAsset('playerShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.2, scaleY: 1.2 }); // Use default hitbox // Health visual (initially invisible) var shieldGraphics = self.attachAsset('health', { anchorX: 0.5, anchorY: 0.5, alpha: 0, scaleX: 1.2, scaleY: 1.2 }); // Final life warning text var finalLifeText = new Text2('FINAL LIFE', { size: 50, fill: 0xFF0000 }); finalLifeText.anchor.set(0.5, 0.5); finalLifeText.y = -110; finalLifeText.alpha = 0; self.addChild(finalLifeText); // Player properties self.speed = 10; self.fireRate = 20; // Ticks between shots self.lastShot = 0; self.health = 4; // Player starts with 4 health self.healthBar = new HealthBar(); self.healthBar.y = -80; // Position above player self.healthBar.x = 0; // Perfectly center the healthbar with the ship self.addChild(self.healthBar); self.shieldActive = false; self.powerUpActive = false; self.quadBulletsActive = false; self.rotationSpeed = 0; self.finalLifeWarningActive = false; // Physics properties for smooth movement self.targetX = null; self.targetY = null; self.isMoving = false; self.moveTween = null; // Update method for rotation and missile text positioning self.update = function () { if (self.quadBulletsActive) { shipGraphics.rotation += self.rotationSpeed; } // Keep missile ready text below the ship if (missileReadyText && missileReadyText.visible) { missileReadyText.x = self.x; missileReadyText.y = self.y + 110; } }; // Use default intersection method // Shield activation self.activateShield = function () { self.shieldActive = true; shieldGraphics.alpha = 0.5; // Play shield activation sound effect LK.getSound('shieldActivation').play(); // Shield times out after 5 seconds LK.setTimeout(function () { self.shieldActive = false; shieldGraphics.alpha = 0; }, 5000); }; // Power-up activation self.activatePowerUp = function () { self.powerUpActive = true; shipGraphics.tint = 0xf1c40f; // Yellow tint for power-up self.fireRate = 10; // Faster firing // Power-up times out after 7 seconds LK.setTimeout(function () { self.powerUpActive = false; shipGraphics.tint = 0xFFFFFF; self.fireRate = 20; }, 7000); }; // Quad bullets activation self.activateQuadBullets = function () { self.quadBulletsActive = true; shipGraphics.tint = 0xe74c3c; // Red tint for quad bullets self.fireRate = 15; // Medium firing speed self.rotationSpeed = 0.05; // Start spinning // Quad bullets time out after 8 seconds LK.setTimeout(function () { self.quadBulletsActive = false; shipGraphics.tint = 0xFFFFFF; self.fireRate = 20; self.rotationSpeed = 0; shipGraphics.rotation = 0; // Reset rotation }, 8000); }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerUpGraphics = self.attachAsset('powerUp', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 }); self.speed = 3; // Add quad bullet type with 1/3 chance var rand = Math.random(); if (rand < 0.33) { self.type = 'health'; } else if (rand < 0.66) { self.type = 'weapon'; } else { self.type = 'quadBullets'; } // Set color based on type if (self.type === 'health') { powerUpGraphics.tint = 0x2ecc71; // Green for health } else if (self.type === 'weapon') { powerUpGraphics.tint = 0xf1c40f; // Yellow for weapon } else { powerUpGraphics.tint = 0xe74c3c; // Red for quad bullets } self.update = function () { self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game constants var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var SPAWN_ENEMY_INTERVAL = 60; // Spawn enemy every 60 ticks initially var SPAWN_POWERUP_INTERVAL = 600; // Spawn power-up every 600 ticks var MIN_SPAWN_INTERVAL = 20; // Minimum spawn rate as difficulty increases // Game state variables var player; var playerBullets = []; var enemies = []; var enemyBullets = []; var powerUps = []; var missiles = []; var explosions = []; var firePools = []; var gameLevel = 1; var spawnCounter = 0; var powerUpCounter = 0; var isGameActive = true; var score = 0; var lastMissileTime = 0; var missileReadyText = new Text2('MISSILE READY', { size: 40, fill: 0xFF0000 }); // Initialize score display var scoreTxt = new Text2('SCORE: 0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); scoreTxt.y = 30; // Initialize level display var levelTxt = new Text2('LEVEL: 1', { size: 60, fill: 0xFFFFFF }); levelTxt.anchor.set(0.5, 0); LK.gui.top.addChild(levelTxt); levelTxt.y = 100; // Create player ship function initializeGame() { player = new PlayerShip(); player.x = GAME_WIDTH / 2; player.y = GAME_HEIGHT - 200; game.addChild(player); // Reset arrays playerBullets = []; enemies = []; enemyBullets = []; powerUps = []; missiles = []; explosions = []; firePools = []; // Reset game state gameLevel = 1; spawnCounter = 0; powerUpCounter = 0; isGameActive = true; lastMissileTime = 0; // Initialize missile ready text missileReadyText.anchor.set(0.5, 0.5); missileReadyText.alpha = 1; missileReadyText.visible = true; // Set initial missile time to be ready at game start lastMissileTime = LK.ticks - 600; // Position text below the player ship game.addChild(missileReadyText); // Flash the text immediately var _flashMissileText = function flashMissileText() { tween(missileReadyText, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { tween(missileReadyText, { alpha: 1 }, { duration: 500, onFinish: _flashMissileText }); } }); }; _flashMissileText(); // Reset score and update display LK.setScore(0); score = 0; updateScoreDisplay(); updateLevelDisplay(); // Play background music when game starts LK.playMusic('gameMusic', { fade: { start: 0, end: 1, duration: 1000 } }); } // Initialize the game initializeGame(); // Update score display function updateScoreDisplay() { scoreTxt.setText('SCORE: ' + score); } // Update level display function updateLevelDisplay() { levelTxt.setText('LEVEL: ' + gameLevel); } // Player shooting function playerShoot() { // Check fire rate cooldown if (LK.ticks - player.lastShot < player.fireRate) { return; } // Always fire dual cannons (left and right) var bulletLeft = new PlayerBullet(); bulletLeft.x = player.x - 20; bulletLeft.y = player.y - 40; bulletLeft.direction = 'up'; game.addChild(bulletLeft); playerBullets.push(bulletLeft); var bulletRight = new PlayerBullet(); bulletRight.x = player.x + 20; bulletRight.y = player.y - 40; bulletRight.direction = 'up'; game.addChild(bulletRight); playerBullets.push(bulletRight); // Triple bullets if weapon power-up is active if (player.powerUpActive) { var bulletCenter = new PlayerBullet(); bulletCenter.x = player.x; bulletCenter.y = player.y - 50; bulletCenter.direction = 'up'; game.addChild(bulletCenter); playerBullets.push(bulletCenter); } // Quad-directional bullets if quad bullets power-up is active if (player.quadBulletsActive) { // Up bullet already covered // Down bullet var bulletDown = new PlayerBullet(); bulletDown.x = player.x; bulletDown.y = player.y + 40; bulletDown.direction = 'down'; bulletDown.isPiercing = true; bulletDown.isBouncing = true; game.addChild(bulletDown); playerBullets.push(bulletDown); // Left bullet var bulletLeft = new PlayerBullet(); bulletLeft.x = player.x - 40; bulletLeft.y = player.y; bulletLeft.direction = 'left'; bulletLeft.isPiercing = true; bulletLeft.isBouncing = true; game.addChild(bulletLeft); playerBullets.push(bulletLeft); // Right bullet var bulletRight = new PlayerBullet(); bulletRight.x = player.x + 40; bulletRight.y = player.y; bulletRight.direction = 'right'; bulletRight.isPiercing = true; bulletRight.isBouncing = true; game.addChild(bulletRight); playerBullets.push(bulletRight); } // Play sound and reset shot timer LK.getSound('playerShoot').play(); player.lastShot = LK.ticks; } // Enemy shooting function enemyShoot(enemy) { if (LK.ticks - enemy.lastShot < enemy.fireRate) { return; } var bullet = new EnemyBullet(); bullet.x = enemy.x; bullet.y = enemy.y + 40; game.addChild(bullet); enemyBullets.push(bullet); LK.getSound('enemyShoot').play(); enemy.lastShot = LK.ticks; } // Spawn new enemy function spawnEnemy() { var enemy = new Enemy(); // Distribute enemies better across the screen width // Check if we have other enemies and avoid spawning too close to them if (enemies.length > 0) { // Find a position away from other enemies var attempts = 0; var potentialX; var validPosition = false; while (!validPosition && attempts < 10) { potentialX = Math.random() * (GAME_WIDTH - 100) + 50; validPosition = true; // Check distance from existing enemies for (var i = 0; i < enemies.length; i++) { if (Math.abs(enemies[i].x - potentialX) < 150) { validPosition = false; break; } } attempts++; } enemy.x = validPosition ? potentialX : Math.random() * (GAME_WIDTH - 100) + 50; } else { enemy.x = Math.random() * (GAME_WIDTH - 100) + 50; } enemy.y = -50; // Increase difficulty with levels if (gameLevel > 1) { enemy.speed = Math.min(2 + gameLevel * 0.5, 6); enemy.health = Math.min(1 + Math.floor(gameLevel / 3), 3); } if (gameLevel > 5) { enemy.fireRate = Math.max(120 - gameLevel * 5, 60); } game.addChild(enemy); enemies.push(enemy); } // Spawn power-up function spawnPowerUp() { var powerUp = new PowerUp(); powerUp.x = Math.random() * (GAME_WIDTH - 100) + 50; powerUp.y = -50; game.addChild(powerUp); powerUps.push(powerUp); } // Check level progress function checkLevelProgress() { // Advance level based on score var shouldAdvanceLevel = Math.floor(score / 1000) + 1; if (shouldAdvanceLevel > gameLevel) { gameLevel = shouldAdvanceLevel; updateLevelDisplay(); // Flash screen to indicate level up LK.effects.flashScreen(0x3498db, 500); // Play level up sound LK.getSound('levelUp').play(); } } // Handle collisions function handleCollisions() { // Check player bullets hitting enemies for (var i = playerBullets.length - 1; i >= 0; i--) { var bullet = playerBullets[i]; var bulletHit = false; // Enemy bullet destruction completely removed // Skip all bullet collision detection logic // If player bullet was destroyed by enemy bullets, skip enemy collision check if (bulletHit) { continue; } // Now check for player bullet hitting enemies for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (bullet.intersects(enemy)) { // Enemy takes damage if (enemy.takeDamage(bullet.power)) { // Enemy destroyed score += enemy.scoreValue; LK.setScore(score); updateScoreDisplay(); LK.getSound('explosion').play(); LK.effects.flashObject(enemy, 0xff0000, 300); // Create explosion animation at enemy position var explosion = new Explosion(); explosion.x = enemy.x; explosion.y = enemy.y; game.addChild(explosion); explosions.push(explosion); // Remove enemy enemy.destroy(); enemies.splice(j, 1); } // Only remove non-piercing bullets on hit if (!bullet.isPiercing) { bullet.explode(); // Add explosion effect when bullet is destroyed bullet.destroy(); playerBullets.splice(i, 1); bulletHit = true; break; } } } // If a non-piercing bullet hit something, skip to the next bullet if (bulletHit) { continue; } } // Check enemy bullets hitting player for (var i = enemyBullets.length - 1; i >= 0; i--) { var bullet = enemyBullets[i]; // Get center points of both objects for more precise collision detection var bulletCenterX = bullet.x; var bulletCenterY = bullet.y; var playerCenterX = player.x; var playerCenterY = player.y; // Calculate distance between centers var dx = bulletCenterX - playerCenterX; var dy = bulletCenterY - playerCenterY; var distance = Math.sqrt(dx * dx + dy * dy); // Get the combined radius (half the width of both objects for a more precise collision) var bulletRadius = bullet.width / 3.5; // Much smaller hitbox for accurate collision var playerRadius = player.width / 3.5; // Much smaller hitbox for accurate collision var combinedRadius = bulletRadius + playerRadius; // Only register hit if the bullet is actually touching the player (more precise collision) if (distance < combinedRadius) { // Player hit bullet.destroy(); enemyBullets.splice(i, 1); if (player.shieldActive) { // Shield absorbs the hit // Play explosion sound for shield hit LK.getSound('explosion').play(); player.shieldActive = false; var shield = player.getChildAt(1); shield.alpha = 0; } else { // Play sound when player gets hit by enemy bullet LK.getSound('playerHit').play(); // Reduce player health player.health--; player.healthBar.updateHealth(player.health); // Flash player to indicate damage LK.effects.flashObject(player, 0xff0000, 300); // Check if player health reaches 1 (final life) if (player.health === 1 && !player.finalLifeWarningActive) { player.finalLifeWarningActive = true; // Hide health bar completely player.healthBar.visible = false; // Show and animate "Final Life" text var finalLifeText = player.getChildAt(2); // Get the final life text finalLifeText.alpha = 1; // Create flashing effect for the text var _flashTween2 = function flashTween() { tween(finalLifeText, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { tween(finalLifeText, { alpha: 1 }, { duration: 500, onFinish: _flashTween2 }); } }); }; _flashTween2(); // Start the flashing animation } // Check if player is out of health if (player.health <= 0) { // Game over LK.effects.flashScreen(0xff0000, 1000); isGameActive = false; // Stop music with fade out LK.playMusic('gameMusic', { fade: { start: 1, end: 0, duration: 800 } }); // Play game over sound effect LK.getSound('gameOver').play(); LK.showGameOver(); break; } } } } // Check enemies colliding with player for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.intersects(player)) { if (player.shieldActive) { // Shield absorbs the hit // Play collision sound when enemy collides with shield LK.getSound('shieldCollision').play(); enemy.destroy(); enemies.splice(i, 1); // Shield gets depleted player.shieldActive = false; var shield = player.getChildAt(1); shield.alpha = 0; score += enemy.scoreValue; LK.setScore(score); updateScoreDisplay(); } else { // Reduce player health by 2 (collision is more dangerous) player.health -= 2; player.healthBar.updateHealth(player.health); // Play collision sound when player collides with enemy LK.getSound('playerCollision').play(); // Remove the enemy enemy.destroy(); enemies.splice(i, 1); // Flash player to indicate damage LK.effects.flashObject(player, 0xff0000, 300); // Check if player health reaches 1 (final life) if (player.health === 1 && !player.finalLifeWarningActive) { player.finalLifeWarningActive = true; // Hide health bar completely player.healthBar.visible = false; // Show and animate "Final Life" text var finalLifeText = player.getChildAt(2); // Get the final life text finalLifeText.alpha = 1; // Create flashing effect for the text var _flashTween2 = function _flashTween() { tween(finalLifeText, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { tween(finalLifeText, { alpha: 1 }, { duration: 500, onFinish: _flashTween2 }); } }); }; _flashTween2(); // Start the flashing animation } // Check if player is out of health if (player.health <= 0) { // Game over LK.effects.flashScreen(0xff0000, 1000); isGameActive = false; LK.showGameOver(); break; } } } } // Check player collecting power-ups for (var i = powerUps.length - 1; i >= 0; i--) { var powerUp = powerUps[i]; if (powerUp.intersects(player)) { LK.getSound('powerUp').play(); // Apply power-up effect if (powerUp.type === 'health') { // Health regeneration logic if (player.health < player.healthBar.maxHealth) { // Add 1 health point player.health = Math.min(player.health + 1, player.healthBar.maxHealth); // If player was at final life, restore health bar and remove warning if (player.finalLifeWarningActive && player.health > 1) { player.finalLifeWarningActive = false; player.healthBar.visible = true; // Get the final life text and hide it var finalLifeText = player.getChildAt(2); // Stop any existing tweens on the final life text tween.stop(finalLifeText); finalLifeText.alpha = 0; } // Update health bar player.healthBar.updateHealth(player.health); } } else if (powerUp.type === 'weapon') { player.activatePowerUp(); } else if (powerUp.type === 'quadBullets') { player.activateQuadBullets(); } // Remove power-up powerUp.destroy(); powerUps.splice(i, 1); } } } // Clean up off-screen objects function cleanupOffscreenObjects() { // Clean up missiles that went off screen for (var i = missiles.length - 1; i >= 0; i--) { var missile = missiles[i]; if (missile.y < -50 || missile.y > GAME_HEIGHT + 50 || missile.x < -50 || missile.x > GAME_WIDTH + 50) { missile.explode(); missile.destroy(); missiles.splice(i, 1); } } // Clean up bullets that went off screen for (var i = playerBullets.length - 1; i >= 0; i--) { var bullet = playerBullets[i]; // Check if bullet is off screen based on direction (unless it's bouncing) if (!bullet.isBouncing) { if (bullet.direction === 'up' && bullet.y < -50 || bullet.direction === 'down' && bullet.y > GAME_HEIGHT + 50 || bullet.direction === 'left' && bullet.x < -50 || bullet.direction === 'right' && bullet.x > GAME_WIDTH + 50) { bullet.destroy(); playerBullets.splice(i, 1); } } else if (bullet.bounceCount >= bullet.maxBounces) { // Add explosion for bouncing bullets that reached max bounce count bullet.explode(); // Play explosion sound when bullet is removed at max bounce count LK.getSound('bulletExplosion').play(); bullet.destroy(); playerBullets.splice(i, 1); } } for (var i = enemyBullets.length - 1; i >= 0; i--) { if (enemyBullets[i].y > GAME_HEIGHT + 50) { enemyBullets[i].destroy(); enemyBullets.splice(i, 1); } } // Clean up enemies that went off screen for (var i = enemies.length - 1; i >= 0; i--) { if (enemies[i].y > GAME_HEIGHT + 100) { enemies[i].destroy(); enemies.splice(i, 1); } } // Clean up power-ups that went off screen for (var i = powerUps.length - 1; i >= 0; i--) { if (powerUps[i].y > GAME_HEIGHT + 50) { powerUps[i].destroy(); powerUps.splice(i, 1); } } } // Player movement var isDragging = false; game.down = function (x, y) { // Fire missile on left click if cooldown is ready if (LK.ticks - lastMissileTime >= 600) { // 10 seconds at 60fps // Find closest enemy as target first var closestEnemy = null; var closestDistance = Number.MAX_VALUE; var potentialTargets = []; // Find up to 6 potential targets for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var dx = enemy.x - player.x; var dy = enemy.y - player.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < closestDistance) { closestDistance = distance; closestEnemy = enemy; } // Add to potential targets list (sort by proximity later) potentialTargets.push({ enemy: enemy, distance: distance }); } // Sort targets by distance potentialTargets.sort(function (a, b) { return a.distance - b.distance; }); // Launch three missiles from the same vertical position but different horizontal positions // Center missile - positioned exactly in the center of player ship var centerMissile = new Missile(); centerMissile.x = player.x; // Center horizontally with player centerMissile.y = player.y - 60; // Launch from front center of player ship centerMissile.turnSpeed = 0.05; // Very slight homing for center missile centerMissile.initialDirection = 'up'; // Make sure it exits straight up first // Left missile - positioned to the left of center missile var leftMissile = new Missile(); leftMissile.x = player.x - 30; // Position left of the player leftMissile.y = player.y - 60; // Same vertical position as center missile leftMissile.angle = -0.3; // Slight left angle for initial trajectory leftMissile.turnSpeed = 0.07; // Reduced homing for more separation leftMissile.initialDirection = 'left-up'; // Make sure it exits left-up first // Right missile - positioned to the right of center missile var rightMissile = new Missile(); rightMissile.x = player.x + 30; // Position right of the player rightMissile.y = player.y - 60; // Same vertical position as center missile rightMissile.angle = 0.3; // Slight right angle for initial trajectory rightMissile.turnSpeed = 0.07; // Reduced homing for more separation rightMissile.initialDirection = 'right-up'; // Make sure it exits right-up first // If we found a target, set it for missiles with different offsets to avoid pairing if (closestEnemy) { // Set slightly different targets for each missile to avoid pairing centerMissile.targetX = closestEnemy.x; centerMissile.targetY = closestEnemy.y; // For side missiles, either use different enemies or offset from main target if (potentialTargets.length > 1) { leftMissile.targetX = potentialTargets[Math.min(1, potentialTargets.length - 1)].enemy.x - 50; leftMissile.targetY = potentialTargets[Math.min(1, potentialTargets.length - 1)].enemy.y; } else { // If not enough targets, offset significantly from main target leftMissile.targetX = closestEnemy.x - 150; leftMissile.targetY = closestEnemy.y; } if (potentialTargets.length > 2) { rightMissile.targetX = potentialTargets[Math.min(2, potentialTargets.length - 1)].enemy.x + 50; rightMissile.targetY = potentialTargets[Math.min(2, potentialTargets.length - 1)].enemy.y; } else { // If not enough targets, offset significantly from main target rightMissile.targetX = closestEnemy.x + 150; rightMissile.targetY = closestEnemy.y; } } // Add first wave of missiles to game game.addChild(centerMissile); missiles.push(centerMissile); game.addChild(leftMissile); missiles.push(leftMissile); game.addChild(rightMissile); missiles.push(rightMissile); // Create a second wave of missiles with slightly different launch positions // Second center missile var centerMissile2 = new Missile(); centerMissile2.x = player.x; centerMissile2.y = player.y - 30; // Slightly higher than first wave centerMissile2.turnSpeed = 0.06; centerMissile2.initialDirection = 'up'; // Second left missile var leftMissile2 = new Missile(); leftMissile2.x = player.x - 40; // Different horizontal offset leftMissile2.y = player.y - 30; leftMissile2.angle = -0.4; // Different initial angle leftMissile2.turnSpeed = 0.08; leftMissile2.initialDirection = 'left-up'; // Second right missile var rightMissile2 = new Missile(); rightMissile2.x = player.x + 40; // Different horizontal offset rightMissile2.y = player.y - 30; rightMissile2.angle = 0.4; // Different initial angle rightMissile2.turnSpeed = 0.08; rightMissile2.initialDirection = 'right-up'; // Set targets for second wave if (closestEnemy) { // Set slightly different targets for second wave missiles if (potentialTargets.length > 3) { centerMissile2.targetX = potentialTargets[3].enemy.x; centerMissile2.targetY = potentialTargets[3].enemy.y; } else { centerMissile2.targetX = closestEnemy.x + 50; centerMissile2.targetY = closestEnemy.y + 50; } if (potentialTargets.length > 4) { leftMissile2.targetX = potentialTargets[4].enemy.x - 70; leftMissile2.targetY = potentialTargets[4].enemy.y; } else { leftMissile2.targetX = closestEnemy.x - 200; leftMissile2.targetY = closestEnemy.y + 50; } if (potentialTargets.length > 5) { rightMissile2.targetX = potentialTargets[5].enemy.x + 70; rightMissile2.targetY = potentialTargets[5].enemy.y; } else { rightMissile2.targetX = closestEnemy.x + 200; rightMissile2.targetY = closestEnemy.y + 50; } } // Add second wave of missiles to game game.addChild(centerMissile2); missiles.push(centerMissile2); game.addChild(leftMissile2); missiles.push(leftMissile2); game.addChild(rightMissile2); missiles.push(rightMissile2); // Play missile launch sound LK.getSound('missileLaunch').play(); // Reset cooldown lastMissileTime = LK.ticks; // Hide missile ready text and stop any active tweens tween.stop(missileReadyText); missileReadyText.visible = false; } //[8F] // Handle regular player movement var targetX = x; var targetY = y; // Clamp target position to game bounds if (targetX < 50) { targetX = 50; } if (targetX > GAME_WIDTH - 50) { targetX = GAME_WIDTH - 50; } if (targetY < 50) { targetY = 50; } if (targetY > GAME_HEIGHT - 50) { targetY = GAME_HEIGHT - 50; } player.targetX = targetX; player.targetY = targetY; player.isMoving = true; // Also shoot when player taps playerShoot(); }; game.move = function (x, y) { if (isGameActive) { // Clamp target position to game bounds var targetX = x; var targetY = y; if (targetX < 50) { targetX = 50; } if (targetX > GAME_WIDTH - 50) { targetX = GAME_WIDTH - 50; } if (targetY < 50) { targetY = 50; } if (targetY > GAME_HEIGHT - 50) { targetY = GAME_HEIGHT - 50; } // Update target position player.targetX = targetX; player.targetY = targetY; // For better tracking during fast mouse movements, directly update position player.x = player.targetX; player.y = player.targetY; player.isMoving = true; //{2K}{2L}{2M}{2N} } }; game.up = function () { // Keep the ship moving toward last target point }; // Main game update loop game.update = function () { if (!isGameActive) { return; } // Update missile ready text if (LK.ticks - lastMissileTime >= 600) { // 10 seconds cooldown if (!missileReadyText.visible) { missileReadyText.visible = true; missileReadyText.x = player.x; missileReadyText.y = player.y + 110; missileReadyText.alpha = 1; // Flash the text when ready var _flashMissileText2 = function flashMissileText() { tween(missileReadyText, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { tween(missileReadyText, { alpha: 1 }, { duration: 500, onFinish: _flashMissileText2 }); } }); }; _flashMissileText2(); } } // Spawn enemies spawnCounter++; var currentSpawnRate = Math.max(SPAWN_ENEMY_INTERVAL - gameLevel * 5, MIN_SPAWN_INTERVAL); if (spawnCounter >= currentSpawnRate) { spawnEnemy(); spawnCounter = 0; } // Spawn power-ups powerUpCounter++; if (powerUpCounter >= SPAWN_POWERUP_INTERVAL) { spawnPowerUp(); powerUpCounter = 0; } // Make player shoot automatically if (player.isMoving) { playerShoot(); } // Update enemy shooting for (var i = 0; i < enemies.length; i++) { enemyShoot(enemies[i]); } // Update missiles for (var i = missiles.length - 1; i >= 0; i--) { var missile = missiles[i]; // If missile doesn't have a target or target is destroyed, find new target if ((missile.targetX === null || missile.targetY === null) && enemies.length > 0) { // Find closest enemy as new target var closestEnemy = null; var closestDistance = Number.MAX_VALUE; // Check all enemies for potential targets for (var k = 0; k < enemies.length; k++) { var dx = enemies[k].x - missile.x; var dy = enemies[k].y - missile.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance < closestDistance) { closestDistance = distance; closestEnemy = enemies[k]; } } // If we found a target, set it with slight offset based on missile type if (closestEnemy) { // Add slightly different offsets to each missile's target to maintain separation // We can determine missile "type" by its position relative to player var offsetX = 0; var offsetY = 0; // Adding vertical offset for better separation // Using angle to identify missile type if (missile.angle < 0) { // Left missile offsetX = -100; // Increased horizontal offset offsetY = -20; // Slight vertical offset } else if (missile.angle > 0) { // Right missile offsetX = 100; // Increased horizontal offset offsetY = -20; // Slight vertical offset } else { // Center missile offsetY = -50; // Different vertical offset for center missile } missile.targetX = closestEnemy.x + offsetX; missile.targetY = closestEnemy.y + offsetY; } } // Check if missile hits an enemy var missileHit = false; for (var j = enemies.length - 1; j >= 0; j--) { if (missile.intersects(enemies[j])) { missile.explode(); missile.destroy(); missiles.splice(i, 1); missileHit = true; break; } } // Check if missile is off screen if (!missileHit && (missile.y < -50 || missile.y > GAME_HEIGHT + 50 || missile.x < -50 || missile.x > GAME_WIDTH + 50)) { missile.explode(); missile.destroy(); missiles.splice(i, 1); } } // Update explosions for (var i = explosions.length - 1; i >= 0; i--) { if (explosions[i].update()) { explosions.splice(i, 1); } } // Update fire pools for (var i = firePools.length - 1; i >= 0; i--) { if (firePools[i].update()) { firePools.splice(i, 1); } } // Check collisions handleCollisions(); // Clean up off-screen objects cleanupOffscreenObjects(); // Check level progression checkLevelProgress(); // Win condition check if (score >= 10000) { // Play win sound effect LK.getSound('winSound').play(); // Stop music with fade out LK.playMusic('gameMusic', { fade: { start: 1, end: 0, duration: 800 } }); LK.showYouWin(); isGameActive = false; } };
===================================================================
--- original.js
+++ change.js
@@ -164,9 +164,9 @@
LK.setScore(score);
updateScoreDisplay();
LK.effects.flashObject(enemy, 0xff0000, 300);
// Play explosion sound when enemy is destroyed by fire pool
- LK.getSound('explosion').play();
+ LK.getSound('firePoolDestroy').play();
enemy.destroy();
enemies.splice(i, 1);
}
}
@@ -459,9 +459,9 @@
self.activateShield = function () {
self.shieldActive = true;
shieldGraphics.alpha = 0.5;
// Play shield activation sound effect
- LK.getSound('powerUp').play();
+ LK.getSound('shieldActivation').play();
// Shield times out after 5 seconds
LK.setTimeout(function () {
self.shieldActive = false;
shieldGraphics.alpha = 0;
@@ -779,9 +779,9 @@
updateLevelDisplay();
// Flash screen to indicate level up
LK.effects.flashScreen(0x3498db, 500);
// Play level up sound
- LK.getSound('powerUp').play();
+ LK.getSound('levelUp').play();
}
}
// Handle collisions
function handleCollisions() {
@@ -861,9 +861,9 @@
var shield = player.getChildAt(1);
shield.alpha = 0;
} else {
// Play sound when player gets hit by enemy bullet
- LK.getSound('explosion').play();
+ LK.getSound('playerHit').play();
// Reduce player health
player.health--;
player.healthBar.updateHealth(player.health);
// Flash player to indicate damage
@@ -907,9 +907,9 @@
duration: 800
}
});
// Play game over sound effect
- LK.getSound('explosion').play();
+ LK.getSound('gameOver').play();
LK.showGameOver();
break;
}
}
@@ -921,9 +921,9 @@
if (enemy.intersects(player)) {
if (player.shieldActive) {
// Shield absorbs the hit
// Play collision sound when enemy collides with shield
- LK.getSound('explosion').play();
+ LK.getSound('shieldCollision').play();
enemy.destroy();
enemies.splice(i, 1);
// Shield gets depleted
player.shieldActive = false;
@@ -936,9 +936,9 @@
// Reduce player health by 2 (collision is more dangerous)
player.health -= 2;
player.healthBar.updateHealth(player.health);
// Play collision sound when player collides with enemy
- LK.getSound('explosion').play();
+ LK.getSound('playerCollision').play();
// Remove the enemy
enemy.destroy();
enemies.splice(i, 1);
// Flash player to indicate damage
@@ -1038,9 +1038,9 @@
} else if (bullet.bounceCount >= bullet.maxBounces) {
// Add explosion for bouncing bullets that reached max bounce count
bullet.explode();
// Play explosion sound when bullet is removed at max bounce count
- LK.getSound('explosion').play();
+ LK.getSound('bulletExplosion').play();
bullet.destroy();
playerBullets.splice(i, 1);
}
}
@@ -1390,9 +1390,9 @@
checkLevelProgress();
// Win condition check
if (score >= 10000) {
// Play win sound effect
- LK.getSound('powerUp').play();
+ LK.getSound('winSound').play();
// Stop music with fade out
LK.playMusic('gameMusic', {
fade: {
start: 1,
An enemy spaceship in a topdown shooter. In-Game asset. 2d. High contrast. No shadows
A player's spaceship in a topdown shooter (mainly blue in colour). In-Game asset. 2d. High contrast. No shadows
A powerup in a top-down shooter (icon of powerup no text). In-Game asset. 2d. High contrast. No shadows
Health Powerup in 2d space shooter (top down). In-Game asset. 2d. High contrast. No shadows
An explosion which contains debris of a spaceship. In-Game asset. 2d. High contrast. No shadows
pool of fire with top down view. In-Game asset. 2d. High contrast. No shadows
Make a small circle that looks like a laser (red colour). In-Game asset. 2d. High contrast. No shadows
Make a very small circle that looks like a laser (blue colour). In-Game asset. 2d. High contrast. No shadows. In-Game asset. 2d. High contrast. No shadows
A missile. In-Game asset. 2d. High contrast. No shadows