User prompt
make 5 lives for you spaceship person
User prompt
make so not just all enemies are bombing and center everything
User prompt
generate a game sound and make the enemies are different colors of blue, red, green, and yellow and home screen for adjusting the Game Settings by the player speed-adjusts the speed of 1x to 12x by shooting, and the enemies-adjusts the bombing rate and speed of 1x to 12x ↪💡 Consider importing and using the following plugins: @upit/storage.v1
Code edit (1 edits merged)
Please save this source code
User prompt
SPACE GALAGA
Initial prompt
Generate a game called SPACE GALAGA a game of Galaga
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { playerSpeed: 1, enemySpeed: 1 }); /**** * Classes ****/ var Enemy = Container.expand(function (enemyType) { var self = Container.call(this); self.enemyType = enemyType || 'enemy'; var assetName = self.enemyType; var graphics = self.attachAsset(assetName, { anchorX: 0.5, anchorY: 0.5 }); self.formationX = 0; self.formationY = 0; self.isDiving = false; self.diveSpeed = 4 * (storage.enemySpeed || 1); self.moveSpeed = 2 * (storage.enemySpeed || 1); self.shootTimer = 0; self.shootDelay = Math.random() * 120 + 60; // Only some enemies can shoot (30% chance) self.canShoot = Math.random() < 0.3; self.update = function () { if (self.isDiving) { self.y += self.diveSpeed; self.x += Math.sin(self.y * 0.02) * 3; } else { // Formation movement var targetX = self.formationX + Math.sin(LK.ticks * 0.02) * 50; var targetY = self.formationY + Math.sin(LK.ticks * 0.01) * 20; self.x += (targetX - self.x) * 0.1; self.y += (targetY - self.y) * 0.1; } // Shooting logic - only if this enemy can shoot if (self.canShoot) { self.shootTimer++; if (self.shootTimer >= self.shootDelay) { self.shootTimer = 0; self.shootDelay = (Math.random() * 180 + 90) / (storage.enemySpeed || 1); var bullet = new EnemyBullet(); bullet.x = self.x; bullet.y = self.y + 30; bullet.lastY = bullet.y; enemyBullets.push(bullet); game.addChild(bullet); } } // Random dive attack if (!self.isDiving && Math.random() < 0.001) { self.isDiving = true; if (self.canShoot) { self.shootDelay = 30; // Shoot more frequently when diving } } }; return self; }); var EnemyBullet = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.update = function () { self.y += self.speed; }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('playerShip', { anchorX: 0.5, anchorY: 0.5 }); self.shootTimer = 0; self.shootDelay = Math.max(1, Math.floor(15 / (storage.playerSpeed || 1))); self.isDead = false; self.update = function () { if (self.isDead) return; self.shootTimer++; if (self.shootTimer >= self.shootDelay && isShooting) { self.shootTimer = 0; var bullet = new PlayerBullet(); bullet.x = self.x; bullet.y = self.y - 30; bullet.lastY = bullet.y; playerBullets.push(bullet); game.addChild(bullet); LK.getSound('shoot').play(); } }; return self; }); var PlayerBullet = Container.expand(function () { var self = Container.call(this); var graphics = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -12; self.update = function () { self.y += self.speed; }; return self; }); var SettingsMenu = Container.expand(function () { var self = Container.call(this); // Background var bg = LK.getAsset('enemy', { anchorX: 0.5, anchorY: 0.5, scaleX: 20, scaleY: 30 }); bg.alpha = 0.8; self.addChild(bg); // Title var titleTxt = new Text2('GAME SETTINGS', { size: 100, fill: 0xFFFFFF }); titleTxt.anchor.set(0.5, 0.5); titleTxt.y = -400; self.addChild(titleTxt); // Player Speed Controls var playerSpeedTxt = new Text2('PLAYER SPEED: ' + (storage.playerSpeed || 1) + 'x', { size: 60, fill: 0x00FFFF }); playerSpeedTxt.anchor.set(0.5, 0.5); playerSpeedTxt.y = -200; self.addChild(playerSpeedTxt); var playerMinusBtn = self.addChild(LK.getAsset('speedButton', { anchorX: 0.5, anchorY: 0.5 })); playerMinusBtn.x = -150; playerMinusBtn.y = -100; var playerMinusTxt = new Text2('-', { size: 60, fill: 0xFFFFFF }); playerMinusTxt.anchor.set(0.5, 0.5); playerMinusBtn.addChild(playerMinusTxt); var playerPlusBtn = self.addChild(LK.getAsset('speedButton', { anchorX: 0.5, anchorY: 0.5 })); playerPlusBtn.x = 150; playerPlusBtn.y = -100; var playerPlusTxt = new Text2('+', { size: 60, fill: 0xFFFFFF }); playerPlusTxt.anchor.set(0.5, 0.5); playerPlusBtn.addChild(playerPlusTxt); // Enemy Speed Controls var enemySpeedTxt = new Text2('ENEMY SPEED: ' + (storage.enemySpeed || 1) + 'x', { size: 60, fill: 0xFF4444 }); enemySpeedTxt.anchor.set(0.5, 0.5); enemySpeedTxt.y = 100; self.addChild(enemySpeedTxt); var enemyMinusBtn = self.addChild(LK.getAsset('speedButton', { anchorX: 0.5, anchorY: 0.5 })); enemyMinusBtn.x = -150; enemyMinusBtn.y = 200; var enemyMinusTxt = new Text2('-', { size: 60, fill: 0xFFFFFF }); enemyMinusTxt.anchor.set(0.5, 0.5); enemyMinusBtn.addChild(enemyMinusTxt); var enemyPlusBtn = self.addChild(LK.getAsset('speedButton', { anchorX: 0.5, anchorY: 0.5 })); enemyPlusBtn.x = 150; enemyPlusBtn.y = 200; var enemyPlusTxt = new Text2('+', { size: 60, fill: 0xFFFFFF }); enemyPlusTxt.anchor.set(0.5, 0.5); enemyPlusBtn.addChild(enemyPlusTxt); // Close Button var closeBtn = self.addChild(LK.getAsset('speedButton', { anchorX: 0.5, anchorY: 0.5 })); closeBtn.x = 0; closeBtn.y = 350; var closeTxt = new Text2('CLOSE', { size: 50, fill: 0xFFFFFF }); closeTxt.anchor.set(0.5, 0.5); closeBtn.addChild(closeTxt); // Button handlers playerMinusBtn.down = function () { LK.getSound('buttonClick').play(); storage.playerSpeed = Math.max(1, (storage.playerSpeed || 1) - 1); playerSpeedTxt.setText('PLAYER SPEED: ' + storage.playerSpeed + 'x'); }; playerPlusBtn.down = function () { LK.getSound('buttonClick').play(); storage.playerSpeed = Math.min(12, (storage.playerSpeed || 1) + 1); playerSpeedTxt.setText('PLAYER SPEED: ' + storage.playerSpeed + 'x'); }; enemyMinusBtn.down = function () { LK.getSound('buttonClick').play(); storage.enemySpeed = Math.max(1, (storage.enemySpeed || 1) - 1); enemySpeedTxt.setText('ENEMY SPEED: ' + storage.enemySpeed + 'x'); }; enemyPlusBtn.down = function () { LK.getSound('buttonClick').play(); storage.enemySpeed = Math.min(12, (storage.enemySpeed || 1) + 1); enemySpeedTxt.setText('ENEMY SPEED: ' + storage.enemySpeed + 'x'); }; closeBtn.down = function () { LK.getSound('buttonClick').play(); settingsMenu.visible = false; gameIsPaused = false; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000011 }); /**** * Game Code ****/ var player; var enemies = []; var playerBullets = []; var enemyBullets = []; var dragNode = null; var isShooting = false; var waveTimer = 0; var waveDelay = 300; var currentWave = 1; var gameSpeed = 1; var settingsMenu = null; var gameIsPaused = false; var settingsButton = null; var playerLives = 5; function resetPlayer() { if (player) { player.destroy(); } player = new Player(); player.x = 2048 / 2; player.y = 2500; player.isDead = false; player.alpha = 1; game.addChild(player); dragNode = null; isShooting = false; } // Create score display var scoreTxt = new Text2('0', { size: 80, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Create wave indicator var waveTxt = new Text2('WAVE 1', { size: 60, fill: 0x00FFFF }); waveTxt.anchor.set(0, 0); waveTxt.x = 50; waveTxt.y = 50; LK.gui.topLeft.addChild(waveTxt); // Create lives display var livesTxt = new Text2('LIVES: 5', { size: 60, fill: 0x00FF00 }); livesTxt.anchor.set(1, 0); livesTxt.x = 1950; livesTxt.y = 50; LK.gui.topRight.addChild(livesTxt); // Create settings button (avoiding top-left 100x100 area) settingsButton = LK.getAsset('settingsButton', { anchorX: 0.5, anchorY: 0.5 }); settingsButton.x = 1900; settingsButton.y = 150; var settingsTxt = new Text2('SET', { size: 30, fill: 0xFFFFFF }); settingsTxt.anchor.set(0.5, 0.5); settingsButton.addChild(settingsTxt); LK.gui.topRight.addChild(settingsButton); settingsButton.down = function () { LK.getSound('settingsOpen').play(); if (!settingsMenu) { settingsMenu = new SettingsMenu(); settingsMenu.x = 1024; settingsMenu.y = 1366; game.addChild(settingsMenu); } settingsMenu.visible = true; gameIsPaused = true; }; // Initialize settings menu but keep it hidden settingsMenu = new SettingsMenu(); settingsMenu.x = 2048 / 2; settingsMenu.y = 2732 / 2; settingsMenu.visible = false; game.addChild(settingsMenu); // Initialize player player = new Player(); player.x = 2048 / 2; player.y = 2500; game.addChild(player); function spawnEnemyWave() { var enemiesPerRow = 8; var rows = 4; var spacingX = 200; var spacingY = 120; var totalWidth = (enemiesPerRow - 1) * spacingX; var totalHeight = (rows - 1) * spacingY; var startX = (2048 - totalWidth) / 2; var startY = 200; var enemyTypes = ['enemy', 'enemyBlue', 'enemyGreen', 'enemyYellow']; for (var row = 0; row < rows; row++) { for (var col = 0; col < enemiesPerRow; col++) { var enemyType = enemyTypes[row % enemyTypes.length]; var enemy = new Enemy(enemyType); enemy.x = startX + col * spacingX; enemy.y = startY + row * spacingY; enemy.formationX = enemy.x; enemy.formationY = enemy.y; enemies.push(enemy); game.addChild(enemy); } } } function handleMove(x, y, obj) { if (dragNode && !player.isDead) { dragNode.x = Math.max(40, Math.min(2008, x)); } } game.move = handleMove; game.down = function (x, y, obj) { if (!player.isDead) { dragNode = player; isShooting = true; handleMove(x, y, obj); } }; game.up = function (x, y, obj) { dragNode = null; isShooting = false; }; // Spawn initial wave spawnEnemyWave(); game.update = function () { if (player.isDead || gameIsPaused) return; // Update wave timer waveTimer++; // Check if all enemies are destroyed if (enemies.length === 0) { if (waveTimer >= waveDelay) { currentWave++; gameSpeed += 0.2; waveTimer = 0; waveTxt.setText('WAVE ' + currentWave); spawnEnemyWave(); } } // Handle player bullets for (var i = playerBullets.length - 1; i >= 0; i--) { var bullet = playerBullets[i]; if (bullet.lastY === undefined) bullet.lastY = bullet.y; // Remove bullets that go off screen if (bullet.lastY >= -30 && bullet.y < -30) { bullet.destroy(); playerBullets.splice(i, 1); continue; } // Check collision with enemies var hitEnemy = false; for (var j = enemies.length - 1; j >= 0; j--) { var enemy = enemies[j]; if (bullet.intersects(enemy)) { // Award more points for diving enemies var points = enemy.isDiving ? 200 : 100; LK.setScore(LK.getScore() + points); scoreTxt.setText(LK.getScore()); LK.getSound('enemyHit').play(); LK.effects.flashObject(enemy, 0xffffff, 200); enemy.destroy(); enemies.splice(j, 1); bullet.destroy(); playerBullets.splice(i, 1); hitEnemy = true; break; } } if (!hitEnemy) { bullet.lastY = bullet.y; } } // Handle enemy bullets for (var i = enemyBullets.length - 1; i >= 0; i--) { var bullet = enemyBullets[i]; if (bullet.lastY === undefined) bullet.lastY = bullet.y; // Remove bullets that go off screen if (bullet.lastY <= 2762 && bullet.y > 2762) { bullet.destroy(); enemyBullets.splice(i, 1); continue; } // Check collision with player if (bullet.intersects(player) && !player.isDead) { playerLives--; livesTxt.setText('LIVES: ' + playerLives); LK.getSound('playerHit').play(); LK.effects.flashScreen(0xff0000, 500); if (playerLives <= 0) { player.isDead = true; tween(player, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { LK.showGameOver(); } }); } else { // Player still has lives, flash and reset position tween(player, { alpha: 0.3 }, { duration: 200, onFinish: function onFinish() { tween(player, { alpha: 1 }, { duration: 200 }); } }); // Temporarily make player invulnerable player.isDead = true; LK.setTimeout(function () { player.isDead = false; }, 1000); } bullet.destroy(); enemyBullets.splice(i, 1); continue; } bullet.lastY = bullet.y; } // Remove enemies that fly off screen during dive attacks for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.isDiving && enemy.y > 2800) { enemy.destroy(); enemies.splice(i, 1); } } // Check if player collides with any enemy if (!player.isDead) { for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (player.intersects(enemy)) { playerLives--; livesTxt.setText('LIVES: ' + playerLives); LK.getSound('playerHit').play(); LK.effects.flashScreen(0xff0000, 500); // Destroy the enemy that hit the player enemy.destroy(); enemies.splice(i, 1); if (playerLives <= 0) { player.isDead = true; tween(player, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { LK.showGameOver(); } }); } else { // Player still has lives, flash and reset position tween(player, { alpha: 0.3 }, { duration: 200, onFinish: function onFinish() { tween(player, { alpha: 1 }, { duration: 200 }); } }); // Temporarily make player invulnerable player.isDead = true; LK.setTimeout(function () { player.isDead = false; }, 1000); } break; } } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
playerSpeed: 1,
enemySpeed: 1
});
/****
* Classes
****/
var Enemy = Container.expand(function (enemyType) {
var self = Container.call(this);
self.enemyType = enemyType || 'enemy';
var assetName = self.enemyType;
var graphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.formationX = 0;
self.formationY = 0;
self.isDiving = false;
self.diveSpeed = 4 * (storage.enemySpeed || 1);
self.moveSpeed = 2 * (storage.enemySpeed || 1);
self.shootTimer = 0;
self.shootDelay = Math.random() * 120 + 60;
// Only some enemies can shoot (30% chance)
self.canShoot = Math.random() < 0.3;
self.update = function () {
if (self.isDiving) {
self.y += self.diveSpeed;
self.x += Math.sin(self.y * 0.02) * 3;
} else {
// Formation movement
var targetX = self.formationX + Math.sin(LK.ticks * 0.02) * 50;
var targetY = self.formationY + Math.sin(LK.ticks * 0.01) * 20;
self.x += (targetX - self.x) * 0.1;
self.y += (targetY - self.y) * 0.1;
}
// Shooting logic - only if this enemy can shoot
if (self.canShoot) {
self.shootTimer++;
if (self.shootTimer >= self.shootDelay) {
self.shootTimer = 0;
self.shootDelay = (Math.random() * 180 + 90) / (storage.enemySpeed || 1);
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 30;
bullet.lastY = bullet.y;
enemyBullets.push(bullet);
game.addChild(bullet);
}
}
// Random dive attack
if (!self.isDiving && Math.random() < 0.001) {
self.isDiving = true;
if (self.canShoot) {
self.shootDelay = 30; // Shoot more frequently when diving
}
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.shootTimer = 0;
self.shootDelay = Math.max(1, Math.floor(15 / (storage.playerSpeed || 1)));
self.isDead = false;
self.update = function () {
if (self.isDead) return;
self.shootTimer++;
if (self.shootTimer >= self.shootDelay && isShooting) {
self.shootTimer = 0;
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - 30;
bullet.lastY = bullet.y;
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
}
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -12;
self.update = function () {
self.y += self.speed;
};
return self;
});
var SettingsMenu = Container.expand(function () {
var self = Container.call(this);
// Background
var bg = LK.getAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 20,
scaleY: 30
});
bg.alpha = 0.8;
self.addChild(bg);
// Title
var titleTxt = new Text2('GAME SETTINGS', {
size: 100,
fill: 0xFFFFFF
});
titleTxt.anchor.set(0.5, 0.5);
titleTxt.y = -400;
self.addChild(titleTxt);
// Player Speed Controls
var playerSpeedTxt = new Text2('PLAYER SPEED: ' + (storage.playerSpeed || 1) + 'x', {
size: 60,
fill: 0x00FFFF
});
playerSpeedTxt.anchor.set(0.5, 0.5);
playerSpeedTxt.y = -200;
self.addChild(playerSpeedTxt);
var playerMinusBtn = self.addChild(LK.getAsset('speedButton', {
anchorX: 0.5,
anchorY: 0.5
}));
playerMinusBtn.x = -150;
playerMinusBtn.y = -100;
var playerMinusTxt = new Text2('-', {
size: 60,
fill: 0xFFFFFF
});
playerMinusTxt.anchor.set(0.5, 0.5);
playerMinusBtn.addChild(playerMinusTxt);
var playerPlusBtn = self.addChild(LK.getAsset('speedButton', {
anchorX: 0.5,
anchorY: 0.5
}));
playerPlusBtn.x = 150;
playerPlusBtn.y = -100;
var playerPlusTxt = new Text2('+', {
size: 60,
fill: 0xFFFFFF
});
playerPlusTxt.anchor.set(0.5, 0.5);
playerPlusBtn.addChild(playerPlusTxt);
// Enemy Speed Controls
var enemySpeedTxt = new Text2('ENEMY SPEED: ' + (storage.enemySpeed || 1) + 'x', {
size: 60,
fill: 0xFF4444
});
enemySpeedTxt.anchor.set(0.5, 0.5);
enemySpeedTxt.y = 100;
self.addChild(enemySpeedTxt);
var enemyMinusBtn = self.addChild(LK.getAsset('speedButton', {
anchorX: 0.5,
anchorY: 0.5
}));
enemyMinusBtn.x = -150;
enemyMinusBtn.y = 200;
var enemyMinusTxt = new Text2('-', {
size: 60,
fill: 0xFFFFFF
});
enemyMinusTxt.anchor.set(0.5, 0.5);
enemyMinusBtn.addChild(enemyMinusTxt);
var enemyPlusBtn = self.addChild(LK.getAsset('speedButton', {
anchorX: 0.5,
anchorY: 0.5
}));
enemyPlusBtn.x = 150;
enemyPlusBtn.y = 200;
var enemyPlusTxt = new Text2('+', {
size: 60,
fill: 0xFFFFFF
});
enemyPlusTxt.anchor.set(0.5, 0.5);
enemyPlusBtn.addChild(enemyPlusTxt);
// Close Button
var closeBtn = self.addChild(LK.getAsset('speedButton', {
anchorX: 0.5,
anchorY: 0.5
}));
closeBtn.x = 0;
closeBtn.y = 350;
var closeTxt = new Text2('CLOSE', {
size: 50,
fill: 0xFFFFFF
});
closeTxt.anchor.set(0.5, 0.5);
closeBtn.addChild(closeTxt);
// Button handlers
playerMinusBtn.down = function () {
LK.getSound('buttonClick').play();
storage.playerSpeed = Math.max(1, (storage.playerSpeed || 1) - 1);
playerSpeedTxt.setText('PLAYER SPEED: ' + storage.playerSpeed + 'x');
};
playerPlusBtn.down = function () {
LK.getSound('buttonClick').play();
storage.playerSpeed = Math.min(12, (storage.playerSpeed || 1) + 1);
playerSpeedTxt.setText('PLAYER SPEED: ' + storage.playerSpeed + 'x');
};
enemyMinusBtn.down = function () {
LK.getSound('buttonClick').play();
storage.enemySpeed = Math.max(1, (storage.enemySpeed || 1) - 1);
enemySpeedTxt.setText('ENEMY SPEED: ' + storage.enemySpeed + 'x');
};
enemyPlusBtn.down = function () {
LK.getSound('buttonClick').play();
storage.enemySpeed = Math.min(12, (storage.enemySpeed || 1) + 1);
enemySpeedTxt.setText('ENEMY SPEED: ' + storage.enemySpeed + 'x');
};
closeBtn.down = function () {
LK.getSound('buttonClick').play();
settingsMenu.visible = false;
gameIsPaused = false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000011
});
/****
* Game Code
****/
var player;
var enemies = [];
var playerBullets = [];
var enemyBullets = [];
var dragNode = null;
var isShooting = false;
var waveTimer = 0;
var waveDelay = 300;
var currentWave = 1;
var gameSpeed = 1;
var settingsMenu = null;
var gameIsPaused = false;
var settingsButton = null;
var playerLives = 5;
function resetPlayer() {
if (player) {
player.destroy();
}
player = new Player();
player.x = 2048 / 2;
player.y = 2500;
player.isDead = false;
player.alpha = 1;
game.addChild(player);
dragNode = null;
isShooting = false;
}
// Create score display
var scoreTxt = new Text2('0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Create wave indicator
var waveTxt = new Text2('WAVE 1', {
size: 60,
fill: 0x00FFFF
});
waveTxt.anchor.set(0, 0);
waveTxt.x = 50;
waveTxt.y = 50;
LK.gui.topLeft.addChild(waveTxt);
// Create lives display
var livesTxt = new Text2('LIVES: 5', {
size: 60,
fill: 0x00FF00
});
livesTxt.anchor.set(1, 0);
livesTxt.x = 1950;
livesTxt.y = 50;
LK.gui.topRight.addChild(livesTxt);
// Create settings button (avoiding top-left 100x100 area)
settingsButton = LK.getAsset('settingsButton', {
anchorX: 0.5,
anchorY: 0.5
});
settingsButton.x = 1900;
settingsButton.y = 150;
var settingsTxt = new Text2('SET', {
size: 30,
fill: 0xFFFFFF
});
settingsTxt.anchor.set(0.5, 0.5);
settingsButton.addChild(settingsTxt);
LK.gui.topRight.addChild(settingsButton);
settingsButton.down = function () {
LK.getSound('settingsOpen').play();
if (!settingsMenu) {
settingsMenu = new SettingsMenu();
settingsMenu.x = 1024;
settingsMenu.y = 1366;
game.addChild(settingsMenu);
}
settingsMenu.visible = true;
gameIsPaused = true;
};
// Initialize settings menu but keep it hidden
settingsMenu = new SettingsMenu();
settingsMenu.x = 2048 / 2;
settingsMenu.y = 2732 / 2;
settingsMenu.visible = false;
game.addChild(settingsMenu);
// Initialize player
player = new Player();
player.x = 2048 / 2;
player.y = 2500;
game.addChild(player);
function spawnEnemyWave() {
var enemiesPerRow = 8;
var rows = 4;
var spacingX = 200;
var spacingY = 120;
var totalWidth = (enemiesPerRow - 1) * spacingX;
var totalHeight = (rows - 1) * spacingY;
var startX = (2048 - totalWidth) / 2;
var startY = 200;
var enemyTypes = ['enemy', 'enemyBlue', 'enemyGreen', 'enemyYellow'];
for (var row = 0; row < rows; row++) {
for (var col = 0; col < enemiesPerRow; col++) {
var enemyType = enemyTypes[row % enemyTypes.length];
var enemy = new Enemy(enemyType);
enemy.x = startX + col * spacingX;
enemy.y = startY + row * spacingY;
enemy.formationX = enemy.x;
enemy.formationY = enemy.y;
enemies.push(enemy);
game.addChild(enemy);
}
}
}
function handleMove(x, y, obj) {
if (dragNode && !player.isDead) {
dragNode.x = Math.max(40, Math.min(2008, x));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
if (!player.isDead) {
dragNode = player;
isShooting = true;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
dragNode = null;
isShooting = false;
};
// Spawn initial wave
spawnEnemyWave();
game.update = function () {
if (player.isDead || gameIsPaused) return;
// Update wave timer
waveTimer++;
// Check if all enemies are destroyed
if (enemies.length === 0) {
if (waveTimer >= waveDelay) {
currentWave++;
gameSpeed += 0.2;
waveTimer = 0;
waveTxt.setText('WAVE ' + currentWave);
spawnEnemyWave();
}
}
// Handle player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
// Remove bullets that go off screen
if (bullet.lastY >= -30 && bullet.y < -30) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with enemies
var hitEnemy = false;
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
// Award more points for diving enemies
var points = enemy.isDiving ? 200 : 100;
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore());
LK.getSound('enemyHit').play();
LK.effects.flashObject(enemy, 0xffffff, 200);
enemy.destroy();
enemies.splice(j, 1);
bullet.destroy();
playerBullets.splice(i, 1);
hitEnemy = true;
break;
}
}
if (!hitEnemy) {
bullet.lastY = bullet.y;
}
}
// Handle enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
// Remove bullets that go off screen
if (bullet.lastY <= 2762 && bullet.y > 2762) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (bullet.intersects(player) && !player.isDead) {
playerLives--;
livesTxt.setText('LIVES: ' + playerLives);
LK.getSound('playerHit').play();
LK.effects.flashScreen(0xff0000, 500);
if (playerLives <= 0) {
player.isDead = true;
tween(player, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
LK.showGameOver();
}
});
} else {
// Player still has lives, flash and reset position
tween(player, {
alpha: 0.3
}, {
duration: 200,
onFinish: function onFinish() {
tween(player, {
alpha: 1
}, {
duration: 200
});
}
});
// Temporarily make player invulnerable
player.isDead = true;
LK.setTimeout(function () {
player.isDead = false;
}, 1000);
}
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
bullet.lastY = bullet.y;
}
// Remove enemies that fly off screen during dive attacks
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy.isDiving && enemy.y > 2800) {
enemy.destroy();
enemies.splice(i, 1);
}
}
// Check if player collides with any enemy
if (!player.isDead) {
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
if (player.intersects(enemy)) {
playerLives--;
livesTxt.setText('LIVES: ' + playerLives);
LK.getSound('playerHit').play();
LK.effects.flashScreen(0xff0000, 500);
// Destroy the enemy that hit the player
enemy.destroy();
enemies.splice(i, 1);
if (playerLives <= 0) {
player.isDead = true;
tween(player, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
LK.showGameOver();
}
});
} else {
// Player still has lives, flash and reset position
tween(player, {
alpha: 0.3
}, {
duration: 200,
onFinish: function onFinish() {
tween(player, {
alpha: 1
}, {
duration: 200
});
}
});
// Temporarily make player invulnerable
player.isDead = true;
LK.setTimeout(function () {
player.isDead = false;
}, 1000);
}
break;
}
}
}
};