User prompt
Let’s make it so I can destroy smaller enemies from across the screen
User prompt
It did not destroy the smaller ships even before the boss enters
User prompt
Make it so it will kill smaller ships within long range
User prompt
Make the range of bullets larger, and the attack damage better
User prompt
No, I mean, make smaller ships be affected by main players bullets
User prompt
Ok so let’s make the bullets kill the smaller ships
User prompt
Let’s make a boss battle ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Remix started
Copy Space Squadron
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BossBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bossBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.update = function () {
self.y += self.speed;
};
return self;
});
var BossShip = Container.expand(function () {
var self = Container.call(this);
// Main body
var shipBody = self.attachAsset('bossShipBody', {
anchorX: 0.5,
anchorY: 0.5
});
// Wings
var wings = self.attachAsset('bossShipWings', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -20
});
// Core
var core = self.attachAsset('bossShipCore', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0
});
// Left turret
var leftTurret = self.attachAsset('bossShipTurrets', {
anchorX: 0.5,
anchorY: 0.5,
x: -80,
y: -10
});
// Right turret
var rightTurret = self.attachAsset('bossShipTurrets', {
anchorX: 0.5,
anchorY: 0.5,
x: 80,
y: -10
});
self.maxHealth = 100;
self.health = self.maxHealth;
self.speed = 1;
self.shootTimer = 0;
self.shootInterval = 30;
self.phase = 1;
self.moveTimer = 0;
self.moveDirection = 1;
self.phaseChangeTimer = 0;
// Entrance animation
self.targetY = 300;
self.y = -200;
tween(self, {
y: self.targetY
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
self.entryComplete = true;
}
});
self.update = function () {
if (!self.entryComplete) return;
// Movement pattern
self.moveTimer++;
if (self.moveTimer % 120 === 0) {
self.moveDirection *= -1;
}
self.x += self.moveDirection * self.speed;
// Keep boss within screen bounds
self.x = Math.max(150, Math.min(1898, self.x));
// Phase transitions based on health
if (self.health <= self.maxHealth * 0.66 && self.phase === 1) {
self.phase = 2;
self.shootInterval = 20;
self.speed = 1.5;
LK.effects.flashObject(self, 0xff0000, 500);
} else if (self.health <= self.maxHealth * 0.33 && self.phase === 2) {
self.phase = 3;
self.shootInterval = 15;
self.speed = 2;
LK.effects.flashObject(self, 0xff0000, 800);
}
// Shooting patterns
self.shootTimer++;
if (self.shootTimer >= self.shootInterval) {
self.shootTimer = 0;
if (self.phase === 1) {
// Single shot toward player
var bullet = new BossBullet();
bullet.x = self.x;
bullet.y = self.y + 75;
bullet.lastY = bullet.y;
bossBullets.push(bullet);
game.addChild(bullet);
} else if (self.phase === 2) {
// Triple spread shot
for (var shotIndex = 0; shotIndex < 3; shotIndex++) {
var bullet = new BossBullet();
bullet.x = self.x + (shotIndex - 1) * 50;
bullet.y = self.y + 75;
bullet.lastY = bullet.y;
bossBullets.push(bullet);
game.addChild(bullet);
}
} else if (self.phase === 3) {
// Five shot spread
for (var shotIndex = 0; shotIndex < 5; shotIndex++) {
var bullet = new BossBullet();
bullet.x = self.x + (shotIndex - 2) * 40;
bullet.y = self.y + 75;
bullet.lastY = bullet.y;
bossBullets.push(bullet);
game.addChild(bullet);
}
}
}
// Health-based visual effects
if (self.health < self.maxHealth * 0.5) {
// Damage effects for low health
if (Math.random() < 0.02) {
LK.effects.flashObject(core, 0xff0000, 100);
}
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.update = function () {
self.y += self.speed;
};
return self;
});
var EnemyShip = Container.expand(function () {
var self = Container.call(this);
// Main body
var shipBody = self.attachAsset('enemyShipBody', {
anchorX: 0.5,
anchorY: 0.5
});
// Wings
var wings = self.attachAsset('enemyShipWings', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -15
});
// Core/cockpit
var core = self.attachAsset('enemyShipCore', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0
});
// Thruster
var thruster = self.attachAsset('enemyShipThruster', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 30
});
self.speed = 3;
self.health = 1;
self.shootTimer = 0;
self.shootInterval = 60 + Math.random() * 120; // Random shooting interval
self.update = function () {
self.y += self.speed;
// Enemy shooting logic
self.shootTimer++;
if (self.shootTimer >= self.shootInterval) {
self.shootTimer = 0;
self.shootInterval = 60 + Math.random() * 120; // Reset with new random interval
// Create enemy bullet
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 40;
bullet.lastY = bullet.y;
enemyBullets.push(bullet);
game.addChild(bullet);
}
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -12;
self.update = function () {
self.y += self.speed;
};
return self;
});
var PlayerShip = Container.expand(function () {
var self = Container.call(this);
// Main body
var shipBody = self.attachAsset('playerShipBody', {
anchorX: 0.5,
anchorY: 0.5
});
// Wings
var leftWing = self.attachAsset('playerShipWings', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 20
});
// Cockpit
var cockpit = self.attachAsset('playerShipCockpit', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: -15
});
// Engine thrusters
var leftEngine = self.attachAsset('playerShipEngines', {
anchorX: 0.5,
anchorY: 0.5,
x: -25,
y: 35
});
var rightEngine = self.attachAsset('playerShipEngines', {
anchorX: 0.5,
anchorY: 0.5,
x: 25,
y: 35
});
// Shield visual effect (initially hidden)
var shieldGraphics = self.attachAsset('shieldEffect', {
anchorX: 0.5,
anchorY: 0.5,
x: 0,
y: 0,
alpha: 0
});
self.shieldGraphics = shieldGraphics;
self.shootTimer = 0;
self.shootInterval = 15; // Shoot every 15 ticks (4 times per second)
self.update = function () {
// Auto-shooting logic
self.shootTimer++;
var currentShootInterval = playerUpgrades.rapidFire ? Math.floor(self.shootInterval / 2) : self.shootInterval;
if (self.shootTimer >= currentShootInterval) {
self.shootTimer = 0;
if (playerUpgrades.tripleShot) {
// Triple shot
for (var shotIndex = 0; shotIndex < 3; shotIndex++) {
var bullet = new PlayerBullet();
bullet.x = self.x + (shotIndex - 1) * 30; // Spread shots
bullet.y = self.y - 50;
bullet.lastY = bullet.y;
playerBullets.push(bullet);
game.addChild(bullet);
}
} else {
// Single shot
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - 50;
bullet.lastY = bullet.y;
playerBullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('shoot').play();
}
};
return self;
});
var Upgrade = Container.expand(function (type) {
var self = Container.call(this);
self.type = type;
self.speed = 4;
var upgradeGraphics = self.attachAsset('upgrade' + type, {
anchorX: 0.5,
anchorY: 0.5
});
// Pulsing animation
tween(upgradeGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(upgradeGraphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: function onFinish() {
// Restart the pulsing animation
if (self.parent) {
tween(upgradeGraphics, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 800,
easing: tween.easeInOut,
onFinish: arguments.callee.caller
});
}
}
});
}
});
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000011
});
/****
* Game Code
****/
// Game variables
var playerBullets = [];
var enemyBullets = [];
var bossBullets = [];
var enemies = [];
var upgrades = [];
var boss = null;
var bossActive = false;
var enemySpawnTimer = 0;
var enemySpawnInterval = 120; // Start with 2 seconds between spawns
var upgradeSpawnTimer = 0;
var upgradeSpawnInterval = 600; // 10 seconds between upgrades
var dragNode = null;
var difficultyTimer = 0;
var nextBossScore = 500; // First boss at 500 points
// Upgrade system
var playerUpgrades = {
rapidFire: false,
rapidFireTimer: 0,
shield: false,
shieldTimer: 0,
tripleShot: false,
tripleShotTimer: 0
};
// Create player ship
var player = game.addChild(new PlayerShip());
player.x = 1024; // Center horizontally
player.y = 2400; // Near bottom of screen
// Create game title
var titleTxt = new Text2('SPACE INVADERS 2.0', {
size: 80,
fill: 0x00ff00
});
titleTxt.anchor.set(0.5, 0);
titleTxt.x = 0;
titleTxt.y = 20;
LK.gui.top.addChild(titleTxt);
// Create score display
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.y = 120;
LK.gui.top.addChild(scoreTxt);
scoreTxt.setText(LK.getScore());
// Boss health bar (initially hidden)
var bossHealthBarBg = new Text2('', {
size: 40,
fill: 0x333333
});
bossHealthBarBg.anchor.set(0.5, 0);
bossHealthBarBg.y = 200;
LK.gui.top.addChild(bossHealthBarBg);
var bossHealthBar = new Text2('', {
size: 40,
fill: 0xff0000
});
bossHealthBar.anchor.set(0.5, 0);
bossHealthBar.y = 200;
LK.gui.top.addChild(bossHealthBar);
var bossNameTxt = new Text2('', {
size: 60,
fill: 0xff0000
});
bossNameTxt.anchor.set(0.5, 0);
bossNameTxt.y = 250;
LK.gui.top.addChild(bossNameTxt);
// Hide boss UI initially
bossHealthBarBg.alpha = 0;
bossHealthBar.alpha = 0;
bossNameTxt.alpha = 0;
// Touch/drag controls
function handleMove(x, y, obj) {
if (dragNode) {
// Keep player within screen bounds
dragNode.x = Math.max(40, Math.min(2008, x));
dragNode.y = Math.max(100, Math.min(2632, y));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
dragNode = player;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
game.update = function () {
// Boss spawning logic
if (!bossActive && LK.getScore() >= nextBossScore) {
bossActive = true;
boss = new BossShip();
boss.x = 1024;
boss.y = -200;
game.addChild(boss);
LK.getSound('bossSpawn').play();
// Show boss UI
bossNameTxt.setText('DESTROYER COMMAND SHIP');
tween(bossHealthBarBg, {
alpha: 1
}, {
duration: 500
});
tween(bossHealthBar, {
alpha: 1
}, {
duration: 500
});
tween(bossNameTxt, {
alpha: 1
}, {
duration: 500
});
// Clear regular enemies during boss fight
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].destroy();
enemies.splice(i, 1);
}
}
// Update boss health bar
if (bossActive && boss) {
var healthPercent = boss.health / boss.maxHealth;
var barWidth = Math.floor(healthPercent * 20);
var bgWidth = 20;
bossHealthBarBg.setText('░'.repeat(bgWidth));
bossHealthBar.setText('█'.repeat(barWidth));
}
// Update difficulty over time (only when boss is not active)
if (!bossActive) {
difficultyTimer++;
if (difficultyTimer % 600 == 0) {
// Every 10 seconds
enemySpawnInterval = Math.max(30, enemySpawnInterval - 10); // Faster spawning, minimum 0.5 seconds
}
}
// Update upgrade timers
if (playerUpgrades.rapidFire) {
playerUpgrades.rapidFireTimer--;
if (playerUpgrades.rapidFireTimer <= 0) {
playerUpgrades.rapidFire = false;
// Flash effect when upgrade expires
LK.effects.flashObject(player, 0x00ff00, 300);
}
}
if (playerUpgrades.shield) {
playerUpgrades.shieldTimer--;
if (playerUpgrades.shieldTimer <= 0) {
playerUpgrades.shield = false;
player.alpha = 1.0; // Reset transparency
// Hide shield visual effect
tween.stop(player.shieldGraphics);
tween(player.shieldGraphics, {
alpha: 0
}, {
duration: 300,
easing: tween.easeOut
});
}
}
if (playerUpgrades.tripleShot) {
playerUpgrades.tripleShotTimer--;
if (playerUpgrades.tripleShotTimer <= 0) {
playerUpgrades.tripleShot = false;
// Flash effect when upgrade expires
LK.effects.flashObject(player, 0xff0080, 300);
}
}
// Spawn upgrades
upgradeSpawnTimer++;
if (upgradeSpawnTimer >= upgradeSpawnInterval) {
upgradeSpawnTimer = 0;
var upgradeTypes = ['RapidFire', 'Shield', 'TripleShot'];
var randomType = upgradeTypes[Math.floor(Math.random() * upgradeTypes.length)];
var upgrade = new Upgrade(randomType);
upgrade.x = 100 + Math.random() * 1848;
upgrade.y = -50;
upgrade.lastY = upgrade.y;
upgrades.push(upgrade);
game.addChild(upgrade);
}
// Spawn enemies (only when boss is not active)
if (!bossActive) {
enemySpawnTimer++;
if (enemySpawnTimer >= enemySpawnInterval) {
enemySpawnTimer = 0;
var enemy = new EnemyShip();
enemy.x = 100 + Math.random() * 1848; // Random x position within screen
enemy.y = -50; // Start above screen
enemy.lastY = enemy.y;
enemy.speed = 2 + Math.random() * 3 + LK.getScore() / 50; // Increase speed with score
enemies.push(enemy);
game.addChild(enemy);
}
}
// Update and check 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 >= -25 && bullet.y < -25) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with boss
var hitTarget = false;
if (bossActive && boss && bullet.intersects(boss)) {
boss.health -= 2;
LK.setScore(LK.getScore() + 5);
scoreTxt.setText(LK.getScore());
// Visual effect
LK.effects.flashObject(boss, 0xffffff, 150);
// Check if boss is defeated
if (boss.health <= 0) {
LK.setScore(LK.getScore() + 200); // Bonus points for boss kill
scoreTxt.setText(LK.getScore());
LK.effects.flashObject(boss, 0xffffff, 1000);
LK.getSound('bossDestroy').play();
boss.destroy();
boss = null;
bossActive = false;
nextBossScore = LK.getScore() + 1000; // Next boss after 1000 more points
// Hide boss UI
tween(bossHealthBarBg, {
alpha: 0
}, {
duration: 500
});
tween(bossHealthBar, {
alpha: 0
}, {
duration: 500
});
tween(bossNameTxt, {
alpha: 0
}, {
duration: 500
});
}
bullet.destroy();
playerBullets.splice(i, 1);
hitTarget = true;
}
// Check collision with regular enemies
if (!hitTarget) {
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
// Enemy destroyed
LK.setScore(LK.getScore() + 10);
scoreTxt.setText(LK.getScore());
// Visual effect
LK.effects.flashObject(enemy, 0xffffff, 200);
// Clean up
bullet.destroy();
enemy.destroy();
playerBullets.splice(i, 1);
enemies.splice(j, 1);
LK.getSound('enemyDestroy').play();
hitTarget = true;
break;
}
}
}
if (!hitTarget) {
bullet.lastY = bullet.y;
}
// Update and check boss bullets
for (var i = bossBullets.length - 1; i >= 0; i--) {
var bullet = bossBullets[i];
if (bullet.lastY === undefined) bullet.lastY = bullet.y;
// Remove bullets that go off screen
if (bullet.lastY <= 2757 && bullet.y > 2757) {
bullet.destroy();
bossBullets.splice(i, 1);
continue;
}
var hitTarget = false;
// Check collision with enemy ships (boss bullets can destroy smaller ships)
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
// Enemy destroyed by boss bullet
LK.effects.flashObject(enemy, 0xffffff, 200);
bullet.destroy();
enemy.destroy();
bossBullets.splice(i, 1);
enemies.splice(j, 1);
LK.getSound('enemyDestroy').play();
hitTarget = true;
break;
}
}
if (!hitTarget) {
// Check collision with player
if (bullet.intersects(player)) {
if (!playerUpgrades.shield) {
LK.effects.flashScreen(0xff0000, 1000);
LK.getSound('playerHit').play();
LK.showGameOver();
return;
} else {
// Shield absorbs the hit
bullet.destroy();
bossBullets.splice(i, 1);
LK.effects.flashObject(player, 0x0080ff, 200);
continue;
}
}
}
if (!hitTarget) {
bullet.lastY = bullet.y;
}
}
}
// Update and check 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 <= 2757 && bullet.y > 2757) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (bullet.intersects(player)) {
if (!playerUpgrades.shield) {
LK.effects.flashScreen(0xff0000, 1000);
LK.getSound('playerHit').play();
LK.showGameOver();
return;
} else {
// Shield absorbs the hit
bullet.destroy();
enemyBullets.splice(i, 1);
LK.effects.flashObject(player, 0x0080ff, 200);
continue;
}
}
bullet.lastY = bullet.y;
}
// Update and check upgrades
for (var i = upgrades.length - 1; i >= 0; i--) {
var upgrade = upgrades[i];
if (upgrade.lastY === undefined) upgrade.lastY = upgrade.y;
// Remove upgrades that go off screen
if (upgrade.lastY <= 2757 && upgrade.y > 2757) {
upgrade.destroy();
upgrades.splice(i, 1);
continue;
}
// Check collision with player
if (upgrade.intersects(player)) {
LK.getSound('upgradePickup').play();
if (upgrade.type === 'RapidFire') {
playerUpgrades.rapidFire = true;
playerUpgrades.rapidFireTimer = 600; // 10 seconds
LK.effects.flashObject(player, 0x00ff00, 500);
} else if (upgrade.type === 'Shield') {
playerUpgrades.shield = true;
playerUpgrades.shieldTimer = 600; // 10 seconds
player.alpha = 0.7; // Make player semi-transparent to show shield
// Show shield visual effect
player.shieldGraphics.alpha = 0.6;
// Start pulsing animation for shield
tween(player.shieldGraphics, {
alpha: 0.3
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
if (playerUpgrades.shield) {
tween(player.shieldGraphics, {
alpha: 0.6
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: arguments.callee.caller
});
}
}
});
LK.effects.flashObject(player, 0x0080ff, 500);
} else if (upgrade.type === 'TripleShot') {
playerUpgrades.tripleShot = true;
playerUpgrades.tripleShotTimer = 600; // 10 seconds
LK.effects.flashObject(player, 0xff0080, 500);
}
upgrade.destroy();
upgrades.splice(i, 1);
continue;
}
upgrade.lastY = upgrade.y;
}
// Update and check enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy.lastY === undefined) enemy.lastY = enemy.y;
// Remove enemies that go off screen
if (enemy.lastY <= 2757 && enemy.y > 2757) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check collision with player
if (enemy.intersects(player)) {
if (!playerUpgrades.shield) {
LK.effects.flashScreen(0xff0000, 1000);
LK.getSound('playerHit').play();
LK.showGameOver();
return;
} else {
// Shield absorbs the hit and destroys the enemy
LK.setScore(LK.getScore() + 5); // Bonus points for shield collision
scoreTxt.setText(LK.getScore());
LK.effects.flashObject(player, 0x0080ff, 200);
enemy.destroy();
enemies.splice(i, 1);
continue;
}
}
enemy.lastY = enemy.y;
}
}; ===================================================================
--- original.js
+++ change.js
@@ -620,24 +620,44 @@
bullet.destroy();
bossBullets.splice(i, 1);
continue;
}
- // Check collision with player
- if (bullet.intersects(player)) {
- if (!playerUpgrades.shield) {
- LK.effects.flashScreen(0xff0000, 1000);
- LK.getSound('playerHit').play();
- LK.showGameOver();
- return;
- } else {
- // Shield absorbs the hit
+ var hitTarget = false;
+ // Check collision with enemy ships (boss bullets can destroy smaller ships)
+ for (var j = enemies.length - 1; j >= 0; j--) {
+ var enemy = enemies[j];
+ if (bullet.intersects(enemy)) {
+ // Enemy destroyed by boss bullet
+ LK.effects.flashObject(enemy, 0xffffff, 200);
bullet.destroy();
+ enemy.destroy();
bossBullets.splice(i, 1);
- LK.effects.flashObject(player, 0x0080ff, 200);
- continue;
+ enemies.splice(j, 1);
+ LK.getSound('enemyDestroy').play();
+ hitTarget = true;
+ break;
}
}
- bullet.lastY = bullet.y;
+ if (!hitTarget) {
+ // Check collision with player
+ if (bullet.intersects(player)) {
+ if (!playerUpgrades.shield) {
+ LK.effects.flashScreen(0xff0000, 1000);
+ LK.getSound('playerHit').play();
+ LK.showGameOver();
+ return;
+ } else {
+ // Shield absorbs the hit
+ bullet.destroy();
+ bossBullets.splice(i, 1);
+ LK.effects.flashObject(player, 0x0080ff, 200);
+ continue;
+ }
+ }
+ }
+ if (!hitTarget) {
+ bullet.lastY = bullet.y;
+ }
}
}
// Update and check enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {