User prompt
add more bullet levels and more enemy types and other bosses
User prompt
add more bullet levels and more enemy types and other bosses
User prompt
make assest cool and realistic
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'weaponTxt.style.fill = 0x66ffff;' Line Number: 741
User prompt
add level upp and new weaponnnsss and make realistic enemy aliens and spaceships
Code edit (1 edits merged)
Please save this source code
User prompt
Cosmic Defender: Orbital Showdown
User prompt
Please continue polishing my design document.
Initial prompt
Make a drawing game, have 5 levels and ask us to draw something in each level, but after the 5th level, let's make it a horror game where we become enemies with the things we draw.
/****
* 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