User prompt
Play space song 1 repeatedly throughout the game
User prompt
make enemy harder
User prompt
delete power ups
User prompt
Start the game with 3 lives
User prompt
make the game infinite and add life mechanics
Code edit (1 edits merged)
Please save this source code
User prompt
Space Defenders
Initial prompt
make game like space invaders
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ // Alien var Alien = Container.expand(function () { var self = Container.call(this); var alien = self.attachAsset('alien', { anchorX: 0.5, anchorY: 0.5 }); self.width = alien.width; self.height = alien.height; self.row = 0; self.col = 0; self.alive = true; self.shootCooldown = 0; self.update = function () { // No per-alien update needed; movement handled by global logic }; self.shoot = function () { var bullet = new AlienBullet(); bullet.x = self.x; bullet.y = self.y + self.height / 2 + bullet.height / 2; alienBullets.push(bullet); game.addChild(bullet); LK.getSound('alienShoot').play(); }; self.hit = function () { self.alive = false; LK.getSound('explosion').play(); LK.effects.flashObject(self, 0xffffff, 200); self.visible = false; }; return self; }); // Alien Bullet var AlienBullet = Container.expand(function () { var self = Container.call(this); var bullet = self.attachAsset('alienBullet', { anchorX: 0.5, anchorY: 0.5 }); self.width = bullet.width; self.height = bullet.height; self.speed = 18; self.update = function () { self.y += self.speed; }; return self; }); // Player Bullet var PlayerBullet = Container.expand(function () { var self = Container.call(this); var bullet = self.attachAsset('playerBullet', { anchorX: 0.5, anchorY: 0.5 }); self.width = bullet.width; self.height = bullet.height; self.speed = -32; self.update = function () { self.y += self.speed; }; return self; }); // Player Ship var PlayerShip = Container.expand(function () { var self = Container.call(this); var ship = self.attachAsset('playerShip', { anchorX: 0.5, anchorY: 0.5 }); self.width = ship.width; self.height = ship.height; self.canShoot = true; self.shootCooldown = 18; // frames between shots self.cooldownTimer = 0; self.lives = 1; self.invincible = false; self.invincibleTimer = 0; self.update = function () { if (self.cooldownTimer > 0) self.cooldownTimer--; if (self.invincible) { self.invincibleTimer--; if (self.invincibleTimer <= 0) { self.invincible = false; ship.alpha = 1; } else { ship.alpha = LK.ticks % 10 < 5 ? 0.4 : 1; } } }; self.shoot = function () { if (self.cooldownTimer === 0 && self.visible) { self.cooldownTimer = self.shootCooldown; var bullet = new PlayerBullet(); bullet.x = self.x; bullet.y = self.y - self.height / 2 - bullet.height / 2; playerBullets.push(bullet); game.addChild(bullet); LK.getSound('shoot').play(); } }; self.hit = function () { if (self.invincible) return; self.lives--; if (self.lives <= 0) { LK.effects.flashScreen(0xff0000, 800); LK.getSound('explosion').play(); LK.showGameOver(); } else { self.invincible = true; self.invincibleTimer = 90; } }; self.applyPowerup = function () { self.shootCooldown = 8; LK.getSound('powerup').play(); LK.effects.flashObject(self, 0xaa66ff, 600); LK.setTimeout(function () { self.shootCooldown = 18; }, 4000); }; return self; }); // Powerup var Powerup = Container.expand(function () { var self = Container.call(this); var p = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.width = p.width; self.height = p.height; self.speed = 10; self.update = function () { self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Music // Sound effects // Powerup: purple ellipse // Alien bullet: red ellipse // Alien: green box // Player bullet: yellow ellipse // Player ship: blue box // Play music LK.playMusic('spaceMusic'); // Score var score = 0; var scoreTxt = new Text2('0', { size: 120, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Player var player = new PlayerShip(); player.x = 2048 / 2; player.y = 2732 - 180; game.addChild(player); // Bullets and objects var playerBullets = []; var alienBullets = []; var aliens = []; var powerups = []; // Alien grid var alienRows = 5; var alienCols = 8; var alienSpacingX = 180; var alienSpacingY = 120; var alienStartX = (2048 - (alienCols - 1) * alienSpacingX) / 2; var alienStartY = 320; var alienDir = 1; // 1: right, -1: left var alienSpeed = 12; // px per move var alienMoveDown = 60; // px to move down when hitting edge var alienMoveTimer = 0; var alienMoveInterval = 32; // frames between moves, decreases as aliens die var alienShootChance = 0.012; // chance per alien per move to shoot function spawnAliens() { aliens.length = 0; for (var row = 0; row < alienRows; row++) { for (var col = 0; col < alienCols; col++) { var a = new Alien(); a.row = row; a.col = col; a.x = alienStartX + col * alienSpacingX; a.y = alienStartY + row * alienSpacingY; aliens.push(a); game.addChild(a); } } } spawnAliens(); // Powerup spawn var powerupTimer = 0; var powerupInterval = 600; // frames // Dragging var dragging = false; var dragOffsetX = 0; // Move handler function handleMove(x, y, obj) { if (dragging) { var newX = x - dragOffsetX; // Clamp to screen var minX = player.width / 2 + 20; var maxX = 2048 - player.width / 2 - 20; player.x = Math.max(minX, Math.min(maxX, newX)); } } game.move = handleMove; game.down = function (x, y, obj) { // Only drag if touch is on player var local = player.toLocal(game.toGlobal({ x: x, y: y })); if (local.x > -player.width / 2 && local.x < player.width / 2 && local.y > -player.height / 2 && local.y < player.height / 2) { dragging = true; dragOffsetX = x - player.x; } }; game.up = function (x, y, obj) { dragging = false; }; // Tap to shoot game.tap = function (x, y, obj) { player.shoot(); }; // For mobile: allow tap anywhere to shoot game.down = function (x, y, obj) { // Drag if on player, else shoot var local = player.toLocal(game.toGlobal({ x: x, y: y })); if (local.x > -player.width / 2 && local.x < player.width / 2 && local.y > -player.height / 2 && local.y < player.height / 2) { dragging = true; dragOffsetX = x - player.x; } else { player.shoot(); } }; // Main update loop game.update = function () { // Player update player.update(); // Player bullets for (var i = playerBullets.length - 1; i >= 0; i--) { var b = playerBullets[i]; b.update(); if (b.y < -b.height) { b.destroy(); playerBullets.splice(i, 1); continue; } // Collide with aliens for (var j = 0; j < aliens.length; j++) { var a = aliens[j]; if (a.alive && b.intersects(a)) { a.hit(); b.destroy(); playerBullets.splice(i, 1); score += 100; scoreTxt.setText(score); break; } } } // Alien bullets for (var i = alienBullets.length - 1; i >= 0; i--) { var b = alienBullets[i]; b.update(); if (b.y > 2732 + b.height) { b.destroy(); alienBullets.splice(i, 1); continue; } // Collide with player if (b.intersects(player) && !player.invincible) { b.destroy(); alienBullets.splice(i, 1); player.hit(); break; } } // Powerups for (var i = powerups.length - 1; i >= 0; i--) { var p = powerups[i]; p.update(); if (p.y > 2732 + p.height) { p.destroy(); powerups.splice(i, 1); continue; } if (p.intersects(player)) { p.destroy(); powerups.splice(i, 1); player.applyPowerup(); break; } } // Aliens movement alienMoveTimer++; if (alienMoveTimer >= alienMoveInterval) { alienMoveTimer = 0; var minX = 99999, maxX = -99999; var minY = 99999, maxY = -99999; for (var i = 0; i < aliens.length; i++) { var a = aliens[i]; if (!a.alive) continue; minX = Math.min(minX, a.x - a.width / 2); maxX = Math.max(maxX, a.x + a.width / 2); minY = Math.min(minY, a.y - a.height / 2); maxY = Math.max(maxY, a.y + a.height / 2); } var edgeHit = false; if (alienDir === 1 && maxX + alienSpeed > 2048 - 40) edgeHit = true; if (alienDir === -1 && minX - alienSpeed < 40) edgeHit = true; if (edgeHit) { alienDir *= -1; for (var i = 0; i < aliens.length; i++) { var a = aliens[i]; if (a.alive) a.y += alienMoveDown; } } else { for (var i = 0; i < aliens.length; i++) { var a = aliens[i]; if (a.alive) a.x += alienDir * alienSpeed; } } // Aliens shoot for (var i = 0; i < aliens.length; i++) { var a = aliens[i]; if (!a.alive) continue; // Only bottom-most alien in column can shoot var isLowest = true; for (var j = 0; j < aliens.length; j++) { var b = aliens[j]; if (b.col === a.col && b.row > a.row && b.alive) { isLowest = false; break; } } if (isLowest && Math.random() < alienShootChance) { a.shoot(); } } // Check for aliens reaching bottom for (var i = 0; i < aliens.length; i++) { var a = aliens[i]; if (a.alive && a.y + a.height / 2 >= player.y - player.height / 2) { LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); return; } } // Speed up as aliens die var aliveCount = 0; for (var i = 0; i < aliens.length; i++) if (aliens[i].alive) aliveCount++; alienMoveInterval = Math.max(8, 32 - Math.floor((40 - aliveCount) / 2)); } // Win condition var allDead = true; for (var i = 0; i < aliens.length; i++) if (aliens[i].alive) allDead = false; if (allDead) { LK.effects.flashScreen(0x00ff00, 800); LK.setScore(score); LK.showYouWin(); return; } // Powerup spawn powerupTimer++; if (powerupTimer > powerupInterval) { powerupTimer = 0; var p = new Powerup(); p.x = 200 + Math.random() * (2048 - 400); p.y = -p.height; powerups.push(p); game.addChild(p); } }; // Set initial score LK.setScore(0); scoreTxt.setText(0);
===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,405 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1");
+
+/****
+* Classes
+****/
+// Alien
+var Alien = Container.expand(function () {
+ var self = Container.call(this);
+ var alien = self.attachAsset('alien', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.width = alien.width;
+ self.height = alien.height;
+ self.row = 0;
+ self.col = 0;
+ self.alive = true;
+ self.shootCooldown = 0;
+ self.update = function () {
+ // No per-alien update needed; movement handled by global logic
+ };
+ self.shoot = function () {
+ var bullet = new AlienBullet();
+ bullet.x = self.x;
+ bullet.y = self.y + self.height / 2 + bullet.height / 2;
+ alienBullets.push(bullet);
+ game.addChild(bullet);
+ LK.getSound('alienShoot').play();
+ };
+ self.hit = function () {
+ self.alive = false;
+ LK.getSound('explosion').play();
+ LK.effects.flashObject(self, 0xffffff, 200);
+ self.visible = false;
+ };
+ return self;
+});
+// Alien Bullet
+var AlienBullet = Container.expand(function () {
+ var self = Container.call(this);
+ var bullet = self.attachAsset('alienBullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.width = bullet.width;
+ self.height = bullet.height;
+ self.speed = 18;
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+// Player Bullet
+var PlayerBullet = Container.expand(function () {
+ var self = Container.call(this);
+ var bullet = self.attachAsset('playerBullet', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.width = bullet.width;
+ self.height = bullet.height;
+ self.speed = -32;
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+// Player Ship
+var PlayerShip = Container.expand(function () {
+ var self = Container.call(this);
+ var ship = self.attachAsset('playerShip', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.width = ship.width;
+ self.height = ship.height;
+ self.canShoot = true;
+ self.shootCooldown = 18; // frames between shots
+ self.cooldownTimer = 0;
+ self.lives = 1;
+ self.invincible = false;
+ self.invincibleTimer = 0;
+ self.update = function () {
+ if (self.cooldownTimer > 0) self.cooldownTimer--;
+ if (self.invincible) {
+ self.invincibleTimer--;
+ if (self.invincibleTimer <= 0) {
+ self.invincible = false;
+ ship.alpha = 1;
+ } else {
+ ship.alpha = LK.ticks % 10 < 5 ? 0.4 : 1;
+ }
+ }
+ };
+ self.shoot = function () {
+ if (self.cooldownTimer === 0 && self.visible) {
+ self.cooldownTimer = self.shootCooldown;
+ var bullet = new PlayerBullet();
+ bullet.x = self.x;
+ bullet.y = self.y - self.height / 2 - bullet.height / 2;
+ playerBullets.push(bullet);
+ game.addChild(bullet);
+ LK.getSound('shoot').play();
+ }
+ };
+ self.hit = function () {
+ if (self.invincible) return;
+ self.lives--;
+ if (self.lives <= 0) {
+ LK.effects.flashScreen(0xff0000, 800);
+ LK.getSound('explosion').play();
+ LK.showGameOver();
+ } else {
+ self.invincible = true;
+ self.invincibleTimer = 90;
+ }
+ };
+ self.applyPowerup = function () {
+ self.shootCooldown = 8;
+ LK.getSound('powerup').play();
+ LK.effects.flashObject(self, 0xaa66ff, 600);
+ LK.setTimeout(function () {
+ self.shootCooldown = 18;
+ }, 4000);
+ };
+ return self;
+});
+// Powerup
+var Powerup = Container.expand(function () {
+ var self = Container.call(this);
+ var p = self.attachAsset('powerup', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.width = p.width;
+ self.height = p.height;
+ self.speed = 10;
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
backgroundColor: 0x000000
-});
\ No newline at end of file
+});
+
+/****
+* Game Code
+****/
+// Music
+// Sound effects
+// Powerup: purple ellipse
+// Alien bullet: red ellipse
+// Alien: green box
+// Player bullet: yellow ellipse
+// Player ship: blue box
+// Play music
+LK.playMusic('spaceMusic');
+// Score
+var score = 0;
+var scoreTxt = new Text2('0', {
+ size: 120,
+ fill: "#fff"
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Player
+var player = new PlayerShip();
+player.x = 2048 / 2;
+player.y = 2732 - 180;
+game.addChild(player);
+// Bullets and objects
+var playerBullets = [];
+var alienBullets = [];
+var aliens = [];
+var powerups = [];
+// Alien grid
+var alienRows = 5;
+var alienCols = 8;
+var alienSpacingX = 180;
+var alienSpacingY = 120;
+var alienStartX = (2048 - (alienCols - 1) * alienSpacingX) / 2;
+var alienStartY = 320;
+var alienDir = 1; // 1: right, -1: left
+var alienSpeed = 12; // px per move
+var alienMoveDown = 60; // px to move down when hitting edge
+var alienMoveTimer = 0;
+var alienMoveInterval = 32; // frames between moves, decreases as aliens die
+var alienShootChance = 0.012; // chance per alien per move to shoot
+function spawnAliens() {
+ aliens.length = 0;
+ for (var row = 0; row < alienRows; row++) {
+ for (var col = 0; col < alienCols; col++) {
+ var a = new Alien();
+ a.row = row;
+ a.col = col;
+ a.x = alienStartX + col * alienSpacingX;
+ a.y = alienStartY + row * alienSpacingY;
+ aliens.push(a);
+ game.addChild(a);
+ }
+ }
+}
+spawnAliens();
+// Powerup spawn
+var powerupTimer = 0;
+var powerupInterval = 600; // frames
+// Dragging
+var dragging = false;
+var dragOffsetX = 0;
+// Move handler
+function handleMove(x, y, obj) {
+ if (dragging) {
+ var newX = x - dragOffsetX;
+ // Clamp to screen
+ var minX = player.width / 2 + 20;
+ var maxX = 2048 - player.width / 2 - 20;
+ player.x = Math.max(minX, Math.min(maxX, newX));
+ }
+}
+game.move = handleMove;
+game.down = function (x, y, obj) {
+ // Only drag if touch is on player
+ var local = player.toLocal(game.toGlobal({
+ x: x,
+ y: y
+ }));
+ if (local.x > -player.width / 2 && local.x < player.width / 2 && local.y > -player.height / 2 && local.y < player.height / 2) {
+ dragging = true;
+ dragOffsetX = x - player.x;
+ }
+};
+game.up = function (x, y, obj) {
+ dragging = false;
+};
+// Tap to shoot
+game.tap = function (x, y, obj) {
+ player.shoot();
+};
+// For mobile: allow tap anywhere to shoot
+game.down = function (x, y, obj) {
+ // Drag if on player, else shoot
+ var local = player.toLocal(game.toGlobal({
+ x: x,
+ y: y
+ }));
+ if (local.x > -player.width / 2 && local.x < player.width / 2 && local.y > -player.height / 2 && local.y < player.height / 2) {
+ dragging = true;
+ dragOffsetX = x - player.x;
+ } else {
+ player.shoot();
+ }
+};
+// Main update loop
+game.update = function () {
+ // Player update
+ player.update();
+ // Player bullets
+ for (var i = playerBullets.length - 1; i >= 0; i--) {
+ var b = playerBullets[i];
+ b.update();
+ if (b.y < -b.height) {
+ b.destroy();
+ playerBullets.splice(i, 1);
+ continue;
+ }
+ // Collide with aliens
+ for (var j = 0; j < aliens.length; j++) {
+ var a = aliens[j];
+ if (a.alive && b.intersects(a)) {
+ a.hit();
+ b.destroy();
+ playerBullets.splice(i, 1);
+ score += 100;
+ scoreTxt.setText(score);
+ break;
+ }
+ }
+ }
+ // Alien bullets
+ for (var i = alienBullets.length - 1; i >= 0; i--) {
+ var b = alienBullets[i];
+ b.update();
+ if (b.y > 2732 + b.height) {
+ b.destroy();
+ alienBullets.splice(i, 1);
+ continue;
+ }
+ // Collide with player
+ if (b.intersects(player) && !player.invincible) {
+ b.destroy();
+ alienBullets.splice(i, 1);
+ player.hit();
+ break;
+ }
+ }
+ // Powerups
+ for (var i = powerups.length - 1; i >= 0; i--) {
+ var p = powerups[i];
+ p.update();
+ if (p.y > 2732 + p.height) {
+ p.destroy();
+ powerups.splice(i, 1);
+ continue;
+ }
+ if (p.intersects(player)) {
+ p.destroy();
+ powerups.splice(i, 1);
+ player.applyPowerup();
+ break;
+ }
+ }
+ // Aliens movement
+ alienMoveTimer++;
+ if (alienMoveTimer >= alienMoveInterval) {
+ alienMoveTimer = 0;
+ var minX = 99999,
+ maxX = -99999;
+ var minY = 99999,
+ maxY = -99999;
+ for (var i = 0; i < aliens.length; i++) {
+ var a = aliens[i];
+ if (!a.alive) continue;
+ minX = Math.min(minX, a.x - a.width / 2);
+ maxX = Math.max(maxX, a.x + a.width / 2);
+ minY = Math.min(minY, a.y - a.height / 2);
+ maxY = Math.max(maxY, a.y + a.height / 2);
+ }
+ var edgeHit = false;
+ if (alienDir === 1 && maxX + alienSpeed > 2048 - 40) edgeHit = true;
+ if (alienDir === -1 && minX - alienSpeed < 40) edgeHit = true;
+ if (edgeHit) {
+ alienDir *= -1;
+ for (var i = 0; i < aliens.length; i++) {
+ var a = aliens[i];
+ if (a.alive) a.y += alienMoveDown;
+ }
+ } else {
+ for (var i = 0; i < aliens.length; i++) {
+ var a = aliens[i];
+ if (a.alive) a.x += alienDir * alienSpeed;
+ }
+ }
+ // Aliens shoot
+ for (var i = 0; i < aliens.length; i++) {
+ var a = aliens[i];
+ if (!a.alive) continue;
+ // Only bottom-most alien in column can shoot
+ var isLowest = true;
+ for (var j = 0; j < aliens.length; j++) {
+ var b = aliens[j];
+ if (b.col === a.col && b.row > a.row && b.alive) {
+ isLowest = false;
+ break;
+ }
+ }
+ if (isLowest && Math.random() < alienShootChance) {
+ a.shoot();
+ }
+ }
+ // Check for aliens reaching bottom
+ for (var i = 0; i < aliens.length; i++) {
+ var a = aliens[i];
+ if (a.alive && a.y + a.height / 2 >= player.y - player.height / 2) {
+ LK.effects.flashScreen(0xff0000, 800);
+ LK.showGameOver();
+ return;
+ }
+ }
+ // Speed up as aliens die
+ var aliveCount = 0;
+ for (var i = 0; i < aliens.length; i++) if (aliens[i].alive) aliveCount++;
+ alienMoveInterval = Math.max(8, 32 - Math.floor((40 - aliveCount) / 2));
+ }
+ // Win condition
+ var allDead = true;
+ for (var i = 0; i < aliens.length; i++) if (aliens[i].alive) allDead = false;
+ if (allDead) {
+ LK.effects.flashScreen(0x00ff00, 800);
+ LK.setScore(score);
+ LK.showYouWin();
+ return;
+ }
+ // Powerup spawn
+ powerupTimer++;
+ if (powerupTimer > powerupInterval) {
+ powerupTimer = 0;
+ var p = new Powerup();
+ p.x = 200 + Math.random() * (2048 - 400);
+ p.y = -p.height;
+ powerups.push(p);
+ game.addChild(p);
+ }
+};
+// Set initial score
+LK.setScore(0);
+scoreTxt.setText(0);
\ No newline at end of file