Code edit (1 edits merged)
Please save this source code
User prompt
The current level should be displayed in the top-left corner of the screen.
User prompt
There should be a level system. The current level number should be displayed at the top-right corner of the screen. The number of enemies in the current level should be displayed at the top-left corner. When the player kills all enemies, the game should automatically progress to the next level. In each new level, the score awarded for killing enemies should increase multiplicatively (e.g., doubled each level). Example: Level 1: each enemy = 10 points Level 2: each enemy = 20 points Level 3: each enemy = 40 points
User prompt
prevent enemies from moving outside the screen area.
User prompt
When I shoot an enemy, they should be removed instantly
User prompt
If I shoot the enemy, the enemy should die
Code edit (1 edits merged)
Please save this source code
User prompt
Space Wars: Galactic Showdown
Initial prompt
make me space wars game
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Enemy bullet class
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
// Attach bullet asset (red, 24x48)
var bullet = self.attachAsset('enemyBullet', {
width: 24,
height: 48,
color: 0xff4444,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 14;
self.radius = 12;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Enemy ship class
var EnemyShip = Container.expand(function () {
var self = Container.call(this);
// Attach enemy asset (ellipse, magenta, 100x80)
var enemy = self.attachAsset('enemyShip', {
width: 100,
height: 80,
color: 0xff33cc,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5
});
self.radius = 50;
self.speed = 4 + Math.random() * 2; // Vary speed
self.dirX = (Math.random() - 0.5) * 2; // Slight horizontal drift
// For movement patterns
self.waveOffset = Math.random() * Math.PI * 2;
// For collision
self.isAlive = true;
// Update per frame
self.update = function () {
// Move down, with a sine wave pattern
self.y += self.speed;
self.x += Math.sin(LK.ticks / 30 + self.waveOffset) * 2 + self.dirX;
};
// Flash on hit
self.flash = function () {
tween(enemy, {
tint: 0xffffff
}, {
duration: 80,
onFinish: function onFinish() {
tween(enemy, {
tint: 0xff33cc
}, {
duration: 120
});
}
});
};
return self;
});
// Player bullet class
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
// Attach bullet asset (yellow, 30x60)
var bullet = self.attachAsset('playerBullet', {
width: 30,
height: 60,
color: 0xffe066,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -22;
self.radius = 15;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Player spaceship class
var PlayerShip = Container.expand(function () {
var self = Container.call(this);
// Attach ship asset (box, blue, 120x120)
var ship = self.attachAsset('playerShip', {
width: 120,
height: 120,
color: 0x3399ff,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5
});
// Ship properties
self.radius = 60; // for collision
self.isAlive = true;
// Ship flash effect on hit
self.flash = function () {
tween(ship, {
tint: 0xff3333
}, {
duration: 100,
onFinish: function onFinish() {
tween(ship, {
tint: 0x3399ff
}, {
duration: 200
});
}
});
};
return self;
});
// Powerup class
var PowerUp = Container.expand(function () {
var self = Container.call(this);
// Attach powerup asset (green ellipse, 60x60)
var pu = self.attachAsset('powerUp', {
width: 60,
height: 60,
color: 0x44ff88,
shape: 'ellipse',
anchorX: 0.5,
anchorY: 0.5
});
self.radius = 30;
self.speed = 6;
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000010
});
/****
* Game Code
****/
// Game constants
var GAME_WIDTH = 2048;
var GAME_HEIGHT = 2732;
var PLAYER_START_X = GAME_WIDTH / 2;
var PLAYER_START_Y = GAME_HEIGHT - 350;
// Game state
var player;
var enemies = [];
var playerBullets = [];
var enemyBullets = [];
var powerUps = [];
var dragNode = null;
var lastScore = 0;
var scoreTxt;
var powerUpActive = false;
var powerUpTimer = 0;
var enemySpawnTimer = 0;
var enemyFireTimer = 0;
var powerUpSpawnTimer = 0;
var gameOver = false;
// Score display
scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Initialize player
player = new PlayerShip();
player.x = PLAYER_START_X;
player.y = PLAYER_START_Y;
game.addChild(player);
// Touch/move controls
function handleMove(x, y, obj) {
if (dragNode && player.isAlive) {
// Clamp to game area, avoid top 100px (menu)
var px = Math.max(60, Math.min(GAME_WIDTH - 60, x));
var py = Math.max(200, Math.min(GAME_HEIGHT - 60, y));
dragNode.x = px;
dragNode.y = py;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
if (player.isAlive) {
dragNode = player;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Helper: collision check (circle vs circle)
function circlesIntersect(a, b) {
var dx = a.x - b.x;
var dy = a.y - b.y;
var dist = Math.sqrt(dx * dx + dy * dy);
return dist < a.radius + b.radius;
}
// Helper: spawn enemy
function spawnEnemy() {
var enemy = new EnemyShip();
// Spawn in random horizontal position, avoid edges
enemy.x = 120 + Math.random() * (GAME_WIDTH - 240);
enemy.y = -100;
enemies.push(enemy);
game.addChild(enemy);
}
// Helper: spawn enemy bullet
function spawnEnemyBullet(enemy) {
var bullet = new EnemyBullet();
bullet.x = enemy.x;
bullet.y = enemy.y + 60;
enemyBullets.push(bullet);
game.addChild(bullet);
}
// Helper: spawn player bullet
function spawnPlayerBullet() {
var bullet = new PlayerBullet();
bullet.x = player.x;
bullet.y = player.y - 80;
playerBullets.push(bullet);
game.addChild(bullet);
}
// Helper: spawn powerup
function spawnPowerUp() {
var pu = new PowerUp();
pu.x = 120 + Math.random() * (GAME_WIDTH - 240);
pu.y = -60;
powerUps.push(pu);
game.addChild(pu);
}
// Powerup effect: double shot
function activatePowerUp() {
powerUpActive = true;
powerUpTimer = LK.ticks + 360; // 6 seconds at 60fps
// Flash player ship green
tween(player, {
tint: 0x44ff88
}, {
duration: 200,
onFinish: function onFinish() {
tween(player, {
tint: 0x3399ff
}, {
duration: 200
});
}
});
}
// Main game update
game.update = function () {
if (!player.isAlive) return;
// --- Player auto-fire ---
if (LK.ticks % (powerUpActive ? 7 : 14) === 0) {
if (powerUpActive) {
// Double shot: two bullets
var b1 = new PlayerBullet();
b1.x = player.x - 36;
b1.y = player.y - 80;
playerBullets.push(b1);
game.addChild(b1);
var b2 = new PlayerBullet();
b2.x = player.x + 36;
b2.y = player.y - 80;
playerBullets.push(b2);
game.addChild(b2);
} else {
spawnPlayerBullet();
}
}
// --- Enemy spawn ---
if (enemySpawnTimer <= LK.ticks) {
spawnEnemy();
// Escalate spawn rate
var minDelay = 24,
maxDelay = 60;
var delay = Math.max(minDelay, maxDelay - Math.floor(LK.getScore() / 10) * 4);
enemySpawnTimer = LK.ticks + delay;
}
// --- Enemy fire ---
if (enemyFireTimer <= LK.ticks && enemies.length > 0) {
// Pick random enemy to fire
var idx = Math.floor(Math.random() * enemies.length);
if (enemies[idx]) {
spawnEnemyBullet(enemies[idx]);
}
// Escalate fire rate
var minFire = 18,
maxFire = 50;
var fireDelay = Math.max(minFire, maxFire - Math.floor(LK.getScore() / 10) * 3);
enemyFireTimer = LK.ticks + fireDelay;
}
// --- Powerup spawn ---
if (powerUpSpawnTimer <= LK.ticks) {
if (Math.random() < 0.18) {
// ~18% chance
spawnPowerUp();
}
powerUpSpawnTimer = LK.ticks + 300 + Math.floor(Math.random() * 200);
}
// --- Powerup timer ---
if (powerUpActive && LK.ticks > powerUpTimer) {
powerUpActive = false;
}
// --- Update player bullets ---
for (var i = playerBullets.length - 1; i >= 0; i--) {
var b = playerBullets[i];
b.update();
// Remove if off screen
if (b.y < -80) {
b.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
if (e.isAlive && circlesIntersect(b, e)) {
e.isAlive = false;
e.flash();
b.destroy();
playerBullets.splice(i, 1);
// Remove enemy after flash
tween(e, {}, {
duration: 120,
onFinish: function onFinish() {
e.destroy();
}
});
enemies.splice(j, 1);
// Score
LK.setScore(LK.getScore() + 1);
scoreTxt.setText(LK.getScore());
break;
}
}
}
// --- Update enemy bullets ---
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var eb = enemyBullets[i];
eb.update();
if (eb.y > GAME_HEIGHT + 80) {
eb.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (player.isAlive && circlesIntersect(eb, player)) {
eb.destroy();
enemyBullets.splice(i, 1);
player.flash();
// Game over
player.isAlive = false;
tween(player, {
alpha: 0.2
}, {
duration: 400
});
LK.effects.flashScreen(0xff0000, 800);
LK.setTimeout(function () {
LK.showGameOver();
}, 900);
break;
}
}
// --- Update enemies ---
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
e.update();
if (e.y > GAME_HEIGHT + 100) {
e.destroy();
enemies.splice(i, 1);
continue;
}
// Check collision with player
if (player.isAlive && e.isAlive && circlesIntersect(e, player)) {
e.isAlive = false;
e.flash();
player.flash();
tween(e, {}, {
duration: 120,
onFinish: function onFinish() {
e.destroy();
}
});
enemies.splice(i, 1);
// Game over
player.isAlive = false;
tween(player, {
alpha: 0.2
}, {
duration: 400
});
LK.effects.flashScreen(0xff0000, 800);
LK.setTimeout(function () {
LK.showGameOver();
}, 900);
break;
}
}
// --- Update powerups ---
for (var i = powerUps.length - 1; i >= 0; i--) {
var pu = powerUps[i];
pu.update();
if (pu.y > GAME_HEIGHT + 80) {
pu.destroy();
powerUps.splice(i, 1);
continue;
}
// Check collision with player
if (player.isAlive && circlesIntersect(pu, player)) {
pu.destroy();
powerUps.splice(i, 1);
activatePowerUp();
}
}
};
// Set initial score
LK.setScore(0);
scoreTxt.setText('0'); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,431 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+
+/****
+* Classes
+****/
+// Enemy bullet class
+var EnemyBullet = Container.expand(function () {
+ var self = Container.call(this);
+ // Attach bullet asset (red, 24x48)
+ var bullet = self.attachAsset('enemyBullet', {
+ width: 24,
+ height: 48,
+ color: 0xff4444,
+ shape: 'box',
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 14;
+ self.radius = 12;
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+// Enemy ship class
+var EnemyShip = Container.expand(function () {
+ var self = Container.call(this);
+ // Attach enemy asset (ellipse, magenta, 100x80)
+ var enemy = self.attachAsset('enemyShip', {
+ width: 100,
+ height: 80,
+ color: 0xff33cc,
+ shape: 'ellipse',
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = 50;
+ self.speed = 4 + Math.random() * 2; // Vary speed
+ self.dirX = (Math.random() - 0.5) * 2; // Slight horizontal drift
+ // For movement patterns
+ self.waveOffset = Math.random() * Math.PI * 2;
+ // For collision
+ self.isAlive = true;
+ // Update per frame
+ self.update = function () {
+ // Move down, with a sine wave pattern
+ self.y += self.speed;
+ self.x += Math.sin(LK.ticks / 30 + self.waveOffset) * 2 + self.dirX;
+ };
+ // Flash on hit
+ self.flash = function () {
+ tween(enemy, {
+ tint: 0xffffff
+ }, {
+ duration: 80,
+ onFinish: function onFinish() {
+ tween(enemy, {
+ tint: 0xff33cc
+ }, {
+ duration: 120
+ });
+ }
+ });
+ };
+ return self;
+});
+// Player bullet class
+var PlayerBullet = Container.expand(function () {
+ var self = Container.call(this);
+ // Attach bullet asset (yellow, 30x60)
+ var bullet = self.attachAsset('playerBullet', {
+ width: 30,
+ height: 60,
+ color: 0xffe066,
+ shape: 'box',
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = -22;
+ self.radius = 15;
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+// Player spaceship class
+var PlayerShip = Container.expand(function () {
+ var self = Container.call(this);
+ // Attach ship asset (box, blue, 120x120)
+ var ship = self.attachAsset('playerShip', {
+ width: 120,
+ height: 120,
+ color: 0x3399ff,
+ shape: 'box',
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Ship properties
+ self.radius = 60; // for collision
+ self.isAlive = true;
+ // Ship flash effect on hit
+ self.flash = function () {
+ tween(ship, {
+ tint: 0xff3333
+ }, {
+ duration: 100,
+ onFinish: function onFinish() {
+ tween(ship, {
+ tint: 0x3399ff
+ }, {
+ duration: 200
+ });
+ }
+ });
+ };
+ return self;
+});
+// Powerup class
+var PowerUp = Container.expand(function () {
+ var self = Container.call(this);
+ // Attach powerup asset (green ellipse, 60x60)
+ var pu = self.attachAsset('powerUp', {
+ width: 60,
+ height: 60,
+ color: 0x44ff88,
+ shape: 'ellipse',
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.radius = 30;
+ self.speed = 6;
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x000010
+});
+
+/****
+* Game Code
+****/
+// Game constants
+var GAME_WIDTH = 2048;
+var GAME_HEIGHT = 2732;
+var PLAYER_START_X = GAME_WIDTH / 2;
+var PLAYER_START_Y = GAME_HEIGHT - 350;
+// Game state
+var player;
+var enemies = [];
+var playerBullets = [];
+var enemyBullets = [];
+var powerUps = [];
+var dragNode = null;
+var lastScore = 0;
+var scoreTxt;
+var powerUpActive = false;
+var powerUpTimer = 0;
+var enemySpawnTimer = 0;
+var enemyFireTimer = 0;
+var powerUpSpawnTimer = 0;
+var gameOver = false;
+// Score display
+scoreTxt = new Text2('0', {
+ size: 120,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0.5, 0);
+LK.gui.top.addChild(scoreTxt);
+// Initialize player
+player = new PlayerShip();
+player.x = PLAYER_START_X;
+player.y = PLAYER_START_Y;
+game.addChild(player);
+// Touch/move controls
+function handleMove(x, y, obj) {
+ if (dragNode && player.isAlive) {
+ // Clamp to game area, avoid top 100px (menu)
+ var px = Math.max(60, Math.min(GAME_WIDTH - 60, x));
+ var py = Math.max(200, Math.min(GAME_HEIGHT - 60, y));
+ dragNode.x = px;
+ dragNode.y = py;
+ }
+}
+game.move = handleMove;
+game.down = function (x, y, obj) {
+ if (player.isAlive) {
+ dragNode = player;
+ handleMove(x, y, obj);
+ }
+};
+game.up = function (x, y, obj) {
+ dragNode = null;
+};
+// Helper: collision check (circle vs circle)
+function circlesIntersect(a, b) {
+ var dx = a.x - b.x;
+ var dy = a.y - b.y;
+ var dist = Math.sqrt(dx * dx + dy * dy);
+ return dist < a.radius + b.radius;
+}
+// Helper: spawn enemy
+function spawnEnemy() {
+ var enemy = new EnemyShip();
+ // Spawn in random horizontal position, avoid edges
+ enemy.x = 120 + Math.random() * (GAME_WIDTH - 240);
+ enemy.y = -100;
+ enemies.push(enemy);
+ game.addChild(enemy);
+}
+// Helper: spawn enemy bullet
+function spawnEnemyBullet(enemy) {
+ var bullet = new EnemyBullet();
+ bullet.x = enemy.x;
+ bullet.y = enemy.y + 60;
+ enemyBullets.push(bullet);
+ game.addChild(bullet);
+}
+// Helper: spawn player bullet
+function spawnPlayerBullet() {
+ var bullet = new PlayerBullet();
+ bullet.x = player.x;
+ bullet.y = player.y - 80;
+ playerBullets.push(bullet);
+ game.addChild(bullet);
+}
+// Helper: spawn powerup
+function spawnPowerUp() {
+ var pu = new PowerUp();
+ pu.x = 120 + Math.random() * (GAME_WIDTH - 240);
+ pu.y = -60;
+ powerUps.push(pu);
+ game.addChild(pu);
+}
+// Powerup effect: double shot
+function activatePowerUp() {
+ powerUpActive = true;
+ powerUpTimer = LK.ticks + 360; // 6 seconds at 60fps
+ // Flash player ship green
+ tween(player, {
+ tint: 0x44ff88
+ }, {
+ duration: 200,
+ onFinish: function onFinish() {
+ tween(player, {
+ tint: 0x3399ff
+ }, {
+ duration: 200
+ });
+ }
+ });
+}
+// Main game update
+game.update = function () {
+ if (!player.isAlive) return;
+ // --- Player auto-fire ---
+ if (LK.ticks % (powerUpActive ? 7 : 14) === 0) {
+ if (powerUpActive) {
+ // Double shot: two bullets
+ var b1 = new PlayerBullet();
+ b1.x = player.x - 36;
+ b1.y = player.y - 80;
+ playerBullets.push(b1);
+ game.addChild(b1);
+ var b2 = new PlayerBullet();
+ b2.x = player.x + 36;
+ b2.y = player.y - 80;
+ playerBullets.push(b2);
+ game.addChild(b2);
+ } else {
+ spawnPlayerBullet();
+ }
+ }
+ // --- Enemy spawn ---
+ if (enemySpawnTimer <= LK.ticks) {
+ spawnEnemy();
+ // Escalate spawn rate
+ var minDelay = 24,
+ maxDelay = 60;
+ var delay = Math.max(minDelay, maxDelay - Math.floor(LK.getScore() / 10) * 4);
+ enemySpawnTimer = LK.ticks + delay;
+ }
+ // --- Enemy fire ---
+ if (enemyFireTimer <= LK.ticks && enemies.length > 0) {
+ // Pick random enemy to fire
+ var idx = Math.floor(Math.random() * enemies.length);
+ if (enemies[idx]) {
+ spawnEnemyBullet(enemies[idx]);
+ }
+ // Escalate fire rate
+ var minFire = 18,
+ maxFire = 50;
+ var fireDelay = Math.max(minFire, maxFire - Math.floor(LK.getScore() / 10) * 3);
+ enemyFireTimer = LK.ticks + fireDelay;
+ }
+ // --- Powerup spawn ---
+ if (powerUpSpawnTimer <= LK.ticks) {
+ if (Math.random() < 0.18) {
+ // ~18% chance
+ spawnPowerUp();
+ }
+ powerUpSpawnTimer = LK.ticks + 300 + Math.floor(Math.random() * 200);
+ }
+ // --- Powerup timer ---
+ if (powerUpActive && LK.ticks > powerUpTimer) {
+ powerUpActive = false;
+ }
+ // --- Update player bullets ---
+ for (var i = playerBullets.length - 1; i >= 0; i--) {
+ var b = playerBullets[i];
+ b.update();
+ // Remove if off screen
+ if (b.y < -80) {
+ b.destroy();
+ playerBullets.splice(i, 1);
+ continue;
+ }
+ // Check collision with enemies
+ for (var j = enemies.length - 1; j >= 0; j--) {
+ var e = enemies[j];
+ if (e.isAlive && circlesIntersect(b, e)) {
+ e.isAlive = false;
+ e.flash();
+ b.destroy();
+ playerBullets.splice(i, 1);
+ // Remove enemy after flash
+ tween(e, {}, {
+ duration: 120,
+ onFinish: function onFinish() {
+ e.destroy();
+ }
+ });
+ enemies.splice(j, 1);
+ // Score
+ LK.setScore(LK.getScore() + 1);
+ scoreTxt.setText(LK.getScore());
+ break;
+ }
+ }
+ }
+ // --- Update enemy bullets ---
+ for (var i = enemyBullets.length - 1; i >= 0; i--) {
+ var eb = enemyBullets[i];
+ eb.update();
+ if (eb.y > GAME_HEIGHT + 80) {
+ eb.destroy();
+ enemyBullets.splice(i, 1);
+ continue;
+ }
+ // Check collision with player
+ if (player.isAlive && circlesIntersect(eb, player)) {
+ eb.destroy();
+ enemyBullets.splice(i, 1);
+ player.flash();
+ // Game over
+ player.isAlive = false;
+ tween(player, {
+ alpha: 0.2
+ }, {
+ duration: 400
+ });
+ LK.effects.flashScreen(0xff0000, 800);
+ LK.setTimeout(function () {
+ LK.showGameOver();
+ }, 900);
+ break;
+ }
+ }
+ // --- Update enemies ---
+ for (var i = enemies.length - 1; i >= 0; i--) {
+ var e = enemies[i];
+ e.update();
+ if (e.y > GAME_HEIGHT + 100) {
+ e.destroy();
+ enemies.splice(i, 1);
+ continue;
+ }
+ // Check collision with player
+ if (player.isAlive && e.isAlive && circlesIntersect(e, player)) {
+ e.isAlive = false;
+ e.flash();
+ player.flash();
+ tween(e, {}, {
+ duration: 120,
+ onFinish: function onFinish() {
+ e.destroy();
+ }
+ });
+ enemies.splice(i, 1);
+ // Game over
+ player.isAlive = false;
+ tween(player, {
+ alpha: 0.2
+ }, {
+ duration: 400
+ });
+ LK.effects.flashScreen(0xff0000, 800);
+ LK.setTimeout(function () {
+ LK.showGameOver();
+ }, 900);
+ break;
+ }
+ }
+ // --- Update powerups ---
+ for (var i = powerUps.length - 1; i >= 0; i--) {
+ var pu = powerUps[i];
+ pu.update();
+ if (pu.y > GAME_HEIGHT + 80) {
+ pu.destroy();
+ powerUps.splice(i, 1);
+ continue;
+ }
+ // Check collision with player
+ if (player.isAlive && circlesIntersect(pu, player)) {
+ pu.destroy();
+ powerUps.splice(i, 1);
+ activatePowerUp();
+ }
+ }
+};
+// Set initial score
+LK.setScore(0);
+scoreTxt.setText('0');
\ No newline at end of file