User prompt
los powerups aparecen con mayor frecuencia.
User prompt
los jefes apareceran cada minuto.
User prompt
despues de derrotar a los jefes los enemigos normales volveran a aparecer. despues de 2 minutos de juego vuelven a aparecer los jefes y se repite el ciclo.
User prompt
mover al jugador un poco hacia la derecha.
User prompt
radio de colisión de power ups: 60 píxeles. radio de colision de balas enemigas: 45 pixeles.
User prompt
reducir los factores de escala de la imagen titulopersonajes.
User prompt
aumentar la calidad de la imagen titulopersonajes.
User prompt
en la pantalla de seleccion de personaje, reemplazar el texto de seleccion de personaje con la imagen de nombre titulopersonajes.
User prompt
baja un poco a los enemigos que aparecen en el centro.
User prompt
baja un poco a los enemigos que aparecen en el centro.
User prompt
baja un poco a los enemigos que aparecen en el centro.
User prompt
baja un poco a los enemigos que aparecen en la esquina superior derecha.
User prompt
los enemigos solo pueden aparecer en 3 lugares, en la esquina superior derecha de la pantalla, la esquina inferior derecha de la pantalla, y el lado derecho de la pantalla en el centro.
User prompt
subir la imagen del titulo un poco mas.
User prompt
reemplaza las letras del titulo del juego con la imagen de nombre titulo.
User prompt
radio de colision de power ups: 25 pixeles. radio de colision de balas enemigas: 35 pixeles.
User prompt
radio de colision de power ups: 60 pixeles. radio de colision de balas enemigas: 45 pixeles.
User prompt
coloca un fondo
User prompt
coloca los numeros que representan las vidas a la derecha de la imagen vidas
User prompt
deja los numeros que representan las vidas al lado de la imagen vidas
User prompt
intercambia las letras lives por del juego por la imagen vidas
User prompt
coloca mas abajo el boton de seleccion de personaje
User prompt
el boton de seleccion de personaje sera la imagen seleccion de personaje
User prompt
el boton jugar del menu de inicio sera la imagen jugar igual con el boton de la seleccion de personaje
User prompt
el menu desaparecera despues de presionar el boton de jugar
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BossEnemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('jefe', { anchorX: 0.5, anchorY: 0.5, scaleX: 2, scaleY: 2 }); self.speed = -1; // Very slow self.lastX = self.x; // Initialize in constructor self.lastY = self.y; // Initialize in constructor self.shootCooldown = 0; self.health = 10; // Takes 10 hits to destroy self.verticalSpeed = 2; self.verticalDirection = 1; self.isFirstFrame = true; // Initialization flag self.update = function () { // Skip first frame logic to ensure proper initialization if (self.isFirstFrame) { self.isFirstFrame = false; return; // Skip first frame to avoid premature trigger } // Move enemy left self.x += self.speed; // Move vertically up and down self.y += self.verticalSpeed * self.verticalDirection; // Calculate bounds based on scaled boss height to keep it fully visible var margin = 50; // Safety margin var scaledHeight = 126 * 2; // Original height * scale factor var topBound = scaledHeight / 2 + margin; var bottomBound = 2732 - scaledHeight / 2 - margin; if (self.y <= topBound || self.y >= bottomBound) { self.verticalDirection *= -1; } // Update shooting cooldown if (self.shootCooldown > 0) { self.shootCooldown--; } // Update last values for next frame self.lastX = self.x; self.lastY = self.y; }; self.canShoot = function () { return self.shootCooldown <= 0; }; self.shoot = function () { if (self.canShoot()) { self.shootCooldown = 60; // Slower shooting return true; } return false; }; self.takeDamage = function () { self.health--; // Visual feedback for taking damage enemyGraphics.alpha = Math.max(0.3, Math.min(1.0, 0.3 + self.health / 10 * 0.7)); return self.health <= 0; }; self.cleanup = function () { // Clear any references and reset properties self.lastX = undefined; self.lastY = undefined; self.shootCooldown = 0; self.speed = 0; self.health = 0; self.verticalSpeed = 0; self.verticalDirection = 1; self.isFirstFrame = true; // Remove from parent if still attached if (self.parent) { self.parent.removeChild(self); } }; return self; }); var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.lastX = self.x; // Initialize in constructor self.lastY = self.y; // Initialize in constructor self.directionX = 1; // Default horizontal direction self.directionY = 0; // Default no vertical movement self.update = function () { // Null checks for safety if (self.lastX === null || self.lastX === undefined) self.lastX = self.x; if (self.lastY === null || self.lastY === undefined) self.lastY = self.y; // Set bullet rotation based on direction var angle = Math.atan2(self.directionY, self.directionX); bulletGraphics.rotation = angle; self.x += self.speed * self.directionX; self.y += self.speed * self.directionY; self.lastX = self.x; self.lastY = self.y; }; self.cleanup = function () { // Clear any references and reset properties self.lastX = undefined; self.lastY = undefined; self.speed = 0; self.directionX = 0; self.directionY = 0; // Remove from parent if still attached if (self.parent) { self.parent.removeChild(self); } }; return self; }); var CharacterSelectionScreen = Container.expand(function () { var self = Container.call(this); // Create title text var titleText = new Text2('SELECCIÓN DE PERSONAJE', { size: 140, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 2048 / 2; titleText.y = 400; self.addChild(titleText); // Create character images var player1Image = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 - 600, y: 1000, scaleX: 1.5, scaleY: 1.5 }); var player2Image = self.attachAsset('jugador2', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 - 200, y: 1000, scaleX: 1.5, scaleY: 1.5 }); var player3Image = self.attachAsset('jugador3', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + 200, y: 1000, scaleX: 1.5, scaleY: 1.5 }); var player4Image = self.attachAsset('jugador4', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2 + 600, y: 1000, scaleX: 1.5, scaleY: 1.5 }); // Create play button image var playImage = self.attachAsset('jugar', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 1400, scaleX: 2, scaleY: 2 }); // Store references for event handling self.player1Image = player1Image; self.player2Image = player2Image; self.player3Image = player3Image; self.player4Image = player4Image; self.playButton = playImage; self.selectedCharacter = 'player'; // Default selection return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -3; self.lastX = self.x; // Initialize in constructor self.shootCooldown = 0; self.isFirstFrame = true; // Initialization flag self.update = function () { // Skip first frame logic to ensure proper initialization if (self.isFirstFrame) { self.isFirstFrame = false; return; // Skip first frame to avoid premature trigger } // Move enemy left self.x += self.speed; // Update shooting cooldown if (self.shootCooldown > 0) { self.shootCooldown--; } // Update lastX for next frame self.lastX = self.x; }; self.canShoot = function () { return self.shootCooldown <= 0; }; self.shoot = function () { if (self.canShoot()) { self.shootCooldown = 180; // 3 second cooldown return true; } return false; }; self.cleanup = function () { // Clear any references and reset properties self.lastX = undefined; self.shootCooldown = 0; self.speed = 0; self.isFirstFrame = true; // Remove from parent if still attached if (self.parent) { self.parent.removeChild(self); } }; return self; }); var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6; self.lastX = self.x; // Initialize in constructor self.lastY = self.y; // Initialize in constructor self.directionX = -1; // Default moving left self.directionY = 0; // Default no vertical movement self.update = function () { // Null checks for safety if (self.lastX === null || self.lastX === undefined) self.lastX = self.x; if (self.lastY === null || self.lastY === undefined) self.lastY = self.y; // Set bullet rotation based on direction var angle = Math.atan2(self.directionY, self.directionX); bulletGraphics.rotation = angle; self.x += self.speed * self.directionX; self.y += self.speed * self.directionY; self.lastX = self.x; self.lastY = self.y; }; self.cleanup = function () { // Clear any references and reset properties self.lastX = undefined; self.lastY = undefined; self.speed = 0; self.directionX = 0; self.directionY = 0; // Remove from parent if still attached if (self.parent) { self.parent.removeChild(self); } }; return self; }); var FastEnemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemigorapido', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -6; // Faster than regular enemy self.lastX = self.x; // Initialize in constructor self.shootCooldown = 0; self.isFirstFrame = true; // Initialization flag self.update = function () { // Skip first frame logic to ensure proper initialization if (self.isFirstFrame) { self.isFirstFrame = false; return; // Skip first frame to avoid premature trigger } // Move enemy left self.x += self.speed; // Update shooting cooldown if (self.shootCooldown > 0) { self.shootCooldown--; } // Update lastX for next frame self.lastX = self.x; }; self.canShoot = function () { return self.shootCooldown <= 0; }; self.shoot = function () { if (self.canShoot()) { self.shootCooldown = 120; // 2 second cooldown return true; } return false; }; self.cleanup = function () { // Clear any references and reset properties self.lastX = undefined; self.shootCooldown = 0; self.speed = 0; self.isFirstFrame = true; // Remove from parent if still attached if (self.parent) { self.parent.removeChild(self); } }; return self; }); var HealthPowerup = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('healthPowerup', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -2; self.lastX = self.x; self.lastY = self.y; self.bobOffset = 0; self.isFirstFrame = true; self.update = function () { if (self.isFirstFrame) { self.isFirstFrame = false; return; } // Move left self.x += self.speed; // Bob up and down for visual appeal self.bobOffset += 0.1; powerupGraphics.y = Math.sin(self.bobOffset) * 10; // Gentle rotation powerupGraphics.rotation += 0.02; self.lastX = self.x; self.lastY = self.y; }; self.cleanup = function () { self.lastX = undefined; self.lastY = undefined; self.speed = 0; self.isFirstFrame = true; if (self.parent) { self.parent.removeChild(self); } }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphics = self.attachAsset(selectedPlayerAsset, { anchorX: 0.5, anchorY: 0.5 }); self.shootCooldown = 0; self.update = function () { if (self.shootCooldown > 0) { self.shootCooldown--; } // Update shield visual effect if (playerShieldTime > 0) { // Pulsing blue tint when shielded var pulse = Math.sin(LK.ticks * 0.3) * 0.3 + 0.7; playerGraphics.tint = 0x4488ff; playerGraphics.alpha = pulse; } else { // Normal appearance playerGraphics.tint = 0xffffff; playerGraphics.alpha = 1.0; } }; self.canShoot = function () { return self.shootCooldown <= 0; }; self.shoot = function () { if (self.canShoot()) { // Faster shooting with weapon upgrades var cooldown = Math.max(5, 10 - (playerWeaponLevel - 1) * 2); self.shootCooldown = cooldown; return playerWeaponLevel; // Return weapon level for multi-shot } return 0; }; return self; }); var ShieldEnemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemigoescudo', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -2; // Slower than regular enemy self.lastX = self.x; // Initialize in constructor self.shootCooldown = 0; self.health = 3; // Takes 3 hits to destroy self.isFirstFrame = true; // Initialization flag self.update = function () { // Skip first frame logic to ensure proper initialization if (self.isFirstFrame) { self.isFirstFrame = false; return; // Skip first frame to avoid premature trigger } // Move enemy left self.x += self.speed; // Update shooting cooldown if (self.shootCooldown > 0) { self.shootCooldown--; } // Update lastX for next frame self.lastX = self.x; }; self.canShoot = function () { return self.shootCooldown <= 0; }; self.shoot = function () { if (self.canShoot()) { self.shootCooldown = 150; // Much slower shooting return true; } return false; }; self.takeDamage = function () { self.health--; // Visual feedback for taking damage enemyGraphics.alpha = Math.max(0.5, Math.min(1.0, 0.5 + self.health / 3 * 0.5)); return self.health <= 0; }; self.cleanup = function () { // Clear any references and reset properties self.lastX = undefined; self.shootCooldown = 0; self.speed = 0; self.health = 0; self.isFirstFrame = true; // Remove from parent if still attached if (self.parent) { self.parent.removeChild(self); } }; return self; }); var ShieldPowerup = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('shieldPowerup', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -2; self.lastX = self.x; self.lastY = self.y; self.bobOffset = 0; self.isFirstFrame = true; self.update = function () { if (self.isFirstFrame) { self.isFirstFrame = false; return; } // Move left self.x += self.speed; // Bob up and down for visual appeal self.bobOffset += 0.15; powerupGraphics.y = Math.sin(self.bobOffset) * 15; // Pulsing effect var pulse = Math.sin(self.bobOffset * 2) * 0.2 + 1.0; powerupGraphics.scaleX = pulse; powerupGraphics.scaleY = pulse; self.lastX = self.x; self.lastY = self.y; }; self.cleanup = function () { self.lastX = undefined; self.lastY = undefined; self.speed = 0; self.isFirstFrame = true; if (self.parent) { self.parent.removeChild(self); } }; return self; }); var StartScreen = Container.expand(function () { var self = Container.call(this); // Create title text var titleText = new Text2('SPACE SHOOTER', { size: 180, fill: 0xFFFFFF }); titleText.anchor.set(0.5, 0.5); titleText.x = 2048 / 2; titleText.y = 2732 / 2 - 300; self.addChild(titleText); // Create play button image var playImage = self.attachAsset('jugar', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 + 50, scaleX: 2, scaleY: 2 }); // Create character selection button image var characterImage = self.attachAsset('seleccionpersonaje', { anchorX: 0.5, anchorY: 0.5, x: 2048 / 2, y: 2732 / 2 + 450, scaleX: 2, scaleY: 2 }); // Store button references for event handling self.playButton = playImage; self.characterButton = characterImage; return self; }); var WeaponPowerup = Container.expand(function () { var self = Container.call(this); var powerupGraphics = self.attachAsset('weaponPowerup', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -2; self.lastX = self.x; self.lastY = self.y; self.bobOffset = 0; self.isFirstFrame = true; self.update = function () { if (self.isFirstFrame) { self.isFirstFrame = false; return; } // Move left self.x += self.speed; // Bob up and down for visual appeal self.bobOffset += 0.12; powerupGraphics.y = Math.sin(self.bobOffset) * 12; // Spinning effect powerupGraphics.rotation += 0.05; self.lastX = self.x; self.lastY = self.y; }; self.cleanup = function () { self.lastX = undefined; self.lastY = undefined; self.speed = 0; self.isFirstFrame = true; if (self.parent) { self.parent.removeChild(self); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x1a1a2e }); /**** * Game Code ****/ // Game state variables var gameStarted = false; var startScreen = null; var characterSelectionScreen = null; var selectedPlayerAsset = 'player'; // Track which character asset to use var player = null; var enemies = []; var fastEnemies = []; var shieldEnemies = []; var bossEnemies = []; var bullets = []; var enemyBullets = []; var enemySpawnTimer = 0; var enemySpawnRate = 120; // Start spawning every 2 seconds (120 frames) var difficultyTimer = 0; var playerLives = 3; var playerShieldTime = 0; // Shield duration in frames var playerWeaponLevel = 1; // Weapon upgrade level (1-3) var playerWeaponTime = 0; // Weapon upgrade duration in frames // Power-up arrays var healthPowerups = []; var shieldPowerups = []; var weaponPowerups = []; var powerupSpawnTimer = 0; var powerupSpawnRate = 300; // Spawn every 5 seconds var enemiesEscaped = 0; // Track how many enemies have escaped var bossTimer = 0; // Track time for boss battle cycles (2 minutes = 7200 frames) var bossPhase = false; // Track if we're in boss phase var bossesSpawned = 0; // Track how many bosses have been spawned in current phase // Arrays to track objects marked for removal (using object references for safer iteration) var bulletsToRemove = []; var healthPowerupsToRemove = []; var shieldPowerupsToRemove = []; var weaponPowerupsToRemove = []; var enemyBulletsToRemove = []; var enemiesToRemove = []; var fastEnemiesToRemove = []; var shieldEnemiesToRemove = []; var bossEnemiesToRemove = []; var isDragging = false; var scoreTxt = null; var livesTxt = null; var livesNumberTxt = null; // Add background image var backgroundImage = game.attachAsset('fondo', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); // Initialize start screen startScreen = new StartScreen(); game.addChild(startScreen); function showCharacterSelection() { // Remove start screen if (startScreen && startScreen.parent) { startScreen.destroy(); startScreen = null; } // Show character selection screen characterSelectionScreen = new CharacterSelectionScreen(); game.addChild(characterSelectionScreen); } function startGame() { gameStarted = true; // Remove start screen if (startScreen && startScreen.parent) { startScreen.destroy(); startScreen = null; } // Remove character selection screen if (characterSelectionScreen && characterSelectionScreen.parent) { characterSelectionScreen.destroy(); characterSelectionScreen = null; } // Initialize player with selected character asset player = new Player(); player.x = 150; player.y = 2732 - 150; // Near bottom with some margin game.addChild(player); // Create score display scoreTxt = new Text2('0', { size: 100, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); scoreTxt.setText(LK.getScore()); // Create lives display with image livesTxt = LK.getAsset('vidas', { anchorX: 0, anchorY: 0, x: 120, y: 20 }); LK.gui.topLeft.addChild(livesTxt); // Create lives number display livesNumberTxt = new Text2(playerLives.toString(), { size: 80, fill: 0xFFFFFF }); livesNumberTxt.anchor.set(0, 0.5); livesNumberTxt.x = 330; // Position to the right of vidas image livesNumberTxt.y = 77; // Center vertically with vidas image LK.gui.topLeft.addChild(livesNumberTxt); } // Touch/mouse down - handle start screen or game play game.down = function (x, y, obj) { if (!gameStarted) { // Handle start screen if (startScreen) { // Check if play button was clicked if (startScreen.playButton) { var deltaX = x - startScreen.playButton.x; var deltaY = y - startScreen.playButton.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < 150) { // Button click radius startGame(); return; } } // Check if character selection button was clicked if (startScreen.characterButton) { var deltaX = x - startScreen.characterButton.x; var deltaY = y - startScreen.characterButton.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < 200) { // Button click radius showCharacterSelection(); return; } } return; } // Handle character selection screen if (characterSelectionScreen) { // Check character image clicks if (characterSelectionScreen.player1Image) { var deltaX = x - characterSelectionScreen.player1Image.x; var deltaY = y - characterSelectionScreen.player1Image.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < 150) { selectedPlayerAsset = 'player'; characterSelectionScreen.selectedCharacter = 'player'; return; } } if (characterSelectionScreen.player2Image) { var deltaX = x - characterSelectionScreen.player2Image.x; var deltaY = y - characterSelectionScreen.player2Image.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < 150) { selectedPlayerAsset = 'jugador2'; characterSelectionScreen.selectedCharacter = 'jugador2'; return; } } if (characterSelectionScreen.player3Image) { var deltaX = x - characterSelectionScreen.player3Image.x; var deltaY = y - characterSelectionScreen.player3Image.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < 150) { selectedPlayerAsset = 'jugador3'; characterSelectionScreen.selectedCharacter = 'jugador3'; return; } } if (characterSelectionScreen.player4Image) { var deltaX = x - characterSelectionScreen.player4Image.x; var deltaY = y - characterSelectionScreen.player4Image.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < 150) { selectedPlayerAsset = 'jugador4'; characterSelectionScreen.selectedCharacter = 'jugador4'; return; } } // Check if play button was clicked if (characterSelectionScreen.playButton) { var deltaX = x - characterSelectionScreen.playButton.x; var deltaY = y - characterSelectionScreen.playButton.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < 150) { // Button click radius startGame(); return; } } return; } } isDragging = true; // Move player to touch position (constrain to vertical movement) player.y = Math.max(100, Math.min(2732 - 100, y)); var weaponLevel = player.shoot(); if (weaponLevel > 0) { // Calculate direction vector from player to tap position var deltaX = x - player.x; var deltaY = y - player.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); var directionX = 1; var directionY = 0; if (distance > 1.0) { directionX = deltaX / distance; directionY = deltaY / distance; } // Create bullets based on weapon level for (var w = 0; w < weaponLevel; w++) { var bullet = new Bullet(); bullet.x = player.x + 40; // Spawn slightly ahead of player bullet.y = player.y - 40 + (w - Math.floor(weaponLevel / 2)) * 20; // Spread bullets vertically bullet.lastX = bullet.x; bullet.lastY = bullet.y; // Slight angle variation for multiple bullets var angleOffset = (w - Math.floor(weaponLevel / 2)) * 0.2; var cos = Math.cos(angleOffset); var sin = Math.sin(angleOffset); bullet.directionX = directionX * cos - directionY * sin; bullet.directionY = directionX * sin + directionY * cos; bullets.push(bullet); game.addChild(bullet); } LK.getSound('shoot').play(); } }; // Touch/mouse move - move player vertically while dragging game.move = function (x, y, obj) { if (!gameStarted || characterSelectionScreen) return; if (isDragging) { // Move player to touch position (constrain to vertical movement) player.y = Math.max(100, Math.min(2732 - 100, y)); } }; // Touch/mouse up - stop dragging game.up = function (x, y, obj) { if (!gameStarted || characterSelectionScreen) return; isDragging = false; }; game.update = function () { // Only update game logic if game has started and not in character selection if (!gameStarted || characterSelectionScreen) return; // Update enemy spawn timer and difficulty enemySpawnTimer++; difficultyTimer++; powerupSpawnTimer++; // Update power-up timers if (playerShieldTime > 0) { playerShieldTime--; } if (playerWeaponTime > 0) { playerWeaponTime--; if (playerWeaponTime <= 0) { playerWeaponLevel = 1; // Reset to normal weapon } } // Increase difficulty every 10 seconds (600 frames) if (difficultyTimer % 600 === 0 && enemySpawnRate > 30) { enemySpawnRate -= 10; // Spawn enemies more frequently } // Update boss timer bossTimer++; // Check for boss battle cycle (every 2 minutes = 7200 frames) if (bossTimer >= 7200) { bossPhase = true; bossTimer = 0; bossesSpawned = 0; } // Spawn enemies based on boss phase if (!bossPhase) { // Normal enemy spawning during non-boss phase if (enemySpawnTimer >= enemySpawnRate) { var spawnType = Math.random(); var spawnY = Math.random() * (2732 - 200) + 100; if (spawnType < 0.6) { // 60% chance for regular enemy var enemy = new Enemy(); enemy.x = 2048 + 30; enemy.y = spawnY; enemy.lastX = enemy.x; enemies.push(enemy); game.addChild(enemy); } else if (spawnType < 0.8) { // 20% chance for fast enemy var fastEnemy = new FastEnemy(); fastEnemy.x = 2048 + 30; fastEnemy.y = spawnY; fastEnemy.lastX = fastEnemy.x; fastEnemies.push(fastEnemy); game.addChild(fastEnemy); } else { // 20% chance for shield enemy var shieldEnemy = new ShieldEnemy(); shieldEnemy.x = 2048 + 30; shieldEnemy.y = spawnY; shieldEnemy.lastX = shieldEnemy.x; shieldEnemies.push(shieldEnemy); game.addChild(shieldEnemy); } enemySpawnTimer = 0; } } else { // Boss phase - spawn 2 bosses then wait for them to be defeated if (bossesSpawned < 2 && enemySpawnTimer >= 60) { // Small delay between boss spawns var spawnY1 = Math.random() * (2732 - 400) + 200; // First boss position var spawnY2 = Math.random() * (2732 - 400) + 200; // Second boss position // Ensure bosses don't spawn too close to each other while (Math.abs(spawnY2 - spawnY1) < 300) { spawnY2 = Math.random() * (2732 - 400) + 200; } // Spawn first boss var bossEnemy1 = new BossEnemy(); bossEnemy1.x = 2048 + 30; bossEnemy1.y = spawnY1; bossEnemy1.lastX = bossEnemy1.x; bossEnemies.push(bossEnemy1); game.addChild(bossEnemy1); // Spawn second boss var bossEnemy2 = new BossEnemy(); bossEnemy2.x = 2048 + 30; bossEnemy2.y = spawnY2; bossEnemy2.lastX = bossEnemy2.x; bossEnemies.push(bossEnemy2); game.addChild(bossEnemy2); bossesSpawned = 2; enemySpawnTimer = 0; } // Check if all bosses are defeated to end boss phase if (bossesSpawned >= 2 && bossEnemies.length === 0) { bossPhase = false; bossTimer = 0; // Reset timer for next boss cycle } } // Spawn power-ups if (powerupSpawnTimer >= powerupSpawnRate) { var powerupType = Math.random(); var spawnY = Math.random() * (2732 - 200) + 100; if (powerupType < 0.4) { // 40% chance for health power-up var healthPowerup = new HealthPowerup(); healthPowerup.x = 2048 + 30; healthPowerup.y = spawnY; healthPowerup.lastX = healthPowerup.x; healthPowerup.lastY = healthPowerup.y; healthPowerups.push(healthPowerup); game.addChild(healthPowerup); } else if (powerupType < 0.7) { // 30% chance for shield power-up var shieldPowerup = new ShieldPowerup(); shieldPowerup.x = 2048 + 30; shieldPowerup.y = spawnY; shieldPowerup.lastX = shieldPowerup.x; shieldPowerup.lastY = shieldPowerup.y; shieldPowerups.push(shieldPowerup); game.addChild(shieldPowerup); } else { // 30% chance for weapon power-up var weaponPowerup = new WeaponPowerup(); weaponPowerup.x = 2048 + 30; weaponPowerup.y = spawnY; weaponPowerup.lastX = weaponPowerup.x; weaponPowerup.lastY = weaponPowerup.y; weaponPowerups.push(weaponPowerup); game.addChild(weaponPowerup); } powerupSpawnTimer = 0; } // Update and check bullets for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; // Mark bullets that go off screen for removal if (bullet.x > 2048 + 50 || bullet.y < -50) { bulletsToRemove.push(bullet); continue; } // Skip collision detection for bullets outside meaningful collision zones if (bullet.x < -50 || bullet.x > 2100 || bullet.y < -50 || bullet.y > 2800) { continue; } // Check bullet vs enemy collisions var bulletHit = false; // Check regular enemies for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; // Skip enemies outside collision zone (bounding box check) if (enemy.x < -250 || enemy.x > 2100 || enemy.y < -50 || enemy.y > 2800) { continue; } // Check bullet collision with regular enemy using distance-based detection var deltaX = bullet.x - enemy.x; var deltaY = bullet.y - enemy.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < 80) { // 80px collision radius for regular enemies // Bullet hit enemy LK.setScore(LK.getScore() + 10); scoreTxt.setText(LK.getScore()); // Check for victory condition if (LK.getScore() >= 10000) { LK.showYouWin(); return; } // Visual feedback tween(enemy, { scaleX: 1.5, scaleY: 1.5, alpha: 0 }, { duration: 200, onFinish: function onFinish() { if (enemy.parent) { enemy.destroy(); } } }); enemiesToRemove.push(enemy); bulletsToRemove.push(bullet); bulletHit = true; LK.getSound('hit').play(); break; } } // Check fast enemies for (var j = fastEnemies.length - 1; j >= 0; j--) { var fastEnemy = fastEnemies[j]; // Skip fast enemies outside collision zone (bounding box check) if (fastEnemy.x < -250 || fastEnemy.x > 2100 || fastEnemy.y < -50 || fastEnemy.y > 2800) { continue; } // Check bullet collision with fast enemy using distance-based detection var deltaX = bullet.x - fastEnemy.x; var deltaY = bullet.y - fastEnemy.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < 85) { // 85px collision radius for fast enemies LK.setScore(LK.getScore() + 15); scoreTxt.setText(LK.getScore()); if (LK.getScore() >= 10000) { LK.showYouWin(); return; } tween(fastEnemy, { scaleX: 1.5, scaleY: 1.5, alpha: 0 }, { duration: 200, onFinish: function onFinish() { if (fastEnemy.parent) { fastEnemy.destroy(); } } }); fastEnemiesToRemove.push(fastEnemy); bulletsToRemove.push(bullet); bulletHit = true; LK.getSound('hit').play(); break; } } // Check shield enemies for (var j = shieldEnemies.length - 1; j >= 0; j--) { var shieldEnemy = shieldEnemies[j]; // Skip shield enemies outside collision zone (bounding box check) if (shieldEnemy.x < -250 || shieldEnemy.x > 2100 || shieldEnemy.y < -50 || shieldEnemy.y > 2800) { continue; } // Check bullet collision with shield enemy using distance-based detection var deltaX = bullet.x - shieldEnemy.x; var deltaY = bullet.y - shieldEnemy.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < 90) { // 90px collision radius for shield enemies (larger due to shield) if (shieldEnemy.takeDamage()) { LK.setScore(LK.getScore() + 30); scoreTxt.setText(LK.getScore()); if (LK.getScore() >= 10000) { LK.showYouWin(); return; } tween(shieldEnemy, { scaleX: 1.5, scaleY: 1.5, alpha: 0 }, { duration: 200, onFinish: function onFinish() { if (shieldEnemy.parent) { shieldEnemy.destroy(); } } }); shieldEnemiesToRemove.push(shieldEnemy); } else { LK.setScore(LK.getScore() + 5); scoreTxt.setText(LK.getScore()); } bulletsToRemove.push(bullet); bulletHit = true; LK.getSound('hit').play(); break; } } // Check boss enemies for (var j = bossEnemies.length - 1; j >= 0; j--) { var bossEnemy = bossEnemies[j]; // Skip boss enemies outside collision zone (bounding box check) if (bossEnemy.x < -250 || bossEnemy.x > 2100 || bossEnemy.y < -50 || bossEnemy.y > 2800) { continue; } // Check bullet collision with boss enemy using distance-based detection var deltaX = bullet.x - bossEnemy.x; var deltaY = bullet.y - bossEnemy.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < 80) { // 80px collision radius for boss enemies (much larger due to 2x scale and boss status) if (bossEnemy.takeDamage()) { LK.setScore(LK.getScore() + 100); scoreTxt.setText(LK.getScore()); if (LK.getScore() >= 10000) { LK.showYouWin(); return; } tween(bossEnemy, { scaleX: 3, scaleY: 3, alpha: 0 }, { duration: 500, onFinish: function onFinish() { if (bossEnemy.parent) { bossEnemy.destroy(); } } }); bossEnemiesToRemove.push(bossEnemy); } else { LK.setScore(LK.getScore() + 10); scoreTxt.setText(LK.getScore()); } bulletsToRemove.push(bullet); bulletHit = true; LK.getSound('hit').play(); break; } } if (bulletHit) continue; } // Update and check enemy bullets for (var m = enemyBullets.length - 1; m >= 0; m--) { var enemyBullet = enemyBullets[m]; // Mark enemy bullets that go off screen for removal if (enemyBullet.x < -50 || enemyBullet.y < -50 || enemyBullet.y > 2732 + 50) { enemyBulletsToRemove.push(enemyBullet); continue; } // Skip collision detection for enemy bullets outside meaningful collision zones if (enemyBullet.x < -50 || enemyBullet.x > 2100 || enemyBullet.y < -50 || enemyBullet.y > 2800) { continue; } // Check if enemy bullet hits player center (more precise collision) var deltaX = enemyBullet.x - player.x; var deltaY = enemyBullet.y - player.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < 45) { // Only hits if within 45 pixels of player center (consistent bullet collision radius) if (playerShieldTime <= 0) { // Only take damage if not shielded playerLives--; // Update lives number display if (livesNumberTxt) { livesNumberTxt.setText(playerLives.toString()); } LK.effects.flashScreen(0xFF0000, 500); if (playerLives <= 0) { LK.showGameOver(); return; } } enemyBulletsToRemove.push(enemyBullet); } } // Update and check regular enemies for (var k = enemies.length - 1; k >= 0; k--) { var enemy = enemies[k]; // Mark enemies that go off screen for removal if (enemy.x < -200) { // Regular enemy width is 200px enemiesEscaped++; if (enemiesEscaped >= 5) { LK.showGameOver(); return; } enemiesToRemove.push(enemy); continue; } // Skip processing for enemies outside meaningful interaction zones if (enemy.x < -250 || enemy.x > 2100 || enemy.y < -50 || enemy.y > 2800) { continue; } // Calculate distance once for collision detection var deltaX = player.x - enemy.x; var deltaY = player.y - enemy.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); // Enemy shooting logic if (enemy.shoot()) { var enemyBullet = new EnemyBullet(); var bulletOffset = 10; // Additional offset beyond enemy edge enemyBullet.x = enemy.x - (enemy.width / 2 + bulletOffset); // Spawn relative to enemy width enemyBullet.y = enemy.y; enemyBullet.lastX = enemyBullet.x; enemyBullet.lastY = enemyBullet.y; // Shoot straight left - no player tracking enemyBullet.directionX = -1; enemyBullet.directionY = 0; enemyBullets.push(enemyBullet); game.addChild(enemyBullet); } // Check if enemy collides with player center using same distance calculation if (distance < 60) { // Only hits if within 60 pixels of player center (larger radius for direct contact) if (playerShieldTime <= 0) { // Only take damage if not shielded playerLives--; // Update lives number display if (livesNumberTxt) { livesNumberTxt.setText(playerLives.toString()); } LK.effects.flashScreen(0xFF0000, 500); if (playerLives <= 0) { LK.showGameOver(); return; } } enemiesToRemove.push(enemy); } } // Update and check fast enemies for (var k = fastEnemies.length - 1; k >= 0; k--) { var fastEnemy = fastEnemies[k]; // Mark fast enemies that go off screen for removal if (fastEnemy.x < -200) { // Fast enemy width is 200px enemiesEscaped++; if (enemiesEscaped >= 5) { LK.showGameOver(); return; } fastEnemiesToRemove.push(fastEnemy); continue; } // Skip processing for fast enemies outside meaningful interaction zones if (fastEnemy.x < -250 || fastEnemy.x > 2100 || fastEnemy.y < -50 || fastEnemy.y > 2800) { continue; } // Calculate distance once for collision detection var deltaX = player.x - fastEnemy.x; var deltaY = player.y - fastEnemy.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (fastEnemy.shoot()) { var enemyBullet = new EnemyBullet(); var bulletOffset = 10; // Additional offset beyond enemy edge enemyBullet.x = fastEnemy.x - (fastEnemy.width / 2 + bulletOffset); // Spawn relative to enemy width enemyBullet.y = fastEnemy.y; enemyBullet.lastX = enemyBullet.x; enemyBullet.lastY = enemyBullet.y; // Shoot straight left - no player tracking enemyBullet.directionX = -1; enemyBullet.directionY = 0; enemyBullets.push(enemyBullet); game.addChild(enemyBullet); } // Check if fast enemy collides with player center using same distance calculation if (distance < 65) { // Only hits if within 65 pixels of player center (slightly larger due to fast movement) if (playerShieldTime <= 0) { // Only take damage if not shielded playerLives--; // Update lives number display if (livesNumberTxt) { livesNumberTxt.setText(playerLives.toString()); } LK.effects.flashScreen(0xFF0000, 500); if (playerLives <= 0) { LK.showGameOver(); return; } } fastEnemiesToRemove.push(fastEnemy); } } // Update and check shield enemies for (var k = shieldEnemies.length - 1; k >= 0; k--) { var shieldEnemy = shieldEnemies[k]; // Mark shield enemies that go off screen for removal if (shieldEnemy.x < -200) { // Shield enemy width is 200px enemiesEscaped++; if (enemiesEscaped >= 5) { LK.showGameOver(); return; } shieldEnemiesToRemove.push(shieldEnemy); continue; } // Skip processing for shield enemies outside meaningful interaction zones if (shieldEnemy.x < -250 || shieldEnemy.x > 2100 || shieldEnemy.y < -50 || shieldEnemy.y > 2800) { continue; } // Calculate distance once for collision detection var deltaX = player.x - shieldEnemy.x; var deltaY = player.y - shieldEnemy.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (shieldEnemy.shoot()) { var enemyBullet = new EnemyBullet(); var bulletOffset = 10; // Additional offset beyond enemy edge enemyBullet.x = shieldEnemy.x - (shieldEnemy.width / 2 + bulletOffset); // Spawn relative to enemy width enemyBullet.y = shieldEnemy.y; enemyBullet.lastX = enemyBullet.x; enemyBullet.lastY = enemyBullet.y; // Shoot straight left - no player tracking enemyBullet.directionX = -1; enemyBullet.directionY = 0; enemyBullets.push(enemyBullet); game.addChild(enemyBullet); } // Check if shield enemy collides with player center using same distance calculation if (distance < 70) { // Only hits if within 70 pixels of player center (larger due to shield size) if (playerShieldTime <= 0) { // Only take damage if not shielded playerLives--; // Update lives number display if (livesNumberTxt) { livesNumberTxt.setText(playerLives.toString()); } LK.effects.flashScreen(0xFF0000, 500); if (playerLives <= 0) { LK.showGameOver(); return; } } shieldEnemiesToRemove.push(shieldEnemy); } } // Update and check health power-ups for (var p = healthPowerups.length - 1; p >= 0; p--) { var healthPowerup = healthPowerups[p]; // Remove if off screen if (healthPowerup.x < -100) { healthPowerupsToRemove.push(healthPowerup); continue; } // Check collision with player var deltaX = healthPowerup.x - player.x; var deltaY = healthPowerup.y - player.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < 60) { // Player collected health power-up if (playerLives < 5) { // Max 5 lives playerLives++; // Update lives number display if (livesNumberTxt) { livesNumberTxt.setText(playerLives.toString()); } LK.getSound('powerup').play(); LK.effects.flashScreen(0x00ff00, 300); } healthPowerupsToRemove.push(healthPowerup); } } // Update and check shield power-ups for (var p = shieldPowerups.length - 1; p >= 0; p--) { var shieldPowerup = shieldPowerups[p]; // Remove if off screen if (shieldPowerup.x < -100) { shieldPowerupsToRemove.push(shieldPowerup); continue; } // Check collision with player var deltaX = shieldPowerup.x - player.x; var deltaY = shieldPowerup.y - player.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < 60) { // Player collected shield power-up playerShieldTime = 600; // 10 seconds of invincibility LK.getSound('powerup').play(); LK.effects.flashScreen(0x0088ff, 300); shieldPowerupsToRemove.push(shieldPowerup); } } // Update and check weapon power-ups for (var p = weaponPowerups.length - 1; p >= 0; p--) { var weaponPowerup = weaponPowerups[p]; // Remove if off screen if (weaponPowerup.x < -100) { weaponPowerupsToRemove.push(weaponPowerup); continue; } // Check collision with player var deltaX = weaponPowerup.x - player.x; var deltaY = weaponPowerup.y - player.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (distance < 60) { // Player collected weapon power-up playerWeaponLevel = Math.min(3, playerWeaponLevel + 1); // Max level 3 playerWeaponTime = 1800; // 30 seconds of upgrade LK.getSound('powerup').play(); LK.effects.flashScreen(0xffaa00, 300); weaponPowerupsToRemove.push(weaponPowerup); } } // Update and check boss enemies for (var k = bossEnemies.length - 1; k >= 0; k--) { var bossEnemy = bossEnemies[k]; // Mark boss enemies that go off screen for removal if (bossEnemy.x < -200) { // Boss enemy width is 100px * 2 scale = 200px enemiesEscaped++; if (enemiesEscaped >= 5) { LK.showGameOver(); return; } bossEnemiesToRemove.push(bossEnemy); continue; } // Skip processing for boss enemies outside meaningful interaction zones if (bossEnemy.x < -250 || bossEnemy.x > 2100 || bossEnemy.y < -50 || bossEnemy.y > 2800) { continue; } // Calculate distance once for collision detection var deltaX = player.x - bossEnemy.x; var deltaY = player.y - bossEnemy.y; var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY); if (bossEnemy.shoot()) { var enemyBullet = new EnemyBullet(); var bulletOffset = 10; // Additional offset beyond enemy edge enemyBullet.x = bossEnemy.x - (bossEnemy.width / 2 + bulletOffset); // Spawn relative to enemy width (scaled) enemyBullet.y = bossEnemy.y; enemyBullet.lastX = enemyBullet.x; enemyBullet.lastY = enemyBullet.y; // Shoot straight left - no player tracking enemyBullet.directionX = -1; enemyBullet.directionY = 0; enemyBullets.push(enemyBullet); game.addChild(enemyBullet); } // Check if boss enemy collides with player center using same distance calculation if (distance < 90) { // Only hits if within 90 pixels of player center (much larger due to 2x scale and boss size) if (playerShieldTime <= 0) { // Only take damage if not shielded playerLives--; // Update lives number display if (livesNumberTxt) { livesNumberTxt.setText(playerLives.toString()); } LK.effects.flashScreen(0xFF0000, 500); if (playerLives <= 0) { LK.showGameOver(); return; } } bossEnemiesToRemove.push(bossEnemy); } } // Deferred cleanup - process all marked objects for removal using safer object-based iteration // Process bullets marked for removal for (var i = bulletsToRemove.length - 1; i >= 0; i--) { var bulletToRemove = bulletsToRemove[i]; if (bulletToRemove && bulletToRemove.parent) { var index = bullets.indexOf(bulletToRemove); if (index !== -1 && index < bullets.length) { bullets[index].cleanup(); bullets[index].destroy(); bullets.splice(index, 1); } } } bulletsToRemove = []; // Process enemy bullets marked for removal for (var i = enemyBulletsToRemove.length - 1; i >= 0; i--) { var enemyBulletToRemove = enemyBulletsToRemove[i]; if (enemyBulletToRemove && enemyBulletToRemove.parent) { var index = enemyBullets.indexOf(enemyBulletToRemove); if (index !== -1 && index < enemyBullets.length) { enemyBullets[index].cleanup(); enemyBullets[index].destroy(); enemyBullets.splice(index, 1); } } } enemyBulletsToRemove = []; // Process regular enemies marked for removal for (var i = enemiesToRemove.length - 1; i >= 0; i--) { var enemyToRemove = enemiesToRemove[i]; if (enemyToRemove && enemyToRemove.parent) { var index = enemies.indexOf(enemyToRemove); if (index !== -1 && index < enemies.length) { enemies[index].cleanup(); enemies[index].destroy(); enemies.splice(index, 1); } } } enemiesToRemove = []; // Process fast enemies marked for removal for (var i = fastEnemiesToRemove.length - 1; i >= 0; i--) { var fastEnemyToRemove = fastEnemiesToRemove[i]; if (fastEnemyToRemove && fastEnemyToRemove.parent) { var index = fastEnemies.indexOf(fastEnemyToRemove); if (index !== -1 && index < fastEnemies.length) { fastEnemies[index].cleanup(); fastEnemies[index].destroy(); fastEnemies.splice(index, 1); } } } fastEnemiesToRemove = []; // Process shield enemies marked for removal for (var i = shieldEnemiesToRemove.length - 1; i >= 0; i--) { var shieldEnemyToRemove = shieldEnemiesToRemove[i]; if (shieldEnemyToRemove && shieldEnemyToRemove.parent) { var index = shieldEnemies.indexOf(shieldEnemyToRemove); if (index !== -1 && index < shieldEnemies.length) { shieldEnemies[index].cleanup(); shieldEnemies[index].destroy(); shieldEnemies.splice(index, 1); } } } shieldEnemiesToRemove = []; // Process boss enemies marked for removal for (var i = bossEnemiesToRemove.length - 1; i >= 0; i--) { var bossEnemyToRemove = bossEnemiesToRemove[i]; if (bossEnemyToRemove && bossEnemyToRemove.parent) { var index = bossEnemies.indexOf(bossEnemyToRemove); if (index !== -1 && index < bossEnemies.length) { bossEnemies[index].cleanup(); bossEnemies[index].destroy(); bossEnemies.splice(index, 1); } } } bossEnemiesToRemove = []; // Process health power-ups marked for removal for (var i = healthPowerupsToRemove.length - 1; i >= 0; i--) { var healthPowerupToRemove = healthPowerupsToRemove[i]; if (healthPowerupToRemove && healthPowerupToRemove.parent) { var index = healthPowerups.indexOf(healthPowerupToRemove); if (index !== -1 && index < healthPowerups.length) { healthPowerups[index].cleanup(); healthPowerups[index].destroy(); healthPowerups.splice(index, 1); } } } healthPowerupsToRemove = []; // Process shield power-ups marked for removal for (var i = shieldPowerupsToRemove.length - 1; i >= 0; i--) { var shieldPowerupToRemove = shieldPowerupsToRemove[i]; if (shieldPowerupToRemove && shieldPowerupToRemove.parent) { var index = shieldPowerups.indexOf(shieldPowerupToRemove); if (index !== -1 && index < shieldPowerups.length) { shieldPowerups[index].cleanup(); shieldPowerups[index].destroy(); shieldPowerups.splice(index, 1); } } } shieldPowerupsToRemove = []; // Process weapon power-ups marked for removal for (var i = weaponPowerupsToRemove.length - 1; i >= 0; i--) { var weaponPowerupToRemove = weaponPowerupsToRemove[i]; if (weaponPowerupToRemove && weaponPowerupToRemove.parent) { var index = weaponPowerups.indexOf(weaponPowerupToRemove); if (index !== -1 && index < weaponPowerups.length) { weaponPowerups[index].cleanup(); weaponPowerups[index].destroy(); weaponPowerups.splice(index, 1); } } } weaponPowerupsToRemove = []; // Monitor array sizes and implement limits to prevent memory leaks var maxBullets = 100; var maxEnemyBullets = 200; var maxEnemies = 50; // Limit bullets array size with safety checks if (bullets.length > maxBullets) { for (var i = bullets.length - 1; i >= maxBullets; i--) { if (i < bullets.length && bullets[i]) { bullets[i].cleanup(); bullets[i].destroy(); bullets.splice(i, 1); } } } // Limit enemy bullets array size with safety checks if (enemyBullets.length > maxEnemyBullets) { for (var i = enemyBullets.length - 1; i >= maxEnemyBullets; i--) { if (i < enemyBullets.length && enemyBullets[i]) { enemyBullets[i].cleanup(); enemyBullets[i].destroy(); enemyBullets.splice(i, 1); } } } // Limit enemies array size with safety checks if (enemies.length > maxEnemies) { for (var i = enemies.length - 1; i >= maxEnemies; i--) { if (i < enemies.length && enemies[i]) { enemies[i].cleanup(); enemies[i].destroy(); enemies.splice(i, 1); } } } // Limit fast enemies array size with safety checks if (fastEnemies.length > maxEnemies) { for (var i = fastEnemies.length - 1; i >= maxEnemies; i--) { if (i < fastEnemies.length && fastEnemies[i]) { fastEnemies[i].cleanup(); fastEnemies[i].destroy(); fastEnemies.splice(i, 1); } } } // Limit shield enemies array size with safety checks if (shieldEnemies.length > maxEnemies) { for (var i = shieldEnemies.length - 1; i >= maxEnemies; i--) { if (i < shieldEnemies.length && shieldEnemies[i]) { shieldEnemies[i].cleanup(); shieldEnemies[i].destroy(); shieldEnemies.splice(i, 1); } } } // Limit boss enemies array size with safety checks if (bossEnemies.length > maxEnemies) { for (var i = bossEnemies.length - 1; i >= maxEnemies; i--) { if (i < bossEnemies.length && bossEnemies[i]) { bossEnemies[i].cleanup(); bossEnemies[i].destroy(); bossEnemies.splice(i, 1); } } } }; // Play background music LK.playMusic('bgmusic');
===================================================================
--- original.js
+++ change.js
@@ -1128,10 +1128,10 @@
// Check if enemy bullet hits player center (more precise collision)
var deltaX = enemyBullet.x - player.x;
var deltaY = enemyBullet.y - player.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
- if (distance < 35) {
- // Only hits if within 35 pixels of player center (consistent bullet collision radius)
+ if (distance < 45) {
+ // Only hits if within 45 pixels of player center (consistent bullet collision radius)
if (playerShieldTime <= 0) {
// Only take damage if not shielded
playerLives--;
// Update lives number display
@@ -1321,9 +1321,9 @@
// Check collision with player
var deltaX = healthPowerup.x - player.x;
var deltaY = healthPowerup.y - player.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
- if (distance < 50) {
+ if (distance < 60) {
// Player collected health power-up
if (playerLives < 5) {
// Max 5 lives
playerLives++;
@@ -1348,9 +1348,9 @@
// Check collision with player
var deltaX = shieldPowerup.x - player.x;
var deltaY = shieldPowerup.y - player.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
- if (distance < 50) {
+ if (distance < 60) {
// Player collected shield power-up
playerShieldTime = 600; // 10 seconds of invincibility
LK.getSound('powerup').play();
LK.effects.flashScreen(0x0088ff, 300);
@@ -1368,9 +1368,9 @@
// Check collision with player
var deltaX = weaponPowerup.x - player.x;
var deltaY = weaponPowerup.y - player.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
- if (distance < 50) {
+ if (distance < 60) {
// Player collected weapon power-up
playerWeaponLevel = Math.min(3, playerWeaponLevel + 1); // Max level 3
playerWeaponTime = 1800; // 30 seconds of upgrade
LK.getSound('powerup').play();
tommy vercetti de gta vice city hecho con pixeles apuntando con un rifle de asalto m4 con la perspcetiva lateral. In-Game asset. 2d. High contrast. No shadows
un mafioso italiano usando un m4 con la perspectiva lateral de cuerpo completo In-Game asset. 2d. High contrast. No shadows
un pandillero mexicano apuntando con un SMG con la perspectiva lateral. In-Game asset. 2d. High contrast. No shadows de cuerpo completo
un pandillero negro con camisa azul oscuro y pantalon blanco usando una escopeta con la perspectiva lateral de cuerpo completo. In-Game asset. 2d. High contrast. No shadows
chaleco antibalas. In-Game asset. 2d. High contrast. No shadows
corazon verde dibujado. In-Game asset. 2d. High contrast. No shadows
escopeta dibujada. In-Game asset. 2d. High contrast. No shadows
claude speed de gta 3 apuntando con una ak47 desde una perspectiva lateral de cuerpo completo In-Game asset. 2d. High contrast. No shadows
las letras play con un color celeste y rosa combinados con una cursiva In-Game asset. 2d. High contrast. No shadows con contorno negro
letras que dicen seleccion de personaje con un color rosa y un color celeste y con contorno azul y rosa cursiva. In-Game asset. 2d. High contrast. No shadows
las letras vidas con un color rosa y azul con contorno rosa y azul combinados hechos con pixeles. In-Game asset. 2d. High contrast. No shadows
una mansion con piso rojo vista completa y totalmente desde arriba y desde dentro con una escalera grande igual que la de scarface la pelicula y pasillos a los lados. In-Game asset. 2d. High contrast. No shadows
no va a tener ese brazo especificamente
un motociclista vestido de negro apuntando con una smg de cuerpo completo con perspectiva lateral In-Game asset. 2d. High contrast. No shadows sin casco y sin moto
letras de color rosa y azul y con cursiva que digan vice city wars. In-Game asset. 2d. High contrast. No shadows
un hombre usando una chaqueta negra pantalones azules disparando un ak47. In-Game asset. 2d. High contrast. No shadows con la perspectiva lateral de cuerpo completo
letras de color rosa que dicen seleccion de personaje en cursiva y con contorno blanco