/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Class for boss bullets with proper destruction
var BossBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bossBullet', {
anchorX: 0.5,
anchorY: 0.5
});
bulletGraphics.alpha = 0;
tween(bulletGraphics, {
alpha: 1
}, {
duration: 100
});
self.speed = 10;
self.update = function () {
self.y += self.speed;
if (self.y > 2732 + bulletGraphics.height && !self.removed) {
self.removed = true;
tween(bulletGraphics, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
self.destroy();
var index = bossBullets.indexOf(self);
if (index !== -1) {
bossBullets.splice(index, 1);
}
}
});
}
};
self.removed = false;
return self;
});
// Class for enemy bullets with increased speed
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self._move_migrated = function () {
self.y += 10; // Increased bullet speed
if (self.y > 2732) {
self.destroy(); // Destroy if off-screen
}
};
return self;
});
// Class for enemy ships with enhanced animation and movement patterns
var EnemyShip = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemyShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4; // Increased downward speed
self.health = 2; // Decreased health
self._move_migrated = function () {
self.y += self.speed; // Move downwards faster
// Remove automatic destruction when off-screen
self.x += Math.sin(self.y / 50) * 5; // Horizontal oscillation
};
// Randomly decide if this enemy will shoot
if (Math.random() < 0.7) {
// Increased chance to shoot
self.canShoot = true;
}
self.update = function () {
self._move_migrated();
};
self.hit = function () {
self.health--;
if (self.health <= 0) {
self.explode();
// Play destruction sound effect
LK.getSound('destroy').play();
return true; // Indicate that the enemy was destroyed
}
return false; // Indicate that the enemy was not destroyed
};
self.explode = function () {
// Play destruction sound effect
LK.getSound('destroy').play();
// Add special reward text
var explosion = new Container();
var explosionGraphics = explosion.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5
});
explosion.x = self.x;
explosion.y = self.y;
game.addChild(explosion);
tween(explosionGraphics, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Remove enemy ship
self.destroy();
var index = enemyShips.indexOf(self);
if (index !== -1) {
enemyShips.splice(index, 1);
}
};
return self;
});
// Class for tougher enemy ships with enhanced boss behaviors
var BossEnemy = EnemyShip.expand(function () {
var self = EnemyShip.call(this);
self.getChildAt(0).destroy(); // Remove the default enemy ship graphic
var bossGraphics = self.attachAsset('bossShip', {
// Attach new boss ship graphic
anchorX: 0.5,
anchorY: 0.5
});
// Make boss larger with pulsing effect
self.getChildAt(0).scale.set(0);
// More impressive boss entrance
tween(self.getChildAt(0).scale, {
x: 1.8,
y: 1.8
}, {
duration: 1200,
easing: tween.easeOutElastic
});
// Pulsing effect for the boss
LK.setInterval(function () {
tween(bossGraphics, {
alpha: 0.7
}, {
duration: 400,
onFinish: function onFinish() {
tween(bossGraphics, {
alpha: 1
}, {
duration: 400
});
}
});
}, 1000);
// Make boss tougher
self.health = 50; // Further increased boss health for more challenge
self.maxHealth = 50; // Store max health for phase transitions
self.speed = 1.5;
self.scoreValue = 10; // Increased score value
self.phase = 1; // Boss has multiple phases
self.movementPattern = 3; // Special boss pattern
self.attackCooldown = 0;
self.attackType = 0; // Different attack types
// Boss attack patterns
self.shoot = function () {
self.attackCooldown = 60; // Set initial cooldown for shooting
switch (self.attackType) {
case 0:
// Single shot
var bullet = new BossBullet();
bullet.x = self.x;
bullet.y = self.y + self.getChildAt(0).height / 2;
bullet.speed = 10;
game.addChild(bullet);
bossBullets.push(bullet);
break;
case 1:
// Triple shot spread
for (var i = -1; i <= 1; i++) {
var bullet = new BossBullet();
bullet.x = self.x + i * 50;
bullet.y = self.y + self.getChildAt(0).height / 2;
bullet.speed = 8;
game.addChild(bullet);
bossBullets.push(bullet);
}
break;
case 2:
// Circle shot
var bulletCount = 16; // Increased bullet count for bullet hell
for (var i = 0; i < bulletCount; i++) {
var angle = Math.PI * 2 / bulletCount * i;
var bullet = new BossBullet();
bullet.x = self.x;
bullet.y = self.y;
// Initial position adjustment for circle pattern
bullet.x += Math.cos(angle) * 70;
bullet.y += Math.sin(angle) * 70;
// Custom update for circular bullets
var originalUpdate = bullet.update;
bullet.angle = angle;
bullet.update = function () {
this.x += Math.cos(this.angle) * 5;
this.y += Math.sin(this.angle) * 5;
// Boss shooting logic
self.attackCooldown--;
if (self.attackCooldown <= 0) {
self.shoot();
self.attackCooldown = 60; // Reset cooldown after shooting
}
originalUpdate.call(this);
};
game.addChild(bullet);
bossBullets.push(bullet);
}
break;
}
// Visual effect for shooting
var flash = new Container();
var flashGraphics = flash.attachAsset('flash', {
anchorX: 0.5,
anchorY: 0.5
});
flash.x = self.x;
flash.y = self.y + self.getChildAt(0).height / 3;
flash.scale.set(2);
game.addChild(flash);
tween(flash, {
alpha: 0,
scale: 3
}, {
duration: 300,
onFinish: function onFinish() {
flash.destroy();
}
});
};
// Override update method for boss-specific behavior
var parentUpdate = self.update;
self.update = function () {
// Update phase based on health percentage
var healthPercent = self.health / self.maxHealth;
if (healthPercent < 0.5 && self.phase === 1) {
self.transitionToPhase(2);
} else if (healthPercent < 0.25 && self.phase === 2) {
self.transitionToPhase(3);
}
// Teleportation and invisibility logic
if (LK.ticks % 500 === 0) {
self.x = Math.random() * 2048;
self.y = Math.random() * 1000;
bossGraphics.alpha = 0;
LK.setTimeout(function () {
bossGraphics.alpha = 1;
}, 500);
}
// Activate weak points at specific intervals
if (LK.ticks % 1000 === 0 && !self.weakPointActive) {
self.weakPointActive = true;
self.weakPointHealth = 3; // Weak point requires 3 hits
// Visual indication of weak point
var weakPoint = new Container();
var weakPointGraphics = weakPoint.attachAsset('flash', {
anchorX: 0.5,
anchorY: 0.5
});
weakPoint.x = self.x;
weakPoint.y = self.y;
game.addChild(weakPoint);
tween(weakPointGraphics, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
weakPoint.destroy();
}
});
}
// Phase-specific movement patterns
switch (self.phase) {
case 1:
// Phase 1: Hover at top, side to side
if (self.y < 400) {
self.y += self.speed;
} else {
// Wide side-to-side movement
self.x = 2048 / 2 + Math.sin(LK.ticks / 100) * 800;
// Attack cooldown
self.attackCooldown--;
if (self.attackCooldown <= 0) {
self.attackType = 0; // Single shot in phase 1
self.shoot();
self.attackCooldown = 120; // Faster attacks in phase 1
}
}
break;
case 2:
// Phase 2: Aggressive movement, triple shots
// Figure-8 movement pattern
var t = LK.ticks / 150;
self.x = 2048 / 2 + Math.sin(t) * 600;
self.y = 500 + Math.sin(t * 2) * 200;
// Boss slightly tilts in direction of movement
var dx = Math.cos(t) * 600;
var tilt = dx * 0.0001;
bossGraphics.rotation = tilt;
// Attack cooldown
self.attackCooldown--;
if (self.attackCooldown <= 0) {
self.attackType = 1; // Triple shot in phase 2
self.shoot();
self.attackCooldown = 100;
}
break;
case 3:
// Phase 3: Erratic movement, circle shots
// Erratic movement with zig-zag and sudden dashes
var t = LK.ticks / 100;
self.x = 2048 / 2 + Math.sin(t) * 500 + Math.cos(t * 2.5) * 300 + (Math.random() - 0.5) * 50;
self.y = 500 + Math.sin(t * 1.5) * 300 + (Math.random() - 0.5) * 50;
// Dramatic rotation
bossGraphics.rotation = Math.sin(t) * 0.2;
// Attack cooldown - mix of attack types
self.attackCooldown--;
if (self.attackCooldown <= 0) {
// Alternate between triple and circle shots
self.attackType = LK.ticks % 300 < 150 ? 1 : 2;
self.shoot();
self.attackCooldown = 80; // Even faster attacks in final phase
}
break;
}
};
// Phase transition effects
self.transitionToPhase = function (newPhase) {
self.phase = newPhase;
// Visual effect for phase transition
bossGraphics.tint = 0xFF0000;
// Dramatic shake effect
var originalX = self.x;
var originalY = self.y;
var shakeAmount = 30;
var shakeTimes = 0;
var shakeInterval = LK.setInterval(function () {
self.x = originalX + (Math.random() * shakeAmount - shakeAmount / 2);
self.y = originalY + (Math.random() * shakeAmount - shakeAmount / 2);
shakeAmount *= 0.8;
shakeTimes++;
if (shakeTimes >= 12) {
LK.clearInterval(shakeInterval);
self.x = originalX;
self.y = originalY;
// Reset tint after shake
tween(bossGraphics, {
tint: 0xFFFFFF
}, {
duration: 500
});
}
}, 50);
// Phase transition announcement
var phaseText = new Text2('PHASE ' + newPhase, {
size: 200,
fill: 0xFF0000
});
phaseText.anchor.set(0.5, 0.5);
phaseText.x = 2048 / 2;
phaseText.y = 2732 / 2;
phaseText.alpha = 0;
game.addChild(phaseText);
// Animate phase text
tween(phaseText, {
alpha: 1
}, {
duration: 300,
onFinish: function onFinish() {
tween(phaseText, {
alpha: 0,
y: phaseText.y - 100
}, {
duration: 700,
delay: 500,
onFinish: function onFinish() {
phaseText.destroy();
}
});
}
});
// Create surrounding explosions for dramatic effect
for (var i = 0; i < 8; i++) {
var delay = i * 100;
LK.setTimeout(function () {
var explosion = new Container();
var explosionGraphics = explosion.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5
});
var angle = Math.random() * Math.PI * 2;
var distance = 150 + Math.random() * 150;
explosion.x = self.x + Math.cos(angle) * distance;
explosion.y = self.y + Math.sin(angle) * distance;
explosionGraphics.scale.set(0.5);
game.addChild(explosion);
tween(explosionGraphics.scale, {
x: 1.5,
y: 1.5
}, {
duration: 500
});
tween(explosionGraphics, {
alpha: 0
}, {
duration: 800,
onFinish: function onFinish() {
explosion.destroy();
}
});
}, delay);
}
};
// Override hit method for boss-specific effect
var parentHit = self.hit;
self.hit = function () {
// Flash the boss with a different color on each hit
var hitColors = [0xFF0000, 0x00FF00, 0x0000FF, 0xFFFF00, 0xFF00FF];
var colorIndex = Math.floor(Math.random() * hitColors.length);
bossGraphics.tint = hitColors[colorIndex];
// Flash the screen slightly
var flashOverlay = new Container();
var flashGraphics = flashOverlay.attachAsset('flash', {
anchorX: 0.5,
anchorY: 0.5
});
flashOverlay.x = 2048 / 2;
flashOverlay.y = 2732 / 2;
flashOverlay.scale.set(3);
flashOverlay.alpha = 0.3;
game.addChild(flashOverlay);
// Remove the flash overlay
LK.setTimeout(function () {
game.removeChild(flashOverlay);
flashOverlay.destroy();
}, 100);
// Reset tint after a short delay
LK.setTimeout(function () {
bossGraphics.tint = 0xFFFFFF;
}, 200);
// Check for weak point hit
if (self.weakPointActive) {
self.weakPointHealth--;
if (self.weakPointHealth <= 0) {
self.weakPointActive = false;
// Destroy weak point and deal damage to boss
self.health -= 5;
}
}
return parentHit.call(self);
};
// Enhanced explode method for epic boss death
var parentExplode = self.explode;
self.explode = function () {
// Create multiple explosions in sequence
var explosionCount = 20;
var interval = LK.setInterval(function () {
var explosion = new Container();
var explosionGraphics = explosion.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5
});
explosion.x = self.x + (Math.random() * 200 - 100);
explosion.y = self.y + (Math.random() * 200 - 100);
var randomScale = 0.5 + Math.random() * 1.5;
explosionGraphics.scale.set(randomScale);
game.addChild(explosion);
tween(explosionGraphics, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
explosion.destroy();
}
});
explosionCount--;
if (explosionCount <= 0) {
LK.clearInterval(interval);
// Add special reward text
var victoryText = new Text2('BOSS DEFEATED!', {
size: 250,
fill: 0xFFD700 // Gold color
});
victoryText.anchor.set(0.5, 0.5);
victoryText.x = 2048 / 2;
victoryText.y = 2732 / 2;
victoryText.alpha = 0;
game.addChild(victoryText);
tween(victoryText, {
alpha: 1,
y: victoryText.y - 50
}, {
duration: 800,
easing: tween.easeOutElastic,
onFinish: function onFinish() {
LK.setTimeout(function () {
tween(victoryText, {
alpha: 0,
y: victoryText.y - 100
}, {
duration: 1000,
onFinish: function onFinish() {
victoryText.destroy();
}
});
}, 1500);
}
});
// Finally call parent explode to remove boss and add score
parentExplode.call(self);
// Add bonus score for defeating boss
increaseScore(20);
}
}, 150);
};
return self;
});
// Class for player bullets with proper destruction
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
// Enhanced bullet appearance
bulletGraphics.alpha = 0;
tween(bulletGraphics, {
alpha: 1
}, {
duration: 100
});
self.speed = -15;
self.update = function () {
self.y += self.speed;
// Add slight wobble to bullets
self.x += Math.sin(LK.ticks / 10) * 0.5;
if (self.y < -bulletGraphics.height && !self.removed) {
self.removed = true;
// Fade out bullets that miss
tween(bulletGraphics, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
self.destroy();
var index = playerBullets.indexOf(self);
if (index !== -1) {
playerBullets.splice(index, 1);
}
}
});
}
};
self.removed = false;
return self;
});
// Class for the player's ship with enhanced movement and effects
var PlayerShip = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10;
self.canShoot = true; // Prevents spam shooting
self.shootCooldown = 150; // Reduced cooldown for faster shooting
self.lives = 3; // Player starts with 3 lives
self.invulnerable = false; // Invulnerability after being hit
self.targetX = null; // Target X position for smooth movement
self.targetY = null; // Target Y position for smooth movement
// Player ship entrance animation
shipGraphics.alpha = 0;
shipGraphics.y = 100;
tween(shipGraphics, {
alpha: 1,
y: 0
}, {
duration: 1000,
easing: tween.easeOutQuad
});
self.shoot = function () {
if (self.canShoot) {
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - shipGraphics.height / 2;
game.addChild(bullet);
playerBullets.push(bullet);
// Play shooting sound effect
LK.getSound('shoot').play();
// Add muzzle flash effect
var flash = new Container();
var flashGraphics = flash.attachAsset('flash', {
anchorX: 0.5,
anchorY: 0.5
});
flash.x = self.x;
flash.y = self.y - shipGraphics.height / 2;
game.addChild(flash);
// Animate and remove flash
tween(flash.scale, {
x: 0,
y: 0
}, {
duration: 200,
onFinish: function onFinish() {
flash.destroy();
}
});
// Add slight recoil effect
tween(shipGraphics, {
y: 5
}, {
duration: 50,
onFinish: function onFinish() {
tween(shipGraphics, {
y: 0
}, {
duration: 100
});
}
});
self.canShoot = false;
LK.setTimeout(function () {
self.canShoot = true;
}, self.shootCooldown);
}
};
self.hit = function () {
if (self.invulnerable) {
return;
}
self.lives--;
updateLivesDisplay();
if (self.lives <= 0) {
// Add dramatic death animation
var explosions = 5;
var explodeInterval = LK.setInterval(function () {
var explosion = new Container();
var explosionGraphics = explosion.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5
});
explosion.x = self.x + (Math.random() * 100 - 50);
explosion.y = self.y + (Math.random() * 100 - 50);
explosionGraphics.scale.set(0.1);
explosionGraphics.alpha = 0.8;
game.addChild(explosion);
tween(explosionGraphics.scale, {
x: 1,
y: 1
}, {
duration: 500
});
tween(explosionGraphics, {
alpha: 0
}, {
duration: 800,
onFinish: function onFinish() {
explosion.destroy();
}
});
explosions--;
if (explosions <= 0) {
LK.clearInterval(explodeInterval);
self.visible = false;
LK.showGameOver();
}
}, 150);
return;
}
// Make player invulnerable temporarily
self.invulnerable = true;
// Enhanced hit effect with shake
var originalX = self.x;
var shakeAmount = 15;
var shakeTimes = 0;
var shakeInterval = LK.setInterval(function () {
self.x = originalX + (Math.random() * shakeAmount - shakeAmount / 2);
shakeAmount *= 0.9;
shakeTimes++;
if (shakeTimes >= 10) {
LK.clearInterval(shakeInterval);
self.x = originalX;
}
}, 50);
// Flash effect
var flashCount = 0;
var flashInterval = LK.setInterval(function () {
shipGraphics.alpha = shipGraphics.alpha === 1 ? 0.3 : 1;
flashCount++;
if (flashCount >= 10) {
LK.clearInterval(flashInterval);
shipGraphics.alpha = 1;
self.invulnerable = false;
}
}, 150);
};
// Move player ship to target position with smooth animation
self.moveToPosition = function (x, y) {
self.targetX = x;
self.targetY = y;
};
self.update = function () {
// Smooth movement toward target position
if (self.targetX !== null && self.targetY !== null) {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
// Only move if the distance is significant
if (Math.abs(dx) > 1 || Math.abs(dy) > 1) {
self.x += dx * 0.1;
self.y += dy * 0.1;
// Slight tilt effect based on horizontal movement
var tiltAmount = -dx * 0.0005;
tiltAmount = Math.max(-0.2, Math.min(0.2, tiltAmount));
shipGraphics.rotation = tiltAmount;
} else {
// Reached target, reset rotation
shipGraphics.rotation = 0;
}
}
// Check for collisions with enemies if not invulnerable
if (!self.invulnerable) {
// Check for collisions with enemy ships
for (var i = 0; i < enemyShips.length; i++) {
if (self.intersects(enemyShips[i])) {
self.hit();
enemyShips[i].explode();
break;
}
}
// Check for collisions with power-ups
for (var i = 0; i < powerUps.length; i++) {
if (self.intersects(powerUps[i])) {
if (powerUps[i].type === 'fireRate') {
self.shootCooldown = 75; // Increase fire rate
LK.setTimeout(function () {
self.shootCooldown = 150; // Reset fire rate after 15 seconds
}, 15000);
}
powerUps[i].destroy();
powerUps.splice(i, 1);
}
}
// Check collisions with boss bullets
for (var j = 0; j < bossBullets.length; j++) {
if (bossBullets[j] && self.intersects(bossBullets[j])) {
self.hit();
// Remove the bullet
bossBullets[j].destroy();
bossBullets.splice(j, 1);
break;
}
}
}
};
return self;
});
// Class for power-up items
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'fireRate'; // Type of power-up
self.update = function () {
self.y += 5; // Move power-up downwards
if (self.y > 2732 + powerUpGraphics.height && !self.removed) {
self.removed = true;
self.destroy();
}
};
self.removed = false;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Initialize destruction sound
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChild(background);
LK.playMusic('bgMusic', {
loop: true,
fade: {
start: 0.5,
end: 1,
duration: 1000
}
});
/****
* Game Variables
****/
var playerBullets = [];
var powerUps = [];
var bossBullets = [];
var enemyShips = [];
var player = game.addChild(new PlayerShip());
player.x = 2048 / 2;
player.y = 2732 - 200;
// Score Display
var scoreText = new Text2('0', {
size: 150,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
scoreText.x = 2048 / 2;
scoreText.y = 50;
LK.gui.top.addChild(scoreText);
// Lives Display
var livesText = new Text2('Lives: 3', {
size: 100,
fill: 0xFFFFFF
});
livesText.anchor.set(0, 0);
livesText.x = 50;
livesText.y = 50;
LK.gui.top.addChild(livesText);
// Wave Display
var waveText = new Text2('Wave: 1', {
size: 100,
fill: 0xFFFFFF
});
waveText.anchor.set(1, 0);
waveText.x = 2048 - 50;
waveText.y = 50;
LK.gui.top.addChild(waveText);
// Wave Variables
var waveNumber = 1;
var enemiesPerWave = 5;
var enemiesSpawned = 0;
var waveInProgress = true;
var waveCooldown = false;
// Helper Functions
function updateLivesDisplay() {
livesText.setText('Lives: ' + player.lives);
}
function increaseScore(amount) {
LK.setScore(LK.getScore() + amount);
scoreText.setText(LK.getScore());
}
function updateWaveDisplay() {
waveText.setText('Wave: ' + waveNumber);
}
// Function to spawn enemies in waves with enhanced patterns
function spawnEnemy() {
if (!waveInProgress || waveCooldown) {
return;
}
if (enemiesSpawned < enemiesPerWave) {
if (waveNumber % 2 === 0) {
// Create a grid of stationary enemy ships
var rows = 3; // Set to 3 rows
var cols = 5; // Set to 5 columns
var spacingX = (2048 - 190 * cols) / (cols + 1); // Adjust spacing to fit within screen
var spacingY = 500 / (rows + 1);
for (var row = 0; row < rows; row++) {
for (var col = 0; col < cols; col++) {
var enemy = new EnemyShip();
enemy.x = spacingX * (col + 1) + 190 / 2; // Center enemy ship
enemy.y = spacingY * (row + 1) + 100; // Adjust Y position to center vertically
game.addChild(enemy);
enemyShips.push(enemy);
}
}
enemiesSpawned = enemiesPerWave; // Skip further spawning
waveInProgress = false;
return;
}
// Spawn regular enemies for odd waves
var enemy = new EnemyShip();
enemy.x = 200 + Math.random() * (2048 - 400); // Random position, avoiding edges
enemy.y = -100; // Start off-screen
game.addChild(enemy);
enemyShips.push(enemy);
enemiesSpawned++;
if (enemiesSpawned >= enemiesPerWave) {
waveInProgress = false;
}
}
}
// Function to start the next wave with enhanced announcement
function startNextWave() {
waveNumber++;
updateWaveDisplay();
// Remove all existing enemy ships
enemyShips.forEach(function (enemy) {
enemy.destroy();
});
enemyShips = [];
// Check if it's the 5th wave or a multiple of 5
if (waveNumber % 5 === 0) {
// Show warning message before boss appears
var warningText = new Text2('WARNING: BOSS INCOMING!', {
size: 200,
fill: 0xFF0000
});
warningText.anchor.set(0.5, 0.5);
warningText.x = 2048 / 2;
warningText.y = 2732 / 2;
game.addChild(warningText);
// Animate and remove warning text
tween(warningText, {
alpha: 0,
y: warningText.y - 100
}, {
duration: 1000,
onFinish: function onFinish() {
warningText.destroy();
// Spawn boss after warning
var boss = new BossEnemy();
boss.x = 2048 / 2;
boss.y = -boss.getChildAt(0).height / 2;
game.addChild(boss);
enemyShips.push(boss);
}
});
return; // Skip regular wave setup
}
// Increase difficulty parameters
enemiesPerWave += 2; // Increase number of enemies per wave
EnemyShip.prototype.speed += 0.5; // Increase speed by 0.5 each wave
EnemyShip.prototype.health += 1; // Increase health by 1 each wave
enemiesSpawned = 0;
waveInProgress = true;
// Spawn a power-up in every odd wave
if (waveNumber % 2 !== 0) {
var powerUp = new PowerUp();
powerUp.x = Math.random() * 2048; // Random x position
powerUp.y = -200; // Start off-screen
game.addChild(powerUp);
powerUps.push(powerUp);
}
// Change background after each wave
var backgroundId = 'background';
if (waveNumber % 3 === 1) {
backgroundId = 'background2';
} else if (waveNumber % 3 === 2) {
backgroundId = 'background3';
} else if (waveNumber % 3 === 0) {
backgroundId = 'background4';
}
background.destroy();
background = LK.getAsset(backgroundId, {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
game.addChildAt(background, 0);
// Enhanced wave announcement with scaling and color
var newWaveText = new Text2('WAVE ' + waveNumber, {
size: 250,
fill: 0x00FFFF
});
newWaveText.anchor.set(0.5, 0.5);
newWaveText.x = 2048 / 2;
newWaveText.y = 2732 / 2;
newWaveText.scale.set(0.5);
game.addChild(newWaveText);
// Animate and remove wave text
tween(newWaveText.scale, {
x: 1.8,
y: 1.8
}, {
duration: 800,
easing: tween.easeOutElastic,
onFinish: function onFinish() {
tween(newWaveText, {
alpha: 0,
y: newWaveText.y - 100
}, {
duration: 500,
easing: tween.easeInQuad,
onFinish: function onFinish() {
newWaveText.destroy();
}
});
}
});
}
// Game update loop
game.update = function () {
// Update player
player.update();
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
if (playerBullets[i]) {
playerBullets[i].update();
}
}
// Update boss bullets
for (var i = bossBullets.length - 1; i >= 0; i--) {
if (bossBullets[i]) {
bossBullets[i].update();
}
}
for (var j = enemyShips.length - 1; j >= 0; j--) {
if (enemyShips[j]) {
enemyShips[j].update();
}
}
// Check for collisions between player bullets and enemy ships
for (var k = playerBullets.length - 1; k >= 0; k--) {
if (!playerBullets[k]) {
continue;
}
for (var l = enemyShips.length - 1; l >= 0; l--) {
if (!enemyShips[l]) {
continue;
}
if (playerBullets[k] && enemyShips[l] && playerBullets[k].intersects(enemyShips[l])) {
// Enemy hit by bullet
var destroyed = enemyShips[l].hit();
// Remove bullet
playerBullets[k].destroy();
playerBullets.splice(k, 1);
break;
}
}
}
// Spawn enemies periodically
if (LK.ticks % 60 === 0) {
spawnEnemy();
}
// Check if wave is complete and start next wave
var allEnemiesOffScreen = enemyShips.every(function (enemy) {
return enemy.y > 2732;
});
if (!waveInProgress && allEnemiesOffScreen && !waveCooldown) {
waveCooldown = true;
// Spawn a power-up in every odd wave after all enemies are off-screen
if (waveNumber % 2 !== 0) {
var powerUp = new PowerUp();
powerUp.x = player.x; // Align with player x position
powerUp.y = player.y - 100; // Spawn closer above player
game.addChild(powerUp);
powerUps.push(powerUp);
}
LK.setTimeout(function () {
startNextWave();
waveCooldown = false;
}, 2000);
}
};
// Handle player movement - Update to allow free movement
game.move = function (x, y, obj) {
// Set target position for smooth movement anywhere on screen
player.moveToPosition(x, y);
};
// Handle shooting
game.down = function (x, y, obj) {
player.shoot();
};
// Continuous shooting for the player ship
var shootingInterval = LK.setInterval(function () {
player.shoot();
}, 150); // Match the reduced cooldown
A 2D top-down view of a futuristic player spaceship with a streamlined silver and blue body, glowing thrusters, and dual laser cannons. The design is sleek and modern for a space shooter game. Single Game Texture. 2d. Blank background. High contrast. No shadows
A 2D top-down view of an alien spaceship with a dark metallic body, glowing red energy cores, and sharp angular wings. The design is sleek and futuristic, suitable for a space shooter game.. Single Game Texture. 2d. Blank background. High contrast. No shadows
A 2D top-down view of a futuristic energy bullet for a space shooter game. The bullet is a glowing blue plasma projectile with a sleek, elongated shape and a slight energy trail behind it. The design is simple, bright, and high-speed-looking, suitable for fast-paced shooting gameplay. Single Game Texture. In-Game asset. Blank background. High contrast. No shadows
A 2D top-down view of a futuristic energy bullet for a space shooter game. The bullet is a glowing red plasma projectile elongated shape and a slight energy trail behind it. The design is simple, bright, and high-speed-looking, suitable for fast-paced shooting gameplay. Single Game Texture. In-Game asset. Blank background. High contrast. No shadows
A vibrant and dynamic 2D space background for a top-down space shooter game. The scene features a deep, dark space filled with glowing nebulae in shades of blue and purple, scattered distant stars, and swirling cosmic dust. A subtle parallax effect is suggested with faintly glowing planets and asteroids in the background. The atmosphere is slightly mysterious and futuristic, with soft light gradients to create depth. The overall tone is immersive but does not distract from gameplay, ensuring clear visibility of player and enemy ships.. Single Game Texture. Blank background. High contrast. No shadows
A vibrant and dynamic 2D space background for a top-down space shooter game. The scene features a deep, dark space filled with glowing nebulae in shades of blue and purple, scattered distant stars, and swirling cosmic dust. A subtle parallax effect is suggested with faintly glowing planets and asteroids in the background. The atmosphere is slightly mysterious and futuristic, with soft light gradients to create depth. The overall tone is immersive but does not distract from gameplay, ensuring clear visibility of player and enemy ships.. Single Game Texture. Blank background. High contrast. No shadows
powerup boll. Single Game Texture. Blank background. High contrast. No shadows