/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 20;
self.maxHealth = 20;
self.points = 2000;
self.speed = 1;
self.phase = 1;
self.fireRate = 60; // Frames between shots
self.lastShot = 0;
self.movementTimer = 0;
self.attacking = false;
self.update = function () {
// Boss enters from top
if (self.y < 400) {
self.y += self.speed;
} else {
self.attacking = true;
// Phase-based movement
if (self.phase === 1) {
// Side-to-side movement
self.x += Math.sin(self.movementTimer / 30) * 5;
self.movementTimer++;
// Regular shooting
self.lastShot++;
if (self.lastShot >= self.fireRate) {
self.shoot();
self.lastShot = 0;
}
} else if (self.phase === 2) {
// More aggressive movement
self.x += Math.sin(self.movementTimer / 20) * 7;
self.y += Math.cos(self.movementTimer / 40) * 2;
self.movementTimer++;
// More frequent shooting
self.lastShot++;
if (self.lastShot >= self.fireRate * 0.7) {
self.shoot();
self.lastShot = 0;
}
} else if (self.phase === 3) {
// Erratic movement
self.x += Math.sin(self.movementTimer / 10) * 8;
self.y += Math.cos(self.movementTimer / 15) * 3;
self.movementTimer++;
// Rapid shooting
self.lastShot++;
if (self.lastShot >= self.fireRate * 0.4) {
self.shoot();
self.lastShot = 0;
}
}
}
// Change phase based on health with enhanced visual feedback
if (self.health <= self.maxHealth * 0.65 && self.phase === 1) {
self.phase = 2;
LK.effects.flashObject(self, 0xff0000, 500);
// Add dramatic phase change effect
bossGraphics.tint = 0xff6600; // Change to orange glow
// Create multiple explosions around boss
for (var i = 0; i < 3; i++) {
var damageExplosion = new Explosion();
damageExplosion.x = self.x + (Math.random() * 120 - 60);
damageExplosion.y = self.y + (Math.random() * 80 - 40);
game.addChild(damageExplosion);
}
} else if (self.health <= self.maxHealth * 0.3 && self.phase === 2) {
self.phase = 3;
LK.effects.flashObject(self, 0xff0000, 500);
// More dramatic effect for final phase
bossGraphics.tint = 0xff0000; // Change to red glow
bossGraphics.scale.x = 1.1; // Slightly expand
bossGraphics.scale.y = 1.1;
// Create more explosions for critical damage
for (var i = 0; i < 5; i++) {
var damageExplosion = new Explosion();
damageExplosion.x = self.x + (Math.random() * 160 - 80);
damageExplosion.y = self.y + (Math.random() * 100 - 50);
game.addChild(damageExplosion);
}
}
};
self.shoot = function () {
// Different shot patterns based on phase
if (self.phase === 1) {
// Single shot
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 80;
game.addChild(bullet);
enemyBullets.push(bullet);
} else if (self.phase === 2) {
// Double shot
for (var i = -1; i <= 1; i += 2) {
var bullet = new EnemyBullet();
bullet.x = self.x + i * 50;
bullet.y = self.y + 80;
game.addChild(bullet);
enemyBullets.push(bullet);
}
} else if (self.phase === 3) {
// Triple shot
for (var i = -1; i <= 1; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x + i * 50;
bullet.y = self.y + 80;
game.addChild(bullet);
enemyBullets.push(bullet);
}
}
LK.getSound('enemyShoot').play();
};
self.takeDamage = function (amount) {
self.health -= amount;
// Flash when taking damage
LK.effects.flashObject(self, 0xffffff, 200);
if (self.health <= 0) {
// Multiple explosions for boss
for (var i = 0; i < 5; i++) {
var explosion = new Explosion();
explosion.x = self.x + (Math.random() * 200 - 100);
explosion.y = self.y + (Math.random() * 100 - 50);
game.addChild(explosion);
}
// Add points to score
score += self.points;
updateScore();
// Boss drops multiple power-ups
// Drop advanced weapon power-up based on level
var weaponPowerUp = new PowerUp();
weaponPowerUp.x = self.x - 60;
weaponPowerUp.y = self.y;
if (level >= 3) {
weaponPowerUp.setType("plasma");
} else {
weaponPowerUp.setType("laser");
}
game.addChild(weaponPowerUp);
powerUps.push(weaponPowerUp);
// Drop shield power-up
var shieldPowerUp = new PowerUp();
shieldPowerUp.x = self.x + 60;
shieldPowerUp.y = self.y;
shieldPowerUp.setType("shield");
game.addChild(shieldPowerUp);
powerUps.push(shieldPowerUp);
LK.getSound('explosion').play();
// Level complete
levelComplete = true;
self.destroy();
return true;
}
return false;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemyShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1;
self.points = 100;
self.speed = 2;
self.fireRate = 180; // Frames between shots
self.lastShot = 0;
self.movementPattern = "straight"; // Default movement
self.movementTimer = 0;
self.update = function () {
// Handle movement patterns
if (self.movementPattern === "straight") {
self.y += self.speed;
} else if (self.movementPattern === "zigzag") {
self.y += self.speed;
self.x += Math.sin(self.movementTimer / 20) * 3;
self.movementTimer++;
} else if (self.movementPattern === "circle") {
self.y += self.speed * 0.7;
self.x += Math.sin(self.movementTimer / 15) * 4;
self.movementTimer++;
}
// Shooting logic
self.lastShot++;
if (self.lastShot >= self.fireRate && self.y > 0 && Math.random() < 0.3) {
self.shoot();
self.lastShot = 0;
}
};
self.shoot = function () {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 40;
game.addChild(bullet);
enemyBullets.push(bullet);
LK.getSound('enemyShoot').play();
};
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health <= 0) {
// Create explosion
var explosion = new Explosion();
explosion.x = self.x;
explosion.y = self.y;
game.addChild(explosion);
// Add points to score
score += self.points;
updateScore();
// Random chance to drop power-up
if (Math.random() < 0.1) {
var powerUp = new PowerUp();
powerUp.x = self.x;
powerUp.y = self.y;
// Random power-up type
var rand = Math.random();
if (rand < 0.5) {
powerUp.setType("weapon");
} else if (rand < 0.8) {
powerUp.setType("shield");
} else if (level >= 2) {
// Special weapon drops in higher levels
if (level >= 3 && rand < 0.9) {
powerUp.setType("plasma");
} else {
powerUp.setType("laser");
}
}
game.addChild(powerUp);
powerUps.push(powerUp);
}
LK.getSound('explosion').play();
self.destroy();
return true;
}
return false;
};
return self;
});
var ScoutShip = Enemy.expand(function () {
var self = Enemy.call(this);
// Replace default graphics with scout ship graphics
self.removeChild(self.children[0]);
var shipGraphics = self.attachAsset('scoutShip', {
anchorX: 0.5,
anchorY: 0.5
});
// Set scout-specific properties
self.health = 1;
self.points = 150;
self.speed = 4; // Faster movement
self.fireRate = 240; // Shoots less frequently
self.movementPattern = "erratic";
// Override update method for erratic movement
var originalUpdate = self.update;
self.update = function () {
if (self.movementPattern === "erratic") {
self.y += self.speed;
self.x += Math.sin(self.movementTimer / 10) * 6;
self.movementTimer++;
} else {
// Use original update for other movement patterns
originalUpdate.call(self);
}
// Handle shooting with lower probability
self.lastShot++;
if (self.lastShot >= self.fireRate && self.y > 0 && Math.random() < 0.2) {
self.shoot();
self.lastShot = 0;
}
};
return self;
});
var EliteScoutShip = ScoutShip.expand(function () {
var self = ScoutShip.call(this);
// Replace graphics with recolored version
self.removeChild(self.children[0]);
var shipGraphics = self.attachAsset('scoutShip', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x33ffff,
scaleX: 1.3,
scaleY: 1.3
});
// Enhanced elite properties
self.health = 3;
self.points = 350;
self.speed = 6; // Even faster
// Override update for more complex movement
var originalUpdate = self.update;
self.update = function () {
// Teleport-like rapid movement changes
if (LK.ticks % 90 === 0 && self.y > 200) {
// Create a flicker effect before "teleporting"
shipGraphics.alpha = 0.5;
// Schedule the "teleport"
LK.setTimeout(function () {
// Random new position
self.x = 300 + Math.random() * (2048 - 600);
shipGraphics.alpha = 1;
// Create visual effect at new position
var flashEffect = new Explosion();
flashEffect.x = self.x;
flashEffect.y = self.y;
game.addChild(flashEffect);
}, 20);
}
// Use original movement pattern with more extreme values
self.y += self.speed;
self.x += Math.sin(self.movementTimer / 8) * 8;
self.movementTimer++;
// Fire more bullets in a spread pattern
self.lastShot++;
if (self.lastShot >= self.fireRate && self.y > 0 && Math.random() < 0.3) {
// Triple spread shot
for (var i = -1; i <= 1; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x + i * 20;
bullet.y = self.y + 40;
// Angled shots
var angle = Math.PI / 2 + i * 0.3;
bullet.speedX = Math.cos(angle) * 10;
bullet.speedY = Math.sin(angle) * 10;
// Override update for angled movement
bullet.update = function () {
this.x += this.speedX;
this.y += this.speedY;
};
game.addChild(bullet);
enemyBullets.push(bullet);
}
LK.getSound('enemyShoot').play();
self.lastShot = 0;
}
};
return self;
});
var HunterShip = Enemy.expand(function () {
var self = Enemy.call(this);
// Replace default graphics with hunter ship graphics
self.removeChild(self.children[0]);
var shipGraphics = self.attachAsset('hunterShip', {
anchorX: 0.5,
anchorY: 0.5
});
// Set hunter-specific properties
self.health = 3;
self.points = 250;
self.speed = 3;
self.fireRate = 100; // Fires more frequently
self.movementPattern = "pursuit"; // New movement pattern that follows player
// Override update method to add pursuit behavior
var originalUpdate = self.update;
self.update = function () {
if (self.movementPattern === "pursuit") {
// Move towards player's x position
if (player.x > self.x) {
self.x += Math.min(self.speed * 0.7, player.x - self.x);
} else if (player.x < self.x) {
self.x -= Math.min(self.speed * 0.7, self.x - player.x);
}
self.y += self.speed * 0.8;
} else {
// Use original update for other movement patterns
originalUpdate.call(self);
}
// Handle shooting regardless of movement pattern
self.lastShot++;
if (self.lastShot >= self.fireRate && self.y > 0 && Math.random() < 0.4) {
self.shoot();
self.lastShot = 0;
}
};
return self;
});
var EliteHunterShip = HunterShip.expand(function () {
var self = HunterShip.call(this);
// Replace graphics with recolored version
self.removeChild(self.children[0]);
var shipGraphics = self.attachAsset('hunterShip', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xff3300,
scaleX: 1.2,
scaleY: 1.2
});
// Enhanced elite properties
self.health = 5;
self.points = 500;
self.speed = 4;
self.fireRate = 70;
// Override update for more aggressive behavior
var originalUpdate = self.update;
self.update = function () {
if (self.movementPattern === "pursuit") {
// More aggressive pursuit
var targetX = player.x;
var dx = targetX - self.x;
self.x += dx * 0.05; // More precise tracking
self.y += self.speed * 0.9;
// Rotate slightly toward movement direction
shipGraphics.rotation = dx * 0.003;
} else {
originalUpdate.call(self);
}
// More frequent shooting with double bullets
self.lastShot++;
if (self.lastShot >= self.fireRate && self.y > 0 && Math.random() < 0.5) {
self.shoot();
// Add slight delay for second shot
LK.setTimeout(function () {
self.shoot();
}, 10);
self.lastShot = 0;
}
};
return self;
});
var CarrierShip = Enemy.expand(function () {
var self = Enemy.call(this);
// Replace default graphics with carrier ship graphics
self.removeChild(self.children[0]);
var shipGraphics = self.attachAsset('carrierShip', {
anchorX: 0.5,
anchorY: 0.5
});
// Set carrier-specific properties
self.health = 5;
self.points = 400;
self.speed = 1; // Slower movement
self.fireRate = 200;
self.lastSpawn = 0; // Timer for spawning small ships
self.spawnRate = 180; // How often to spawn small ships
// Override update method to add spawning behavior
var originalUpdate = self.update;
self.update = function () {
originalUpdate.call(self);
// Spawn small scout ships periodically
self.lastSpawn++;
if (self.lastSpawn >= self.spawnRate && self.y > 100 && self.y < 1000) {
self.spawnScout();
self.lastSpawn = 0;
}
};
// Method to spawn a scout ship
self.spawnScout = function () {
var scout = new ScoutShip();
scout.x = self.x;
scout.y = self.y + 50;
game.addChild(scout);
enemies.push(scout);
};
// Override takeDamage to drop power-ups more often
var originalTakeDamage = self.takeDamage;
self.takeDamage = function (amount) {
if (originalTakeDamage.call(self, amount)) {
// If ship was destroyed and original method returned true
// Carriers have a higher chance to drop power-ups (40%)
if (Math.random() < 0.4) {
var powerUp = new PowerUp();
powerUp.x = self.x;
powerUp.y = self.y;
// Random power-up type with better odds for weapon power-ups
var rand = Math.random();
if (rand < 0.7) {
powerUp.type = "weapon";
} else {
powerUp.type = "shield";
}
game.addChild(powerUp);
powerUps.push(powerUp);
}
return true;
}
return false;
};
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 = 10;
self.damage = 1;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var explosionGraphics = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9
});
self.lifetime = 30; // frames
self.update = function () {
self.lifetime--;
// Scale up and fade out with improved effects
explosionGraphics.scale.x = 1 + (30 - self.lifetime) / 12;
explosionGraphics.scale.y = 1 + (30 - self.lifetime) / 12;
explosionGraphics.alpha = self.lifetime / 30;
explosionGraphics.rotation += 0.05; // Add rotation for more dynamic effect
// Add pulsing glow effect
if (self.lifetime % 3 === 0) {
explosionGraphics.tint = 0xffcc00; // Original color
} else if (self.lifetime % 3 === 1) {
explosionGraphics.tint = 0xff6600; // Orange
} else {
explosionGraphics.tint = 0xff2200; // Red-orange
}
if (self.lifetime <= 0) {
self.destroy();
}
};
return self;
});
var LaserBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('laserBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -20; // Faster than regular bullets
self.damage = 2; // More damage
self.update = function () {
self.y += self.speed;
// Add laser trail effect
if (LK.ticks % 3 === 0) {
var trailEffect = LK.getAsset('laserBullet', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
scaleX: 0.7,
scaleY: 0.7
});
trailEffect.x = self.x;
trailEffect.y = self.y + 15;
game.addChild(trailEffect);
// Create a simple fade-out animation
var trailDuration = 10;
var fadeInterval = LK.setInterval(function () {
trailDuration--;
trailEffect.alpha -= 0.05;
trailEffect.scaleX -= 0.05;
trailEffect.scaleY -= 0.05;
if (trailDuration <= 0) {
LK.clearInterval(fadeInterval);
trailEffect.destroy();
}
}, 1);
}
// Add pulsing glow effect
var time = LK.ticks % 10;
bulletGraphics.tint = time < 5 ? 0x00ffaa : 0x00ddaa;
};
return self;
});
var MegaBoss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8,
tint: 0xff3300
});
self.health = 50;
self.maxHealth = 50;
self.points = 5000;
self.speed = 0.8;
self.phase = 1;
self.fireRate = 45; // Faster than normal boss
self.lastShot = 0;
self.specialAttackTimer = 0;
self.movementTimer = 0;
self.attacking = false;
// Create energy shield effect
var shieldGraphics = LK.getAsset('shieldEffect', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3,
scaleX: 2.2,
scaleY: 2.2,
tint: 0xff6600
});
self.addChild(shieldGraphics);
self.update = function () {
// Boss enters from top
if (self.y < 500) {
self.y += self.speed;
} else {
self.attacking = true;
// Phase-based movement and attacks
if (self.phase === 1) {
// Phase 1: Circular movement
self.x = 2048 / 2 + Math.sin(self.movementTimer / 40) * 500;
self.y = 500 + Math.cos(self.movementTimer / 40) * 200;
self.movementTimer++;
// Regular shooting
self.lastShot++;
if (self.lastShot >= self.fireRate) {
self.shootSpread(3, 20); // 3 bullets in spread
self.lastShot = 0;
}
} else if (self.phase === 2) {
// Phase 2: Figure-8 movement
self.x = 2048 / 2 + Math.sin(self.movementTimer / 50) * 400;
self.y = 500 + Math.sin(self.movementTimer / 25) * 150;
self.movementTimer++;
// More frequent shooting
self.lastShot++;
if (self.lastShot >= self.fireRate * 0.6) {
self.shootSpread(5, 15); // 5 bullets in spread
self.lastShot = 0;
}
// Special attack: summon enemies
self.specialAttackTimer++;
if (self.specialAttackTimer >= 300) {
// Every 5 seconds
self.summonMinions();
self.specialAttackTimer = 0;
}
} else if (self.phase === 3) {
// Phase 3: Erratic movement
self.x += Math.sin(self.movementTimer / 10) * 12;
self.y = 400 + Math.sin(self.movementTimer / 5) * 100;
self.movementTimer++;
// Rapid shooting with pattern
self.lastShot++;
if (self.lastShot >= self.fireRate * 0.3) {
if (self.lastShot % 3 === 0) {
self.shootCircle(8); // Circle of 8 bullets
} else {
self.shootSpread(3, 30); // 3 bullets in spread
}
self.lastShot = 0;
}
// Special attack: laser beam
self.specialAttackTimer++;
if (self.specialAttackTimer >= 240) {
// Every 4 seconds
self.firingLaser = true;
self.fireLaserBeam();
self.specialAttackTimer = 0;
}
}
// Shield effect animation
shieldGraphics.rotation += 0.02;
shieldGraphics.alpha = 0.2 + Math.sin(LK.ticks / 10) * 0.1;
}
// Change phase based on health
if (self.health <= self.maxHealth * 0.65 && self.phase === 1) {
self.phase = 2;
LK.effects.flashObject(self, 0xff0000, 800);
bossGraphics.tint = 0xff4400;
// Create explosion effects
for (var i = 0; i < 5; i++) {
var damageExplosion = new Explosion();
damageExplosion.x = self.x + (Math.random() * 150 - 75);
damageExplosion.y = self.y + (Math.random() * 150 - 75);
game.addChild(damageExplosion);
}
} else if (self.health <= self.maxHealth * 0.3 && self.phase === 2) {
self.phase = 3;
LK.effects.flashObject(self, 0xff0000, 1000);
bossGraphics.tint = 0xff0000;
bossGraphics.scale.x = 1.3;
bossGraphics.scale.y = 1.3;
// More dramatic explosions
for (var i = 0; i < 8; i++) {
var damageExplosion = new Explosion();
damageExplosion.x = self.x + (Math.random() * 200 - 100);
damageExplosion.y = self.y + (Math.random() * 200 - 100);
game.addChild(damageExplosion);
}
}
};
self.shootSpread = function (count, angle) {
var spreadAngle = angle * (Math.PI / 180);
var startAngle = Math.PI / 2 - spreadAngle / 2;
var angleStep = spreadAngle / (count - 1);
for (var i = 0; i < count; i++) {
var bullet = new EnemyBullet();
var currentAngle = startAngle + angleStep * i;
bullet.x = self.x;
bullet.y = self.y + 80;
bullet.speedX = Math.cos(currentAngle) * 8;
bullet.speedY = Math.sin(currentAngle) * 8;
// Override update method for angled movement
bullet.update = function () {
this.x += this.speedX;
this.y += this.speedY;
};
game.addChild(bullet);
enemyBullets.push(bullet);
}
LK.getSound('enemyShoot').play();
};
self.shootCircle = function (count) {
var angleStep = Math.PI * 2 / count;
for (var i = 0; i < count; i++) {
var bullet = new EnemyBullet();
var currentAngle = angleStep * i;
bullet.x = self.x;
bullet.y = self.y;
bullet.speedX = Math.cos(currentAngle) * 7;
bullet.speedY = Math.sin(currentAngle) * 7;
// Override update method for circular pattern
bullet.update = function () {
this.x += this.speedX;
this.y += this.speedY;
};
game.addChild(bullet);
enemyBullets.push(bullet);
}
LK.getSound('enemyShoot').play();
};
self.summonMinions = function () {
// Spawn 2-3 smaller enemies
var count = 2 + Math.floor(Math.random() * 2);
for (var i = 0; i < count; i++) {
var enemy;
if (Math.random() < 0.5) {
enemy = new ScoutShip();
} else {
enemy = new HunterShip();
}
enemy.x = self.x + (Math.random() * 300 - 150);
enemy.y = self.y + 100;
game.addChild(enemy);
enemies.push(enemy);
// Visual effect for spawning
var spawnEffect = new Explosion();
spawnEffect.x = enemy.x;
spawnEffect.y = enemy.y;
game.addChild(spawnEffect);
}
};
self.fireLaserBeam = function () {
// Visual effect for charging laser
var chargeEffect = new Explosion();
chargeEffect.x = self.x;
chargeEffect.y = self.y + 50;
game.addChild(chargeEffect);
// Create laser beam after short delay
LK.setTimeout(function () {
var laserBeam = new Container();
var laserGraphics = LK.getAsset('laserBullet', {
anchorX: 0.5,
anchorY: 0,
scaleX: 8,
scaleY: 30,
tint: 0xff3300
});
laserBeam.addChild(laserGraphics);
laserBeam.x = self.x;
laserBeam.y = self.y + 80;
game.addChild(laserBeam);
// Damage player if in path of laser
if (Math.abs(player.x - self.x) < 150) {
player.takeDamage(2);
}
// Remove laser after a short time
LK.setTimeout(function () {
laserBeam.destroy();
self.firingLaser = false;
}, 1000);
}, 500);
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xffffff, 200);
if (self.health <= 0) {
// Multiple explosions for boss death
for (var i = 0; i < 12; i++) {
var explosion = new Explosion();
explosion.x = self.x + (Math.random() * 300 - 150);
explosion.y = self.y + (Math.random() * 200 - 100);
game.addChild(explosion);
// Stagger explosions
LK.setTimeout(function () {
var delayedExplosion = new Explosion();
delayedExplosion.x = self.x + (Math.random() * 300 - 150);
delayedExplosion.y = self.y + (Math.random() * 200 - 100);
game.addChild(delayedExplosion);
}, 100 + i * 100);
}
// Add points to score
score += self.points;
updateScore();
// Drop multiple power-ups
for (var i = 0; i < 3; i++) {
var powerUp = new PowerUp();
powerUp.x = self.x + (i - 1) * 80;
powerUp.y = self.y;
if (i === 0) {
powerUp.setType("shield");
} else if (i === 1) {
powerUp.setType("ultra");
} else {
powerUp.setType("plasma");
}
game.addChild(powerUp);
powerUps.push(powerUp);
}
LK.getSound('explosion').play();
levelComplete = true;
self.destroy();
return true;
}
return false;
};
return self;
});
var PlasmaBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('plasmaBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -12; // Medium speed
self.damage = 3; // Highest damage
// Add pulsating effect
self.pulseFactor = 0;
self.update = function () {
self.y += self.speed;
// Enhanced pulsating effect with rotation
self.pulseFactor += 0.1;
var scale = 1 + Math.sin(self.pulseFactor) * 0.2;
bulletGraphics.scale.x = scale;
bulletGraphics.scale.y = scale;
bulletGraphics.rotation += 0.1; // Add rotation for energy ball effect
// Add color cycling for plasma effect
var colorPhase = LK.ticks % 120 / 120;
var r = Math.floor(255 * Math.sin(Math.PI * colorPhase));
var g = Math.floor(50 * Math.sin(Math.PI * (colorPhase + 0.33)));
var b = Math.floor(255 * Math.sin(Math.PI * (colorPhase + 0.67)));
bulletGraphics.tint = r << 16 | g << 8 | b;
// Add slight x-axis wobble for unstable plasma effect
self.x += Math.sin(self.pulseFactor * 2) * 0.8;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 3;
self.maxHealth = 3;
self.weaponLevel = 1;
self.weaponType = "standard"; // Initialize with standard weapon
self.weaponUpgrades = 0;
self.weaponTimer = 0;
self.speed = 10;
self.shieldEffect = null; // Reference to shield visual effect
self.fireRate = 15; // Frames between shots
self.lastShot = 0;
self.shieldActive = false;
self.shieldTimer = 0;
self.invulnerable = false;
self.invulnerabilityTimer = 0;
self.update = function () {
// Decrement timers
if (self.weaponTimer > 0) {
self.weaponTimer--;
if (self.weaponTimer === 0) {
self.weaponLevel = 1; // Reset weapon level when timer expires
self.weaponType = "standard";
}
}
if (self.shieldActive) {
self.shieldTimer--;
if (self.shieldTimer === 0) {
self.shieldActive = false;
// Remove shield visual effect
if (self.shieldEffect) {
self.shieldEffect.destroy();
self.shieldEffect = null;
}
}
}
if (self.invulnerable) {
self.invulnerabilityTimer--;
// Flash while invulnerable
self.visible = self.invulnerabilityTimer % 6 < 3;
if (self.invulnerabilityTimer === 0) {
self.invulnerable = false;
self.visible = true;
}
}
// Auto-fire
self.lastShot++;
if (self.lastShot >= self.fireRate) {
self.shoot();
self.lastShot = 0;
}
// Update shield effect position if active
if (self.shieldActive && self.shieldEffect) {
self.shieldEffect.x = self.x;
self.shieldEffect.y = self.y;
}
};
self.shoot = function () {
// Choose bullet type based on weaponType
var BulletClass;
switch (self.weaponType) {
case "laser":
BulletClass = LaserBullet;
break;
case "plasma":
BulletClass = PlasmaBullet;
break;
case "ultra":
BulletClass = UltraBullet;
break;
default:
BulletClass = PlayerBullet;
}
if (self.weaponLevel === 1) {
// Single shot
var bullet = new BulletClass();
bullet.x = self.x;
bullet.y = self.y - 40;
game.addChild(bullet);
playerBullets.push(bullet);
} else if (self.weaponLevel === 2) {
// Double shot
for (var i = -1; i <= 1; i += 2) {
var bullet = new BulletClass();
bullet.x = self.x + i * 20;
bullet.y = self.y - 40;
game.addChild(bullet);
playerBullets.push(bullet);
}
} else if (self.weaponLevel === 3) {
// Triple shot
for (var i = -1; i <= 1; i++) {
var bullet = new BulletClass();
bullet.x = self.x + i * 25;
bullet.y = self.y - 40;
game.addChild(bullet);
playerBullets.push(bullet);
}
} else if (self.weaponLevel >= 4) {
// Quad shot - for level 4+
for (var i = -1.5; i <= 1.5; i += 1) {
var bullet = new BulletClass();
bullet.x = self.x + i * 25;
bullet.y = self.y - 40;
game.addChild(bullet);
playerBullets.push(bullet);
}
}
LK.getSound('playerShoot').play();
};
self.takeDamage = function (amount) {
if (self.invulnerable) {
return false;
}
if (self.shieldActive) {
// Shield absorbs the hit
self.shieldActive = false;
self.shieldTimer = 0;
return false;
}
self.health -= amount;
LK.getSound('damage').play();
// Make player invulnerable briefly
self.invulnerable = true;
self.invulnerabilityTimer = 90; // 1.5 seconds at 60fps
if (self.health <= 0) {
// Game over logic
var explosion = new Explosion();
explosion.x = self.x;
explosion.y = self.y;
game.addChild(explosion);
LK.getSound('explosion').play();
// Record high score if needed
if (score > highScore) {
highScore = score;
storage.highScore = highScore;
}
gameOver = true;
return true;
}
return false;
};
self.collectPowerUp = function (powerUp) {
if (powerUp.type === "weapon") {
// Increment weapon level - now up to level 4
self.weaponLevel = Math.min(self.weaponLevel + 1, 4);
self.weaponTimer = 600; // 10 seconds at 60fps
// Determine weapon type based on collected power-ups
if (self.weaponUpgrades === undefined) {
self.weaponUpgrades = 0;
}
self.weaponUpgrades++;
if (self.weaponUpgrades >= 3) {
self.weaponType = "plasma"; // Advanced weapon
} else if (self.weaponUpgrades >= 1) {
self.weaponType = "laser"; // Medium weapon
} else {
self.weaponType = "standard"; // Basic weapon
}
} else if (powerUp.type === "shield") {
self.shieldActive = true;
self.shieldTimer = 600; // 10 seconds at 60fps
// Create shield visual effect if it doesn't exist
if (!self.shieldEffect) {
self.shieldEffect = new ShieldEffect();
self.shieldEffect.x = self.x;
self.shieldEffect.y = self.y;
game.addChild(self.shieldEffect);
}
} else if (powerUp.type === "laser") {
// Direct upgrade to laser weapon
self.weaponType = "laser";
self.weaponLevel = Math.min(self.weaponLevel + 1, 4);
self.weaponTimer = 600; // 10 seconds at 60fps
} else if (powerUp.type === "plasma") {
// Direct upgrade to plasma weapon
self.weaponType = "plasma";
self.weaponLevel = Math.min(self.weaponLevel + 1, 4);
self.weaponTimer = 600; // 10 seconds at 60fps
} else if (powerUp.type === "ultra") {
// Ultimate weapon upgrade
self.weaponType = "ultra";
self.weaponLevel = 4; // Set to max level
self.weaponTimer = 900; // 15 seconds at 60fps
}
LK.getSound('powerUp').play();
};
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 = -15;
self.damage = 1;
self.update = function () {
self.y += self.speed;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = "weapon"; // Default type
self.speed = 5;
self.pulseTimer = 0;
// Set different colors based on type
self.setType = function (type) {
self.type = type;
if (type === "weapon") {
powerUpGraphics.tint = 0x00ff00; // Green for weapons
} else if (type === "shield") {
powerUpGraphics.tint = 0x33ccff; // Blue for shields
} else if (type === "laser") {
powerUpGraphics.tint = 0x00ffaa; // Cyan for laser upgrade
} else if (type === "plasma") {
powerUpGraphics.tint = 0xff00ff; // Magenta for plasma upgrade
} else if (type === "ultra") {
powerUpGraphics.tint = 0xffff00; // Yellow for ultra weapon
}
};
self.update = function () {
self.y += self.speed;
// Enhance visual effect with pulsating and rotation
self.pulseTimer += 0.1;
powerUpGraphics.scale.x = 1 + Math.sin(self.pulseTimer) * 0.2;
powerUpGraphics.scale.y = 1 + Math.sin(self.pulseTimer) * 0.2;
powerUpGraphics.rotation += 0.02;
// Slight oscillation for visual effect
self.x += Math.sin(LK.ticks / 10) * 1;
};
return self;
});
var ShieldEffect = Container.expand(function () {
var self = Container.call(this);
var shieldGraphics = self.attachAsset('shieldEffect', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
self.pulseFactor = 0;
self.update = function () {
// Pulsating effect with enhanced visuals
self.pulseFactor += 0.05;
shieldGraphics.alpha = 0.3 + Math.sin(self.pulseFactor) * 0.2;
shieldGraphics.rotation += 0.01; // Slow rotation for energy field effect
// Create shimmering effect with color changes
var blueIntensity = 0.5 + Math.sin(self.pulseFactor * 1.5) * 0.3;
var cyanIntensity = 0.7 + Math.cos(self.pulseFactor * 0.8) * 0.3;
shieldGraphics.tint = Math.floor(0x33 * blueIntensity) << 16 | Math.floor(0xcc * cyanIntensity) << 8 | 0xff;
// Scale effect for "energy bubble" appearance
var scaleVar = 1 + Math.sin(self.pulseFactor * 0.7) * 0.05;
shieldGraphics.scale.x = scaleVar;
shieldGraphics.scale.y = scaleVar;
};
return self;
});
var UltraBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('plasmaBullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
tint: 0xffff00
});
self.speed = -18; // Very fast
self.damage = 5; // Highest damage
self.pulseFactor = 0;
self.update = function () {
self.y += self.speed;
// Dynamic visual effects
self.pulseFactor += 0.15;
var scale = 1.2 + Math.sin(self.pulseFactor) * 0.3;
bulletGraphics.scale.x = scale;
bulletGraphics.scale.y = scale;
bulletGraphics.rotation += 0.15;
// Electric discharge effect
if (LK.ticks % 2 === 0) {
var sparkEffect = LK.getAsset('plasmaBullet', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7,
scaleX: 0.4,
scaleY: 0.4,
tint: 0xffff00
});
sparkEffect.x = self.x + (Math.random() * 40 - 20);
sparkEffect.y = self.y + (Math.random() * 40 - 20);
game.addChild(sparkEffect);
// Create fade-out effect
var sparkDuration = 8;
var fadeInterval = LK.setInterval(function () {
sparkDuration--;
sparkEffect.alpha -= 0.09;
sparkEffect.scaleX -= 0.04;
sparkEffect.scaleY -= 0.04;
if (sparkDuration <= 0) {
LK.clearInterval(fadeInterval);
sparkEffect.destroy();
}
}, 1);
}
// Colorful effect
var time = LK.ticks % 20;
var r = 255;
var g = 255;
var b = Math.floor(100 + time * 7);
bulletGraphics.tint = r << 16 | g << 8 | b;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000022
});
/****
* Game Code
****/
// Game variables
// Initialize main assets with high-quality shapes
var score = 0;
var highScore = storage.highScore || 0;
var level = 1;
var enemySpawnTimer = 0;
var enemySpawnRate = 60; // Frames between enemy spawns
var playerBullets = [];
var enemyBullets = [];
var enemies = [];
var powerUps = [];
var bossSpawned = false;
var levelComplete = false;
var gameOver = false;
var nextEnemy = 0;
// Create dynamic starfield background
var stars = [];
var starLayers = 3; // Multiple layers for parallax effect
// Initialize stars
for (var layer = 0; layer < starLayers; layer++) {
var count = 30 + layer * 20; // More stars in deeper layers
var speed = 1 + layer * 1.5; // Deeper layers move faster
var size = 3 - layer * 0.8; // Deeper layers have smaller stars
var alpha = 0.7 - layer * 0.2; // Deeper layers are more transparent
for (var i = 0; i < count; i++) {
var star = new Container();
var starGraphic = LK.getAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFFFFF,
alpha: alpha,
scaleX: size / 60,
scaleY: size / 60
});
star.addChild(starGraphic);
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.speed = speed;
star.layer = layer;
// Add occasional color variation to brightest stars
if (layer === 0 && Math.random() < 0.3) {
var colors = [0xFFFFCC, 0xCCFFFF, 0xFFCCFF]; // Yellow, blue, pink tints
starGraphic.tint = colors[Math.floor(Math.random() * colors.length)];
}
game.addChild(star);
stars.push(star);
}
}
// Add function to update stars in main update loop
function updateStars() {
for (var i = 0; i < stars.length; i++) {
var star = stars[i];
star.y += star.speed;
// Reset stars when they go off screen
if (star.y > 2732) {
star.y = -10;
star.x = Math.random() * 2048;
}
}
}
// UI elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
var levelTxt = new Text2('Level: 1', {
size: 60,
fill: 0xFFFFFF
});
levelTxt.anchor.set(1, 0);
LK.gui.topLeft.addChild(levelTxt);
// Move it away from the top-left corner
levelTxt.x = 200;
var healthTxt = new Text2('Health: 3', {
size: 60,
fill: 0xFFFFFF
});
healthTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(healthTxt);
// Weapon type indicator
var weaponTxt = new Text2('Weapon: Standard', {
size: 40,
fill: 0xFFFFFF
});
weaponTxt.style = {
fill: 0xFFFFFF
}; // Initialize style object
weaponTxt.anchor.set(0, 0);
LK.gui.bottomLeft.addChild(weaponTxt);
weaponTxt.y = -100; // Position it above the bottom edge
// Function to update weapon display
function updateWeapon() {
var typeText = player.weaponType.charAt(0).toUpperCase() + player.weaponType.slice(1);
weaponTxt.setText('Weapon: ' + typeText + ' (Lv.' + player.weaponLevel + ')');
// Set text color based on weapon type
if (player.weaponType === "standard") {
weaponTxt.style.fill = 0x66ffff;
} else if (player.weaponType === "laser") {
weaponTxt.style.fill = 0x00ffaa;
} else if (player.weaponType === "plasma") {
weaponTxt.style.fill = 0xff00ff;
} else if (player.weaponType === "ultra") {
weaponTxt.style.fill = 0xffff00;
}
}
// Create player
var player = new Player();
player.x = 2048 / 2;
player.y = 2732 - 300;
game.addChild(player);
// Function to update score display
function updateScore() {
scoreTxt.setText('Score: ' + score);
// Update LK score system for leaderboards
LK.setScore(score);
}
// Function to update health display
function updateHealth() {
healthTxt.setText('Health: ' + player.health);
}
// Function to update level display
function updateLevel() {
levelTxt.setText('Level: ' + level);
}
// Function to spawn regular enemies
function spawnEnemy() {
var enemyType;
var enemy;
// Select enemy type based on level and randomness
if (level === 1) {
// Level 1: Only basic enemies
enemy = new Enemy();
enemy.health = 1;
enemy.movementPattern = "straight";
enemy.fireRate = 180;
} else if (level === 2) {
// Level 2: Basic enemies and some hunters
var rand = Math.random();
if (rand < 0.3) {
enemy = new HunterShip();
} else if (rand < 0.6) {
enemy = new Enemy();
enemy.health = 2;
enemy.points = 200;
enemy.movementPattern = "zigzag";
enemy.fireRate = 150;
} else {
enemy = new Enemy();
enemy.health = 1;
enemy.movementPattern = "straight";
enemy.fireRate = 180;
}
} else if (level >= 3 && level < 5) {
// Level 3-4: All enemy types
var rand = Math.random();
if (rand < 0.25) {
enemy = new CarrierShip();
} else if (rand < 0.5) {
enemy = new HunterShip();
} else if (rand < 0.7) {
enemy = new ScoutShip();
} else if (rand < 0.85) {
enemy = new Enemy();
enemy.health = 3;
enemy.points = 300;
enemy.movementPattern = "circle";
enemy.fireRate = 120;
} else {
enemy = new Enemy();
enemy.health = 2;
enemy.points = 200;
enemy.movementPattern = "zigzag";
enemy.fireRate = 150;
}
} else if (level >= 5) {
// Level 5+: Include elite enemies
var rand = Math.random();
if (rand < 0.2) {
enemy = new CarrierShip();
// Enhance carrier properties at higher levels
if (level >= 6) {
enemy.health += 2;
enemy.spawnRate = 150; // Faster spawning
}
} else if (rand < 0.35) {
enemy = new EliteHunterShip(); // Elite hunter
} else if (rand < 0.5) {
enemy = new HunterShip();
} else if (rand < 0.65) {
enemy = new EliteScoutShip(); // Elite scout
} else if (rand < 0.8) {
enemy = new ScoutShip();
} else {
enemy = new Enemy();
enemy.health = 3 + Math.min(level - 5, 3); // Scale up health
enemy.points = 300 + (level - 5) * 50;
enemy.movementPattern = "circle";
enemy.fireRate = Math.max(120 - (level - 5) * 10, 70); // Scale down fire rate (faster shooting)
}
}
// Random position at top of screen
enemy.x = 200 + Math.random() * (2048 - 400);
enemy.y = -100;
game.addChild(enemy);
enemies.push(enemy);
}
// Function to spawn boss
function spawnBoss() {
var boss;
// At higher levels, spawn the MegaBoss instead
if (level >= 4) {
boss = new MegaBoss();
boss.x = 2048 / 2;
boss.y = -300;
// Scale mega boss difficulty with level
boss.health = 50 + (level - 4) * 15;
boss.maxHealth = boss.health;
} else {
boss = new Boss();
boss.x = 2048 / 2;
boss.y = -200;
// Scale boss difficulty with level
boss.health = 20 + (level - 1) * 10;
boss.maxHealth = boss.health;
}
game.addChild(boss);
enemies.push(boss);
bossSpawned = true;
}
// Function to start the next level
function startNextLevel() {
level++;
updateLevel();
enemies = [];
enemyBullets = [];
bossSpawned = false;
levelComplete = false;
nextEnemy = 0;
// Speed up enemy spawns as level increases
enemySpawnRate = Math.max(60 - (level - 1) * 5, 30);
}
// Mouse/Touch handlers
var dragNode = null;
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp position to stay on screen
dragNode.x = Math.max(60, Math.min(x, 2048 - 60));
dragNode.y = Math.max(60, Math.min(y, 2732 - 60));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
dragNode = player;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game update loop
game.update = function () {
// Update starfield background for space atmosphere
updateStars();
if (gameOver) {
// Show game over screen
LK.showGameOver();
return;
}
if (levelComplete) {
startNextLevel();
}
// Update player
player.update();
updateHealth();
updateWeapon();
// Spawn enemies
if (!bossSpawned) {
enemySpawnTimer++;
if (enemySpawnTimer >= enemySpawnRate) {
enemySpawnTimer = 0;
spawnEnemy();
nextEnemy++;
// Spawn boss after certain number of enemies
if (nextEnemy >= 15 + level * 5) {
spawnBoss();
}
}
}
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
// Check if bullet is off screen
if (bullet.y < -50) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check for collisions with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
if (enemy.takeDamage(bullet.damage)) {
enemies.splice(j, 1);
}
bullet.destroy();
playerBullets.splice(i, 1);
break;
}
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
// Check if bullet is off screen
if (bullet.y > 2732 + 50) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check for collision with player
if (bullet.intersects(player)) {
if (player.takeDamage(bullet.damage)) {
// Player destroyed, game over
gameOver = true;
}
bullet.destroy();
enemyBullets.splice(i, 1);
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
// Check if enemy is off screen
if (enemy.y > 2732 + 100) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check for collision with player
if (enemy.intersects(player)) {
if (player.takeDamage(1)) {
// Player destroyed, game over
gameOver = true;
}
// Enemy also takes damage
if (enemy.takeDamage(1)) {
enemies.splice(i, 1);
}
continue;
}
}
// Update power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
// Check if power-up is off screen
if (powerUp.y > 2732 + 50) {
powerUp.destroy();
powerUps.splice(i, 1);
continue;
}
// Check for collision with player
if (powerUp.intersects(player)) {
player.collectPowerUp(powerUp);
powerUp.destroy();
powerUps.splice(i, 1);
}
}
// Check if level is complete (no enemies and boss killed)
if (bossSpawned && enemies.length === 0) {
levelComplete = true;
}
};
// Start background music
LK.playMusic('bgMusic'); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 20;
self.maxHealth = 20;
self.points = 2000;
self.speed = 1;
self.phase = 1;
self.fireRate = 60; // Frames between shots
self.lastShot = 0;
self.movementTimer = 0;
self.attacking = false;
self.update = function () {
// Boss enters from top
if (self.y < 400) {
self.y += self.speed;
} else {
self.attacking = true;
// Phase-based movement
if (self.phase === 1) {
// Side-to-side movement
self.x += Math.sin(self.movementTimer / 30) * 5;
self.movementTimer++;
// Regular shooting
self.lastShot++;
if (self.lastShot >= self.fireRate) {
self.shoot();
self.lastShot = 0;
}
} else if (self.phase === 2) {
// More aggressive movement
self.x += Math.sin(self.movementTimer / 20) * 7;
self.y += Math.cos(self.movementTimer / 40) * 2;
self.movementTimer++;
// More frequent shooting
self.lastShot++;
if (self.lastShot >= self.fireRate * 0.7) {
self.shoot();
self.lastShot = 0;
}
} else if (self.phase === 3) {
// Erratic movement
self.x += Math.sin(self.movementTimer / 10) * 8;
self.y += Math.cos(self.movementTimer / 15) * 3;
self.movementTimer++;
// Rapid shooting
self.lastShot++;
if (self.lastShot >= self.fireRate * 0.4) {
self.shoot();
self.lastShot = 0;
}
}
}
// Change phase based on health with enhanced visual feedback
if (self.health <= self.maxHealth * 0.65 && self.phase === 1) {
self.phase = 2;
LK.effects.flashObject(self, 0xff0000, 500);
// Add dramatic phase change effect
bossGraphics.tint = 0xff6600; // Change to orange glow
// Create multiple explosions around boss
for (var i = 0; i < 3; i++) {
var damageExplosion = new Explosion();
damageExplosion.x = self.x + (Math.random() * 120 - 60);
damageExplosion.y = self.y + (Math.random() * 80 - 40);
game.addChild(damageExplosion);
}
} else if (self.health <= self.maxHealth * 0.3 && self.phase === 2) {
self.phase = 3;
LK.effects.flashObject(self, 0xff0000, 500);
// More dramatic effect for final phase
bossGraphics.tint = 0xff0000; // Change to red glow
bossGraphics.scale.x = 1.1; // Slightly expand
bossGraphics.scale.y = 1.1;
// Create more explosions for critical damage
for (var i = 0; i < 5; i++) {
var damageExplosion = new Explosion();
damageExplosion.x = self.x + (Math.random() * 160 - 80);
damageExplosion.y = self.y + (Math.random() * 100 - 50);
game.addChild(damageExplosion);
}
}
};
self.shoot = function () {
// Different shot patterns based on phase
if (self.phase === 1) {
// Single shot
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 80;
game.addChild(bullet);
enemyBullets.push(bullet);
} else if (self.phase === 2) {
// Double shot
for (var i = -1; i <= 1; i += 2) {
var bullet = new EnemyBullet();
bullet.x = self.x + i * 50;
bullet.y = self.y + 80;
game.addChild(bullet);
enemyBullets.push(bullet);
}
} else if (self.phase === 3) {
// Triple shot
for (var i = -1; i <= 1; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x + i * 50;
bullet.y = self.y + 80;
game.addChild(bullet);
enemyBullets.push(bullet);
}
}
LK.getSound('enemyShoot').play();
};
self.takeDamage = function (amount) {
self.health -= amount;
// Flash when taking damage
LK.effects.flashObject(self, 0xffffff, 200);
if (self.health <= 0) {
// Multiple explosions for boss
for (var i = 0; i < 5; i++) {
var explosion = new Explosion();
explosion.x = self.x + (Math.random() * 200 - 100);
explosion.y = self.y + (Math.random() * 100 - 50);
game.addChild(explosion);
}
// Add points to score
score += self.points;
updateScore();
// Boss drops multiple power-ups
// Drop advanced weapon power-up based on level
var weaponPowerUp = new PowerUp();
weaponPowerUp.x = self.x - 60;
weaponPowerUp.y = self.y;
if (level >= 3) {
weaponPowerUp.setType("plasma");
} else {
weaponPowerUp.setType("laser");
}
game.addChild(weaponPowerUp);
powerUps.push(weaponPowerUp);
// Drop shield power-up
var shieldPowerUp = new PowerUp();
shieldPowerUp.x = self.x + 60;
shieldPowerUp.y = self.y;
shieldPowerUp.setType("shield");
game.addChild(shieldPowerUp);
powerUps.push(shieldPowerUp);
LK.getSound('explosion').play();
// Level complete
levelComplete = true;
self.destroy();
return true;
}
return false;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemyShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1;
self.points = 100;
self.speed = 2;
self.fireRate = 180; // Frames between shots
self.lastShot = 0;
self.movementPattern = "straight"; // Default movement
self.movementTimer = 0;
self.update = function () {
// Handle movement patterns
if (self.movementPattern === "straight") {
self.y += self.speed;
} else if (self.movementPattern === "zigzag") {
self.y += self.speed;
self.x += Math.sin(self.movementTimer / 20) * 3;
self.movementTimer++;
} else if (self.movementPattern === "circle") {
self.y += self.speed * 0.7;
self.x += Math.sin(self.movementTimer / 15) * 4;
self.movementTimer++;
}
// Shooting logic
self.lastShot++;
if (self.lastShot >= self.fireRate && self.y > 0 && Math.random() < 0.3) {
self.shoot();
self.lastShot = 0;
}
};
self.shoot = function () {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 40;
game.addChild(bullet);
enemyBullets.push(bullet);
LK.getSound('enemyShoot').play();
};
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health <= 0) {
// Create explosion
var explosion = new Explosion();
explosion.x = self.x;
explosion.y = self.y;
game.addChild(explosion);
// Add points to score
score += self.points;
updateScore();
// Random chance to drop power-up
if (Math.random() < 0.1) {
var powerUp = new PowerUp();
powerUp.x = self.x;
powerUp.y = self.y;
// Random power-up type
var rand = Math.random();
if (rand < 0.5) {
powerUp.setType("weapon");
} else if (rand < 0.8) {
powerUp.setType("shield");
} else if (level >= 2) {
// Special weapon drops in higher levels
if (level >= 3 && rand < 0.9) {
powerUp.setType("plasma");
} else {
powerUp.setType("laser");
}
}
game.addChild(powerUp);
powerUps.push(powerUp);
}
LK.getSound('explosion').play();
self.destroy();
return true;
}
return false;
};
return self;
});
var ScoutShip = Enemy.expand(function () {
var self = Enemy.call(this);
// Replace default graphics with scout ship graphics
self.removeChild(self.children[0]);
var shipGraphics = self.attachAsset('scoutShip', {
anchorX: 0.5,
anchorY: 0.5
});
// Set scout-specific properties
self.health = 1;
self.points = 150;
self.speed = 4; // Faster movement
self.fireRate = 240; // Shoots less frequently
self.movementPattern = "erratic";
// Override update method for erratic movement
var originalUpdate = self.update;
self.update = function () {
if (self.movementPattern === "erratic") {
self.y += self.speed;
self.x += Math.sin(self.movementTimer / 10) * 6;
self.movementTimer++;
} else {
// Use original update for other movement patterns
originalUpdate.call(self);
}
// Handle shooting with lower probability
self.lastShot++;
if (self.lastShot >= self.fireRate && self.y > 0 && Math.random() < 0.2) {
self.shoot();
self.lastShot = 0;
}
};
return self;
});
var EliteScoutShip = ScoutShip.expand(function () {
var self = ScoutShip.call(this);
// Replace graphics with recolored version
self.removeChild(self.children[0]);
var shipGraphics = self.attachAsset('scoutShip', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0x33ffff,
scaleX: 1.3,
scaleY: 1.3
});
// Enhanced elite properties
self.health = 3;
self.points = 350;
self.speed = 6; // Even faster
// Override update for more complex movement
var originalUpdate = self.update;
self.update = function () {
// Teleport-like rapid movement changes
if (LK.ticks % 90 === 0 && self.y > 200) {
// Create a flicker effect before "teleporting"
shipGraphics.alpha = 0.5;
// Schedule the "teleport"
LK.setTimeout(function () {
// Random new position
self.x = 300 + Math.random() * (2048 - 600);
shipGraphics.alpha = 1;
// Create visual effect at new position
var flashEffect = new Explosion();
flashEffect.x = self.x;
flashEffect.y = self.y;
game.addChild(flashEffect);
}, 20);
}
// Use original movement pattern with more extreme values
self.y += self.speed;
self.x += Math.sin(self.movementTimer / 8) * 8;
self.movementTimer++;
// Fire more bullets in a spread pattern
self.lastShot++;
if (self.lastShot >= self.fireRate && self.y > 0 && Math.random() < 0.3) {
// Triple spread shot
for (var i = -1; i <= 1; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x + i * 20;
bullet.y = self.y + 40;
// Angled shots
var angle = Math.PI / 2 + i * 0.3;
bullet.speedX = Math.cos(angle) * 10;
bullet.speedY = Math.sin(angle) * 10;
// Override update for angled movement
bullet.update = function () {
this.x += this.speedX;
this.y += this.speedY;
};
game.addChild(bullet);
enemyBullets.push(bullet);
}
LK.getSound('enemyShoot').play();
self.lastShot = 0;
}
};
return self;
});
var HunterShip = Enemy.expand(function () {
var self = Enemy.call(this);
// Replace default graphics with hunter ship graphics
self.removeChild(self.children[0]);
var shipGraphics = self.attachAsset('hunterShip', {
anchorX: 0.5,
anchorY: 0.5
});
// Set hunter-specific properties
self.health = 3;
self.points = 250;
self.speed = 3;
self.fireRate = 100; // Fires more frequently
self.movementPattern = "pursuit"; // New movement pattern that follows player
// Override update method to add pursuit behavior
var originalUpdate = self.update;
self.update = function () {
if (self.movementPattern === "pursuit") {
// Move towards player's x position
if (player.x > self.x) {
self.x += Math.min(self.speed * 0.7, player.x - self.x);
} else if (player.x < self.x) {
self.x -= Math.min(self.speed * 0.7, self.x - player.x);
}
self.y += self.speed * 0.8;
} else {
// Use original update for other movement patterns
originalUpdate.call(self);
}
// Handle shooting regardless of movement pattern
self.lastShot++;
if (self.lastShot >= self.fireRate && self.y > 0 && Math.random() < 0.4) {
self.shoot();
self.lastShot = 0;
}
};
return self;
});
var EliteHunterShip = HunterShip.expand(function () {
var self = HunterShip.call(this);
// Replace graphics with recolored version
self.removeChild(self.children[0]);
var shipGraphics = self.attachAsset('hunterShip', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xff3300,
scaleX: 1.2,
scaleY: 1.2
});
// Enhanced elite properties
self.health = 5;
self.points = 500;
self.speed = 4;
self.fireRate = 70;
// Override update for more aggressive behavior
var originalUpdate = self.update;
self.update = function () {
if (self.movementPattern === "pursuit") {
// More aggressive pursuit
var targetX = player.x;
var dx = targetX - self.x;
self.x += dx * 0.05; // More precise tracking
self.y += self.speed * 0.9;
// Rotate slightly toward movement direction
shipGraphics.rotation = dx * 0.003;
} else {
originalUpdate.call(self);
}
// More frequent shooting with double bullets
self.lastShot++;
if (self.lastShot >= self.fireRate && self.y > 0 && Math.random() < 0.5) {
self.shoot();
// Add slight delay for second shot
LK.setTimeout(function () {
self.shoot();
}, 10);
self.lastShot = 0;
}
};
return self;
});
var CarrierShip = Enemy.expand(function () {
var self = Enemy.call(this);
// Replace default graphics with carrier ship graphics
self.removeChild(self.children[0]);
var shipGraphics = self.attachAsset('carrierShip', {
anchorX: 0.5,
anchorY: 0.5
});
// Set carrier-specific properties
self.health = 5;
self.points = 400;
self.speed = 1; // Slower movement
self.fireRate = 200;
self.lastSpawn = 0; // Timer for spawning small ships
self.spawnRate = 180; // How often to spawn small ships
// Override update method to add spawning behavior
var originalUpdate = self.update;
self.update = function () {
originalUpdate.call(self);
// Spawn small scout ships periodically
self.lastSpawn++;
if (self.lastSpawn >= self.spawnRate && self.y > 100 && self.y < 1000) {
self.spawnScout();
self.lastSpawn = 0;
}
};
// Method to spawn a scout ship
self.spawnScout = function () {
var scout = new ScoutShip();
scout.x = self.x;
scout.y = self.y + 50;
game.addChild(scout);
enemies.push(scout);
};
// Override takeDamage to drop power-ups more often
var originalTakeDamage = self.takeDamage;
self.takeDamage = function (amount) {
if (originalTakeDamage.call(self, amount)) {
// If ship was destroyed and original method returned true
// Carriers have a higher chance to drop power-ups (40%)
if (Math.random() < 0.4) {
var powerUp = new PowerUp();
powerUp.x = self.x;
powerUp.y = self.y;
// Random power-up type with better odds for weapon power-ups
var rand = Math.random();
if (rand < 0.7) {
powerUp.type = "weapon";
} else {
powerUp.type = "shield";
}
game.addChild(powerUp);
powerUps.push(powerUp);
}
return true;
}
return false;
};
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 = 10;
self.damage = 1;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var explosionGraphics = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9
});
self.lifetime = 30; // frames
self.update = function () {
self.lifetime--;
// Scale up and fade out with improved effects
explosionGraphics.scale.x = 1 + (30 - self.lifetime) / 12;
explosionGraphics.scale.y = 1 + (30 - self.lifetime) / 12;
explosionGraphics.alpha = self.lifetime / 30;
explosionGraphics.rotation += 0.05; // Add rotation for more dynamic effect
// Add pulsing glow effect
if (self.lifetime % 3 === 0) {
explosionGraphics.tint = 0xffcc00; // Original color
} else if (self.lifetime % 3 === 1) {
explosionGraphics.tint = 0xff6600; // Orange
} else {
explosionGraphics.tint = 0xff2200; // Red-orange
}
if (self.lifetime <= 0) {
self.destroy();
}
};
return self;
});
var LaserBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('laserBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -20; // Faster than regular bullets
self.damage = 2; // More damage
self.update = function () {
self.y += self.speed;
// Add laser trail effect
if (LK.ticks % 3 === 0) {
var trailEffect = LK.getAsset('laserBullet', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5,
scaleX: 0.7,
scaleY: 0.7
});
trailEffect.x = self.x;
trailEffect.y = self.y + 15;
game.addChild(trailEffect);
// Create a simple fade-out animation
var trailDuration = 10;
var fadeInterval = LK.setInterval(function () {
trailDuration--;
trailEffect.alpha -= 0.05;
trailEffect.scaleX -= 0.05;
trailEffect.scaleY -= 0.05;
if (trailDuration <= 0) {
LK.clearInterval(fadeInterval);
trailEffect.destroy();
}
}, 1);
}
// Add pulsing glow effect
var time = LK.ticks % 10;
bulletGraphics.tint = time < 5 ? 0x00ffaa : 0x00ddaa;
};
return self;
});
var MegaBoss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.8,
scaleY: 1.8,
tint: 0xff3300
});
self.health = 50;
self.maxHealth = 50;
self.points = 5000;
self.speed = 0.8;
self.phase = 1;
self.fireRate = 45; // Faster than normal boss
self.lastShot = 0;
self.specialAttackTimer = 0;
self.movementTimer = 0;
self.attacking = false;
// Create energy shield effect
var shieldGraphics = LK.getAsset('shieldEffect', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3,
scaleX: 2.2,
scaleY: 2.2,
tint: 0xff6600
});
self.addChild(shieldGraphics);
self.update = function () {
// Boss enters from top
if (self.y < 500) {
self.y += self.speed;
} else {
self.attacking = true;
// Phase-based movement and attacks
if (self.phase === 1) {
// Phase 1: Circular movement
self.x = 2048 / 2 + Math.sin(self.movementTimer / 40) * 500;
self.y = 500 + Math.cos(self.movementTimer / 40) * 200;
self.movementTimer++;
// Regular shooting
self.lastShot++;
if (self.lastShot >= self.fireRate) {
self.shootSpread(3, 20); // 3 bullets in spread
self.lastShot = 0;
}
} else if (self.phase === 2) {
// Phase 2: Figure-8 movement
self.x = 2048 / 2 + Math.sin(self.movementTimer / 50) * 400;
self.y = 500 + Math.sin(self.movementTimer / 25) * 150;
self.movementTimer++;
// More frequent shooting
self.lastShot++;
if (self.lastShot >= self.fireRate * 0.6) {
self.shootSpread(5, 15); // 5 bullets in spread
self.lastShot = 0;
}
// Special attack: summon enemies
self.specialAttackTimer++;
if (self.specialAttackTimer >= 300) {
// Every 5 seconds
self.summonMinions();
self.specialAttackTimer = 0;
}
} else if (self.phase === 3) {
// Phase 3: Erratic movement
self.x += Math.sin(self.movementTimer / 10) * 12;
self.y = 400 + Math.sin(self.movementTimer / 5) * 100;
self.movementTimer++;
// Rapid shooting with pattern
self.lastShot++;
if (self.lastShot >= self.fireRate * 0.3) {
if (self.lastShot % 3 === 0) {
self.shootCircle(8); // Circle of 8 bullets
} else {
self.shootSpread(3, 30); // 3 bullets in spread
}
self.lastShot = 0;
}
// Special attack: laser beam
self.specialAttackTimer++;
if (self.specialAttackTimer >= 240) {
// Every 4 seconds
self.firingLaser = true;
self.fireLaserBeam();
self.specialAttackTimer = 0;
}
}
// Shield effect animation
shieldGraphics.rotation += 0.02;
shieldGraphics.alpha = 0.2 + Math.sin(LK.ticks / 10) * 0.1;
}
// Change phase based on health
if (self.health <= self.maxHealth * 0.65 && self.phase === 1) {
self.phase = 2;
LK.effects.flashObject(self, 0xff0000, 800);
bossGraphics.tint = 0xff4400;
// Create explosion effects
for (var i = 0; i < 5; i++) {
var damageExplosion = new Explosion();
damageExplosion.x = self.x + (Math.random() * 150 - 75);
damageExplosion.y = self.y + (Math.random() * 150 - 75);
game.addChild(damageExplosion);
}
} else if (self.health <= self.maxHealth * 0.3 && self.phase === 2) {
self.phase = 3;
LK.effects.flashObject(self, 0xff0000, 1000);
bossGraphics.tint = 0xff0000;
bossGraphics.scale.x = 1.3;
bossGraphics.scale.y = 1.3;
// More dramatic explosions
for (var i = 0; i < 8; i++) {
var damageExplosion = new Explosion();
damageExplosion.x = self.x + (Math.random() * 200 - 100);
damageExplosion.y = self.y + (Math.random() * 200 - 100);
game.addChild(damageExplosion);
}
}
};
self.shootSpread = function (count, angle) {
var spreadAngle = angle * (Math.PI / 180);
var startAngle = Math.PI / 2 - spreadAngle / 2;
var angleStep = spreadAngle / (count - 1);
for (var i = 0; i < count; i++) {
var bullet = new EnemyBullet();
var currentAngle = startAngle + angleStep * i;
bullet.x = self.x;
bullet.y = self.y + 80;
bullet.speedX = Math.cos(currentAngle) * 8;
bullet.speedY = Math.sin(currentAngle) * 8;
// Override update method for angled movement
bullet.update = function () {
this.x += this.speedX;
this.y += this.speedY;
};
game.addChild(bullet);
enemyBullets.push(bullet);
}
LK.getSound('enemyShoot').play();
};
self.shootCircle = function (count) {
var angleStep = Math.PI * 2 / count;
for (var i = 0; i < count; i++) {
var bullet = new EnemyBullet();
var currentAngle = angleStep * i;
bullet.x = self.x;
bullet.y = self.y;
bullet.speedX = Math.cos(currentAngle) * 7;
bullet.speedY = Math.sin(currentAngle) * 7;
// Override update method for circular pattern
bullet.update = function () {
this.x += this.speedX;
this.y += this.speedY;
};
game.addChild(bullet);
enemyBullets.push(bullet);
}
LK.getSound('enemyShoot').play();
};
self.summonMinions = function () {
// Spawn 2-3 smaller enemies
var count = 2 + Math.floor(Math.random() * 2);
for (var i = 0; i < count; i++) {
var enemy;
if (Math.random() < 0.5) {
enemy = new ScoutShip();
} else {
enemy = new HunterShip();
}
enemy.x = self.x + (Math.random() * 300 - 150);
enemy.y = self.y + 100;
game.addChild(enemy);
enemies.push(enemy);
// Visual effect for spawning
var spawnEffect = new Explosion();
spawnEffect.x = enemy.x;
spawnEffect.y = enemy.y;
game.addChild(spawnEffect);
}
};
self.fireLaserBeam = function () {
// Visual effect for charging laser
var chargeEffect = new Explosion();
chargeEffect.x = self.x;
chargeEffect.y = self.y + 50;
game.addChild(chargeEffect);
// Create laser beam after short delay
LK.setTimeout(function () {
var laserBeam = new Container();
var laserGraphics = LK.getAsset('laserBullet', {
anchorX: 0.5,
anchorY: 0,
scaleX: 8,
scaleY: 30,
tint: 0xff3300
});
laserBeam.addChild(laserGraphics);
laserBeam.x = self.x;
laserBeam.y = self.y + 80;
game.addChild(laserBeam);
// Damage player if in path of laser
if (Math.abs(player.x - self.x) < 150) {
player.takeDamage(2);
}
// Remove laser after a short time
LK.setTimeout(function () {
laserBeam.destroy();
self.firingLaser = false;
}, 1000);
}, 500);
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xffffff, 200);
if (self.health <= 0) {
// Multiple explosions for boss death
for (var i = 0; i < 12; i++) {
var explosion = new Explosion();
explosion.x = self.x + (Math.random() * 300 - 150);
explosion.y = self.y + (Math.random() * 200 - 100);
game.addChild(explosion);
// Stagger explosions
LK.setTimeout(function () {
var delayedExplosion = new Explosion();
delayedExplosion.x = self.x + (Math.random() * 300 - 150);
delayedExplosion.y = self.y + (Math.random() * 200 - 100);
game.addChild(delayedExplosion);
}, 100 + i * 100);
}
// Add points to score
score += self.points;
updateScore();
// Drop multiple power-ups
for (var i = 0; i < 3; i++) {
var powerUp = new PowerUp();
powerUp.x = self.x + (i - 1) * 80;
powerUp.y = self.y;
if (i === 0) {
powerUp.setType("shield");
} else if (i === 1) {
powerUp.setType("ultra");
} else {
powerUp.setType("plasma");
}
game.addChild(powerUp);
powerUps.push(powerUp);
}
LK.getSound('explosion').play();
levelComplete = true;
self.destroy();
return true;
}
return false;
};
return self;
});
var PlasmaBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('plasmaBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -12; // Medium speed
self.damage = 3; // Highest damage
// Add pulsating effect
self.pulseFactor = 0;
self.update = function () {
self.y += self.speed;
// Enhanced pulsating effect with rotation
self.pulseFactor += 0.1;
var scale = 1 + Math.sin(self.pulseFactor) * 0.2;
bulletGraphics.scale.x = scale;
bulletGraphics.scale.y = scale;
bulletGraphics.rotation += 0.1; // Add rotation for energy ball effect
// Add color cycling for plasma effect
var colorPhase = LK.ticks % 120 / 120;
var r = Math.floor(255 * Math.sin(Math.PI * colorPhase));
var g = Math.floor(50 * Math.sin(Math.PI * (colorPhase + 0.33)));
var b = Math.floor(255 * Math.sin(Math.PI * (colorPhase + 0.67)));
bulletGraphics.tint = r << 16 | g << 8 | b;
// Add slight x-axis wobble for unstable plasma effect
self.x += Math.sin(self.pulseFactor * 2) * 0.8;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 3;
self.maxHealth = 3;
self.weaponLevel = 1;
self.weaponType = "standard"; // Initialize with standard weapon
self.weaponUpgrades = 0;
self.weaponTimer = 0;
self.speed = 10;
self.shieldEffect = null; // Reference to shield visual effect
self.fireRate = 15; // Frames between shots
self.lastShot = 0;
self.shieldActive = false;
self.shieldTimer = 0;
self.invulnerable = false;
self.invulnerabilityTimer = 0;
self.update = function () {
// Decrement timers
if (self.weaponTimer > 0) {
self.weaponTimer--;
if (self.weaponTimer === 0) {
self.weaponLevel = 1; // Reset weapon level when timer expires
self.weaponType = "standard";
}
}
if (self.shieldActive) {
self.shieldTimer--;
if (self.shieldTimer === 0) {
self.shieldActive = false;
// Remove shield visual effect
if (self.shieldEffect) {
self.shieldEffect.destroy();
self.shieldEffect = null;
}
}
}
if (self.invulnerable) {
self.invulnerabilityTimer--;
// Flash while invulnerable
self.visible = self.invulnerabilityTimer % 6 < 3;
if (self.invulnerabilityTimer === 0) {
self.invulnerable = false;
self.visible = true;
}
}
// Auto-fire
self.lastShot++;
if (self.lastShot >= self.fireRate) {
self.shoot();
self.lastShot = 0;
}
// Update shield effect position if active
if (self.shieldActive && self.shieldEffect) {
self.shieldEffect.x = self.x;
self.shieldEffect.y = self.y;
}
};
self.shoot = function () {
// Choose bullet type based on weaponType
var BulletClass;
switch (self.weaponType) {
case "laser":
BulletClass = LaserBullet;
break;
case "plasma":
BulletClass = PlasmaBullet;
break;
case "ultra":
BulletClass = UltraBullet;
break;
default:
BulletClass = PlayerBullet;
}
if (self.weaponLevel === 1) {
// Single shot
var bullet = new BulletClass();
bullet.x = self.x;
bullet.y = self.y - 40;
game.addChild(bullet);
playerBullets.push(bullet);
} else if (self.weaponLevel === 2) {
// Double shot
for (var i = -1; i <= 1; i += 2) {
var bullet = new BulletClass();
bullet.x = self.x + i * 20;
bullet.y = self.y - 40;
game.addChild(bullet);
playerBullets.push(bullet);
}
} else if (self.weaponLevel === 3) {
// Triple shot
for (var i = -1; i <= 1; i++) {
var bullet = new BulletClass();
bullet.x = self.x + i * 25;
bullet.y = self.y - 40;
game.addChild(bullet);
playerBullets.push(bullet);
}
} else if (self.weaponLevel >= 4) {
// Quad shot - for level 4+
for (var i = -1.5; i <= 1.5; i += 1) {
var bullet = new BulletClass();
bullet.x = self.x + i * 25;
bullet.y = self.y - 40;
game.addChild(bullet);
playerBullets.push(bullet);
}
}
LK.getSound('playerShoot').play();
};
self.takeDamage = function (amount) {
if (self.invulnerable) {
return false;
}
if (self.shieldActive) {
// Shield absorbs the hit
self.shieldActive = false;
self.shieldTimer = 0;
return false;
}
self.health -= amount;
LK.getSound('damage').play();
// Make player invulnerable briefly
self.invulnerable = true;
self.invulnerabilityTimer = 90; // 1.5 seconds at 60fps
if (self.health <= 0) {
// Game over logic
var explosion = new Explosion();
explosion.x = self.x;
explosion.y = self.y;
game.addChild(explosion);
LK.getSound('explosion').play();
// Record high score if needed
if (score > highScore) {
highScore = score;
storage.highScore = highScore;
}
gameOver = true;
return true;
}
return false;
};
self.collectPowerUp = function (powerUp) {
if (powerUp.type === "weapon") {
// Increment weapon level - now up to level 4
self.weaponLevel = Math.min(self.weaponLevel + 1, 4);
self.weaponTimer = 600; // 10 seconds at 60fps
// Determine weapon type based on collected power-ups
if (self.weaponUpgrades === undefined) {
self.weaponUpgrades = 0;
}
self.weaponUpgrades++;
if (self.weaponUpgrades >= 3) {
self.weaponType = "plasma"; // Advanced weapon
} else if (self.weaponUpgrades >= 1) {
self.weaponType = "laser"; // Medium weapon
} else {
self.weaponType = "standard"; // Basic weapon
}
} else if (powerUp.type === "shield") {
self.shieldActive = true;
self.shieldTimer = 600; // 10 seconds at 60fps
// Create shield visual effect if it doesn't exist
if (!self.shieldEffect) {
self.shieldEffect = new ShieldEffect();
self.shieldEffect.x = self.x;
self.shieldEffect.y = self.y;
game.addChild(self.shieldEffect);
}
} else if (powerUp.type === "laser") {
// Direct upgrade to laser weapon
self.weaponType = "laser";
self.weaponLevel = Math.min(self.weaponLevel + 1, 4);
self.weaponTimer = 600; // 10 seconds at 60fps
} else if (powerUp.type === "plasma") {
// Direct upgrade to plasma weapon
self.weaponType = "plasma";
self.weaponLevel = Math.min(self.weaponLevel + 1, 4);
self.weaponTimer = 600; // 10 seconds at 60fps
} else if (powerUp.type === "ultra") {
// Ultimate weapon upgrade
self.weaponType = "ultra";
self.weaponLevel = 4; // Set to max level
self.weaponTimer = 900; // 15 seconds at 60fps
}
LK.getSound('powerUp').play();
};
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 = -15;
self.damage = 1;
self.update = function () {
self.y += self.speed;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = "weapon"; // Default type
self.speed = 5;
self.pulseTimer = 0;
// Set different colors based on type
self.setType = function (type) {
self.type = type;
if (type === "weapon") {
powerUpGraphics.tint = 0x00ff00; // Green for weapons
} else if (type === "shield") {
powerUpGraphics.tint = 0x33ccff; // Blue for shields
} else if (type === "laser") {
powerUpGraphics.tint = 0x00ffaa; // Cyan for laser upgrade
} else if (type === "plasma") {
powerUpGraphics.tint = 0xff00ff; // Magenta for plasma upgrade
} else if (type === "ultra") {
powerUpGraphics.tint = 0xffff00; // Yellow for ultra weapon
}
};
self.update = function () {
self.y += self.speed;
// Enhance visual effect with pulsating and rotation
self.pulseTimer += 0.1;
powerUpGraphics.scale.x = 1 + Math.sin(self.pulseTimer) * 0.2;
powerUpGraphics.scale.y = 1 + Math.sin(self.pulseTimer) * 0.2;
powerUpGraphics.rotation += 0.02;
// Slight oscillation for visual effect
self.x += Math.sin(LK.ticks / 10) * 1;
};
return self;
});
var ShieldEffect = Container.expand(function () {
var self = Container.call(this);
var shieldGraphics = self.attachAsset('shieldEffect', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
self.pulseFactor = 0;
self.update = function () {
// Pulsating effect with enhanced visuals
self.pulseFactor += 0.05;
shieldGraphics.alpha = 0.3 + Math.sin(self.pulseFactor) * 0.2;
shieldGraphics.rotation += 0.01; // Slow rotation for energy field effect
// Create shimmering effect with color changes
var blueIntensity = 0.5 + Math.sin(self.pulseFactor * 1.5) * 0.3;
var cyanIntensity = 0.7 + Math.cos(self.pulseFactor * 0.8) * 0.3;
shieldGraphics.tint = Math.floor(0x33 * blueIntensity) << 16 | Math.floor(0xcc * cyanIntensity) << 8 | 0xff;
// Scale effect for "energy bubble" appearance
var scaleVar = 1 + Math.sin(self.pulseFactor * 0.7) * 0.05;
shieldGraphics.scale.x = scaleVar;
shieldGraphics.scale.y = scaleVar;
};
return self;
});
var UltraBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('plasmaBullet', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
tint: 0xffff00
});
self.speed = -18; // Very fast
self.damage = 5; // Highest damage
self.pulseFactor = 0;
self.update = function () {
self.y += self.speed;
// Dynamic visual effects
self.pulseFactor += 0.15;
var scale = 1.2 + Math.sin(self.pulseFactor) * 0.3;
bulletGraphics.scale.x = scale;
bulletGraphics.scale.y = scale;
bulletGraphics.rotation += 0.15;
// Electric discharge effect
if (LK.ticks % 2 === 0) {
var sparkEffect = LK.getAsset('plasmaBullet', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7,
scaleX: 0.4,
scaleY: 0.4,
tint: 0xffff00
});
sparkEffect.x = self.x + (Math.random() * 40 - 20);
sparkEffect.y = self.y + (Math.random() * 40 - 20);
game.addChild(sparkEffect);
// Create fade-out effect
var sparkDuration = 8;
var fadeInterval = LK.setInterval(function () {
sparkDuration--;
sparkEffect.alpha -= 0.09;
sparkEffect.scaleX -= 0.04;
sparkEffect.scaleY -= 0.04;
if (sparkDuration <= 0) {
LK.clearInterval(fadeInterval);
sparkEffect.destroy();
}
}, 1);
}
// Colorful effect
var time = LK.ticks % 20;
var r = 255;
var g = 255;
var b = Math.floor(100 + time * 7);
bulletGraphics.tint = r << 16 | g << 8 | b;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000022
});
/****
* Game Code
****/
// Game variables
// Initialize main assets with high-quality shapes
var score = 0;
var highScore = storage.highScore || 0;
var level = 1;
var enemySpawnTimer = 0;
var enemySpawnRate = 60; // Frames between enemy spawns
var playerBullets = [];
var enemyBullets = [];
var enemies = [];
var powerUps = [];
var bossSpawned = false;
var levelComplete = false;
var gameOver = false;
var nextEnemy = 0;
// Create dynamic starfield background
var stars = [];
var starLayers = 3; // Multiple layers for parallax effect
// Initialize stars
for (var layer = 0; layer < starLayers; layer++) {
var count = 30 + layer * 20; // More stars in deeper layers
var speed = 1 + layer * 1.5; // Deeper layers move faster
var size = 3 - layer * 0.8; // Deeper layers have smaller stars
var alpha = 0.7 - layer * 0.2; // Deeper layers are more transparent
for (var i = 0; i < count; i++) {
var star = new Container();
var starGraphic = LK.getAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFFFFF,
alpha: alpha,
scaleX: size / 60,
scaleY: size / 60
});
star.addChild(starGraphic);
star.x = Math.random() * 2048;
star.y = Math.random() * 2732;
star.speed = speed;
star.layer = layer;
// Add occasional color variation to brightest stars
if (layer === 0 && Math.random() < 0.3) {
var colors = [0xFFFFCC, 0xCCFFFF, 0xFFCCFF]; // Yellow, blue, pink tints
starGraphic.tint = colors[Math.floor(Math.random() * colors.length)];
}
game.addChild(star);
stars.push(star);
}
}
// Add function to update stars in main update loop
function updateStars() {
for (var i = 0; i < stars.length; i++) {
var star = stars[i];
star.y += star.speed;
// Reset stars when they go off screen
if (star.y > 2732) {
star.y = -10;
star.x = Math.random() * 2048;
}
}
}
// UI elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
var levelTxt = new Text2('Level: 1', {
size: 60,
fill: 0xFFFFFF
});
levelTxt.anchor.set(1, 0);
LK.gui.topLeft.addChild(levelTxt);
// Move it away from the top-left corner
levelTxt.x = 200;
var healthTxt = new Text2('Health: 3', {
size: 60,
fill: 0xFFFFFF
});
healthTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(healthTxt);
// Weapon type indicator
var weaponTxt = new Text2('Weapon: Standard', {
size: 40,
fill: 0xFFFFFF
});
weaponTxt.style = {
fill: 0xFFFFFF
}; // Initialize style object
weaponTxt.anchor.set(0, 0);
LK.gui.bottomLeft.addChild(weaponTxt);
weaponTxt.y = -100; // Position it above the bottom edge
// Function to update weapon display
function updateWeapon() {
var typeText = player.weaponType.charAt(0).toUpperCase() + player.weaponType.slice(1);
weaponTxt.setText('Weapon: ' + typeText + ' (Lv.' + player.weaponLevel + ')');
// Set text color based on weapon type
if (player.weaponType === "standard") {
weaponTxt.style.fill = 0x66ffff;
} else if (player.weaponType === "laser") {
weaponTxt.style.fill = 0x00ffaa;
} else if (player.weaponType === "plasma") {
weaponTxt.style.fill = 0xff00ff;
} else if (player.weaponType === "ultra") {
weaponTxt.style.fill = 0xffff00;
}
}
// Create player
var player = new Player();
player.x = 2048 / 2;
player.y = 2732 - 300;
game.addChild(player);
// Function to update score display
function updateScore() {
scoreTxt.setText('Score: ' + score);
// Update LK score system for leaderboards
LK.setScore(score);
}
// Function to update health display
function updateHealth() {
healthTxt.setText('Health: ' + player.health);
}
// Function to update level display
function updateLevel() {
levelTxt.setText('Level: ' + level);
}
// Function to spawn regular enemies
function spawnEnemy() {
var enemyType;
var enemy;
// Select enemy type based on level and randomness
if (level === 1) {
// Level 1: Only basic enemies
enemy = new Enemy();
enemy.health = 1;
enemy.movementPattern = "straight";
enemy.fireRate = 180;
} else if (level === 2) {
// Level 2: Basic enemies and some hunters
var rand = Math.random();
if (rand < 0.3) {
enemy = new HunterShip();
} else if (rand < 0.6) {
enemy = new Enemy();
enemy.health = 2;
enemy.points = 200;
enemy.movementPattern = "zigzag";
enemy.fireRate = 150;
} else {
enemy = new Enemy();
enemy.health = 1;
enemy.movementPattern = "straight";
enemy.fireRate = 180;
}
} else if (level >= 3 && level < 5) {
// Level 3-4: All enemy types
var rand = Math.random();
if (rand < 0.25) {
enemy = new CarrierShip();
} else if (rand < 0.5) {
enemy = new HunterShip();
} else if (rand < 0.7) {
enemy = new ScoutShip();
} else if (rand < 0.85) {
enemy = new Enemy();
enemy.health = 3;
enemy.points = 300;
enemy.movementPattern = "circle";
enemy.fireRate = 120;
} else {
enemy = new Enemy();
enemy.health = 2;
enemy.points = 200;
enemy.movementPattern = "zigzag";
enemy.fireRate = 150;
}
} else if (level >= 5) {
// Level 5+: Include elite enemies
var rand = Math.random();
if (rand < 0.2) {
enemy = new CarrierShip();
// Enhance carrier properties at higher levels
if (level >= 6) {
enemy.health += 2;
enemy.spawnRate = 150; // Faster spawning
}
} else if (rand < 0.35) {
enemy = new EliteHunterShip(); // Elite hunter
} else if (rand < 0.5) {
enemy = new HunterShip();
} else if (rand < 0.65) {
enemy = new EliteScoutShip(); // Elite scout
} else if (rand < 0.8) {
enemy = new ScoutShip();
} else {
enemy = new Enemy();
enemy.health = 3 + Math.min(level - 5, 3); // Scale up health
enemy.points = 300 + (level - 5) * 50;
enemy.movementPattern = "circle";
enemy.fireRate = Math.max(120 - (level - 5) * 10, 70); // Scale down fire rate (faster shooting)
}
}
// Random position at top of screen
enemy.x = 200 + Math.random() * (2048 - 400);
enemy.y = -100;
game.addChild(enemy);
enemies.push(enemy);
}
// Function to spawn boss
function spawnBoss() {
var boss;
// At higher levels, spawn the MegaBoss instead
if (level >= 4) {
boss = new MegaBoss();
boss.x = 2048 / 2;
boss.y = -300;
// Scale mega boss difficulty with level
boss.health = 50 + (level - 4) * 15;
boss.maxHealth = boss.health;
} else {
boss = new Boss();
boss.x = 2048 / 2;
boss.y = -200;
// Scale boss difficulty with level
boss.health = 20 + (level - 1) * 10;
boss.maxHealth = boss.health;
}
game.addChild(boss);
enemies.push(boss);
bossSpawned = true;
}
// Function to start the next level
function startNextLevel() {
level++;
updateLevel();
enemies = [];
enemyBullets = [];
bossSpawned = false;
levelComplete = false;
nextEnemy = 0;
// Speed up enemy spawns as level increases
enemySpawnRate = Math.max(60 - (level - 1) * 5, 30);
}
// Mouse/Touch handlers
var dragNode = null;
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp position to stay on screen
dragNode.x = Math.max(60, Math.min(x, 2048 - 60));
dragNode.y = Math.max(60, Math.min(y, 2732 - 60));
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
dragNode = player;
handleMove(x, y, obj);
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game update loop
game.update = function () {
// Update starfield background for space atmosphere
updateStars();
if (gameOver) {
// Show game over screen
LK.showGameOver();
return;
}
if (levelComplete) {
startNextLevel();
}
// Update player
player.update();
updateHealth();
updateWeapon();
// Spawn enemies
if (!bossSpawned) {
enemySpawnTimer++;
if (enemySpawnTimer >= enemySpawnRate) {
enemySpawnTimer = 0;
spawnEnemy();
nextEnemy++;
// Spawn boss after certain number of enemies
if (nextEnemy >= 15 + level * 5) {
spawnBoss();
}
}
}
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
// Check if bullet is off screen
if (bullet.y < -50) {
bullet.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check for collisions with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
if (enemy.takeDamage(bullet.damage)) {
enemies.splice(j, 1);
}
bullet.destroy();
playerBullets.splice(i, 1);
break;
}
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
// Check if bullet is off screen
if (bullet.y > 2732 + 50) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check for collision with player
if (bullet.intersects(player)) {
if (player.takeDamage(bullet.damage)) {
// Player destroyed, game over
gameOver = true;
}
bullet.destroy();
enemyBullets.splice(i, 1);
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
// Check if enemy is off screen
if (enemy.y > 2732 + 100) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check for collision with player
if (enemy.intersects(player)) {
if (player.takeDamage(1)) {
// Player destroyed, game over
gameOver = true;
}
// Enemy also takes damage
if (enemy.takeDamage(1)) {
enemies.splice(i, 1);
}
continue;
}
}
// Update power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
// Check if power-up is off screen
if (powerUp.y > 2732 + 50) {
powerUp.destroy();
powerUps.splice(i, 1);
continue;
}
// Check for collision with player
if (powerUp.intersects(player)) {
player.collectPowerUp(powerUp);
powerUp.destroy();
powerUps.splice(i, 1);
}
}
// Check if level is complete (no enemies and boss killed)
if (bossSpawned && enemies.length === 0) {
levelComplete = true;
}
};
// Start background music
LK.playMusic('bgMusic');
a boss robot space ship . No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a enemy space ship. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a red enemy bullet plasma. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a enemy space ship crarrier ship. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a explosion. In-Game asset. 2d. High contrast. No shadows
a enemy space ship hunter ship. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a blue plasma laser. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a blue plasma flame fire. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a player bullet. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a player space ship good. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a level up power up orb. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a tiny enemy ship. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
a shield. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat