User prompt
Please fix the bug: 'Uncaught TypeError: Cannot set properties of null (setting 'x')' in or related to this line: 'player.x = px;' Line Number: 348
User prompt
Add a starting screen ( with the title and a play button )
User prompt
Make the boss to take 6 hits to defeat it
User prompt
Make the boss to shoot the rockets less frequently, and less spread themed rather faster bullets in single direction and ricochet.
User prompt
Make the enemy ships to stay in one place too ( randomly ) also decrease the frequency of the rockets from enemies to spawn
User prompt
make the enemy space ship to take 3 hits to defeat it ( instead of 1 ), also at 0 point spawn in 2 enemies, 1 point add an enemy ship with the previous ones, continue the same until point 6, cap the number of ships to be 6
User prompt
For each point gained upto 5, add one more enemy ship in the screen
User prompt
Revert the logic, make random ships to spawn
User prompt
Fix after defeating the first 2 enemy ships, no ship is spawning in
User prompt
If there is no enemy ship spawn in +1 ship
User prompt
Start by spawning in 2 enemy ship and for each rocket defeated spawn in +1 enemy ship
User prompt
Get the hearts little bit to the left
User prompt
Slow down the enemy speed and bullet speed. And the bullet should only go vertically down ( don't target the player )
Code edit (1 edits merged)
Please save this source code
User prompt
Space Shooter: Alien Onslaught
Initial prompt
Hi Ava, Now I want to create a game based on space shooter. Game Mechanic: -> We control a space ship beginning from the bottom of the screen, which shoots out rockets. -> Enemies are alien space ship that follows from above the screen. -> Enemies shoot rockets at us too, and we have to dodge it. -> Certain enemies are different ( very rare to spawn ) which can give power ups. Gameplay: -> Make the ship to follow the clicked mouse, ( the ship should be constantly shooting the rockets ) -> The ship has 3 lives, when hit by enemy rockets, we loose health -> power ups from aliens: Fast shooting guns, extra life ( grants extra life ), destroy all ball ( grab to destroy everything ), shield ( to protect from enemy attacks for a brief time ) Gameplay mech: -> Clearing enemies grants points, enemies should go to random locations on top, should not come down, they shoot randomly. each alien ship defeated grants 1 point, when reaching 20 points, a single boss spaceship appears, when defeated we win ( the boss shoot rockets frequently, and in different directions that richochet the screens )
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Bomb (for screen clear effect)
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bomb = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
return self;
});
// Boss
var Boss = Container.expand(function () {
var self = Container.call(this);
var boss = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
self.hp = 30;
self.targetX = 1024;
self.moveSpeed = 18;
self.shootCooldown = 30;
self.update = function () {
// Move horizontally only
var dx = self.targetX - self.x;
if (Math.abs(dx) > self.moveSpeed) {
self.x += dx > 0 ? self.moveSpeed : -self.moveSpeed;
} else {
self.x = self.targetX;
// Pick new target
self.targetX = 300 + Math.random() * (2048 - 600);
}
// Shooting
self.shootCooldown--;
if (self.shootCooldown <= 0) {
self.shootCooldown = 18;
spawnBossRockets(self);
}
};
return self;
});
// Boss Rocket
var BossRocket = Container.expand(function () {
var self = Container.call(this);
var rocket = self.attachAsset('bossRocket', {
anchorX: 0.5,
anchorY: 0.5
});
self.dx = 0;
self.dy = 28;
self.ricochet = true;
self.update = function () {
self.x += self.dx;
self.y += self.dy;
// Ricochet off walls
if (self.ricochet) {
if (self.x < 0 && self.dx < 0) self.dx *= -1;
if (self.x > 2048 && self.dx > 0) self.dx *= -1;
}
};
return self;
});
// Enemy Rocket
var EnemyRocket = Container.expand(function () {
var self = Container.call(this);
var rocket = self.attachAsset('enemyRocket', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10; // slowed down enemy rocket speed
self.dx = 0; // always vertical, no horizontal movement
self.dy = self.speed;
self.ricochet = false;
self.update = function () {
self.x += self.dx;
self.y += self.dy;
// Ricochet off walls if enabled
if (self.ricochet) {
if (self.x < 0 && self.dx < 0) self.dx *= -1;
if (self.x > 2048 && self.dx > 0) self.dx *= -1;
}
};
return self;
});
// Enemy Ship
var EnemyShip = Container.expand(function () {
var self = Container.call(this);
var ship = self.attachAsset('enemyShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetX = 0;
self.targetY = 0;
self.moveSpeed = 5 + Math.random() * 3; // slowed down enemy movement
self.shootCooldown = 60 + Math.floor(Math.random() * 60);
self.isRare = false; // rare enemies drop powerups
self.update = function () {
// Move toward target
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > self.moveSpeed) {
self.x += dx / dist * self.moveSpeed;
self.y += dy / dist * self.moveSpeed;
} else {
self.x = self.targetX;
self.y = self.targetY;
// Pick new target
self.targetX = 200 + Math.random() * (2048 - 400);
self.targetY = 200 + Math.random() * 800;
}
// Shooting
self.shootCooldown--;
if (self.shootCooldown <= 0) {
self.shootCooldown = 60 + Math.floor(Math.random() * 60);
spawnEnemyRocket(self);
}
};
return self;
});
// Player Rocket
var PlayerRocket = Container.expand(function () {
var self = Container.call(this);
var rocket = self.attachAsset('playerRocket', {
anchorX: 0.5,
anchorY: 0.5
});
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.lives = 3;
self.shielded = false;
self.fastShoot = false;
self.shootTimer = 0;
self.shieldNode = null;
self.update = function () {
// nothing here, movement is handled by drag
};
self.setShield = function (active) {
if (active && !self.shielded) {
self.shielded = true;
self.shieldNode = new Shield();
self.shieldNode.x = 0;
self.shieldNode.y = 0;
self.addChild(self.shieldNode);
} else if (!active && self.shielded) {
if (self.shieldNode) {
self.shieldNode.destroy();
self.shieldNode = null;
}
self.shielded = false;
}
};
return self;
});
// PowerUp
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerup = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'fast'; // 'fast', 'life', 'shield', 'bomb'
self.speed = 12;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Shield
var Shield = Container.expand(function () {
var self = Container.call(this);
var shield = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.4
});
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Music
// Sounds
// Bomb: white ellipse
// Boss rocket: magenta box
// Boss: purple box
// Shield: cyan ellipse
// Power-up: green ellipse
// Enemy rocket: orange box
// Enemy ship: red ellipse
// Player rocket: yellow box
// Player ship: blue box
// Play music
LK.playMusic('spacebg');
// Score, lives, state
var score = 0;
var lives = 3;
var player = null;
var playerShieldTimeout = 0;
var playerFastShootTimeout = 0;
var playerBombActive = false;
var playerInvulnTimeout = 0;
var boss = null;
var bossActive = false;
var bossDefeated = false;
var bossHpTxt = null;
// Arrays for game objects
var playerRockets = [];
var enemyRockets = [];
var bossRockets = [];
var enemies = [];
var powerups = [];
var bombs = [];
// GUI
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var livesTxt = new Text2('♥♥♥', {
size: 90,
fill: 0xFF6666
});
livesTxt.anchor.set(1, 0);
livesTxt.x = -60;
LK.gui.topRight.addChild(livesTxt);
// Helper: update GUI
function updateScore() {
scoreTxt.setText(score);
}
function updateLives() {
var s = '';
for (var i = 0; i < lives; ++i) s += '♥';
livesTxt.setText(s);
}
function showBossHp(hp) {
if (!bossHpTxt) {
bossHpTxt = new Text2('Boss: ' + hp, {
size: 90,
fill: 0xFFCCFF
});
bossHpTxt.anchor.set(0.5, 0);
LK.gui.bottom.addChild(bossHpTxt);
} else {
bossHpTxt.setText('Boss: ' + hp);
}
}
function hideBossHp() {
if (bossHpTxt) {
bossHpTxt.destroy();
bossHpTxt = null;
}
}
// Spawn player
player = new PlayerShip();
player.x = 1024;
player.y = 2732 - 180;
game.addChild(player);
// Dragging
var dragNode = null;
game.down = function (x, y, obj) {
// Only allow drag if touch is on player
if (player && Math.abs(x - player.x) < 120 && Math.abs(y - player.y) < 80) {
dragNode = player;
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
function handleMove(x, y, obj) {
if (dragNode === player) {
// Clamp to screen
var px = Math.max(80, Math.min(2048 - 80, x));
var py = Math.max(2732 - 300, Math.min(2732 - 80, y));
player.x = px;
player.y = py;
}
}
game.move = handleMove;
// Spawn enemy
function spawnEnemy() {
var e = new EnemyShip();
e.x = 200 + Math.random() * (2048 - 400);
e.y = 100 + Math.random() * 200;
e.targetX = 200 + Math.random() * (2048 - 400);
e.targetY = 200 + Math.random() * 800;
// 1 in 7 is rare
if (Math.random() < 0.14) {
e.isRare = true;
// Tint rare enemies
e.children[0].tint = 0x00ff99;
}
enemies.push(e);
game.addChild(e);
}
// Spawn powerup
function spawnPowerUp(x, y) {
var p = new PowerUp();
p.x = x;
p.y = y;
// Random type
var r = Math.random();
if (r < 0.25) p.type = 'fast';else if (r < 0.5) p.type = 'life';else if (r < 0.75) p.type = 'shield';else p.type = 'bomb';
// Color by type
if (p.type === 'fast') p.children[0].tint = 0x44ff44;
if (p.type === 'life') p.children[0].tint = 0xff66cc;
if (p.type === 'shield') p.children[0].tint = 0x00ffff;
if (p.type === 'bomb') p.children[0].tint = 0xffffff;
powerups.push(p);
game.addChild(p);
}
// Spawn player rocket
function spawnPlayerRocket() {
var r = new PlayerRocket();
r.x = player.x;
r.y = player.y - 80;
playerRockets.push(r);
game.addChild(r);
LK.getSound('shoot').play();
}
// Spawn enemy rocket
function spawnEnemyRocket(enemy) {
var r = new EnemyRocket();
r.x = enemy.x;
r.y = enemy.y + 60;
// Only shoot vertically down, no targeting
r.dx = 0;
r.dy = r.speed;
r.ricochet = false;
enemyRockets.push(r);
game.addChild(r);
LK.getSound('enemyShoot').play();
}
// Spawn boss
function spawnBoss() {
boss = new Boss();
boss.x = 1024;
boss.y = 400;
boss.hp = 30;
bossActive = true;
game.addChild(boss);
showBossHp(boss.hp);
}
// Spawn boss rockets (multi-directional)
function spawnBossRockets(bossObj) {
var angles = [0, -0.3, 0.3, -0.6, 0.6];
for (var i = 0; i < angles.length; ++i) {
var r = new BossRocket();
r.x = bossObj.x;
r.y = bossObj.y + 100;
var angle = Math.PI / 2 + angles[i];
r.dx = Math.cos(angle) * 18;
r.dy = Math.sin(angle) * 28;
r.ricochet = true;
bossRockets.push(r);
game.addChild(r);
}
LK.getSound('bossShoot').play();
}
// Bomb effect: clear all enemy/boss rockets and damage all enemies
function activateBomb() {
if (playerBombActive) return;
playerBombActive = true;
var bomb = new Bomb();
bomb.x = player.x;
bomb.y = player.y - 100;
bombs.push(bomb);
game.addChild(bomb);
LK.getSound('bomb').play();
// Flash
LK.effects.flashScreen(0xffffff, 400);
// Destroy all enemy/boss rockets
for (var i = enemyRockets.length - 1; i >= 0; --i) {
enemyRockets[i].destroy();
enemyRockets.splice(i, 1);
}
for (var i = bossRockets.length - 1; i >= 0; --i) {
bossRockets[i].destroy();
bossRockets.splice(i, 1);
}
// Damage all enemies
for (var i = enemies.length - 1; i >= 0; --i) {
enemies[i].destroy();
enemies.splice(i, 1);
score += 1;
updateScore();
}
// Damage boss if present
if (bossActive && boss) {
boss.hp -= 5;
if (boss.hp < 0) boss.hp = 0;
showBossHp(boss.hp);
LK.effects.flashObject(boss, 0xffffff, 400);
}
// Remove bomb after effect
LK.setTimeout(function () {
if (bomb) bomb.destroy();
playerBombActive = false;
}, 600);
}
// Main update
game.update = function () {
// Player shooting
if (player) {
player.shootTimer--;
var shootInterval = player.fastShoot ? 7 : 18;
if (player.shootTimer <= 0) {
player.shootTimer = shootInterval;
spawnPlayerRocket();
}
}
// Player powerup timers
if (playerFastShootTimeout > 0) {
playerFastShootTimeout--;
if (playerFastShootTimeout === 0) {
player.fastShoot = false;
}
}
if (playerShieldTimeout > 0) {
playerShieldTimeout--;
if (playerShieldTimeout === 0) {
player.setShield(false);
}
}
if (playerInvulnTimeout > 0) {
playerInvulnTimeout--;
}
// Update player rockets
for (var i = playerRockets.length - 1; i >= 0; --i) {
var r = playerRockets[i];
r.update();
// Off screen
if (r.y < -80) {
r.destroy();
playerRockets.splice(i, 1);
continue;
}
// Hit enemy
for (var j = enemies.length - 1; j >= 0; --j) {
var e = enemies[j];
if (r.intersects(e)) {
LK.getSound('explosion').play();
r.destroy();
playerRockets.splice(i, 1);
// Powerup drop
if (e.isRare) {
spawnPowerUp(e.x, e.y);
}
e.destroy();
enemies.splice(j, 1);
score += 1;
updateScore();
break;
}
}
// Hit boss
if (bossActive && boss && r.intersects(boss)) {
LK.getSound('hit').play();
r.destroy();
playerRockets.splice(i, 1);
boss.hp -= 1;
showBossHp(boss.hp);
LK.effects.flashObject(boss, 0xff33cc, 200);
if (boss.hp <= 0) {
// Boss defeated
bossDefeated = true;
boss.destroy();
boss = null;
bossActive = false;
hideBossHp();
LK.effects.flashScreen(0x00ffcc, 1200);
LK.setScore(score);
LK.showYouWin();
return;
}
}
}
// Update enemy rockets
for (var i = enemyRockets.length - 1; i >= 0; --i) {
var r = enemyRockets[i];
r.update();
// Off screen
if (r.y > 2732 + 80 || r.x < -80 || r.x > 2048 + 80) {
r.destroy();
enemyRockets.splice(i, 1);
continue;
}
// Hit player
if (player && r.intersects(player)) {
r.destroy();
enemyRockets.splice(i, 1);
if (player.shielded) {
LK.getSound('shield').play();
player.setShield(false);
} else if (playerInvulnTimeout === 0) {
lives -= 1;
updateLives();
LK.getSound('hit').play();
LK.effects.flashObject(player, 0xff0000, 600);
playerInvulnTimeout = 60;
if (lives <= 0) {
LK.effects.flashScreen(0xff0000, 1200);
LK.setScore(score);
LK.showGameOver();
return;
}
}
}
}
// Update boss rockets
for (var i = bossRockets.length - 1; i >= 0; --i) {
var r = bossRockets[i];
r.update();
// Off screen
if (r.y > 2732 + 80 || r.x < -80 || r.x > 2048 + 80) {
r.destroy();
bossRockets.splice(i, 1);
continue;
}
// Hit player
if (player && r.intersects(player)) {
r.destroy();
bossRockets.splice(i, 1);
if (player.shielded) {
LK.getSound('shield').play();
player.setShield(false);
} else if (playerInvulnTimeout === 0) {
lives -= 1;
updateLives();
LK.getSound('hit').play();
LK.effects.flashObject(player, 0xff0000, 600);
playerInvulnTimeout = 60;
if (lives <= 0) {
LK.effects.flashScreen(0xff0000, 1200);
LK.setScore(score);
LK.showGameOver();
return;
}
}
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; --i) {
var e = enemies[i];
e.update();
// Off screen (shouldn't happen)
if (e.y > 2732 + 100) {
e.destroy();
enemies.splice(i, 1);
continue;
}
// Collide with player
if (player && e.intersects(player)) {
LK.getSound('hit').play();
e.destroy();
enemies.splice(i, 1);
if (player.shielded) {
player.setShield(false);
} else if (playerInvulnTimeout === 0) {
lives -= 1;
updateLives();
LK.effects.flashObject(player, 0xff0000, 600);
playerInvulnTimeout = 60;
if (lives <= 0) {
LK.effects.flashScreen(0xff0000, 1200);
LK.setScore(score);
LK.showGameOver();
return;
}
}
}
}
// Update powerups
for (var i = powerups.length - 1; i >= 0; --i) {
var p = powerups[i];
p.update();
// Off screen
if (p.y > 2732 + 80) {
p.destroy();
powerups.splice(i, 1);
continue;
}
// Collect
if (player && p.intersects(player)) {
LK.getSound('powerup').play();
if (p.type === 'fast') {
player.fastShoot = true;
playerFastShootTimeout = 360;
} else if (p.type === 'life') {
lives += 1;
updateLives();
LK.getSound('lifeup').play();
} else if (p.type === 'shield') {
player.setShield(true);
playerShieldTimeout = 360;
LK.getSound('shield').play();
} else if (p.type === 'bomb') {
activateBomb();
}
p.destroy();
powerups.splice(i, 1);
}
}
// Update bombs
for (var i = bombs.length - 1; i >= 0; --i) {
// Bombs are visual only, auto destroy after effect
}
// Boss
if (bossActive && boss) {
boss.update();
}
// Track initial spawn
var initialEnemiesSpawned = false;
// Track last score for enemy spawn logic
if (typeof game._lastPlayerRocketEnemyScore === "undefined") game._lastPlayerRocketEnemyScore = 0;
// Spawn enemies
if (!bossActive && !initialEnemiesSpawned && score === 0 && enemies.length === 0) {
// At game start, spawn 2 enemies
spawnEnemy();
spawnEnemy();
initialEnemiesSpawned = true;
game._lastPlayerRocketEnemyScore = 0;
} else if (!bossActive && initialEnemiesSpawned && score < 20) {
// For each enemy defeated by player rocket, spawn +1 enemy
var defeated = score - game._lastPlayerRocketEnemyScore;
if (defeated > 0) {
for (var i = 0; i < defeated; ++i) {
spawnEnemy();
}
game._lastPlayerRocketEnemyScore = score;
}
// If there are no enemy ships, spawn one
if (enemies.length === 0) {
spawnEnemy();
// Also update _lastPlayerRocketEnemyScore to avoid double-spawning
game._lastPlayerRocketEnemyScore = score;
}
}
// Boss appears at 20 points
if (!bossActive && !bossDefeated && score >= 20) {
// Remove all enemies
for (var i = enemies.length - 1; i >= 0; --i) {
enemies[i].destroy();
enemies.splice(i, 1);
}
spawnBoss();
}
};
// Set initial GUI
updateScore();
updateLives(); ===================================================================
--- original.js
+++ change.js
@@ -637,18 +637,19 @@
boss.update();
}
// Track initial spawn
var initialEnemiesSpawned = false;
+ // Track last score for enemy spawn logic
+ if (typeof game._lastPlayerRocketEnemyScore === "undefined") game._lastPlayerRocketEnemyScore = 0;
// Spawn enemies
if (!bossActive && !initialEnemiesSpawned && score === 0 && enemies.length === 0) {
// At game start, spawn 2 enemies
spawnEnemy();
spawnEnemy();
initialEnemiesSpawned = true;
+ game._lastPlayerRocketEnemyScore = 0;
} else if (!bossActive && initialEnemiesSpawned && score < 20) {
// For each enemy defeated by player rocket, spawn +1 enemy
- // Count how many enemies were defeated this frame
- if (typeof game._lastPlayerRocketEnemyScore === "undefined") game._lastPlayerRocketEnemyScore = 0;
var defeated = score - game._lastPlayerRocketEnemyScore;
if (defeated > 0) {
for (var i = 0; i < defeated; ++i) {
spawnEnemy();
@@ -657,8 +658,10 @@
}
// If there are no enemy ships, spawn one
if (enemies.length === 0) {
spawnEnemy();
+ // Also update _lastPlayerRocketEnemyScore to avoid double-spawning
+ game._lastPlayerRocketEnemyScore = score;
}
}
// Boss appears at 20 points
if (!bossActive && !bossDefeated && score >= 20) {
A bomb. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Boss ship top down. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Enemy ship. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Spaceship for players. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
make it greyish
Kinda a spike ball very red. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Diamond, . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat