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