/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Alien = Container.expand(function () { var self = Container.call(this); var alienGraphics = self.attachAsset('alien', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.2, scaleY: 2.2 }); self.width = alienGraphics.width * 2.0; self.height = alienGraphics.height * 2.0; self.active = true; self.points = 10; self.canShoot = true; self.shotsFired = 0; // Counter for shots fired // Add a subtle pulsing animation to the aliens tween(alienGraphics, { scaleX: 2.4, scaleY: 2.4 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { tween(alienGraphics, { scaleX: 2.2, scaleY: 2.2 }, { duration: 1000, easing: tween.easeInOut, onFinish: function onFinish() { if (self.active) { // Repeat the animation if alien is still active tween(alienGraphics, { scaleX: 2.4, scaleY: 2.4 }, { duration: 1000, easing: tween.easeInOut }); } } }); } }); self.hit = function () { if (self.active) { self.active = false; LK.getSound('alienExplode').play(); LK.effects.flashObject(self, 0xffffff, 100); tween(self, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { self.destroy(); } }); return self.points; } return 0; }; return self; }); var AlienBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('alienBullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.8, scaleY: 1.8 }); self.speed = 8; self.active = true; self.width = bulletGraphics.width; self.height = bulletGraphics.height; self.update = function () { self.y += self.speed; if (self.y > 2800) { self.active = false; } }; return self; }); var BossAlien = Container.expand(function () { var self = Container.call(this); var alienGraphics = self.attachAsset('alien', { anchorX: 0.5, anchorY: 0.5, scaleX: 4.0, scaleY: 4.0, tint: 0xff0000 // Red tint for boss }); self.width = alienGraphics.width * 2.5; self.height = alienGraphics.height * 2.5; self.active = true; self.points = 50; // More points than regular aliens self.canShoot = true; self.shotsFired = 0; self.health = 10; // Takes 10 shots to defeat self.lastHitTime = 0; // Add a pulsing animation for the boss tween(alienGraphics, { scaleX: 4.2, scaleY: 4.2 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { tween(alienGraphics, { scaleX: 4.0, scaleY: 4.0 }, { duration: 800, easing: tween.easeInOut, onFinish: function onFinish() { if (self.active) { tween(alienGraphics, { scaleX: 4.2, scaleY: 4.2 }, { duration: 800, easing: tween.easeInOut }); } } }); } }); self.hit = function () { if (self.active) { LK.getSound('alienExplode').play(); LK.effects.flashObject(self, 0xffffff, 100); self.health--; self.lastHitTime = Date.now(); // Create visual feedback for hits tween(alienGraphics, { tint: 0xffffff }, { duration: 100, onFinish: function onFinish() { tween(alienGraphics, { tint: 0xff0000 }, { duration: 100 }); } }); // Only destroy when health reaches 0 if (self.health <= 0) { self.active = false; tween(self, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { self.destroy(); } }); return self.points; } return 0; // Return 0 points if not destroyed yet } return 0; }; self.update = function () { // Boss-specific update logic can be added here }; return self; }); var ExplosiveAlienBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('alienBullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.2, scaleY: 2.2, tint: 0xff5500 // Orange-red color for explosive bullets }); self.speed = 8; self.active = true; self.width = bulletGraphics.width; self.height = bulletGraphics.height; self.isExplosive = true; // Flag to identify explosive bullets // Add pulsing effect to show it's explosive tween(bulletGraphics, { scaleX: 2.5, scaleY: 2.5 }, { duration: 300, easing: tween.easeInOut, onFinish: function onFinish() { tween(bulletGraphics, { scaleX: 2.2, scaleY: 2.2 }, { duration: 300, easing: tween.easeInOut, repeat: true }); } }); self.update = function () { self.y += self.speed; if (self.y > 2800) { self.active = false; } }; return self; }); var FastAlien = Container.expand(function () { var self = Container.call(this); var alienGraphics = self.attachAsset('alien', { anchorX: 0.5, anchorY: 0.5, scaleX: 2.0, scaleY: 2.0, tint: 0x00ffff // Cyan tint for fast aliens }); self.width = alienGraphics.width * 2.0; self.height = alienGraphics.height * 2.0; self.active = true; self.points = 50; // Worth more points than regular aliens self.speed = 20; // Very fast horizontal movement self.direction = Math.random() > 0.5 ? 1 : -1; // Random direction (left or right) // Add a stretching effect to show speed tween(alienGraphics, { scaleX: 2.3, scaleY: 1.8 }, { duration: 300, easing: tween.easeInOut, repeat: true, yoyo: true }); self.update = function () { self.x += self.speed * self.direction; // If off screen, mark as inactive if (self.direction > 0 && self.x > gameWidth + 100 || self.direction < 0 && self.x < -100) { self.active = false; } }; self.hit = function () { if (self.active) { self.active = false; LK.getSound('alienExplode').play(); LK.effects.flashObject(self, 0xffffff, 100); tween(self, { alpha: 0 }, { duration: 300, onFinish: function onFinish() { self.destroy(); } }); return self.points; } return 0; }; return self; }); var PlayerBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5, scaleX: 8.0, scaleY: 8.0 }); self.speed = -15; self.active = true; self.width = bulletGraphics.width * 2; self.height = bulletGraphics.height * 2; self.update = function () { self.y += self.speed; if (self.y < -50) { self.active = false; } }; return self; }); var PlayerShip = Container.expand(function () { var self = Container.call(this); var shipGraphics = self.attachAsset('playerShip', { anchorX: 0.5, anchorY: 0.5, scaleX: 80.0, scaleY: 80.0 }); self.speed = 12; self.lives = 3; self.hasShield = true; self.multiShot = false; self.width = shipGraphics.width * 2; self.height = shipGraphics.height * 2; self.shield = self.attachAsset('shield', { anchorX: 0.5, anchorY: 0.5, y: -40, alpha: 0.7, scaleX: 5.0, scaleY: 5.0 }); self.activateShield = function () { self.hasShield = true; self.shield.alpha = 0.7; }; self.deactivateShield = function () { self.hasShield = false; self.shield.alpha = 0; }; self.hit = function () { if (self.hasShield) { self.deactivateShield(); return false; } else { LK.getSound('playerHit').play(); self.lives--; LK.effects.flashObject(self, 0xff0000, 500); return true; } }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerUpGraphics = self.attachAsset('powerUp', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.8, scaleY: 1.8 }); self.type = Math.floor(Math.random() * 3); // 0: shield, 1: multishot, 2: extra life self.speed = 5; self.active = true; self.width = powerUpGraphics.width; self.height = powerUpGraphics.height; // Change color based on type if (self.type === 0) { powerUpGraphics.tint = 0x9b59b6; // Shield - purple } else if (self.type === 1) { powerUpGraphics.tint = 0xf39c12; // Multishot - orange } else { powerUpGraphics.tint = 0x2ecc71; // Extra life - green } // Add a pulsing animation for level completion power-ups if (self.type === 2) { // Extra life power-up tween(powerUpGraphics, { scaleX: 2.2, scaleY: 2.2 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(powerUpGraphics, { scaleX: 1.8, scaleY: 1.8 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { if (self.active) { // Repeat the animation if still active tween(powerUpGraphics, { scaleX: 2.2, scaleY: 2.2 }, { duration: 500, easing: tween.easeInOut }); } } }); } }); } self.update = function () { self.y += self.speed; if (self.y > 2800) { self.active = false; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game state variables var playerShip; var playerBullets = []; var aliens = []; var alienBullets = []; var powerUps = []; var shields = []; var gameActive = true; var score = 0; var level = 1; var alienDirection = 1; // 1 = right, -1 = left var alienMoveSpeed = 1; var alienDropAmount = 40; var alienShootChance = 0.01; var powerUpChance = 0.1; var lastShootTime = 0; var shootCooldown = 300; // ms var multiShotTimer = 0; var gameWidth = 2048; var gameHeight = 2732; var aliensKilled = 0; var bossActive = false; var boss = null; var bossSpawnThreshold = 10; // Spawn boss after 10 aliens killed // UI elements var scoreTxt; var levelTxt; var livesTxt; // Initialize game function initGame() { // Reset game state playerBullets = []; aliens = []; alienBullets = []; powerUps = []; shields = []; gameActive = true; score = 0; level = 1; alienDirection = 1; alienMoveSpeed = 1; alienShootChance = 0.01; multiShotTimer = 0; aliensKilled = 0; bossActive = false; boss = null; // Set score LK.setScore(0); // Create player ship playerShip = new PlayerShip(); playerShip.x = gameWidth / 2; playerShip.y = gameHeight - 150; game.addChild(playerShip); playerShip.activateShield(); // Activate shield immediately // Create shields createShields(); // Create UI createUI(); // Create aliens for first level createAlienWave(); // Play background music LK.playMusic('backgroundMusic'); } function createUI() { // Score text scoreTxt = new Text2('Score: 0', { size: 100, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); LK.gui.topLeft.addChild(scoreTxt); scoreTxt.x = 120; // Keep away from the top left menu area // Level text levelTxt = new Text2('Level: 1', { size: 100, fill: 0xFFFFFF }); levelTxt.anchor.set(0.5, 0); LK.gui.top.addChild(levelTxt); // Lives text livesTxt = new Text2('Lives: 3', { size: 100, fill: 0xFFFFFF }); livesTxt.anchor.set(1, 0); LK.gui.topRight.addChild(livesTxt); } function createShields() { // Create 4 shields across the bottom var shieldCount = 4; var shieldSpacing = gameWidth / (shieldCount + 1); for (var i = 0; i < shieldCount; i++) { var shield = game.addChild(LK.getAsset('shield', { anchorX: 0.5, anchorY: 0.5, scaleX: 1.5, scaleY: 1.5 })); shield.x = shieldSpacing * (i + 1); shield.y = gameHeight - 300; shield.health = 10; shields.push(shield); } } function createAlienWave() { // Clear any remaining aliens for (var i = aliens.length - 1; i >= 0; i--) { aliens[i].destroy(); } aliens = []; // Increase difficulty with level alienMoveSpeed = 1 + level * 0.5; alienShootChance = 0.01 + level * 0.005; // Create alien grid - rows based on level, 1 row for level 1, 2 rows for level 2, etc. up to 5 var rows = Math.min(level, 5); // Level 1-5 has corresponding number of rows var cols = 6 + Math.min(level, 4); // Max 10 columns var alienWidth = 200; // Further increased width to account for larger aliens var alienHeight = 160; // Further increased height to account for larger aliens var startX = (gameWidth - cols * alienWidth) / 2 + alienWidth / 2; var startY = 200; for (var row = 0; row < rows; row++) { for (var col = 0; col < cols; col++) { var alien = new Alien(); alien.x = startX + col * alienWidth; alien.y = startY + row * alienHeight; alien.row = row; alien.col = col; alien.points = (rows - row) * 10; // More points for aliens at the top game.addChild(alien); aliens.push(alien); } } } function playerShoot() { var now = Date.now(); if (now - lastShootTime < shootCooldown) { return; } lastShootTime = now; // Create bullet var bullet = new PlayerBullet(); bullet.x = playerShip.x; bullet.y = playerShip.y - playerShip.height / 2; game.addChild(bullet); playerBullets.push(bullet); // If player has multishot, create additional bullets if (playerShip.multiShot) { for (var i = -1; i <= 1; i += 2) { var sideBullet = new PlayerBullet(); sideBullet.x = playerShip.x + i * 20; sideBullet.y = playerShip.y - playerShip.height / 2; game.addChild(sideBullet); playerBullets.push(sideBullet); } } LK.getSound('playerShoot').play(); } function alienShoot() { // Find shooting aliens (bottom row of each column) var shootingAliens = []; var colMap = {}; for (var i = 0; i < aliens.length; i++) { var alien = aliens[i]; if (!alien.active) { continue; } // If this alien is lower than the current lowest in its column, it becomes the shooter if (!colMap[alien.col] || alien.row > colMap[alien.col].row) { colMap[alien.col] = alien; } } // Get all bottom aliens for (var col in colMap) { shootingAliens.push(colMap[col]); } // Randomly choose aliens to shoot based on difficulty for (var i = 0; i < shootingAliens.length; i++) { if (Math.random() < alienShootChance) { var shooter = shootingAliens[i]; // Increment shotsFired counter for this alien shooter.shotsFired = (shooter.shotsFired || 0) + 1; // Every 10 shots, create an explosive bullet var bullet; if (shooter.shotsFired % 10 === 0) { bullet = new ExplosiveAlienBullet(); // Add visual effect for explosive bullet firing LK.effects.flashObject(shooter, 0xff5500, 100); } else { bullet = new AlienBullet(); } bullet.x = shooter.x; bullet.y = shooter.y + shooter.height / 2; game.addChild(bullet); alienBullets.push(bullet); } } } function checkAlienMovement() { if (aliens.length === 0) { return; } var moveDown = false; var minX = gameWidth; var maxX = 0; // Find leftmost and rightmost aliens for (var i = 0; i < aliens.length; i++) { var alien = aliens[i]; if (alien.active) { minX = Math.min(minX, alien.x); maxX = Math.max(maxX, alien.x); } } // Check if aliens need to change direction if (maxX > gameWidth - 50 && alienDirection > 0 || minX < 50 && alienDirection < 0) { alienDirection *= -1; moveDown = true; } // Move aliens for (var i = 0; i < aliens.length; i++) { var alien = aliens[i]; if (alien.active) { alien.x += alienDirection * alienMoveSpeed; if (moveDown) { alien.y += alienDropAmount; // Check if aliens reached the bottom (game over condition) if (alien.y > gameHeight - 200) { gameOver(); return; } } } } } function spawnPowerUp(x, y) { if (Math.random() < powerUpChance) { var powerUp = new PowerUp(); powerUp.x = x; powerUp.y = y; game.addChild(powerUp); powerUps.push(powerUp); } } function checkCollisions() { // Player bullets vs aliens for (var i = playerBullets.length - 1; i >= 0; i--) { var bullet = playerBullets[i]; if (!bullet.active) { bullet.destroy(); playerBullets.splice(i, 1); continue; } var bulletHit = false; // Check against aliens for (var j = 0; j < aliens.length; j++) { var alien = aliens[j]; if (alien.active && bullet.intersects(alien)) { // Add points var pointsEarned = alien.hit(); score += pointsEarned; LK.setScore(score); scoreTxt.setText('Score: ' + score); // If hit is a fast alien, add extra score (on top of the 50 already earned) if (alien instanceof FastAlien) { // Add another 50 points for hitting a fast alien score += 50; LK.setScore(score); scoreTxt.setText('Score: ' + score); // Create visual feedback for the bonus var bonusText = new Text2('+50!', { size: 80, fill: 0x00ffff }); bonusText.x = alien.x; bonusText.y = alien.y; bonusText.anchor.set(0.5, 0.5); game.addChild(bonusText); tween(bonusText, { y: bonusText.y - 100, alpha: 0 }, { duration: 1000, onFinish: function onFinish() { bonusText.destroy(); } }); } // Chance to spawn power up spawnPowerUp(alien.x, alien.y); // Remove alien from array if no longer active if (!alien.active) { aliens.splice(j, 1); // Increment aliens killed counter aliensKilled++; // Check if we should spawn a boss if (!bossActive && aliensKilled >= bossSpawnThreshold) { spawnBoss(); } } // Remove bullet bullet.destroy(); playerBullets.splice(i, 1); bulletHit = true; break; } } // If already hit an alien, skip further checks if (bulletHit) { continue; } // Check against boss if active if (bossActive && boss && boss.active && bullet.intersects(boss)) { var bossPoints = boss.hit(); if (bossPoints > 0) { // Boss was destroyed score += bossPoints; LK.setScore(score); scoreTxt.setText('Score: ' + score); // Spawn power up when boss is destroyed spawnPowerUp(boss.x, boss.y); spawnPowerUp(boss.x - 50, boss.y); // Extra powerups for boss spawnPowerUp(boss.x + 50, boss.y); bossActive = false; boss = null; } bullet.destroy(); playerBullets.splice(i, 1); bulletHit = true; continue; } // Player bullets should pass through shields // No need to check player bullets against shields } // Alien bullets vs player for (var i = alienBullets.length - 1; i >= 0; i--) { var bullet = alienBullets[i]; if (!bullet.active) { bullet.destroy(); alienBullets.splice(i, 1); continue; } // Check against player if (bullet.intersects(playerShip)) { var playerDamaged = playerShip.hit(); // Update lives display livesTxt.setText('Lives: ' + playerShip.lives); // Check for game over if (playerShip.lives <= 0) { gameOver(); } bullet.destroy(); alienBullets.splice(i, 1); continue; } // Check against shields for (var j = 0; j < shields.length; j++) { var shield = shields[j]; if (shield.health > 0 && bullet.intersects(shield)) { // Explosive bullets do 2 damage instead of 1 if (bullet.isExplosive) { shield.health -= 2; // Visual explosion effect LK.effects.flashObject(shield, 0xff5500, 200); } else { shield.health--; } shield.alpha = shield.health / 3; if (shield.health <= 0) { shield.alpha = 0; } bullet.destroy(); alienBullets.splice(i, 1); break; } } } // Power-ups vs player for (var i = powerUps.length - 1; i >= 0; i--) { var powerUp = powerUps[i]; if (!powerUp.active) { powerUp.destroy(); powerUps.splice(i, 1); continue; } if (powerUp.intersects(playerShip)) { LK.getSound('powerUpCollect').play(); // Apply power-up effect if (powerUp.type === 0) { // Shield playerShip.activateShield(); } else if (powerUp.type === 1) { // Multi-shot playerShip.multiShot = true; multiShotTimer = 300; // Duration in ticks (5 seconds at 60fps) } else { // Extra life playerShip.lives++; livesTxt.setText('Lives: ' + playerShip.lives); } powerUp.destroy(); powerUps.splice(i, 1); } } } function checkLevelComplete() { // Check if there are any regular aliens left (not fast aliens) var regularAliensLeft = false; for (var i = 0; i < aliens.length; i++) { if (!(aliens[i] instanceof FastAlien)) { regularAliensLeft = true; break; } } if (!regularAliensLeft) { level++; levelTxt.setText('Level: ' + level); // Spawn power-ups on both sides of the player after level completion spawnLevelCompletionPowerUp(); createAlienWave(); } } function spawnLevelCompletionPowerUp() { // Create two power-ups, one on each side of the player var leftPowerUp = new PowerUp(); var rightPowerUp = new PowerUp(); // Force the type to be extra life (type 2) leftPowerUp.type = 2; rightPowerUp.type = 2; // Set their color to green (extra life color) leftPowerUp.getChildAt(0).tint = 0x2ecc71; rightPowerUp.getChildAt(0).tint = 0x2ecc71; // Position them on either side of the player var offset = 200; // Distance from player leftPowerUp.x = playerShip.x - offset; leftPowerUp.y = playerShip.y; rightPowerUp.x = playerShip.x + offset; rightPowerUp.y = playerShip.y; // Add them to the game game.addChild(leftPowerUp); game.addChild(rightPowerUp); powerUps.push(leftPowerUp); powerUps.push(rightPowerUp); // Add a visual effect to highlight them LK.effects.flashObject(leftPowerUp, 0x2ecc71, 500); LK.effects.flashObject(rightPowerUp, 0x2ecc71, 500); } function gameOver() { gameActive = false; LK.effects.flashScreen(0xff0000, 1000); LK.stopMusic(); LK.showGameOver(); } // Touch controls var touchX = null; game.down = function (x, y, obj) { touchX = x; playerShoot(); }; game.up = function (x, y, obj) { touchX = null; }; game.move = function (x, y, obj) { if (touchX !== null) { touchX = x; } }; // Game update loop game.update = function () { if (!gameActive) { return; } // Process player movement from touch if (touchX !== null) { // Move player toward touch position var moveDir = touchX > playerShip.x ? 1 : -1; if (Math.abs(touchX - playerShip.x) > 5) { playerShip.x += moveDir * playerShip.speed; } // Keep player in bounds if (playerShip.x < playerShip.width / 2) { playerShip.x = playerShip.width / 2; } if (playerShip.x > gameWidth - playerShip.width / 2) { playerShip.x = gameWidth - playerShip.width / 2; } } // Update multishot timer if (playerShip.multiShot) { multiShotTimer--; if (multiShotTimer <= 0) { playerShip.multiShot = false; } } // Update game objects checkAlienMovement(); // Update fast aliens manually as they have their own movement pattern for (var i = 0; i < aliens.length; i++) { if (aliens[i] instanceof FastAlien && aliens[i].active) { aliens[i].update(); } } // Boss update logic if (bossActive && boss && boss.active) { // Make boss move side to side independently boss.x += Math.sin(LK.ticks / 60) * 3; // Gentle sine wave movement // Make boss shoot more frequently if (LK.ticks % 180 === 0) { // Every 3 seconds var bullet = new ExplosiveAlienBullet(); bullet.x = boss.x; bullet.y = boss.y + boss.height / 2; game.addChild(bullet); alienBullets.push(bullet); // Sometimes fire a spread of bullets if (Math.random() < 0.5) { for (var i = -1; i <= 1; i += 2) { var sideBullet = new AlienBullet(); sideBullet.x = boss.x + i * 40; sideBullet.y = boss.y + boss.height / 2; game.addChild(sideBullet); alienBullets.push(sideBullet); } } } // Update boss custom logic if any if (boss.update) { boss.update(); } } // Alien shooting if (LK.ticks % 300 === 0) { // Check every 5 seconds alienShoot(); } // Automatic player shooting every 2 seconds (120 ticks at 60fps) if (LK.ticks % 120 === 0) { playerShoot(); } // Update bullets for (var i = 0; i < playerBullets.length; i++) { playerBullets[i].update(); } for (var i = 0; i < alienBullets.length; i++) { alienBullets[i].update(); } // Update power-ups for (var i = 0; i < powerUps.length; i++) { powerUps[i].update(); } // Check collisions checkCollisions(); // Check if level is complete checkLevelComplete(); }; // Initialize the game initGame(); // Function to spawn fast aliens function spawnFastAlien() { var fastAlien = new FastAlien(); // Set starting position - either left or right edge of screen if (fastAlien.direction > 0) { // Moving right to left fastAlien.x = -50; } else { // Moving left to right fastAlien.x = gameWidth + 50; } // Random Y position in the top half of the screen fastAlien.y = Math.random() * (gameHeight / 2) + 100; game.addChild(fastAlien); aliens.push(fastAlien); // Visual effect for fast alien spawn LK.effects.flashObject(fastAlien, 0x00ffff, 200); } // Set interval to spawn fast aliens every 5 seconds (300 frames at 60fps) LK.setInterval(spawnFastAlien, 5000); function spawnBoss() { bossActive = true; boss = new BossAlien(); // Find the back row position var backRow = 0; var startX = gameWidth / 2; var startY = 200; // If there are aliens, position the boss behind them if (aliens.length > 0) { for (var i = 0; i < aliens.length; i++) { if (aliens[i].row < backRow) { backRow = aliens[i].row; } } backRow = backRow - 1; // Position boss one row behind furthest back row if (backRow < 0) { backRow = 0; } startY = 200 + backRow * 160; // Use same spacing as alien rows } boss.x = startX; boss.y = startY; boss.row = backRow; boss.col = -1; // Special column marker for boss game.addChild(boss); // Visual effect for boss spawn LK.effects.flashObject(boss, 0xffff00, 500); }
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Alien = Container.expand(function () {
var self = Container.call(this);
var alienGraphics = self.attachAsset('alien', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.2,
scaleY: 2.2
});
self.width = alienGraphics.width * 2.0;
self.height = alienGraphics.height * 2.0;
self.active = true;
self.points = 10;
self.canShoot = true;
self.shotsFired = 0; // Counter for shots fired
// Add a subtle pulsing animation to the aliens
tween(alienGraphics, {
scaleX: 2.4,
scaleY: 2.4
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(alienGraphics, {
scaleX: 2.2,
scaleY: 2.2
}, {
duration: 1000,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.active) {
// Repeat the animation if alien is still active
tween(alienGraphics, {
scaleX: 2.4,
scaleY: 2.4
}, {
duration: 1000,
easing: tween.easeInOut
});
}
}
});
}
});
self.hit = function () {
if (self.active) {
self.active = false;
LK.getSound('alienExplode').play();
LK.effects.flashObject(self, 0xffffff, 100);
tween(self, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
return self.points;
}
return 0;
};
return self;
});
var AlienBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('alienBullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8
});
self.speed = 8;
self.active = true;
self.width = bulletGraphics.width;
self.height = bulletGraphics.height;
self.update = function () {
self.y += self.speed;
if (self.y > 2800) {
self.active = false;
}
};
return self;
});
var BossAlien = Container.expand(function () {
var self = Container.call(this);
var alienGraphics = self.attachAsset('alien', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 4.0,
scaleY: 4.0,
tint: 0xff0000 // Red tint for boss
});
self.width = alienGraphics.width * 2.5;
self.height = alienGraphics.height * 2.5;
self.active = true;
self.points = 50; // More points than regular aliens
self.canShoot = true;
self.shotsFired = 0;
self.health = 10; // Takes 10 shots to defeat
self.lastHitTime = 0;
// Add a pulsing animation for the boss
tween(alienGraphics, {
scaleX: 4.2,
scaleY: 4.2
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(alienGraphics, {
scaleX: 4.0,
scaleY: 4.0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.active) {
tween(alienGraphics, {
scaleX: 4.2,
scaleY: 4.2
}, {
duration: 800,
easing: tween.easeInOut
});
}
}
});
}
});
self.hit = function () {
if (self.active) {
LK.getSound('alienExplode').play();
LK.effects.flashObject(self, 0xffffff, 100);
self.health--;
self.lastHitTime = Date.now();
// Create visual feedback for hits
tween(alienGraphics, {
tint: 0xffffff
}, {
duration: 100,
onFinish: function onFinish() {
tween(alienGraphics, {
tint: 0xff0000
}, {
duration: 100
});
}
});
// Only destroy when health reaches 0
if (self.health <= 0) {
self.active = false;
tween(self, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
self.destroy();
}
});
return self.points;
}
return 0; // Return 0 points if not destroyed yet
}
return 0;
};
self.update = function () {
// Boss-specific update logic can be added here
};
return self;
});
var ExplosiveAlienBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('alienBullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.2,
scaleY: 2.2,
tint: 0xff5500 // Orange-red color for explosive bullets
});
self.speed = 8;
self.active = true;
self.width = bulletGraphics.width;
self.height = bulletGraphics.height;
self.isExplosive = true; // Flag to identify explosive bullets
// Add pulsing effect to show it's explosive
tween(bulletGraphics, {
scaleX: 2.5,
scaleY: 2.5
}, {
duration: 300,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(bulletGraphics, {
scaleX: 2.2,
scaleY: 2.2
}, {
duration: 300,
easing: tween.easeInOut,
repeat: true
});
}
});
self.update = function () {
self.y += self.speed;
if (self.y > 2800) {
self.active = false;
}
};
return self;
});
var FastAlien = Container.expand(function () {
var self = Container.call(this);
var alienGraphics = self.attachAsset('alien', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.0,
scaleY: 2.0,
tint: 0x00ffff // Cyan tint for fast aliens
});
self.width = alienGraphics.width * 2.0;
self.height = alienGraphics.height * 2.0;
self.active = true;
self.points = 50; // Worth more points than regular aliens
self.speed = 20; // Very fast horizontal movement
self.direction = Math.random() > 0.5 ? 1 : -1; // Random direction (left or right)
// Add a stretching effect to show speed
tween(alienGraphics, {
scaleX: 2.3,
scaleY: 1.8
}, {
duration: 300,
easing: tween.easeInOut,
repeat: true,
yoyo: true
});
self.update = function () {
self.x += self.speed * self.direction;
// If off screen, mark as inactive
if (self.direction > 0 && self.x > gameWidth + 100 || self.direction < 0 && self.x < -100) {
self.active = false;
}
};
self.hit = function () {
if (self.active) {
self.active = false;
LK.getSound('alienExplode').play();
LK.effects.flashObject(self, 0xffffff, 100);
tween(self, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
return self.points;
}
return 0;
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 8.0,
scaleY: 8.0
});
self.speed = -15;
self.active = true;
self.width = bulletGraphics.width * 2;
self.height = bulletGraphics.height * 2;
self.update = function () {
self.y += self.speed;
if (self.y < -50) {
self.active = false;
}
};
return self;
});
var PlayerShip = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 80.0,
scaleY: 80.0
});
self.speed = 12;
self.lives = 3;
self.hasShield = true;
self.multiShot = false;
self.width = shipGraphics.width * 2;
self.height = shipGraphics.height * 2;
self.shield = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
y: -40,
alpha: 0.7,
scaleX: 5.0,
scaleY: 5.0
});
self.activateShield = function () {
self.hasShield = true;
self.shield.alpha = 0.7;
};
self.deactivateShield = function () {
self.hasShield = false;
self.shield.alpha = 0;
};
self.hit = function () {
if (self.hasShield) {
self.deactivateShield();
return false;
} else {
LK.getSound('playerHit').play();
self.lives--;
LK.effects.flashObject(self, 0xff0000, 500);
return true;
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8
});
self.type = Math.floor(Math.random() * 3); // 0: shield, 1: multishot, 2: extra life
self.speed = 5;
self.active = true;
self.width = powerUpGraphics.width;
self.height = powerUpGraphics.height;
// Change color based on type
if (self.type === 0) {
powerUpGraphics.tint = 0x9b59b6; // Shield - purple
} else if (self.type === 1) {
powerUpGraphics.tint = 0xf39c12; // Multishot - orange
} else {
powerUpGraphics.tint = 0x2ecc71; // Extra life - green
}
// Add a pulsing animation for level completion power-ups
if (self.type === 2) {
// Extra life power-up
tween(powerUpGraphics, {
scaleX: 2.2,
scaleY: 2.2
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(powerUpGraphics, {
scaleX: 1.8,
scaleY: 1.8
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (self.active) {
// Repeat the animation if still active
tween(powerUpGraphics, {
scaleX: 2.2,
scaleY: 2.2
}, {
duration: 500,
easing: tween.easeInOut
});
}
}
});
}
});
}
self.update = function () {
self.y += self.speed;
if (self.y > 2800) {
self.active = false;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Game state variables
var playerShip;
var playerBullets = [];
var aliens = [];
var alienBullets = [];
var powerUps = [];
var shields = [];
var gameActive = true;
var score = 0;
var level = 1;
var alienDirection = 1; // 1 = right, -1 = left
var alienMoveSpeed = 1;
var alienDropAmount = 40;
var alienShootChance = 0.01;
var powerUpChance = 0.1;
var lastShootTime = 0;
var shootCooldown = 300; // ms
var multiShotTimer = 0;
var gameWidth = 2048;
var gameHeight = 2732;
var aliensKilled = 0;
var bossActive = false;
var boss = null;
var bossSpawnThreshold = 10; // Spawn boss after 10 aliens killed
// UI elements
var scoreTxt;
var levelTxt;
var livesTxt;
// Initialize game
function initGame() {
// Reset game state
playerBullets = [];
aliens = [];
alienBullets = [];
powerUps = [];
shields = [];
gameActive = true;
score = 0;
level = 1;
alienDirection = 1;
alienMoveSpeed = 1;
alienShootChance = 0.01;
multiShotTimer = 0;
aliensKilled = 0;
bossActive = false;
boss = null;
// Set score
LK.setScore(0);
// Create player ship
playerShip = new PlayerShip();
playerShip.x = gameWidth / 2;
playerShip.y = gameHeight - 150;
game.addChild(playerShip);
playerShip.activateShield(); // Activate shield immediately
// Create shields
createShields();
// Create UI
createUI();
// Create aliens for first level
createAlienWave();
// Play background music
LK.playMusic('backgroundMusic');
}
function createUI() {
// Score text
scoreTxt = new Text2('Score: 0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(scoreTxt);
scoreTxt.x = 120; // Keep away from the top left menu area
// Level text
levelTxt = new Text2('Level: 1', {
size: 100,
fill: 0xFFFFFF
});
levelTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(levelTxt);
// Lives text
livesTxt = new Text2('Lives: 3', {
size: 100,
fill: 0xFFFFFF
});
livesTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(livesTxt);
}
function createShields() {
// Create 4 shields across the bottom
var shieldCount = 4;
var shieldSpacing = gameWidth / (shieldCount + 1);
for (var i = 0; i < shieldCount; i++) {
var shield = game.addChild(LK.getAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
}));
shield.x = shieldSpacing * (i + 1);
shield.y = gameHeight - 300;
shield.health = 10;
shields.push(shield);
}
}
function createAlienWave() {
// Clear any remaining aliens
for (var i = aliens.length - 1; i >= 0; i--) {
aliens[i].destroy();
}
aliens = [];
// Increase difficulty with level
alienMoveSpeed = 1 + level * 0.5;
alienShootChance = 0.01 + level * 0.005;
// Create alien grid - rows based on level, 1 row for level 1, 2 rows for level 2, etc. up to 5
var rows = Math.min(level, 5); // Level 1-5 has corresponding number of rows
var cols = 6 + Math.min(level, 4); // Max 10 columns
var alienWidth = 200; // Further increased width to account for larger aliens
var alienHeight = 160; // Further increased height to account for larger aliens
var startX = (gameWidth - cols * alienWidth) / 2 + alienWidth / 2;
var startY = 200;
for (var row = 0; row < rows; row++) {
for (var col = 0; col < cols; col++) {
var alien = new Alien();
alien.x = startX + col * alienWidth;
alien.y = startY + row * alienHeight;
alien.row = row;
alien.col = col;
alien.points = (rows - row) * 10; // More points for aliens at the top
game.addChild(alien);
aliens.push(alien);
}
}
}
function playerShoot() {
var now = Date.now();
if (now - lastShootTime < shootCooldown) {
return;
}
lastShootTime = now;
// Create bullet
var bullet = new PlayerBullet();
bullet.x = playerShip.x;
bullet.y = playerShip.y - playerShip.height / 2;
game.addChild(bullet);
playerBullets.push(bullet);
// If player has multishot, create additional bullets
if (playerShip.multiShot) {
for (var i = -1; i <= 1; i += 2) {
var sideBullet = new PlayerBullet();
sideBullet.x = playerShip.x + i * 20;
sideBullet.y = playerShip.y - playerShip.height / 2;
game.addChild(sideBullet);
playerBullets.push(sideBullet);
}
}
LK.getSound('playerShoot').play();
}
function alienShoot() {
// Find shooting aliens (bottom row of each column)
var shootingAliens = [];
var colMap = {};
for (var i = 0; i < aliens.length; i++) {
var alien = aliens[i];
if (!alien.active) {
continue;
}
// If this alien is lower than the current lowest in its column, it becomes the shooter
if (!colMap[alien.col] || alien.row > colMap[alien.col].row) {
colMap[alien.col] = alien;
}
}
// Get all bottom aliens
for (var col in colMap) {
shootingAliens.push(colMap[col]);
}
// Randomly choose aliens to shoot based on difficulty
for (var i = 0; i < shootingAliens.length; i++) {
if (Math.random() < alienShootChance) {
var shooter = shootingAliens[i];
// Increment shotsFired counter for this alien
shooter.shotsFired = (shooter.shotsFired || 0) + 1;
// Every 10 shots, create an explosive bullet
var bullet;
if (shooter.shotsFired % 10 === 0) {
bullet = new ExplosiveAlienBullet();
// Add visual effect for explosive bullet firing
LK.effects.flashObject(shooter, 0xff5500, 100);
} else {
bullet = new AlienBullet();
}
bullet.x = shooter.x;
bullet.y = shooter.y + shooter.height / 2;
game.addChild(bullet);
alienBullets.push(bullet);
}
}
}
function checkAlienMovement() {
if (aliens.length === 0) {
return;
}
var moveDown = false;
var minX = gameWidth;
var maxX = 0;
// Find leftmost and rightmost aliens
for (var i = 0; i < aliens.length; i++) {
var alien = aliens[i];
if (alien.active) {
minX = Math.min(minX, alien.x);
maxX = Math.max(maxX, alien.x);
}
}
// Check if aliens need to change direction
if (maxX > gameWidth - 50 && alienDirection > 0 || minX < 50 && alienDirection < 0) {
alienDirection *= -1;
moveDown = true;
}
// Move aliens
for (var i = 0; i < aliens.length; i++) {
var alien = aliens[i];
if (alien.active) {
alien.x += alienDirection * alienMoveSpeed;
if (moveDown) {
alien.y += alienDropAmount;
// Check if aliens reached the bottom (game over condition)
if (alien.y > gameHeight - 200) {
gameOver();
return;
}
}
}
}
}
function spawnPowerUp(x, y) {
if (Math.random() < powerUpChance) {
var powerUp = new PowerUp();
powerUp.x = x;
powerUp.y = y;
game.addChild(powerUp);
powerUps.push(powerUp);
}
}
function checkCollisions() {
// Player bullets vs aliens
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (!bullet.active) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
var bulletHit = false;
// Check against aliens
for (var j = 0; j < aliens.length; j++) {
var alien = aliens[j];
if (alien.active && bullet.intersects(alien)) {
// Add points
var pointsEarned = alien.hit();
score += pointsEarned;
LK.setScore(score);
scoreTxt.setText('Score: ' + score);
// If hit is a fast alien, add extra score (on top of the 50 already earned)
if (alien instanceof FastAlien) {
// Add another 50 points for hitting a fast alien
score += 50;
LK.setScore(score);
scoreTxt.setText('Score: ' + score);
// Create visual feedback for the bonus
var bonusText = new Text2('+50!', {
size: 80,
fill: 0x00ffff
});
bonusText.x = alien.x;
bonusText.y = alien.y;
bonusText.anchor.set(0.5, 0.5);
game.addChild(bonusText);
tween(bonusText, {
y: bonusText.y - 100,
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
bonusText.destroy();
}
});
}
// Chance to spawn power up
spawnPowerUp(alien.x, alien.y);
// Remove alien from array if no longer active
if (!alien.active) {
aliens.splice(j, 1);
// Increment aliens killed counter
aliensKilled++;
// Check if we should spawn a boss
if (!bossActive && aliensKilled >= bossSpawnThreshold) {
spawnBoss();
}
}
// Remove bullet
bullet.destroy();
playerBullets.splice(i, 1);
bulletHit = true;
break;
}
}
// If already hit an alien, skip further checks
if (bulletHit) {
continue;
}
// Check against boss if active
if (bossActive && boss && boss.active && bullet.intersects(boss)) {
var bossPoints = boss.hit();
if (bossPoints > 0) {
// Boss was destroyed
score += bossPoints;
LK.setScore(score);
scoreTxt.setText('Score: ' + score);
// Spawn power up when boss is destroyed
spawnPowerUp(boss.x, boss.y);
spawnPowerUp(boss.x - 50, boss.y); // Extra powerups for boss
spawnPowerUp(boss.x + 50, boss.y);
bossActive = false;
boss = null;
}
bullet.destroy();
playerBullets.splice(i, 1);
bulletHit = true;
continue;
}
// Player bullets should pass through shields
// No need to check player bullets against shields
}
// Alien bullets vs player
for (var i = alienBullets.length - 1; i >= 0; i--) {
var bullet = alienBullets[i];
if (!bullet.active) {
bullet.destroy();
alienBullets.splice(i, 1);
continue;
}
// Check against player
if (bullet.intersects(playerShip)) {
var playerDamaged = playerShip.hit();
// Update lives display
livesTxt.setText('Lives: ' + playerShip.lives);
// Check for game over
if (playerShip.lives <= 0) {
gameOver();
}
bullet.destroy();
alienBullets.splice(i, 1);
continue;
}
// Check against shields
for (var j = 0; j < shields.length; j++) {
var shield = shields[j];
if (shield.health > 0 && bullet.intersects(shield)) {
// Explosive bullets do 2 damage instead of 1
if (bullet.isExplosive) {
shield.health -= 2;
// Visual explosion effect
LK.effects.flashObject(shield, 0xff5500, 200);
} else {
shield.health--;
}
shield.alpha = shield.health / 3;
if (shield.health <= 0) {
shield.alpha = 0;
}
bullet.destroy();
alienBullets.splice(i, 1);
break;
}
}
}
// Power-ups vs player
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
if (!powerUp.active) {
powerUp.destroy();
powerUps.splice(i, 1);
continue;
}
if (powerUp.intersects(playerShip)) {
LK.getSound('powerUpCollect').play();
// Apply power-up effect
if (powerUp.type === 0) {
// Shield
playerShip.activateShield();
} else if (powerUp.type === 1) {
// Multi-shot
playerShip.multiShot = true;
multiShotTimer = 300; // Duration in ticks (5 seconds at 60fps)
} else {
// Extra life
playerShip.lives++;
livesTxt.setText('Lives: ' + playerShip.lives);
}
powerUp.destroy();
powerUps.splice(i, 1);
}
}
}
function checkLevelComplete() {
// Check if there are any regular aliens left (not fast aliens)
var regularAliensLeft = false;
for (var i = 0; i < aliens.length; i++) {
if (!(aliens[i] instanceof FastAlien)) {
regularAliensLeft = true;
break;
}
}
if (!regularAliensLeft) {
level++;
levelTxt.setText('Level: ' + level);
// Spawn power-ups on both sides of the player after level completion
spawnLevelCompletionPowerUp();
createAlienWave();
}
}
function spawnLevelCompletionPowerUp() {
// Create two power-ups, one on each side of the player
var leftPowerUp = new PowerUp();
var rightPowerUp = new PowerUp();
// Force the type to be extra life (type 2)
leftPowerUp.type = 2;
rightPowerUp.type = 2;
// Set their color to green (extra life color)
leftPowerUp.getChildAt(0).tint = 0x2ecc71;
rightPowerUp.getChildAt(0).tint = 0x2ecc71;
// Position them on either side of the player
var offset = 200; // Distance from player
leftPowerUp.x = playerShip.x - offset;
leftPowerUp.y = playerShip.y;
rightPowerUp.x = playerShip.x + offset;
rightPowerUp.y = playerShip.y;
// Add them to the game
game.addChild(leftPowerUp);
game.addChild(rightPowerUp);
powerUps.push(leftPowerUp);
powerUps.push(rightPowerUp);
// Add a visual effect to highlight them
LK.effects.flashObject(leftPowerUp, 0x2ecc71, 500);
LK.effects.flashObject(rightPowerUp, 0x2ecc71, 500);
}
function gameOver() {
gameActive = false;
LK.effects.flashScreen(0xff0000, 1000);
LK.stopMusic();
LK.showGameOver();
}
// Touch controls
var touchX = null;
game.down = function (x, y, obj) {
touchX = x;
playerShoot();
};
game.up = function (x, y, obj) {
touchX = null;
};
game.move = function (x, y, obj) {
if (touchX !== null) {
touchX = x;
}
};
// Game update loop
game.update = function () {
if (!gameActive) {
return;
}
// Process player movement from touch
if (touchX !== null) {
// Move player toward touch position
var moveDir = touchX > playerShip.x ? 1 : -1;
if (Math.abs(touchX - playerShip.x) > 5) {
playerShip.x += moveDir * playerShip.speed;
}
// Keep player in bounds
if (playerShip.x < playerShip.width / 2) {
playerShip.x = playerShip.width / 2;
}
if (playerShip.x > gameWidth - playerShip.width / 2) {
playerShip.x = gameWidth - playerShip.width / 2;
}
}
// Update multishot timer
if (playerShip.multiShot) {
multiShotTimer--;
if (multiShotTimer <= 0) {
playerShip.multiShot = false;
}
}
// Update game objects
checkAlienMovement();
// Update fast aliens manually as they have their own movement pattern
for (var i = 0; i < aliens.length; i++) {
if (aliens[i] instanceof FastAlien && aliens[i].active) {
aliens[i].update();
}
}
// Boss update logic
if (bossActive && boss && boss.active) {
// Make boss move side to side independently
boss.x += Math.sin(LK.ticks / 60) * 3; // Gentle sine wave movement
// Make boss shoot more frequently
if (LK.ticks % 180 === 0) {
// Every 3 seconds
var bullet = new ExplosiveAlienBullet();
bullet.x = boss.x;
bullet.y = boss.y + boss.height / 2;
game.addChild(bullet);
alienBullets.push(bullet);
// Sometimes fire a spread of bullets
if (Math.random() < 0.5) {
for (var i = -1; i <= 1; i += 2) {
var sideBullet = new AlienBullet();
sideBullet.x = boss.x + i * 40;
sideBullet.y = boss.y + boss.height / 2;
game.addChild(sideBullet);
alienBullets.push(sideBullet);
}
}
}
// Update boss custom logic if any
if (boss.update) {
boss.update();
}
}
// Alien shooting
if (LK.ticks % 300 === 0) {
// Check every 5 seconds
alienShoot();
}
// Automatic player shooting every 2 seconds (120 ticks at 60fps)
if (LK.ticks % 120 === 0) {
playerShoot();
}
// Update bullets
for (var i = 0; i < playerBullets.length; i++) {
playerBullets[i].update();
}
for (var i = 0; i < alienBullets.length; i++) {
alienBullets[i].update();
}
// Update power-ups
for (var i = 0; i < powerUps.length; i++) {
powerUps[i].update();
}
// Check collisions
checkCollisions();
// Check if level is complete
checkLevelComplete();
};
// Initialize the game
initGame();
// Function to spawn fast aliens
function spawnFastAlien() {
var fastAlien = new FastAlien();
// Set starting position - either left or right edge of screen
if (fastAlien.direction > 0) {
// Moving right to left
fastAlien.x = -50;
} else {
// Moving left to right
fastAlien.x = gameWidth + 50;
}
// Random Y position in the top half of the screen
fastAlien.y = Math.random() * (gameHeight / 2) + 100;
game.addChild(fastAlien);
aliens.push(fastAlien);
// Visual effect for fast alien spawn
LK.effects.flashObject(fastAlien, 0x00ffff, 200);
}
// Set interval to spawn fast aliens every 5 seconds (300 frames at 60fps)
LK.setInterval(spawnFastAlien, 5000);
function spawnBoss() {
bossActive = true;
boss = new BossAlien();
// Find the back row position
var backRow = 0;
var startX = gameWidth / 2;
var startY = 200;
// If there are aliens, position the boss behind them
if (aliens.length > 0) {
for (var i = 0; i < aliens.length; i++) {
if (aliens[i].row < backRow) {
backRow = aliens[i].row;
}
}
backRow = backRow - 1; // Position boss one row behind furthest back row
if (backRow < 0) {
backRow = 0;
}
startY = 200 + backRow * 160; // Use same spacing as alien rows
}
boss.x = startX;
boss.y = startY;
boss.row = backRow;
boss.col = -1; // Special column marker for boss
game.addChild(boss);
// Visual effect for boss spawn
LK.effects.flashObject(boss, 0xffff00, 500);
}
Steel beam. In-Game asset. 2d. High contrast. No shadows
Bullet. In-Game asset. 2d. High contrast. No shadows
Military Tank. In-Game asset. 2d. High contrast. No shadows
Medkit. In-Game asset. 2d. High contrast. No shadows
Blue alien in a UFO, he’s mad and his body is inside the ufo. In-Game asset. 2d. High contrast. No shadows