/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { highScore: 0, level: 1 }); /**** * Classes ****/ var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.width = enemyGraphics.width; self.height = enemyGraphics.height; self.hp = 1; self.scoreValue = 100; self.canShoot = true; self.movingRight = true; self.moveSpeed = 2; self.dropDistance = 40; self.shoot = function () { if (!self.canShoot || Math.random() > 0.01) { return; } // Random chance to shoot var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y + self.height / 2; game.addChild(bullet); enemyBullets.push(bullet); // Cooldown between shots self.canShoot = false; LK.setTimeout(function () { self.canShoot = true; }, 2000); }; self.takeDamage = function () { self.hp--; if (self.hp <= 0) { // Update score LK.setScore(LK.getScore() + self.scoreValue); scoreTxt.setText(LK.getScore()); // Chance to drop power-up if (Math.random() < 0.1) { // 10% chance var powerUp = new PowerUp(); powerUp.x = self.x; powerUp.y = self.y; game.addChild(powerUp); powerUps.push(powerUp); } // Play sound LK.getSound('enemyDestroyed').play(); // Visual effect LK.effects.flashObject(self, 0xffff00, 300); // Remove enemy self.destroy(); var index = enemies.indexOf(self); if (index > -1) { enemies.splice(index, 1); } // Check if level complete if (enemies.length === 0) { levelComplete(); } } else { // Visual effect for damage LK.effects.flashObject(self, 0xffff00, 200); } }; return self; }); var Boss = Enemy.expand(function () { var self = Enemy.call(this); // Replace graphics with boss graphics self.removeChildAt(0); var bossGraphics = self.attachAsset('boss', { anchorX: 0.5, anchorY: 0.5 }); self.width = bossGraphics.width; self.height = bossGraphics.height; self.hp = 20; self.scoreValue = 2000; self.moveSpeed = 3; self.attackPattern = 0; self.attackTimer = null; self.startAttackPattern = function () { self.attackTimer = LK.setInterval(function () { self.performAttack(); }, 2000); }; self.performAttack = function () { self.attackPattern = (self.attackPattern + 1) % 3; switch (self.attackPattern) { case 0: // Single strong shot var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y + self.height / 2; bullet.speed = 8; bullet.scale.set(2, 2); game.addChild(bullet); enemyBullets.push(bullet); break; case 1: // Multiple shots in a spread for (var i = -2; i <= 2; i++) { var bullet = new EnemyBullet(); bullet.x = self.x + i * 40; bullet.y = self.y + self.height / 2; game.addChild(bullet); enemyBullets.push(bullet); } break; case 2: // Wave pattern of bullets var interval = LK.setInterval(function () { var bullet = new EnemyBullet(); bullet.x = self.x + (Math.random() * 200 - 100); bullet.y = self.y + self.height / 2; game.addChild(bullet); enemyBullets.push(bullet); }, 200); LK.setTimeout(function () { LK.clearInterval(interval); }, 1000); break; } }; var parentTakeDamage = self.takeDamage; self.takeDamage = function () { parentTakeDamage.call(self); // When boss is destroyed, clear the attack timer if (self.hp <= 0 && self.attackTimer) { LK.clearInterval(self.attackTimer); } }; return self; }); var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6; self.update = function () { self.y += self.speed; // Destroy if out of bounds if (self.y > 2732 + 50) { self.destroy(); var index = enemyBullets.indexOf(self); if (index > -1) { enemyBullets.splice(index, 1); } } }; return self; }); var PlayerBullet = Container.expand(function () { var self = Container.call(this); var bulletGraphics = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -15; // Negative because moving upward self.update = function () { self.y += self.speed; // Destroy if out of bounds if (self.y < -50) { self.destroy(); var index = bullets.indexOf(self); if (index > -1) { bullets.splice(index, 1); } } }; return self; }); var PlayerShip = Container.expand(function () { var self = Container.call(this); var shipGraphics = self.attachAsset('playerShip', { anchorX: 0.5, anchorY: 0.5 }); self.width = shipGraphics.width; self.height = shipGraphics.height; self.lives = 3; self.speed = 15; self.canShoot = true; self.shootCooldown = 300; // milliseconds self.invulnerable = false; self.powerUpActive = false; self.startShootCooldown = function () { self.canShoot = false; LK.setTimeout(function () { self.canShoot = true; }, self.shootCooldown); }; self.shoot = function () { if (!self.canShoot) { return; } var bullet = new PlayerBullet(); bullet.x = self.x; bullet.y = self.y - self.height / 2; game.addChild(bullet); bullets.push(bullet); LK.getSound('shoot').play(); self.startShootCooldown(); // Create double bullet when power-up is active if (self.powerUpActive) { var bulletLeft = new PlayerBullet(); bulletLeft.x = self.x - 20; bulletLeft.y = self.y - self.height / 2; var bulletRight = new PlayerBullet(); bulletRight.x = self.x + 20; bulletRight.y = self.y - self.height / 2; game.addChild(bulletLeft); game.addChild(bulletRight); bullets.push(bulletLeft); bullets.push(bulletRight); } }; self.hit = function () { if (self.invulnerable) { return; } self.lives--; LK.getSound('playerHit').play(); // Flash player ship to indicate damage LK.effects.flashObject(self, 0xff0000, 1000); // Make player temporarily invulnerable self.invulnerable = true; LK.setTimeout(function () { self.invulnerable = false; }, 2000); // Check for game over if (self.lives <= 0) { LK.showGameOver(); } }; self.activatePowerUp = function (type) { LK.getSound('powerUpCollected').play(); switch (type) { case 'rapidFire': var oldCooldown = self.shootCooldown; self.shootCooldown = 150; LK.setTimeout(function () { self.shootCooldown = oldCooldown; }, 5000); break; case 'doubleBullet': self.powerUpActive = true; LK.setTimeout(function () { self.powerUpActive = false; }, 8000); break; case 'shield': // Create shield createShield(); break; } }; self.update = function () { // Movement logic handled in game.update }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerUpGraphics = self.attachAsset('powerUp', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; self.type = ['rapidFire', 'doubleBullet', 'shield'][Math.floor(Math.random() * 3)]; // Set color based on power-up type switch (self.type) { case 'rapidFire': powerUpGraphics.tint = 0xff0000; // Red break; case 'doubleBullet': powerUpGraphics.tint = 0x00ff00; // Green break; case 'shield': powerUpGraphics.tint = 0x0000ff; // Blue break; } self.update = function () { self.y += self.speed; // Destroy if out of bounds if (self.y > 2732 + 50) { self.destroy(); var index = powerUps.indexOf(self); if (index > -1) { powerUps.splice(index, 1); } } }; return self; }); var Shield = Container.expand(function () { var self = Container.call(this); var shieldGraphics = self.attachAsset('shield', { anchorX: 0.5, anchorY: 0.5 }); self.hp = 3; self.takeDamage = function () { self.hp--; // Visual feedback LK.effects.flashObject(self, 0x2980b9, 200); // Adjust opacity based on remaining HP self.alpha = self.hp / 3; if (self.hp <= 0) { self.destroy(); var index = shields.indexOf(self); if (index > -1) { shields.splice(index, 1); } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Game constants var GAME_WIDTH = 2048; var GAME_HEIGHT = 2732; var GAME_MARGIN = 100; var ENEMY_ROWS = 5; var ENEMY_COLUMNS = 8; var ENEMY_SPACING_X = 150; var ENEMY_SPACING_Y = 120; var ENEMY_START_Y = 300; var GROUP_MOVE_AMOUNT = 15; var GROUP_DROP_AMOUNT = 40; var MOVE_INTERVAL = 800; // ms // Game variables var level = storage.level || 1; var player; var bullets = []; var enemies = []; var enemyBullets = []; var shields = []; var powerUps = []; var enemyMoveTimer; var movingRight = true; var bossActive = false; var touchX = null; // Create UI elements var scoreTxt = new Text2('0', { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0, 0); LK.gui.topRight.addChild(scoreTxt); scoreTxt.x = -250; // Offset from the right edge var levelTxt = new Text2('LEVEL ' + level, { size: 60, fill: 0xFFFFFF }); levelTxt.anchor.set(0.5, 0); LK.gui.top.addChild(levelTxt); var livesTxt = new Text2('LIVES: 3', { size: 60, fill: 0xFFFFFF }); livesTxt.anchor.set(0, 0); LK.gui.topLeft.addChild(livesTxt); livesTxt.x = 120; // Ensure we don't place this in the top-left 100x100 area // Game functions function initializeGame() { // Reset game state clearArrays(); // Set difficulty based on level var enemyHp = Math.min(Math.floor(level / 3) + 1, 3); var enemySpeed = Math.min(2 + level * 0.5, 8); var moveInterval = Math.max(MOVE_INTERVAL - level * 50, 300); // Create player player = new PlayerShip(); player.x = GAME_WIDTH / 2; player.y = GAME_HEIGHT - 200; game.addChild(player); // Create enemies createEnemies(enemyHp); // Start enemy movement startEnemyMovement(moveInterval); // Reset score if starting a new game if (level === 1) { LK.setScore(0); } // Update UI scoreTxt.setText(LK.getScore()); levelTxt.setText('LEVEL ' + level); // Play music LK.playMusic('gameMusic', { fade: { start: 0, end: 0.8, duration: 1000 } }); } function clearArrays() { // Clear existing game objects for (var i = bullets.length - 1; i >= 0; i--) { bullets[i].destroy(); } for (var i = enemies.length - 1; i >= 0; i--) { enemies[i].destroy(); } for (var i = enemyBullets.length - 1; i >= 0; i--) { enemyBullets[i].destroy(); } for (var i = shields.length - 1; i >= 0; i--) { shields[i].destroy(); } for (var i = powerUps.length - 1; i >= 0; i--) { powerUps[i].destroy(); } bullets = []; enemies = []; enemyBullets = []; shields = []; powerUps = []; // Clear any existing timers if (enemyMoveTimer) { LK.clearInterval(enemyMoveTimer); } } function createEnemies(hp) { bossActive = false; // Boss level every 5 levels if (level % 5 === 0) { createBoss(); return; } // Create grid of enemies var startX = (GAME_WIDTH - (ENEMY_COLUMNS - 1) * ENEMY_SPACING_X) / 2; for (var row = 0; row < ENEMY_ROWS; row++) { for (var col = 0; col < ENEMY_COLUMNS; col++) { var enemy = new Enemy(); // Different types/strength based on row if (row === 0) { enemy.hp = hp + 1; enemy.scoreValue = 300; enemy.tint = 0xff0000; // Red top row } else if (row === 1 || row === 2) { enemy.hp = hp; enemy.scoreValue = 200; enemy.tint = 0x00ff00; // Green middle rows } else { enemy.hp = Math.max(1, hp - 1); enemy.scoreValue = 100; enemy.tint = 0x0000ff; // Blue bottom rows } enemy.x = startX + col * ENEMY_SPACING_X; enemy.y = ENEMY_START_Y + row * ENEMY_SPACING_Y; game.addChild(enemy); enemies.push(enemy); } } } function createBoss() { bossActive = true; var boss = new Boss(); boss.x = GAME_WIDTH / 2; boss.y = 300; boss.hp = 15 + level / 5 * 5; // Increases with level game.addChild(boss); enemies.push(boss); boss.startAttackPattern(); } function startEnemyMovement(interval) { enemyMoveTimer = LK.setInterval(function () { moveEnemyGroup(); }, interval); } function moveEnemyGroup() { if (enemies.length === 0) { return; } var reachedEdge = false; var moveAmount = bossActive ? GROUP_MOVE_AMOUNT * 1.5 : GROUP_MOVE_AMOUNT; // Check if any enemy would go beyond screen edge for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (movingRight && enemy.x + enemy.width / 2 + moveAmount > GAME_WIDTH - GAME_MARGIN || !movingRight && enemy.x - enemy.width / 2 - moveAmount < GAME_MARGIN) { reachedEdge = true; break; } } // Move group horizontally or drop and change direction if (reachedEdge) { movingRight = !movingRight; // Move all enemies down for (var i = 0; i < enemies.length; i++) { enemies[i].y += GROUP_DROP_AMOUNT; } // Check if enemies reached player's area checkEnemiesBottom(); } else { // Move enemies sideways for (var i = 0; i < enemies.length; i++) { enemies[i].x += movingRight ? moveAmount : -moveAmount; } } // Try to make some enemies shoot for (var i = 0; i < enemies.length; i++) { enemies[i].shoot(); } } function checkEnemiesBottom() { for (var i = 0; i < enemies.length; i++) { if (enemies[i].y + enemies[i].height / 2 > player.y - 100) { // Game over if enemies get too close to bottom LK.showGameOver(); return; } } } function createShield() { var shield = new Shield(); shield.x = player.x; shield.y = player.y - 80; game.addChild(shield); shields.push(shield); } function levelComplete() { LK.getSound('levelComplete').play(); // Save high score if it's better than previous if (LK.getScore() > storage.highScore) { storage.highScore = LK.getScore(); } // Increment level level++; storage.level = level; // Show level transition var levelCompleteTxt = new Text2('LEVEL COMPLETE!', { size: 120, fill: 0xFFFFFF }); levelCompleteTxt.anchor.set(0.5, 0.5); levelCompleteTxt.x = GAME_WIDTH / 2; levelCompleteTxt.y = GAME_HEIGHT / 2; game.addChild(levelCompleteTxt); // Fade out current level tween(levelCompleteTxt, { alpha: 0 }, { duration: 2000, onFinish: function onFinish() { levelCompleteTxt.destroy(); // Start next level initializeGame(); } }); } function checkCollisions() { // Player bullets vs enemies for (var i = bullets.length - 1; i >= 0; i--) { var bullet = bullets[i]; for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (bullet.intersects(enemy)) { // Handle hit enemy.takeDamage(); // Remove bullet bullet.destroy(); bullets.splice(i, 1); break; } } } // Enemy bullets vs player for (var i = enemyBullets.length - 1; i >= 0; i--) { var bullet = enemyBullets[i]; // Check for shield hits first var hitShield = false; for (var j = shields.length - 1; j >= 0; j--) { var shield = shields[j]; if (bullet.intersects(shield)) { shield.takeDamage(); // Remove bullet bullet.destroy(); enemyBullets.splice(i, 1); hitShield = true; break; } } if (hitShield) { continue; } // Check for player hit if (bullet.intersects(player)) { player.hit(); // Remove bullet bullet.destroy(); enemyBullets.splice(i, 1); } } // Player vs power-ups for (var i = powerUps.length - 1; i >= 0; i--) { var powerUp = powerUps[i]; if (powerUp.intersects(player)) { player.activatePowerUp(powerUp.type); // Remove power-up powerUp.destroy(); powerUps.splice(i, 1); } } // Update lives display livesTxt.setText('LIVES: ' + player.lives); } function movePlayer() { // If touch input is active, move towards it if (touchX !== null) { var moveSpeed = player.speed; var distanceToTouch = touchX - player.x; if (Math.abs(distanceToTouch) < moveSpeed) { player.x = touchX; } else if (distanceToTouch > 0) { player.x += moveSpeed; } else { player.x -= moveSpeed; } } // Keep player within screen bounds if (player.x < GAME_MARGIN + player.width / 2) { player.x = GAME_MARGIN + player.width / 2; } else if (player.x > GAME_WIDTH - GAME_MARGIN - player.width / 2) { player.x = GAME_WIDTH - GAME_MARGIN - player.width / 2; } } // Handle touch/mouse input game.down = function (x, y, obj) { touchX = x; // Shoot when tapping player.shoot(); }; game.move = function (x, y, obj) { touchX = x; }; game.up = function (x, y, obj) { touchX = null; }; // Game update loop game.update = function () { movePlayer(); // Update all game objects for (var i = 0; i < bullets.length; i++) { bullets[i].update(); } for (var i = 0; i < enemyBullets.length; i++) { enemyBullets[i].update(); } for (var i = 0; i < powerUps.length; i++) { powerUps[i].update(); } // Check for collisions checkCollisions(); }; // Initialize the game initializeGame();
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,681 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ highScore: 0,
+ level: 1
+});
+
+/****
+* Classes
+****/
+var Enemy = Container.expand(function () {
+ var self = Container.call(this);
+ var enemyGraphics = self.attachAsset('enemy', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.width = enemyGraphics.width;
+ self.height = enemyGraphics.height;
+ self.hp = 1;
+ self.scoreValue = 100;
+ self.canShoot = true;
+ self.movingRight = true;
+ self.moveSpeed = 2;
+ self.dropDistance = 40;
+ self.shoot = function () {
+ if (!self.canShoot || Math.random() > 0.01) {
+ return;
+ } // Random chance to shoot
+ var bullet = new EnemyBullet();
+ bullet.x = self.x;
+ bullet.y = self.y + self.height / 2;
+ game.addChild(bullet);
+ enemyBullets.push(bullet);
+ // Cooldown between shots
+ self.canShoot = false;
+ LK.setTimeout(function () {
+ self.canShoot = true;
+ }, 2000);
+ };
+ self.takeDamage = function () {
+ self.hp--;
+ if (self.hp <= 0) {
+ // Update score
+ LK.setScore(LK.getScore() + self.scoreValue);
+ scoreTxt.setText(LK.getScore());
+ // Chance to drop power-up
+ if (Math.random() < 0.1) {
+ // 10% chance
+ var powerUp = new PowerUp();
+ powerUp.x = self.x;
+ powerUp.y = self.y;
+ game.addChild(powerUp);
+ powerUps.push(powerUp);
+ }
+ // Play sound
+ LK.getSound('enemyDestroyed').play();
+ // Visual effect
+ LK.effects.flashObject(self, 0xffff00, 300);
+ // Remove enemy
+ self.destroy();
+ var index = enemies.indexOf(self);
+ if (index > -1) {
+ enemies.splice(index, 1);
+ }
+ // Check if level complete
+ if (enemies.length === 0) {
+ levelComplete();
+ }
+ } else {
+ // Visual effect for damage
+ LK.effects.flashObject(self, 0xffff00, 200);
+ }
+ };
+ return self;
+});
+var Boss = Enemy.expand(function () {
+ var self = Enemy.call(this);
+ // Replace graphics with boss graphics
+ self.removeChildAt(0);
+ var bossGraphics = self.attachAsset('boss', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.width = bossGraphics.width;
+ self.height = bossGraphics.height;
+ self.hp = 20;
+ self.scoreValue = 2000;
+ self.moveSpeed = 3;
+ self.attackPattern = 0;
+ self.attackTimer = null;
+ self.startAttackPattern = function () {
+ self.attackTimer = LK.setInterval(function () {
+ self.performAttack();
+ }, 2000);
+ };
+ self.performAttack = function () {
+ self.attackPattern = (self.attackPattern + 1) % 3;
+ switch (self.attackPattern) {
+ case 0:
+ // Single strong shot
+ var bullet = new EnemyBullet();
+ bullet.x = self.x;
+ bullet.y = self.y + self.height / 2;
+ bullet.speed = 8;
+ bullet.scale.set(2, 2);
+ game.addChild(bullet);
+ enemyBullets.push(bullet);
+ break;
+ case 1:
+ // Multiple shots in a spread
+ for (var i = -2; i <= 2; i++) {
+ var bullet = new EnemyBullet();
+ bullet.x = self.x + i * 40;
+ bullet.y = self.y + self.height / 2;
+ game.addChild(bullet);
+ enemyBullets.push(bullet);
+ }
+ break;
+ case 2:
+ // Wave pattern of bullets
+ var interval = LK.setInterval(function () {
+ var bullet = new EnemyBullet();
+ bullet.x = self.x + (Math.random() * 200 - 100);
+ bullet.y = self.y + self.height / 2;
+ game.addChild(bullet);
+ enemyBullets.push(bullet);
+ }, 200);
+ LK.setTimeout(function () {
+ LK.clearInterval(interval);
+ }, 1000);
+ break;
+ }
+ };
+ var parentTakeDamage = self.takeDamage;
+ self.takeDamage = function () {
+ parentTakeDamage.call(self);
+ // When boss is destroyed, clear the attack timer
+ if (self.hp <= 0 && self.attackTimer) {
+ LK.clearInterval(self.attackTimer);
+ }
+ };
+ return self;
+});
+var EnemyBullet = Container.expand(function () {
+ var self = Container.call(this);
+ var bulletGraphics = self.attachAsset('enemyBullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 6;
+ self.update = function () {
+ self.y += self.speed;
+ // Destroy if out of bounds
+ if (self.y > 2732 + 50) {
+ self.destroy();
+ var index = enemyBullets.indexOf(self);
+ if (index > -1) {
+ enemyBullets.splice(index, 1);
+ }
+ }
+ };
+ return self;
+});
+var PlayerBullet = Container.expand(function () {
+ var self = Container.call(this);
+ var bulletGraphics = self.attachAsset('playerBullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = -15; // Negative because moving upward
+ self.update = function () {
+ self.y += self.speed;
+ // Destroy if out of bounds
+ if (self.y < -50) {
+ self.destroy();
+ var index = bullets.indexOf(self);
+ if (index > -1) {
+ bullets.splice(index, 1);
+ }
+ }
+ };
+ return self;
+});
+var PlayerShip = Container.expand(function () {
+ var self = Container.call(this);
+ var shipGraphics = self.attachAsset('playerShip', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.width = shipGraphics.width;
+ self.height = shipGraphics.height;
+ self.lives = 3;
+ self.speed = 15;
+ self.canShoot = true;
+ self.shootCooldown = 300; // milliseconds
+ self.invulnerable = false;
+ self.powerUpActive = false;
+ self.startShootCooldown = function () {
+ self.canShoot = false;
+ LK.setTimeout(function () {
+ self.canShoot = true;
+ }, self.shootCooldown);
+ };
+ self.shoot = function () {
+ if (!self.canShoot) {
+ return;
+ }
+ var bullet = new PlayerBullet();
+ bullet.x = self.x;
+ bullet.y = self.y - self.height / 2;
+ game.addChild(bullet);
+ bullets.push(bullet);
+ LK.getSound('shoot').play();
+ self.startShootCooldown();
+ // Create double bullet when power-up is active
+ if (self.powerUpActive) {
+ var bulletLeft = new PlayerBullet();
+ bulletLeft.x = self.x - 20;
+ bulletLeft.y = self.y - self.height / 2;
+ var bulletRight = new PlayerBullet();
+ bulletRight.x = self.x + 20;
+ bulletRight.y = self.y - self.height / 2;
+ game.addChild(bulletLeft);
+ game.addChild(bulletRight);
+ bullets.push(bulletLeft);
+ bullets.push(bulletRight);
+ }
+ };
+ self.hit = function () {
+ if (self.invulnerable) {
+ return;
+ }
+ self.lives--;
+ LK.getSound('playerHit').play();
+ // Flash player ship to indicate damage
+ LK.effects.flashObject(self, 0xff0000, 1000);
+ // Make player temporarily invulnerable
+ self.invulnerable = true;
+ LK.setTimeout(function () {
+ self.invulnerable = false;
+ }, 2000);
+ // Check for game over
+ if (self.lives <= 0) {
+ LK.showGameOver();
+ }
+ };
+ self.activatePowerUp = function (type) {
+ LK.getSound('powerUpCollected').play();
+ switch (type) {
+ case 'rapidFire':
+ var oldCooldown = self.shootCooldown;
+ self.shootCooldown = 150;
+ LK.setTimeout(function () {
+ self.shootCooldown = oldCooldown;
+ }, 5000);
+ break;
+ case 'doubleBullet':
+ self.powerUpActive = true;
+ LK.setTimeout(function () {
+ self.powerUpActive = false;
+ }, 8000);
+ break;
+ case 'shield':
+ // Create shield
+ createShield();
+ break;
+ }
+ };
+ self.update = function () {
+ // Movement logic handled in game.update
+ };
+ return self;
+});
+var PowerUp = Container.expand(function () {
+ var self = Container.call(this);
+ var powerUpGraphics = self.attachAsset('powerUp', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 3;
+ self.type = ['rapidFire', 'doubleBullet', 'shield'][Math.floor(Math.random() * 3)];
+ // Set color based on power-up type
+ switch (self.type) {
+ case 'rapidFire':
+ powerUpGraphics.tint = 0xff0000; // Red
+ break;
+ case 'doubleBullet':
+ powerUpGraphics.tint = 0x00ff00; // Green
+ break;
+ case 'shield':
+ powerUpGraphics.tint = 0x0000ff; // Blue
+ break;
+ }
+ self.update = function () {
+ self.y += self.speed;
+ // Destroy if out of bounds
+ if (self.y > 2732 + 50) {
+ self.destroy();
+ var index = powerUps.indexOf(self);
+ if (index > -1) {
+ powerUps.splice(index, 1);
+ }
+ }
+ };
+ return self;
+});
+var Shield = Container.expand(function () {
+ var self = Container.call(this);
+ var shieldGraphics = self.attachAsset('shield', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.hp = 3;
+ self.takeDamage = function () {
+ self.hp--;
+ // Visual feedback
+ LK.effects.flashObject(self, 0x2980b9, 200);
+ // Adjust opacity based on remaining HP
+ self.alpha = self.hp / 3;
+ if (self.hp <= 0) {
+ self.destroy();
+ var index = shields.indexOf(self);
+ if (index > -1) {
+ shields.splice(index, 1);
+ }
+ }
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
backgroundColor: 0x000000
-});
\ No newline at end of file
+});
+
+/****
+* Game Code
+****/
+// Game constants
+var GAME_WIDTH = 2048;
+var GAME_HEIGHT = 2732;
+var GAME_MARGIN = 100;
+var ENEMY_ROWS = 5;
+var ENEMY_COLUMNS = 8;
+var ENEMY_SPACING_X = 150;
+var ENEMY_SPACING_Y = 120;
+var ENEMY_START_Y = 300;
+var GROUP_MOVE_AMOUNT = 15;
+var GROUP_DROP_AMOUNT = 40;
+var MOVE_INTERVAL = 800; // ms
+// Game variables
+var level = storage.level || 1;
+var player;
+var bullets = [];
+var enemies = [];
+var enemyBullets = [];
+var shields = [];
+var powerUps = [];
+var enemyMoveTimer;
+var movingRight = true;
+var bossActive = false;
+var touchX = null;
+// Create UI elements
+var scoreTxt = new Text2('0', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0, 0);
+LK.gui.topRight.addChild(scoreTxt);
+scoreTxt.x = -250; // Offset from the right edge
+var levelTxt = new Text2('LEVEL ' + level, {
+ size: 60,
+ fill: 0xFFFFFF
+});
+levelTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(levelTxt);
+var livesTxt = new Text2('LIVES: 3', {
+ size: 60,
+ fill: 0xFFFFFF
+});
+livesTxt.anchor.set(0, 0);
+LK.gui.topLeft.addChild(livesTxt);
+livesTxt.x = 120; // Ensure we don't place this in the top-left 100x100 area
+// Game functions
+function initializeGame() {
+ // Reset game state
+ clearArrays();
+ // Set difficulty based on level
+ var enemyHp = Math.min(Math.floor(level / 3) + 1, 3);
+ var enemySpeed = Math.min(2 + level * 0.5, 8);
+ var moveInterval = Math.max(MOVE_INTERVAL - level * 50, 300);
+ // Create player
+ player = new PlayerShip();
+ player.x = GAME_WIDTH / 2;
+ player.y = GAME_HEIGHT - 200;
+ game.addChild(player);
+ // Create enemies
+ createEnemies(enemyHp);
+ // Start enemy movement
+ startEnemyMovement(moveInterval);
+ // Reset score if starting a new game
+ if (level === 1) {
+ LK.setScore(0);
+ }
+ // Update UI
+ scoreTxt.setText(LK.getScore());
+ levelTxt.setText('LEVEL ' + level);
+ // Play music
+ LK.playMusic('gameMusic', {
+ fade: {
+ start: 0,
+ end: 0.8,
+ duration: 1000
+ }
+ });
+}
+function clearArrays() {
+ // Clear existing game objects
+ for (var i = bullets.length - 1; i >= 0; i--) {
+ bullets[i].destroy();
+ }
+ for (var i = enemies.length - 1; i >= 0; i--) {
+ enemies[i].destroy();
+ }
+ for (var i = enemyBullets.length - 1; i >= 0; i--) {
+ enemyBullets[i].destroy();
+ }
+ for (var i = shields.length - 1; i >= 0; i--) {
+ shields[i].destroy();
+ }
+ for (var i = powerUps.length - 1; i >= 0; i--) {
+ powerUps[i].destroy();
+ }
+ bullets = [];
+ enemies = [];
+ enemyBullets = [];
+ shields = [];
+ powerUps = [];
+ // Clear any existing timers
+ if (enemyMoveTimer) {
+ LK.clearInterval(enemyMoveTimer);
+ }
+}
+function createEnemies(hp) {
+ bossActive = false;
+ // Boss level every 5 levels
+ if (level % 5 === 0) {
+ createBoss();
+ return;
+ }
+ // Create grid of enemies
+ var startX = (GAME_WIDTH - (ENEMY_COLUMNS - 1) * ENEMY_SPACING_X) / 2;
+ for (var row = 0; row < ENEMY_ROWS; row++) {
+ for (var col = 0; col < ENEMY_COLUMNS; col++) {
+ var enemy = new Enemy();
+ // Different types/strength based on row
+ if (row === 0) {
+ enemy.hp = hp + 1;
+ enemy.scoreValue = 300;
+ enemy.tint = 0xff0000; // Red top row
+ } else if (row === 1 || row === 2) {
+ enemy.hp = hp;
+ enemy.scoreValue = 200;
+ enemy.tint = 0x00ff00; // Green middle rows
+ } else {
+ enemy.hp = Math.max(1, hp - 1);
+ enemy.scoreValue = 100;
+ enemy.tint = 0x0000ff; // Blue bottom rows
+ }
+ enemy.x = startX + col * ENEMY_SPACING_X;
+ enemy.y = ENEMY_START_Y + row * ENEMY_SPACING_Y;
+ game.addChild(enemy);
+ enemies.push(enemy);
+ }
+ }
+}
+function createBoss() {
+ bossActive = true;
+ var boss = new Boss();
+ boss.x = GAME_WIDTH / 2;
+ boss.y = 300;
+ boss.hp = 15 + level / 5 * 5; // Increases with level
+ game.addChild(boss);
+ enemies.push(boss);
+ boss.startAttackPattern();
+}
+function startEnemyMovement(interval) {
+ enemyMoveTimer = LK.setInterval(function () {
+ moveEnemyGroup();
+ }, interval);
+}
+function moveEnemyGroup() {
+ if (enemies.length === 0) {
+ return;
+ }
+ var reachedEdge = false;
+ var moveAmount = bossActive ? GROUP_MOVE_AMOUNT * 1.5 : GROUP_MOVE_AMOUNT;
+ // Check if any enemy would go beyond screen edge
+ for (var i = 0; i < enemies.length; i++) {
+ var enemy = enemies[i];
+ if (movingRight && enemy.x + enemy.width / 2 + moveAmount > GAME_WIDTH - GAME_MARGIN || !movingRight && enemy.x - enemy.width / 2 - moveAmount < GAME_MARGIN) {
+ reachedEdge = true;
+ break;
+ }
+ }
+ // Move group horizontally or drop and change direction
+ if (reachedEdge) {
+ movingRight = !movingRight;
+ // Move all enemies down
+ for (var i = 0; i < enemies.length; i++) {
+ enemies[i].y += GROUP_DROP_AMOUNT;
+ }
+ // Check if enemies reached player's area
+ checkEnemiesBottom();
+ } else {
+ // Move enemies sideways
+ for (var i = 0; i < enemies.length; i++) {
+ enemies[i].x += movingRight ? moveAmount : -moveAmount;
+ }
+ }
+ // Try to make some enemies shoot
+ for (var i = 0; i < enemies.length; i++) {
+ enemies[i].shoot();
+ }
+}
+function checkEnemiesBottom() {
+ for (var i = 0; i < enemies.length; i++) {
+ if (enemies[i].y + enemies[i].height / 2 > player.y - 100) {
+ // Game over if enemies get too close to bottom
+ LK.showGameOver();
+ return;
+ }
+ }
+}
+function createShield() {
+ var shield = new Shield();
+ shield.x = player.x;
+ shield.y = player.y - 80;
+ game.addChild(shield);
+ shields.push(shield);
+}
+function levelComplete() {
+ LK.getSound('levelComplete').play();
+ // Save high score if it's better than previous
+ if (LK.getScore() > storage.highScore) {
+ storage.highScore = LK.getScore();
+ }
+ // Increment level
+ level++;
+ storage.level = level;
+ // Show level transition
+ var levelCompleteTxt = new Text2('LEVEL COMPLETE!', {
+ size: 120,
+ fill: 0xFFFFFF
+ });
+ levelCompleteTxt.anchor.set(0.5, 0.5);
+ levelCompleteTxt.x = GAME_WIDTH / 2;
+ levelCompleteTxt.y = GAME_HEIGHT / 2;
+ game.addChild(levelCompleteTxt);
+ // Fade out current level
+ tween(levelCompleteTxt, {
+ alpha: 0
+ }, {
+ duration: 2000,
+ onFinish: function onFinish() {
+ levelCompleteTxt.destroy();
+ // Start next level
+ initializeGame();
+ }
+ });
+}
+function checkCollisions() {
+ // Player bullets vs enemies
+ for (var i = bullets.length - 1; i >= 0; i--) {
+ var bullet = bullets[i];
+ for (var j = enemies.length - 1; j >= 0; j--) {
+ var enemy = enemies[j];
+ if (bullet.intersects(enemy)) {
+ // Handle hit
+ enemy.takeDamage();
+ // Remove bullet
+ bullet.destroy();
+ bullets.splice(i, 1);
+ break;
+ }
+ }
+ }
+ // Enemy bullets vs player
+ for (var i = enemyBullets.length - 1; i >= 0; i--) {
+ var bullet = enemyBullets[i];
+ // Check for shield hits first
+ var hitShield = false;
+ for (var j = shields.length - 1; j >= 0; j--) {
+ var shield = shields[j];
+ if (bullet.intersects(shield)) {
+ shield.takeDamage();
+ // Remove bullet
+ bullet.destroy();
+ enemyBullets.splice(i, 1);
+ hitShield = true;
+ break;
+ }
+ }
+ if (hitShield) {
+ continue;
+ }
+ // Check for player hit
+ if (bullet.intersects(player)) {
+ player.hit();
+ // Remove bullet
+ bullet.destroy();
+ enemyBullets.splice(i, 1);
+ }
+ }
+ // Player vs power-ups
+ for (var i = powerUps.length - 1; i >= 0; i--) {
+ var powerUp = powerUps[i];
+ if (powerUp.intersects(player)) {
+ player.activatePowerUp(powerUp.type);
+ // Remove power-up
+ powerUp.destroy();
+ powerUps.splice(i, 1);
+ }
+ }
+ // Update lives display
+ livesTxt.setText('LIVES: ' + player.lives);
+}
+function movePlayer() {
+ // If touch input is active, move towards it
+ if (touchX !== null) {
+ var moveSpeed = player.speed;
+ var distanceToTouch = touchX - player.x;
+ if (Math.abs(distanceToTouch) < moveSpeed) {
+ player.x = touchX;
+ } else if (distanceToTouch > 0) {
+ player.x += moveSpeed;
+ } else {
+ player.x -= moveSpeed;
+ }
+ }
+ // Keep player within screen bounds
+ if (player.x < GAME_MARGIN + player.width / 2) {
+ player.x = GAME_MARGIN + player.width / 2;
+ } else if (player.x > GAME_WIDTH - GAME_MARGIN - player.width / 2) {
+ player.x = GAME_WIDTH - GAME_MARGIN - player.width / 2;
+ }
+}
+// Handle touch/mouse input
+game.down = function (x, y, obj) {
+ touchX = x;
+ // Shoot when tapping
+ player.shoot();
+};
+game.move = function (x, y, obj) {
+ touchX = x;
+};
+game.up = function (x, y, obj) {
+ touchX = null;
+};
+// Game update loop
+game.update = function () {
+ movePlayer();
+ // Update all game objects
+ for (var i = 0; i < bullets.length; i++) {
+ bullets[i].update();
+ }
+ for (var i = 0; i < enemyBullets.length; i++) {
+ enemyBullets[i].update();
+ }
+ for (var i = 0; i < powerUps.length; i++) {
+ powerUps[i].update();
+ }
+ // Check for collisions
+ checkCollisions();
+};
+// Initialize the game
+initializeGame();
\ No newline at end of file