User prompt
Please fix the bug: 'TypeError: null is not an object (evaluating 'player.upgrade')' in or related to this line: 'player.upgrade('coin');' Line Number: 875
User prompt
Make it where if enemylaser hits player player turns into Deadship and then the game is over it says “you lost”
User prompt
If any bugs appear please fix them.
User prompt
If there is any bugs please fix them
User prompt
Make it where if you shoot meteor the meteor explodes everything around it and a text says “ You won. 🏆” Then make the game stop and restart. Make it where if you shoot enemylaser is explodes into coins that you collect and then you shoot laser faster and you do more damage.
User prompt
Make it where if you shoot meteor the meteor explodes everything around it and a text says “ You won. 🏆”
Remix started
Copy Cosmic Defender: Space Shooter
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0 }); /**** * Classes ****/ var Asteroid = Container.expand(function () { var self = Container.call(this); var asteroid = self.attachAsset('asteroid', { anchorX: 0.5, anchorY: 0.5 }); self.health = 2; self.speed = { y: 2 + Math.random() * 2, x: (Math.random() - 0.5) * 2 }; self.rotation = Math.random() * 0.1 - 0.05; self.scoreValue = 15; // Random size variation var scale = 0.7 + Math.random() * 0.8; asteroid.scale.set(scale, scale); self.damage = function (amount) { self.health -= amount || 1; tween(asteroid, { tint: 0xffffff }, { duration: 200, onFinish: function onFinish() { asteroid.tint = 0x95a5a6; } }); return self.health <= 0; }; self.update = function () { self.y += self.speed.y; self.x += self.speed.x; asteroid.rotation += self.rotation; }; return self; }); var Boss = Container.expand(function (level) { var self = Container.call(this); var ship = self.attachAsset('boss', { anchorX: 0.5, anchorY: 0.5 }); self.level = level || 1; self.maxHealth = 20 * self.level; self.health = self.maxHealth; self.scoreValue = 200 * self.level; self.phase = 0; self.phaseTime = 0; self.patterns = ['side-to-side', 'charge', 'retreat']; self.currentPattern = 0; self.targetX = 0; self.targetY = 0; // Adjust boss based on level if (self.level > 1) { ship.tint = 0xcc00cc; } // Health bar self.healthBar = new Container(); self.addChild(self.healthBar); var healthBarBg = self.healthBar.attachAsset('playerLaser', { anchorX: 0, anchorY: 0.5, scaleX: 2, scaleY: 0.5 }); healthBarBg.tint = 0x333333; healthBarBg.width = 200; self.healthBarFill = self.healthBar.attachAsset('playerLaser', { anchorX: 0, anchorY: 0.5, scaleX: 2, scaleY: 0.4 }); self.healthBarFill.tint = 0xff3333; self.healthBarFill.width = 200; self.healthBar.y = -120; self.damage = function (amount) { self.health -= amount || 1; // Update health bar var healthPercent = self.health / self.maxHealth; self.healthBarFill.width = 200 * healthPercent; tween(ship, { tint: 0xffffff }, { duration: 100, onFinish: function onFinish() { ship.tint = self.level > 1 ? 0xcc00cc : 0x9b59b6; } }); // Change patterns more quickly when damaged if (self.health < self.maxHealth * 0.5 && self.phaseTime > 150) { self.changePattern(); } return self.health <= 0; }; self.changePattern = function () { self.currentPattern = (self.currentPattern + 1) % self.patterns.length; self.phaseTime = 0; self.phase = 0; }; self.update = function () { self.phaseTime++; // Change pattern every so often if (self.phaseTime > 300) { self.changePattern(); } var pattern = self.patterns[self.currentPattern]; switch (pattern) { case 'side-to-side': // Move side to side self.targetX = 1024 + Math.sin(self.phaseTime * 0.02) * 800; if (self.phaseTime < 60) { self.targetY = Math.min(self.y + 2, 400); } else { self.targetY = 400; } break; case 'charge': // Charge down then back up if (self.phase === 0) { self.targetY = self.y + 5; if (self.y > 800) { self.phase = 1; } } else { self.targetY = Math.max(self.y - 3, 300); if (self.y <= 300) { self.phase = 0; } } self.targetX = 1024 + Math.sin(self.phaseTime * 0.03) * 500; break; case 'retreat': // Stay near top and move quickly self.targetY = 300; self.targetX = 1024 + Math.sin(self.phaseTime * 0.05) * 900; break; } // Move toward target position self.x += (self.targetX - self.x) * 0.05; self.y += (self.targetY - self.y) * 0.05; }; return self; }); var Enemy = Container.expand(function (type) { var self = Container.call(this); self.type = type || 'basic'; var assetType = self.type === 'fast' ? 'enemy' : 'enemy'; var ship = self.attachAsset(assetType, { anchorX: 0.5, anchorY: 0.5 }); // Different enemy types if (self.type === 'basic') { self.health = 1; self.speed = 2; self.scoreValue = 10; self.shootChance = 0.01; } else if (self.type === 'fast') { self.health = 1; self.speed = 3.5; self.scoreValue = 15; ship.scaleX = 0.8; ship.scaleY = 0.8; self.shootChance = 0.005; ship.tint = 0xff9966; } else if (self.type === 'tank') { self.health = 3; self.speed = 1.5; self.scoreValue = 25; ship.scaleX = 1.2; ship.scaleY = 1.2; self.shootChance = 0.015; ship.tint = 0x66ff66; } self.movement = { pattern: 'straight', phase: Math.random() * Math.PI * 2, amplitude: 60 + Math.random() * 60 }; self.initialX = 0; self.damage = function (amount) { self.health -= amount || 1; tween(ship, { tint: 0xffffff }, { duration: 200, onFinish: function onFinish() { ship.tint = self.type === 'fast' ? 0xff9966 : self.type === 'tank' ? 0x66ff66 : 0xe74c3c; } }); return self.health <= 0; }; self.update = function () { // Basic movement self.y += self.speed; // Pattern movement if (self.movement.pattern === 'sine') { self.x = self.initialX + Math.sin(LK.ticks * 0.05 + self.movement.phase) * self.movement.amplitude; } else if (self.movement.pattern === 'zigzag') { var timeScale = 0.02; var t = LK.ticks * timeScale + self.movement.phase; var triangleWave = Math.abs(t % 2 - 1) * 2 - 1; self.x = self.initialX + triangleWave * self.movement.amplitude; } }; return self; }); var EnemyLaser = Container.expand(function () { var self = Container.call(this); var laser = self.attachAsset('enemyLaser', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.update = function () { self.y += self.speed; }; return self; }); var Explosion = Container.expand(function () { var self = Container.call(this); var explosion = self.attachAsset('explosion', { anchorX: 0.5, anchorY: 0.5, alpha: 0.9 }); // Set up fade and scale tween(explosion, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 500, onFinish: function onFinish() { self.destroy(); } }); return self; }); var Player = Container.expand(function () { var self = Container.call(this); var ship = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.shield = self.attachAsset('shield', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); self.lives = 3; self.shieldActive = false; self.fireRate = 20; self.lastShot = 0; self.canShoot = true; self.power = 1; self.invulnerable = false; self.activateShield = function (duration) { self.shieldActive = true; self.shield.alpha = 0.4; LK.setTimeout(function () { self.shieldActive = false; tween(self.shield, { alpha: 0 }, { duration: 500 }); }, duration); }; self.damage = function () { if (self.invulnerable || self.shieldActive) { return; } self.lives--; LK.getSound('playerDamage').play(); // Make player temporarily invulnerable self.invulnerable = true; // Flash the player to show invulnerability var flashCount = 0; var flashInterval = LK.setInterval(function () { ship.alpha = ship.alpha === 0.3 ? 1 : 0.3; flashCount++; if (flashCount >= 10) { LK.clearInterval(flashInterval); ship.alpha = 1; self.invulnerable = false; } }, 150); }; self.upgrade = function (type) { LK.getSound('powerup').play(); if (type === 'shield') { self.activateShield(8000); } else if (type === 'power') { self.power = Math.min(self.power + 1, 3); // Reset power after some time LK.setTimeout(function () { self.power = Math.max(1, self.power - 1); }, 10000); } else if (type === 'life') { self.lives = Math.min(self.lives + 1, 5); } else if (type === 'speed') { var oldFireRate = self.fireRate; self.fireRate = Math.max(self.fireRate - 5, 10); // Reset fire rate after some time LK.setTimeout(function () { self.fireRate = oldFireRate; }, 10000); } }; return self; }); var PlayerLaser = Container.expand(function () { var self = Container.call(this); var laser = self.attachAsset('playerLaser', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -15; self.power = 1; self.update = function () { self.y += self.speed; }; return self; }); var Powerup = Container.expand(function (type) { var self = Container.call(this); self.type = type || ['shield', 'power', 'life', 'speed'][Math.floor(Math.random() * 4)]; var powerup = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); // Set color based on type if (self.type === 'shield') { powerup.tint = 0x3498db; // Blue } else if (self.type === 'power') { powerup.tint = 0xe74c3c; // Red } else if (self.type === 'life') { powerup.tint = 0x2ecc71; // Green } else if (self.type === 'speed') { powerup.tint = 0xf1c40f; // Yellow } self.speed = 3; self.update = function () { self.y += self.speed; powerup.rotation += 0.05; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000022 }); /**** * Game Code ****/ // Game variables var player; var playerLasers = []; var enemies = []; var enemyLasers = []; var asteroids = []; var powerups = []; var explosions = []; var boss = null; var gameState = 'playing'; var score = 0; var waveNumber = 1; var enemiesThisWave = 0; var enemiesDefeated = 0; var waveDelay = 0; var bossWave = false; var dragStartPosition = { x: 0, y: 0 }; // UI elements var scoreTxt = new Text2('SCORE: 0', { size: 40, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); LK.gui.topRight.addChild(scoreTxt); scoreTxt.x = -250; scoreTxt.y = 50; var waveText = new Text2('WAVE: 1', { size: 40, fill: 0xFFFFFF }); waveText.anchor.set(0.5, 0); LK.gui.top.addChild(waveText); waveText.y = 50; var livesText = new Text2('LIVES: 3', { size: 40, fill: 0xFFFFFF }); livesText.anchor.set(0, 0); LK.gui.topLeft.addChild(livesText); livesText.x = 150; // Keep away from the top-left menu icon livesText.y = 50; // Create game elements function initGame() { // Reset game variables playerLasers = []; enemies = []; enemyLasers = []; asteroids = []; powerups = []; explosions = []; boss = null; gameState = 'playing'; score = 0; waveNumber = 1; enemiesThisWave = 10; enemiesDefeated = 0; waveDelay = 0; bossWave = false; // Update UI scoreTxt.setText('SCORE: ' + score); waveText.setText('WAVE: ' + waveNumber); // Create player player = new Player(); player.x = 1024; player.y = 2200; game.addChild(player); livesText.setText('LIVES: ' + player.lives); // Start with player moving up tween(player, { y: 2000 }, { duration: 1000 }); // Start the music LK.playMusic('gameMusic', { fade: { start: 0, end: 0.7, duration: 1000 } }); // Create first wave createWave(); } // Create a new wave of enemies function createWave() { waveNumber++; waveText.setText('WAVE: ' + waveNumber); // Every 5 waves is a boss wave bossWave = waveNumber % 5 === 0; if (bossWave) { // Create a boss var bossLevel = Math.ceil(waveNumber / 5); LK.getSound('bossAlert').play(); boss = new Boss(bossLevel); boss.x = 1024; boss.y = -200; game.addChild(boss); tween(boss, { y: 300 }, { duration: 2000 }); // Show boss wave text var bossText = new Text2('BOSS WAVE!', { size: 80, fill: 0xFF0000 }); bossText.anchor.set(0.5, 0.5); bossText.x = 1024; bossText.y = 800; game.addChild(bossText); tween(bossText, { alpha: 0, y: 700 }, { duration: 2000, onFinish: function onFinish() { bossText.destroy(); } }); return; } // Regular wave enemiesThisWave = 10 + waveNumber * 2; enemiesDefeated = 0; // Show wave text var newWaveText = new Text2('WAVE ' + waveNumber, { size: 80, fill: 0xFFFFFF }); newWaveText.anchor.set(0.5, 0.5); newWaveText.x = 1024; newWaveText.y = 800; game.addChild(newWaveText); tween(newWaveText, { alpha: 0, y: 700 }, { duration: 2000, onFinish: function onFinish() { newWaveText.destroy(); } }); // Start spawning enemies after a short delay waveDelay = 120; } // Create a new enemy function spawnEnemy() { var types = ['basic']; // Add more enemy types as waves progress if (waveNumber >= 2) { types.push('fast'); } if (waveNumber >= 3) { types.push('tank'); } var type = types[Math.floor(Math.random() * types.length)]; var enemy = new Enemy(type); // Position the enemy enemy.x = Math.random() * 1800 + 124; enemy.y = -100; enemy.initialX = enemy.x; // Set random movement pattern var patterns = ['straight']; if (waveNumber >= 2) { patterns.push('sine'); } if (waveNumber >= 4) { patterns.push('zigzag'); } enemy.movement.pattern = patterns[Math.floor(Math.random() * patterns.length)]; // Add to game enemies.push(enemy); game.addChild(enemy); } // Create a new asteroid function spawnAsteroid() { var asteroid = new Asteroid(); // Position the asteroid asteroid.x = Math.random() * 1800 + 124; asteroid.y = -100; // Add to game asteroids.push(asteroid); game.addChild(asteroid); } // Create a player laser function firePlayerLaser() { if (!player || !player.canShoot || player.lastShot + player.fireRate > LK.ticks) { return; } player.lastShot = LK.ticks; LK.getSound('playerShoot').play(); // Fire based on power level if (player.power === 1) { var laser = new PlayerLaser(); laser.x = player.x; laser.y = player.y - 50; laser.power = player.power; playerLasers.push(laser); game.addChild(laser); } else if (player.power === 2) { for (var i = -1; i <= 1; i += 2) { var laser = new PlayerLaser(); laser.x = player.x + i * 30; laser.y = player.y - 40; laser.power = player.power; playerLasers.push(laser); game.addChild(laser); } } else if (player.power >= 3) { var centerLaser = new PlayerLaser(); centerLaser.x = player.x; centerLaser.y = player.y - 50; centerLaser.power = player.power; playerLasers.push(centerLaser); game.addChild(centerLaser); for (var i = -1; i <= 1; i += 2) { var sideLaser = new PlayerLaser(); sideLaser.x = player.x + i * 40; sideLaser.y = player.y - 30; sideLaser.power = player.power - 1; playerLasers.push(sideLaser); game.addChild(sideLaser); } } } // Create an enemy laser function fireEnemyLaser(enemy) { var laser = new EnemyLaser(); laser.x = enemy.x; laser.y = enemy.y + 40; enemyLasers.push(laser); game.addChild(laser); LK.getSound('enemyShoot').play({ volume: 0.2 }); } // Fire boss laser pattern function fireBossLasers() { if (!boss) { return; } // Different patterns based on boss level and health var healthPercent = boss.health / boss.maxHealth; var pattern = 'spread'; if (boss.level >= 2 && healthPercent < 0.5) { pattern = 'circle'; } if (pattern === 'spread') { for (var i = -2; i <= 2; i++) { var laser = new EnemyLaser(); laser.x = boss.x + i * 50; laser.y = boss.y + 80; enemyLasers.push(laser); game.addChild(laser); } } else if (pattern === 'circle') { var numLasers = 8; for (var i = 0; i < numLasers; i++) { var angle = i / numLasers * Math.PI * 2; var laser = new EnemyLaser(); laser.x = boss.x + Math.cos(angle) * 100; laser.y = boss.y + Math.sin(angle) * 100; enemyLasers.push(laser); game.addChild(laser); // Add directional motion laser.update = function () { var dx = this.x - boss.x; var dy = this.y - boss.y; var length = Math.sqrt(dx * dx + dy * dy); this.x += dx / length * 5; this.y += dy / length * 5; }; } } LK.getSound('enemyShoot').play({ volume: 0.4 }); } // Create explosion animation function createExplosion(x, y, scale) { var explosion = new Explosion(); explosion.x = x; explosion.y = y; if (scale) { explosion.scale.set(scale, scale); } explosions.push(explosion); game.addChild(explosion); LK.getSound('explosion').play(); } // Create a powerup function spawnPowerup(x, y, type) { var powerup = new Powerup(type); powerup.x = x; powerup.y = y; powerups.push(powerup); game.addChild(powerup); } // Handle player shooting and movement function handlePlayerInput() { // Keep player in bounds player.x = Math.max(100, Math.min(player.x, 2048 - 100)); player.y = Math.max(100, Math.min(player.y, 2732 - 100)); // Auto-fire if (LK.ticks % 10 === 0) { firePlayerLaser(); } } // Handle collisions between game objects function handleCollisions() { // Player lasers vs enemies for (var i = playerLasers.length - 1; i >= 0; i--) { var laser = playerLasers[i]; var hitSomething = false; // Check against enemies for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (laser.intersects(enemy)) { // Damage enemy if (enemy.damage(laser.power)) { // Enemy destroyed createExplosion(enemy.x, enemy.y); // Add score score += enemy.scoreValue; scoreTxt.setText('SCORE: ' + score); // Count enemy as defeated enemiesDefeated++; // Chance to spawn powerup if (Math.random() < 0.1) { spawnPowerup(enemy.x, enemy.y); } enemy.destroy(); enemies.splice(j, 1); } // Remove laser laser.destroy(); playerLasers.splice(i, 1); hitSomething = true; break; } } // Only check other collisions if we haven't hit an enemy if (!hitSomething) { // Check against boss if (boss && laser.intersects(boss)) { // Damage boss if (boss.damage(laser.power)) { // Boss destroyed createExplosion(boss.x, boss.y, 2); // Add score score += boss.scoreValue; scoreTxt.setText('SCORE: ' + score); // Spawn multiple powerups for (var p = 0; p < 3; p++) { var powerupType = ['shield', 'power', 'life', 'speed'][Math.floor(Math.random() * 4)]; spawnPowerup(boss.x + (Math.random() * 200 - 100), boss.y + (Math.random() * 200 - 100), powerupType); } boss.destroy(); boss = null; // Move to next wave createWave(); } // Remove laser laser.destroy(); playerLasers.splice(i, 1); hitSomething = true; } // Check against asteroids for (var k = asteroids.length - 1; k >= 0; k--) { var asteroid = asteroids[k]; if (laser.intersects(asteroid)) { // Damage asteroid if (asteroid.damage(laser.power)) { // Asteroid destroyed createExplosion(asteroid.x, asteroid.y, 0.7); // Add score score += asteroid.scoreValue; scoreTxt.setText('SCORE: ' + score); asteroid.destroy(); asteroids.splice(k, 1); } // Remove laser laser.destroy(); playerLasers.splice(i, 1); hitSomething = true; break; } } } // Remove laser if it's off screen if (!hitSomething && laser.y < -50) { laser.destroy(); playerLasers.splice(i, 1); } } // Enemy lasers vs player for (var i = enemyLasers.length - 1; i >= 0; i--) { var laser = enemyLasers[i]; if (player && laser.intersects(player)) { // Damage player player.damage(); // Update UI livesText.setText('LIVES: ' + player.lives); // Check for game over if (player.lives <= 0) { // Game over createExplosion(player.x, player.y, 1.5); player.destroy(); player = null; // Save high score if needed if (score > storage.highScore) { storage.highScore = score; } // Show game over after a delay LK.setTimeout(function () { LK.showGameOver(); }, 1000); } // Remove laser laser.destroy(); enemyLasers.splice(i, 1); } else if (laser.y > 2732 + 50) { // Remove laser if it's off screen laser.destroy(); enemyLasers.splice(i, 1); } } // Player vs enemies for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (player && player.intersects(enemy)) { // Damage player player.damage(); // Damage enemy enemy.damage(1); // Update UI livesText.setText('LIVES: ' + player.lives); // Check for enemy death if (enemy.health <= 0) { // Enemy destroyed createExplosion(enemy.x, enemy.y); // Add score score += enemy.scoreValue; scoreTxt.setText('SCORE: ' + score); // Count enemy as defeated enemiesDefeated++; enemy.destroy(); enemies.splice(i, 1); } // Check for game over if (player.lives <= 0) { // Game over createExplosion(player.x, player.y, 1.5); player.destroy(); player = null; // Save high score if needed if (score > storage.highScore) { storage.highScore = score; } // Show game over after a delay LK.setTimeout(function () { LK.showGameOver(); }, 1000); } } // Remove enemy if it's off screen if (enemy.y > 2732 + 100) { enemy.destroy(); enemies.splice(i, 1); } } // Player vs asteroids for (var i = asteroids.length - 1; i >= 0; i--) { var asteroid = asteroids[i]; if (player && player.intersects(asteroid)) { // Damage player player.damage(); // Damage asteroid asteroid.damage(1); // Update UI livesText.setText('LIVES: ' + player.lives); // Check for asteroid death if (asteroid.health <= 0) { // Asteroid destroyed createExplosion(asteroid.x, asteroid.y, 0.7); // Add score score += asteroid.scoreValue; scoreTxt.setText('SCORE: ' + score); asteroid.destroy(); asteroids.splice(i, 1); } // Check for game over if (player.lives <= 0) { // Game over createExplosion(player.x, player.y, 1.5); player.destroy(); player = null; // Save high score if needed if (score > storage.highScore) { storage.highScore = score; } // Show game over after a delay LK.setTimeout(function () { LK.showGameOver(); }, 1000); } } // Remove asteroid if it's off screen if (asteroid.y > 2732 + 100 || asteroid.x < -100 || asteroid.x > 2048 + 100) { asteroid.destroy(); asteroids.splice(i, 1); } } // Player vs powerups for (var i = powerups.length - 1; i >= 0; i--) { var powerup = powerups[i]; if (player && player.intersects(powerup)) { // Apply powerup player.upgrade(powerup.type); // Update UI if life powerup if (powerup.type === 'life') { livesText.setText('LIVES: ' + player.lives); } // Remove powerup powerup.destroy(); powerups.splice(i, 1); } else if (powerup.y > 2732 + 50) { // Remove powerup if it's off screen powerup.destroy(); powerups.splice(i, 1); } } // Player vs boss if (player && boss && player.intersects(boss)) { // Damage player player.damage(); // Update UI livesText.setText('LIVES: ' + player.lives); // Check for game over if (player.lives <= 0) { // Game over createExplosion(player.x, player.y, 1.5); player.destroy(); player = null; // Save high score if needed if (score > storage.highScore) { storage.highScore = score; } // Show game over after a delay LK.setTimeout(function () { LK.showGameOver(); }, 1000); } } } // Initialize the game initGame(); // Game down event handler game.down = function (x, y, obj) { if (!player) { return; } dragStartPosition.x = x; dragStartPosition.y = y; // Fire lasers on tap firePlayerLaser(); }; // Game move event handler game.move = function (x, y, obj) { if (!player) { return; } // Move player with drag player.x = x; player.y = y; }; // Game update handler game.update = function () { if (gameState !== 'playing') { return; } // Handle player input if (player) { handlePlayerInput(); } // Handle wave creation if (waveDelay > 0) { waveDelay--; } else if (!bossWave && enemies.length === 0 && enemiesDefeated >= enemiesThisWave) { // All enemies for this wave defeated, create next wave createWave(); } else if (!bossWave && enemies.length < 5 && enemiesDefeated < enemiesThisWave && LK.ticks % 30 === 0) { // Spawn more enemies for this wave spawnEnemy(); } // Spawn asteroids occasionally if (LK.ticks % 180 === 0 && Math.random() < 0.7) { spawnAsteroid(); } // Boss shooting if (boss && LK.ticks % 90 === 0) { fireBossLasers(); } // Enemy shooting for (var i = 0; i < enemies.length; i++) { if (Math.random() < enemies[i].shootChance) { fireEnemyLaser(enemies[i]); } } // Collision detection handleCollisions(); };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Asteroid = Container.expand(function () {
var self = Container.call(this);
var asteroid = self.attachAsset('asteroid', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 2;
self.speed = {
y: 2 + Math.random() * 2,
x: (Math.random() - 0.5) * 2
};
self.rotation = Math.random() * 0.1 - 0.05;
self.scoreValue = 15;
// Random size variation
var scale = 0.7 + Math.random() * 0.8;
asteroid.scale.set(scale, scale);
self.damage = function (amount) {
self.health -= amount || 1;
tween(asteroid, {
tint: 0xffffff
}, {
duration: 200,
onFinish: function onFinish() {
asteroid.tint = 0x95a5a6;
}
});
return self.health <= 0;
};
self.update = function () {
self.y += self.speed.y;
self.x += self.speed.x;
asteroid.rotation += self.rotation;
};
return self;
});
var Boss = Container.expand(function (level) {
var self = Container.call(this);
var ship = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
self.level = level || 1;
self.maxHealth = 20 * self.level;
self.health = self.maxHealth;
self.scoreValue = 200 * self.level;
self.phase = 0;
self.phaseTime = 0;
self.patterns = ['side-to-side', 'charge', 'retreat'];
self.currentPattern = 0;
self.targetX = 0;
self.targetY = 0;
// Adjust boss based on level
if (self.level > 1) {
ship.tint = 0xcc00cc;
}
// Health bar
self.healthBar = new Container();
self.addChild(self.healthBar);
var healthBarBg = self.healthBar.attachAsset('playerLaser', {
anchorX: 0,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.5
});
healthBarBg.tint = 0x333333;
healthBarBg.width = 200;
self.healthBarFill = self.healthBar.attachAsset('playerLaser', {
anchorX: 0,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.4
});
self.healthBarFill.tint = 0xff3333;
self.healthBarFill.width = 200;
self.healthBar.y = -120;
self.damage = function (amount) {
self.health -= amount || 1;
// Update health bar
var healthPercent = self.health / self.maxHealth;
self.healthBarFill.width = 200 * healthPercent;
tween(ship, {
tint: 0xffffff
}, {
duration: 100,
onFinish: function onFinish() {
ship.tint = self.level > 1 ? 0xcc00cc : 0x9b59b6;
}
});
// Change patterns more quickly when damaged
if (self.health < self.maxHealth * 0.5 && self.phaseTime > 150) {
self.changePattern();
}
return self.health <= 0;
};
self.changePattern = function () {
self.currentPattern = (self.currentPattern + 1) % self.patterns.length;
self.phaseTime = 0;
self.phase = 0;
};
self.update = function () {
self.phaseTime++;
// Change pattern every so often
if (self.phaseTime > 300) {
self.changePattern();
}
var pattern = self.patterns[self.currentPattern];
switch (pattern) {
case 'side-to-side':
// Move side to side
self.targetX = 1024 + Math.sin(self.phaseTime * 0.02) * 800;
if (self.phaseTime < 60) {
self.targetY = Math.min(self.y + 2, 400);
} else {
self.targetY = 400;
}
break;
case 'charge':
// Charge down then back up
if (self.phase === 0) {
self.targetY = self.y + 5;
if (self.y > 800) {
self.phase = 1;
}
} else {
self.targetY = Math.max(self.y - 3, 300);
if (self.y <= 300) {
self.phase = 0;
}
}
self.targetX = 1024 + Math.sin(self.phaseTime * 0.03) * 500;
break;
case 'retreat':
// Stay near top and move quickly
self.targetY = 300;
self.targetX = 1024 + Math.sin(self.phaseTime * 0.05) * 900;
break;
}
// Move toward target position
self.x += (self.targetX - self.x) * 0.05;
self.y += (self.targetY - self.y) * 0.05;
};
return self;
});
var Enemy = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'basic';
var assetType = self.type === 'fast' ? 'enemy' : 'enemy';
var ship = self.attachAsset(assetType, {
anchorX: 0.5,
anchorY: 0.5
});
// Different enemy types
if (self.type === 'basic') {
self.health = 1;
self.speed = 2;
self.scoreValue = 10;
self.shootChance = 0.01;
} else if (self.type === 'fast') {
self.health = 1;
self.speed = 3.5;
self.scoreValue = 15;
ship.scaleX = 0.8;
ship.scaleY = 0.8;
self.shootChance = 0.005;
ship.tint = 0xff9966;
} else if (self.type === 'tank') {
self.health = 3;
self.speed = 1.5;
self.scoreValue = 25;
ship.scaleX = 1.2;
ship.scaleY = 1.2;
self.shootChance = 0.015;
ship.tint = 0x66ff66;
}
self.movement = {
pattern: 'straight',
phase: Math.random() * Math.PI * 2,
amplitude: 60 + Math.random() * 60
};
self.initialX = 0;
self.damage = function (amount) {
self.health -= amount || 1;
tween(ship, {
tint: 0xffffff
}, {
duration: 200,
onFinish: function onFinish() {
ship.tint = self.type === 'fast' ? 0xff9966 : self.type === 'tank' ? 0x66ff66 : 0xe74c3c;
}
});
return self.health <= 0;
};
self.update = function () {
// Basic movement
self.y += self.speed;
// Pattern movement
if (self.movement.pattern === 'sine') {
self.x = self.initialX + Math.sin(LK.ticks * 0.05 + self.movement.phase) * self.movement.amplitude;
} else if (self.movement.pattern === 'zigzag') {
var timeScale = 0.02;
var t = LK.ticks * timeScale + self.movement.phase;
var triangleWave = Math.abs(t % 2 - 1) * 2 - 1;
self.x = self.initialX + triangleWave * self.movement.amplitude;
}
};
return self;
});
var EnemyLaser = Container.expand(function () {
var self = Container.call(this);
var laser = self.attachAsset('enemyLaser', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var explosion = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9
});
// Set up fade and scale
tween(explosion, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 500,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var ship = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.shield = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.lives = 3;
self.shieldActive = false;
self.fireRate = 20;
self.lastShot = 0;
self.canShoot = true;
self.power = 1;
self.invulnerable = false;
self.activateShield = function (duration) {
self.shieldActive = true;
self.shield.alpha = 0.4;
LK.setTimeout(function () {
self.shieldActive = false;
tween(self.shield, {
alpha: 0
}, {
duration: 500
});
}, duration);
};
self.damage = function () {
if (self.invulnerable || self.shieldActive) {
return;
}
self.lives--;
LK.getSound('playerDamage').play();
// Make player temporarily invulnerable
self.invulnerable = true;
// Flash the player to show invulnerability
var flashCount = 0;
var flashInterval = LK.setInterval(function () {
ship.alpha = ship.alpha === 0.3 ? 1 : 0.3;
flashCount++;
if (flashCount >= 10) {
LK.clearInterval(flashInterval);
ship.alpha = 1;
self.invulnerable = false;
}
}, 150);
};
self.upgrade = function (type) {
LK.getSound('powerup').play();
if (type === 'shield') {
self.activateShield(8000);
} else if (type === 'power') {
self.power = Math.min(self.power + 1, 3);
// Reset power after some time
LK.setTimeout(function () {
self.power = Math.max(1, self.power - 1);
}, 10000);
} else if (type === 'life') {
self.lives = Math.min(self.lives + 1, 5);
} else if (type === 'speed') {
var oldFireRate = self.fireRate;
self.fireRate = Math.max(self.fireRate - 5, 10);
// Reset fire rate after some time
LK.setTimeout(function () {
self.fireRate = oldFireRate;
}, 10000);
}
};
return self;
});
var PlayerLaser = Container.expand(function () {
var self = Container.call(this);
var laser = self.attachAsset('playerLaser', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -15;
self.power = 1;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Powerup = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || ['shield', 'power', 'life', 'speed'][Math.floor(Math.random() * 4)];
var powerup = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
// Set color based on type
if (self.type === 'shield') {
powerup.tint = 0x3498db; // Blue
} else if (self.type === 'power') {
powerup.tint = 0xe74c3c; // Red
} else if (self.type === 'life') {
powerup.tint = 0x2ecc71; // Green
} else if (self.type === 'speed') {
powerup.tint = 0xf1c40f; // Yellow
}
self.speed = 3;
self.update = function () {
self.y += self.speed;
powerup.rotation += 0.05;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000022
});
/****
* Game Code
****/
// Game variables
var player;
var playerLasers = [];
var enemies = [];
var enemyLasers = [];
var asteroids = [];
var powerups = [];
var explosions = [];
var boss = null;
var gameState = 'playing';
var score = 0;
var waveNumber = 1;
var enemiesThisWave = 0;
var enemiesDefeated = 0;
var waveDelay = 0;
var bossWave = false;
var dragStartPosition = {
x: 0,
y: 0
};
// UI elements
var scoreTxt = new Text2('SCORE: 0', {
size: 40,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -250;
scoreTxt.y = 50;
var waveText = new Text2('WAVE: 1', {
size: 40,
fill: 0xFFFFFF
});
waveText.anchor.set(0.5, 0);
LK.gui.top.addChild(waveText);
waveText.y = 50;
var livesText = new Text2('LIVES: 3', {
size: 40,
fill: 0xFFFFFF
});
livesText.anchor.set(0, 0);
LK.gui.topLeft.addChild(livesText);
livesText.x = 150; // Keep away from the top-left menu icon
livesText.y = 50;
// Create game elements
function initGame() {
// Reset game variables
playerLasers = [];
enemies = [];
enemyLasers = [];
asteroids = [];
powerups = [];
explosions = [];
boss = null;
gameState = 'playing';
score = 0;
waveNumber = 1;
enemiesThisWave = 10;
enemiesDefeated = 0;
waveDelay = 0;
bossWave = false;
// Update UI
scoreTxt.setText('SCORE: ' + score);
waveText.setText('WAVE: ' + waveNumber);
// Create player
player = new Player();
player.x = 1024;
player.y = 2200;
game.addChild(player);
livesText.setText('LIVES: ' + player.lives);
// Start with player moving up
tween(player, {
y: 2000
}, {
duration: 1000
});
// Start the music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.7,
duration: 1000
}
});
// Create first wave
createWave();
}
// Create a new wave of enemies
function createWave() {
waveNumber++;
waveText.setText('WAVE: ' + waveNumber);
// Every 5 waves is a boss wave
bossWave = waveNumber % 5 === 0;
if (bossWave) {
// Create a boss
var bossLevel = Math.ceil(waveNumber / 5);
LK.getSound('bossAlert').play();
boss = new Boss(bossLevel);
boss.x = 1024;
boss.y = -200;
game.addChild(boss);
tween(boss, {
y: 300
}, {
duration: 2000
});
// Show boss wave text
var bossText = new Text2('BOSS WAVE!', {
size: 80,
fill: 0xFF0000
});
bossText.anchor.set(0.5, 0.5);
bossText.x = 1024;
bossText.y = 800;
game.addChild(bossText);
tween(bossText, {
alpha: 0,
y: 700
}, {
duration: 2000,
onFinish: function onFinish() {
bossText.destroy();
}
});
return;
}
// Regular wave
enemiesThisWave = 10 + waveNumber * 2;
enemiesDefeated = 0;
// Show wave text
var newWaveText = new Text2('WAVE ' + waveNumber, {
size: 80,
fill: 0xFFFFFF
});
newWaveText.anchor.set(0.5, 0.5);
newWaveText.x = 1024;
newWaveText.y = 800;
game.addChild(newWaveText);
tween(newWaveText, {
alpha: 0,
y: 700
}, {
duration: 2000,
onFinish: function onFinish() {
newWaveText.destroy();
}
});
// Start spawning enemies after a short delay
waveDelay = 120;
}
// Create a new enemy
function spawnEnemy() {
var types = ['basic'];
// Add more enemy types as waves progress
if (waveNumber >= 2) {
types.push('fast');
}
if (waveNumber >= 3) {
types.push('tank');
}
var type = types[Math.floor(Math.random() * types.length)];
var enemy = new Enemy(type);
// Position the enemy
enemy.x = Math.random() * 1800 + 124;
enemy.y = -100;
enemy.initialX = enemy.x;
// Set random movement pattern
var patterns = ['straight'];
if (waveNumber >= 2) {
patterns.push('sine');
}
if (waveNumber >= 4) {
patterns.push('zigzag');
}
enemy.movement.pattern = patterns[Math.floor(Math.random() * patterns.length)];
// Add to game
enemies.push(enemy);
game.addChild(enemy);
}
// Create a new asteroid
function spawnAsteroid() {
var asteroid = new Asteroid();
// Position the asteroid
asteroid.x = Math.random() * 1800 + 124;
asteroid.y = -100;
// Add to game
asteroids.push(asteroid);
game.addChild(asteroid);
}
// Create a player laser
function firePlayerLaser() {
if (!player || !player.canShoot || player.lastShot + player.fireRate > LK.ticks) {
return;
}
player.lastShot = LK.ticks;
LK.getSound('playerShoot').play();
// Fire based on power level
if (player.power === 1) {
var laser = new PlayerLaser();
laser.x = player.x;
laser.y = player.y - 50;
laser.power = player.power;
playerLasers.push(laser);
game.addChild(laser);
} else if (player.power === 2) {
for (var i = -1; i <= 1; i += 2) {
var laser = new PlayerLaser();
laser.x = player.x + i * 30;
laser.y = player.y - 40;
laser.power = player.power;
playerLasers.push(laser);
game.addChild(laser);
}
} else if (player.power >= 3) {
var centerLaser = new PlayerLaser();
centerLaser.x = player.x;
centerLaser.y = player.y - 50;
centerLaser.power = player.power;
playerLasers.push(centerLaser);
game.addChild(centerLaser);
for (var i = -1; i <= 1; i += 2) {
var sideLaser = new PlayerLaser();
sideLaser.x = player.x + i * 40;
sideLaser.y = player.y - 30;
sideLaser.power = player.power - 1;
playerLasers.push(sideLaser);
game.addChild(sideLaser);
}
}
}
// Create an enemy laser
function fireEnemyLaser(enemy) {
var laser = new EnemyLaser();
laser.x = enemy.x;
laser.y = enemy.y + 40;
enemyLasers.push(laser);
game.addChild(laser);
LK.getSound('enemyShoot').play({
volume: 0.2
});
}
// Fire boss laser pattern
function fireBossLasers() {
if (!boss) {
return;
}
// Different patterns based on boss level and health
var healthPercent = boss.health / boss.maxHealth;
var pattern = 'spread';
if (boss.level >= 2 && healthPercent < 0.5) {
pattern = 'circle';
}
if (pattern === 'spread') {
for (var i = -2; i <= 2; i++) {
var laser = new EnemyLaser();
laser.x = boss.x + i * 50;
laser.y = boss.y + 80;
enemyLasers.push(laser);
game.addChild(laser);
}
} else if (pattern === 'circle') {
var numLasers = 8;
for (var i = 0; i < numLasers; i++) {
var angle = i / numLasers * Math.PI * 2;
var laser = new EnemyLaser();
laser.x = boss.x + Math.cos(angle) * 100;
laser.y = boss.y + Math.sin(angle) * 100;
enemyLasers.push(laser);
game.addChild(laser);
// Add directional motion
laser.update = function () {
var dx = this.x - boss.x;
var dy = this.y - boss.y;
var length = Math.sqrt(dx * dx + dy * dy);
this.x += dx / length * 5;
this.y += dy / length * 5;
};
}
}
LK.getSound('enemyShoot').play({
volume: 0.4
});
}
// Create explosion animation
function createExplosion(x, y, scale) {
var explosion = new Explosion();
explosion.x = x;
explosion.y = y;
if (scale) {
explosion.scale.set(scale, scale);
}
explosions.push(explosion);
game.addChild(explosion);
LK.getSound('explosion').play();
}
// Create a powerup
function spawnPowerup(x, y, type) {
var powerup = new Powerup(type);
powerup.x = x;
powerup.y = y;
powerups.push(powerup);
game.addChild(powerup);
}
// Handle player shooting and movement
function handlePlayerInput() {
// Keep player in bounds
player.x = Math.max(100, Math.min(player.x, 2048 - 100));
player.y = Math.max(100, Math.min(player.y, 2732 - 100));
// Auto-fire
if (LK.ticks % 10 === 0) {
firePlayerLaser();
}
}
// Handle collisions between game objects
function handleCollisions() {
// Player lasers vs enemies
for (var i = playerLasers.length - 1; i >= 0; i--) {
var laser = playerLasers[i];
var hitSomething = false;
// Check against enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (laser.intersects(enemy)) {
// Damage enemy
if (enemy.damage(laser.power)) {
// Enemy destroyed
createExplosion(enemy.x, enemy.y);
// Add score
score += enemy.scoreValue;
scoreTxt.setText('SCORE: ' + score);
// Count enemy as defeated
enemiesDefeated++;
// Chance to spawn powerup
if (Math.random() < 0.1) {
spawnPowerup(enemy.x, enemy.y);
}
enemy.destroy();
enemies.splice(j, 1);
}
// Remove laser
laser.destroy();
playerLasers.splice(i, 1);
hitSomething = true;
break;
}
}
// Only check other collisions if we haven't hit an enemy
if (!hitSomething) {
// Check against boss
if (boss && laser.intersects(boss)) {
// Damage boss
if (boss.damage(laser.power)) {
// Boss destroyed
createExplosion(boss.x, boss.y, 2);
// Add score
score += boss.scoreValue;
scoreTxt.setText('SCORE: ' + score);
// Spawn multiple powerups
for (var p = 0; p < 3; p++) {
var powerupType = ['shield', 'power', 'life', 'speed'][Math.floor(Math.random() * 4)];
spawnPowerup(boss.x + (Math.random() * 200 - 100), boss.y + (Math.random() * 200 - 100), powerupType);
}
boss.destroy();
boss = null;
// Move to next wave
createWave();
}
// Remove laser
laser.destroy();
playerLasers.splice(i, 1);
hitSomething = true;
}
// Check against asteroids
for (var k = asteroids.length - 1; k >= 0; k--) {
var asteroid = asteroids[k];
if (laser.intersects(asteroid)) {
// Damage asteroid
if (asteroid.damage(laser.power)) {
// Asteroid destroyed
createExplosion(asteroid.x, asteroid.y, 0.7);
// Add score
score += asteroid.scoreValue;
scoreTxt.setText('SCORE: ' + score);
asteroid.destroy();
asteroids.splice(k, 1);
}
// Remove laser
laser.destroy();
playerLasers.splice(i, 1);
hitSomething = true;
break;
}
}
}
// Remove laser if it's off screen
if (!hitSomething && laser.y < -50) {
laser.destroy();
playerLasers.splice(i, 1);
}
}
// Enemy lasers vs player
for (var i = enemyLasers.length - 1; i >= 0; i--) {
var laser = enemyLasers[i];
if (player && laser.intersects(player)) {
// Damage player
player.damage();
// Update UI
livesText.setText('LIVES: ' + player.lives);
// Check for game over
if (player.lives <= 0) {
// Game over
createExplosion(player.x, player.y, 1.5);
player.destroy();
player = null;
// Save high score if needed
if (score > storage.highScore) {
storage.highScore = score;
}
// Show game over after a delay
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
// Remove laser
laser.destroy();
enemyLasers.splice(i, 1);
} else if (laser.y > 2732 + 50) {
// Remove laser if it's off screen
laser.destroy();
enemyLasers.splice(i, 1);
}
}
// Player vs enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (player && player.intersects(enemy)) {
// Damage player
player.damage();
// Damage enemy
enemy.damage(1);
// Update UI
livesText.setText('LIVES: ' + player.lives);
// Check for enemy death
if (enemy.health <= 0) {
// Enemy destroyed
createExplosion(enemy.x, enemy.y);
// Add score
score += enemy.scoreValue;
scoreTxt.setText('SCORE: ' + score);
// Count enemy as defeated
enemiesDefeated++;
enemy.destroy();
enemies.splice(i, 1);
}
// Check for game over
if (player.lives <= 0) {
// Game over
createExplosion(player.x, player.y, 1.5);
player.destroy();
player = null;
// Save high score if needed
if (score > storage.highScore) {
storage.highScore = score;
}
// Show game over after a delay
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
// Remove enemy if it's off screen
if (enemy.y > 2732 + 100) {
enemy.destroy();
enemies.splice(i, 1);
}
}
// Player vs asteroids
for (var i = asteroids.length - 1; i >= 0; i--) {
var asteroid = asteroids[i];
if (player && player.intersects(asteroid)) {
// Damage player
player.damage();
// Damage asteroid
asteroid.damage(1);
// Update UI
livesText.setText('LIVES: ' + player.lives);
// Check for asteroid death
if (asteroid.health <= 0) {
// Asteroid destroyed
createExplosion(asteroid.x, asteroid.y, 0.7);
// Add score
score += asteroid.scoreValue;
scoreTxt.setText('SCORE: ' + score);
asteroid.destroy();
asteroids.splice(i, 1);
}
// Check for game over
if (player.lives <= 0) {
// Game over
createExplosion(player.x, player.y, 1.5);
player.destroy();
player = null;
// Save high score if needed
if (score > storage.highScore) {
storage.highScore = score;
}
// Show game over after a delay
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
// Remove asteroid if it's off screen
if (asteroid.y > 2732 + 100 || asteroid.x < -100 || asteroid.x > 2048 + 100) {
asteroid.destroy();
asteroids.splice(i, 1);
}
}
// Player vs powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
if (player && player.intersects(powerup)) {
// Apply powerup
player.upgrade(powerup.type);
// Update UI if life powerup
if (powerup.type === 'life') {
livesText.setText('LIVES: ' + player.lives);
}
// Remove powerup
powerup.destroy();
powerups.splice(i, 1);
} else if (powerup.y > 2732 + 50) {
// Remove powerup if it's off screen
powerup.destroy();
powerups.splice(i, 1);
}
}
// Player vs boss
if (player && boss && player.intersects(boss)) {
// Damage player
player.damage();
// Update UI
livesText.setText('LIVES: ' + player.lives);
// Check for game over
if (player.lives <= 0) {
// Game over
createExplosion(player.x, player.y, 1.5);
player.destroy();
player = null;
// Save high score if needed
if (score > storage.highScore) {
storage.highScore = score;
}
// Show game over after a delay
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
}
// Initialize the game
initGame();
// Game down event handler
game.down = function (x, y, obj) {
if (!player) {
return;
}
dragStartPosition.x = x;
dragStartPosition.y = y;
// Fire lasers on tap
firePlayerLaser();
};
// Game move event handler
game.move = function (x, y, obj) {
if (!player) {
return;
}
// Move player with drag
player.x = x;
player.y = y;
};
// Game update handler
game.update = function () {
if (gameState !== 'playing') {
return;
}
// Handle player input
if (player) {
handlePlayerInput();
}
// Handle wave creation
if (waveDelay > 0) {
waveDelay--;
} else if (!bossWave && enemies.length === 0 && enemiesDefeated >= enemiesThisWave) {
// All enemies for this wave defeated, create next wave
createWave();
} else if (!bossWave && enemies.length < 5 && enemiesDefeated < enemiesThisWave && LK.ticks % 30 === 0) {
// Spawn more enemies for this wave
spawnEnemy();
}
// Spawn asteroids occasionally
if (LK.ticks % 180 === 0 && Math.random() < 0.7) {
spawnAsteroid();
}
// Boss shooting
if (boss && LK.ticks % 90 === 0) {
fireBossLasers();
}
// Enemy shooting
for (var i = 0; i < enemies.length; i++) {
if (Math.random() < enemies[i].shootChance) {
fireEnemyLaser(enemies[i]);
}
}
// Collision detection
handleCollisions();
};
space ship. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
asteroid. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
space enemy. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
explosion. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
shield. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
powerup. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
space boss ufo. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
green laser. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
red laser. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
space ship. Space ship that’s broken down. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat