/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
bombGraphics.tint = 0xFF4500; // Orange tint for bombs
self.speed = 6;
self.dirX = 0;
self.dirY = 1;
self.update = function () {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
};
self.explode = function () {
// Create explosion effect
tween(self, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
LK.effects.flashScreen(0xFF4500, 300);
LK.getSound('explosion').play();
};
return self;
});
var Enemy = Container.expand(function (enemyType) {
var self = Container.call(this);
self.enemyType = enemyType || 1;
var assetName = self.enemyType === 1 ? 'enemy1' : self.enemyType === 2 ? 'enemy2' : 'enemy3';
var enemyGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = self.enemyType === 1 ? 4 : self.enemyType === 2 ? 8 : 2;
self.moveSpeed = self.enemyType === 1 ? 1.5 : self.enemyType === 2 ? 3 : 1;
self.direction = 1;
self.points = self.enemyType === 1 ? 10 : self.enemyType === 2 ? 20 : 100;
self.maxHealth = self.enemyType === 1 ? 3 : self.enemyType === 2 ? 5 : 50;
self.health = self.maxHealth;
self.shootTimer = Math.random() * 120 + 60;
self.diving = false;
self.diveSpeed = 0;
self.zigzagTimer = 0;
self.zigzagDirection = 1;
self.shootsBeforeDive = 0;
self.maxShootsBeforeDive = 2 + Math.floor(Math.random() * 3);
self.hasReachedMiddle = false;
self.bombTimer = self.enemyType === 3 ? Math.random() * 180 + 120 : 0;
self.omnishootTimer = self.enemyType === 3 ? Math.random() * 240 + 180 : 0;
self.takeDamage = function () {
self.health--;
// Flash red damage effect
tween.stop(enemyGraphics, {
tint: true
});
enemyGraphics.tint = 0xff0000;
tween(enemyGraphics, {
tint: 0xffffff
}, {
duration: 200
});
return self.health <= 0;
};
self.update = function () {
if (self.diving) {
self.y += self.diveSpeed;
self.diveSpeed += 0.4;
} else {
// Move down until reaching middle of screen
if (!self.hasReachedMiddle) {
self.y += self.speed;
if (self.y >= 2732 / 3) {
self.hasReachedMiddle = true;
}
} else {
// Zigzag movement once in middle
self.zigzagTimer++;
if (self.zigzagTimer > 120) {
self.zigzagDirection *= -1;
self.zigzagTimer = 0;
}
self.x += self.zigzagDirection * self.moveSpeed;
self.y += self.speed * 0.2;
}
}
self.shootTimer--;
if (self.shootTimer <= 0 && !self.diving && self.hasReachedMiddle) {
self.shootTimer = Math.random() * 100 + 80;
if (self.enemyType === 3) {
// Boss enemy shoots bullets in all directions
for (var angle = 0; angle < 360; angle += 45) {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y;
var rad = angle * Math.PI / 180;
bullet.dirX = Math.cos(rad);
bullet.dirY = Math.sin(rad);
bullet.speed = 12;
enemyBullets.push(bullet);
game.addChild(bullet);
}
} else if (self.enemyType === 2) {
// Enemy type 2 shoots 5 bullets in a spread pattern
for (var i = 0; i < 5; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x + (i - 2) * 30; // Spread bullets horizontally
bullet.y = self.y + 40;
bullet.speed = 16; // Double speed for type 2 bullets
enemyBullets.push(bullet);
game.addChild(bullet);
}
} else {
// Enemy type 1 shoots single bullet
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 40;
enemyBullets.push(bullet);
game.addChild(bullet);
}
self.shootsBeforeDive++;
}
// Boss bomb shooting
if (self.enemyType === 3) {
self.bombTimer--;
if (self.bombTimer <= 0) {
self.bombTimer = Math.random() * 300 + 200;
var bomb = new Bomb();
bomb.x = self.x;
bomb.y = self.y + 50;
bomb.dirX = (player.x - self.x) / 300; // Aim towards player
bomb.dirY = Math.abs(bomb.dirX) + 0.5;
bombs.push(bomb);
game.addChild(bomb);
}
}
if (self.shootsBeforeDive >= self.maxShootsBeforeDive && Math.random() < 0.003 && !self.diving && self.hasReachedMiddle) {
self.diving = true;
self.diveSpeed = 2;
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.dirX = 0;
self.dirY = 1;
self.update = function () {
if (self.dirX !== 0 || self.dirY !== 1) {
// Directional movement for boss bullets
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
} else {
// Default downward movement
self.y += self.speed;
}
};
return self;
});
var HealthOrb = Container.expand(function () {
var self = Container.call(this);
var orbGraphics = self.attachAsset('healthOrb', {
anchorX: 0.5,
anchorY: 0.5
});
orbGraphics.tint = 0x00ff00; // Green tint for health
self.update = function () {
// Pulse effect
self.rotation += 0.05;
var scale = 1 + Math.sin(LK.ticks * 0.15) * 0.3;
self.scaleX = scale;
self.scaleY = scale;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.shootCooldown = 0;
self.lives = 3;
self.maxHealth = 100;
self.health = self.maxHealth;
self.update = function () {
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
self.shoot = function () {
if (self.shootCooldown <= 0) {
if (tripleShot) {
// Triple shot
var bullet1 = new PlayerBullet();
bullet1.x = self.x - 30;
bullet1.y = self.y - 50;
playerBullets.push(bullet1);
game.addChild(bullet1);
var bullet2 = new PlayerBullet();
bullet2.x = self.x;
bullet2.y = self.y - 50;
playerBullets.push(bullet2);
game.addChild(bullet2);
var bullet3 = new PlayerBullet();
bullet3.x = self.x + 30;
bullet3.y = self.y - 50;
playerBullets.push(bullet3);
game.addChild(bullet3);
} else {
// Single shot
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - 50;
playerBullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('shoot').play();
self.shootCooldown = 10;
}
};
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 = -18;
self.update = function () {
self.y += self.speed;
};
return self;
});
var PowerOrb = Container.expand(function () {
var self = Container.call(this);
var orbGraphics = self.attachAsset('powerOrb', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Pulse effect
self.rotation += 0.1;
var scale = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
self.scaleX = scale;
self.scaleY = scale;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
var player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 - 150;
var playerBullets = [];
var enemyBullets = [];
var enemies = [];
var wave = 1;
var enemiesPerWave = 8;
var waveSpawnTimer = 0;
var enemiesSpawned = 0;
var gameStarted = false;
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 150;
scoreTxt.y = 50;
LK.gui.addChild(scoreTxt);
var waveTxt = new Text2('Wave: 1', {
size: 60,
fill: 0xFFFFFF
});
waveTxt.anchor.set(1, 0);
waveTxt.x = -150;
waveTxt.y = 50;
LK.gui.topRight.addChild(waveTxt);
var healthTxt = new Text2('Health: 100', {
size: 60,
fill: 0x00ff00
});
healthTxt.anchor.set(0.5, 0);
healthTxt.x = 0;
healthTxt.y = 50;
LK.gui.top.addChild(healthTxt);
var dragTarget = null;
var powerOrb = null;
var tripleShot = false;
var tripleShotTimer = 0;
var orbSpawned = false;
var healthOrbs = [];
var lastHealthBelowFifty = false;
var bombs = [];
var bossActive = false;
function spawnEnemyWave() {
// Check if boss should spawn (every 5th wave)
if (wave % 5 === 0 && !bossActive && enemies.length === 0) {
var boss = new Enemy(3);
boss.x = 2048 / 2;
boss.y = -200;
enemies.push(boss);
game.addChild(boss);
bossActive = true;
enemiesSpawned = enemiesPerWave; // Prevent other spawns
return;
}
// Don't spawn regular enemies if boss is active
if (bossActive) {
return;
}
if (enemiesSpawned < enemiesPerWave) {
if (waveSpawnTimer <= 0) {
var enemyType = Math.random() < 0.7 ? 1 : 2;
var enemy = new Enemy(enemyType);
enemy.x = 200 + enemiesSpawned * 200;
enemy.y = -100;
enemies.push(enemy);
game.addChild(enemy);
enemiesSpawned++;
waveSpawnTimer = 30;
} else {
waveSpawnTimer--;
}
}
}
function checkCollisions() {
// Player bullets vs enemies
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
LK.getSound('enemyHit').play();
bullet.destroy();
playerBullets.splice(i, 1);
var enemyDestroyed = enemy.takeDamage();
if (enemyDestroyed) {
LK.setScore(LK.getScore() + enemy.points);
scoreTxt.setText('Score: ' + LK.getScore());
enemy.destroy();
enemies.splice(j, 1);
}
break;
}
}
}
// Enemy bullets vs player
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (bullet.intersects(player)) {
player.health -= 20;
healthTxt.setText('Health: ' + player.health);
if (player.health <= 0) {
healthTxt.tint = 0xff0000;
} else if (player.health <= 30) {
healthTxt.tint = 0xff6600;
} else {
healthTxt.tint = 0x00ff00;
}
LK.effects.flashScreen(0xff0000, 500);
bullet.destroy();
enemyBullets.splice(i, 1);
LK.getSound('explosion').play();
if (player.health <= 0) {
LK.showGameOver();
return;
}
}
}
// Enemies vs player
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy.intersects(player)) {
player.health -= 30;
healthTxt.setText('Health: ' + player.health);
if (player.health <= 0) {
healthTxt.tint = 0xff0000;
} else if (player.health <= 30) {
healthTxt.tint = 0xff6600;
} else {
healthTxt.tint = 0x00ff00;
}
LK.effects.flashScreen(0xff0000, 500);
enemy.destroy();
enemies.splice(i, 1);
LK.getSound('explosion').play();
if (player.health <= 0) {
LK.showGameOver();
return;
}
}
}
// Player bullets vs bombs
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
for (var b = bombs.length - 1; b >= 0; b--) {
var bomb = bombs[b];
if (bullet.intersects(bomb)) {
bullet.destroy();
playerBullets.splice(i, 1);
bomb.explode();
bombs.splice(b, 1);
break;
}
}
}
// Bombs vs player
for (var b = bombs.length - 1; b >= 0; b--) {
var bomb = bombs[b];
if (bomb.intersects(player)) {
player.health -= 40;
healthTxt.setText('Health: ' + player.health);
if (player.health <= 0) {
healthTxt.tint = 0xff0000;
} else if (player.health <= 30) {
healthTxt.tint = 0xff6600;
} else {
healthTxt.tint = 0x00ff00;
}
bomb.explode();
bombs.splice(b, 1);
if (player.health <= 0) {
LK.showGameOver();
return;
}
}
}
}
function updateBullets() {
// Clean up player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.y < -50) {
bullet.destroy();
playerBullets.splice(i, 1);
}
}
// Clean up enemy bullets and award dodge points
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (bullet.y > 2732 + 50) {
// Award points for dodging bullet
LK.setScore(LK.getScore() + 5);
scoreTxt.setText('Score: ' + LK.getScore());
bullet.destroy();
enemyBullets.splice(i, 1);
}
}
// Check power orb collision
if (powerOrb) {
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.intersects(powerOrb)) {
// Activate triple shot
tripleShot = true;
tripleShotTimer = 600; // 10 seconds at 60fps
// Remove orb and bullet
powerOrb.destroy();
powerOrb = null;
bullet.destroy();
playerBullets.splice(i, 1);
// Flash screen blue
LK.effects.flashScreen(0x00ffff, 500);
break;
}
}
}
// Check health orb collisions
for (var h = healthOrbs.length - 1; h >= 0; h--) {
var healthOrb = healthOrbs[h];
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.intersects(healthOrb)) {
// Restore health
player.health = Math.min(player.maxHealth, player.health + 25);
healthTxt.setText('Health: ' + player.health);
if (player.health <= 30) {
healthTxt.tint = 0xff6600;
} else {
healthTxt.tint = 0x00ff00;
}
// Remove orb and bullet
healthOrb.destroy();
healthOrbs.splice(h, 1);
bullet.destroy();
playerBullets.splice(i, 1);
// Flash screen green
LK.effects.flashScreen(0x00ff00, 500);
break;
}
}
}
// Clean up bombs that go off screen
for (var b = bombs.length - 1; b >= 0; b--) {
var bomb = bombs[b];
if (bomb.y > 2732 + 100 || bomb.y < -100 || bomb.x < -100 || bomb.x > 2148) {
bomb.destroy();
bombs.splice(b, 1);
}
}
}
function updateEnemies() {
// Clean up enemies that went off screen
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy.y > 2732 + 100) {
enemy.destroy();
enemies.splice(i, 1);
}
// Reverse direction if hitting screen edges
if (enemy.x <= 50 || enemy.x >= 1998) {
enemy.direction *= -1;
}
}
}
function checkWaveComplete() {
if (enemies.length === 0 && enemiesSpawned >= enemiesPerWave) {
if (bossActive) {
bossActive = false;
// Extra bonus for defeating boss
LK.setScore(LK.getScore() + 500);
scoreTxt.setText('Score: ' + LK.getScore());
}
wave++;
enemiesPerWave += 2;
enemiesSpawned = 0;
waveSpawnTimer = 0;
waveTxt.setText('Wave: ' + wave);
// Bonus points for completing wave
LK.setScore(LK.getScore() + wave * 50);
scoreTxt.setText('Score: ' + LK.getScore());
}
}
game.down = function (x, y, obj) {
dragTarget = player;
player.x = x;
player.y = Math.max(100, Math.min(2632, y));
player.shoot();
};
game.move = function (x, y, obj) {
if (dragTarget) {
dragTarget.x = Math.max(40, Math.min(2008, x));
dragTarget.y = Math.max(100, Math.min(2632, y));
}
};
game.up = function (x, y, obj) {
dragTarget = null;
};
game.update = function () {
if (!gameStarted) {
gameStarted = true;
}
spawnEnemyWave();
updateBullets();
updateEnemies();
checkCollisions();
checkWaveComplete();
// Spawn power orb when score reaches 100
if (LK.getScore() >= 100 && !powerOrb && !orbSpawned) {
powerOrb = new PowerOrb();
powerOrb.x = 2048 / 2;
powerOrb.y = 2732 / 2;
game.addChild(powerOrb);
orbSpawned = true;
}
// Spawn health orbs when health drops below 50
var currentHealthBelowFifty = player.health < 50;
if (!lastHealthBelowFifty && currentHealthBelowFifty && healthOrbs.length === 0) {
// Spawn 2-3 health orbs
var numOrbs = 2 + Math.floor(Math.random() * 2);
for (var o = 0; o < numOrbs; o++) {
var healthOrb = new HealthOrb();
healthOrb.x = 300 + o * 400 + Math.random() * 200;
healthOrb.y = 500 + Math.random() * 1000;
healthOrbs.push(healthOrb);
game.addChild(healthOrb);
}
}
lastHealthBelowFifty = currentHealthBelowFifty;
// Clean up health orbs that go off screen
for (var h = healthOrbs.length - 1; h >= 0; h--) {
var healthOrb = healthOrbs[h];
if (healthOrb.y > 2732 + 100 || healthOrb.y < -100 || healthOrb.x < -100 || healthOrb.x > 2148) {
healthOrb.destroy();
healthOrbs.splice(h, 1);
}
}
// Manage triple shot timer
if (tripleShot) {
tripleShotTimer--;
if (tripleShotTimer <= 0) {
tripleShot = false;
}
}
// Auto-shoot for continuous fire
if (LK.ticks % 8 === 0) {
player.shoot();
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Bomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('bomb', {
anchorX: 0.5,
anchorY: 0.5
});
bombGraphics.tint = 0xFF4500; // Orange tint for bombs
self.speed = 6;
self.dirX = 0;
self.dirY = 1;
self.update = function () {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
};
self.explode = function () {
// Create explosion effect
tween(self, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
LK.effects.flashScreen(0xFF4500, 300);
LK.getSound('explosion').play();
};
return self;
});
var Enemy = Container.expand(function (enemyType) {
var self = Container.call(this);
self.enemyType = enemyType || 1;
var assetName = self.enemyType === 1 ? 'enemy1' : self.enemyType === 2 ? 'enemy2' : 'enemy3';
var enemyGraphics = self.attachAsset(assetName, {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = self.enemyType === 1 ? 4 : self.enemyType === 2 ? 8 : 2;
self.moveSpeed = self.enemyType === 1 ? 1.5 : self.enemyType === 2 ? 3 : 1;
self.direction = 1;
self.points = self.enemyType === 1 ? 10 : self.enemyType === 2 ? 20 : 100;
self.maxHealth = self.enemyType === 1 ? 3 : self.enemyType === 2 ? 5 : 50;
self.health = self.maxHealth;
self.shootTimer = Math.random() * 120 + 60;
self.diving = false;
self.diveSpeed = 0;
self.zigzagTimer = 0;
self.zigzagDirection = 1;
self.shootsBeforeDive = 0;
self.maxShootsBeforeDive = 2 + Math.floor(Math.random() * 3);
self.hasReachedMiddle = false;
self.bombTimer = self.enemyType === 3 ? Math.random() * 180 + 120 : 0;
self.omnishootTimer = self.enemyType === 3 ? Math.random() * 240 + 180 : 0;
self.takeDamage = function () {
self.health--;
// Flash red damage effect
tween.stop(enemyGraphics, {
tint: true
});
enemyGraphics.tint = 0xff0000;
tween(enemyGraphics, {
tint: 0xffffff
}, {
duration: 200
});
return self.health <= 0;
};
self.update = function () {
if (self.diving) {
self.y += self.diveSpeed;
self.diveSpeed += 0.4;
} else {
// Move down until reaching middle of screen
if (!self.hasReachedMiddle) {
self.y += self.speed;
if (self.y >= 2732 / 3) {
self.hasReachedMiddle = true;
}
} else {
// Zigzag movement once in middle
self.zigzagTimer++;
if (self.zigzagTimer > 120) {
self.zigzagDirection *= -1;
self.zigzagTimer = 0;
}
self.x += self.zigzagDirection * self.moveSpeed;
self.y += self.speed * 0.2;
}
}
self.shootTimer--;
if (self.shootTimer <= 0 && !self.diving && self.hasReachedMiddle) {
self.shootTimer = Math.random() * 100 + 80;
if (self.enemyType === 3) {
// Boss enemy shoots bullets in all directions
for (var angle = 0; angle < 360; angle += 45) {
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y;
var rad = angle * Math.PI / 180;
bullet.dirX = Math.cos(rad);
bullet.dirY = Math.sin(rad);
bullet.speed = 12;
enemyBullets.push(bullet);
game.addChild(bullet);
}
} else if (self.enemyType === 2) {
// Enemy type 2 shoots 5 bullets in a spread pattern
for (var i = 0; i < 5; i++) {
var bullet = new EnemyBullet();
bullet.x = self.x + (i - 2) * 30; // Spread bullets horizontally
bullet.y = self.y + 40;
bullet.speed = 16; // Double speed for type 2 bullets
enemyBullets.push(bullet);
game.addChild(bullet);
}
} else {
// Enemy type 1 shoots single bullet
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 40;
enemyBullets.push(bullet);
game.addChild(bullet);
}
self.shootsBeforeDive++;
}
// Boss bomb shooting
if (self.enemyType === 3) {
self.bombTimer--;
if (self.bombTimer <= 0) {
self.bombTimer = Math.random() * 300 + 200;
var bomb = new Bomb();
bomb.x = self.x;
bomb.y = self.y + 50;
bomb.dirX = (player.x - self.x) / 300; // Aim towards player
bomb.dirY = Math.abs(bomb.dirX) + 0.5;
bombs.push(bomb);
game.addChild(bomb);
}
}
if (self.shootsBeforeDive >= self.maxShootsBeforeDive && Math.random() < 0.003 && !self.diving && self.hasReachedMiddle) {
self.diving = true;
self.diveSpeed = 2;
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.dirX = 0;
self.dirY = 1;
self.update = function () {
if (self.dirX !== 0 || self.dirY !== 1) {
// Directional movement for boss bullets
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
} else {
// Default downward movement
self.y += self.speed;
}
};
return self;
});
var HealthOrb = Container.expand(function () {
var self = Container.call(this);
var orbGraphics = self.attachAsset('healthOrb', {
anchorX: 0.5,
anchorY: 0.5
});
orbGraphics.tint = 0x00ff00; // Green tint for health
self.update = function () {
// Pulse effect
self.rotation += 0.05;
var scale = 1 + Math.sin(LK.ticks * 0.15) * 0.3;
self.scaleX = scale;
self.scaleY = scale;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.shootCooldown = 0;
self.lives = 3;
self.maxHealth = 100;
self.health = self.maxHealth;
self.update = function () {
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
self.shoot = function () {
if (self.shootCooldown <= 0) {
if (tripleShot) {
// Triple shot
var bullet1 = new PlayerBullet();
bullet1.x = self.x - 30;
bullet1.y = self.y - 50;
playerBullets.push(bullet1);
game.addChild(bullet1);
var bullet2 = new PlayerBullet();
bullet2.x = self.x;
bullet2.y = self.y - 50;
playerBullets.push(bullet2);
game.addChild(bullet2);
var bullet3 = new PlayerBullet();
bullet3.x = self.x + 30;
bullet3.y = self.y - 50;
playerBullets.push(bullet3);
game.addChild(bullet3);
} else {
// Single shot
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - 50;
playerBullets.push(bullet);
game.addChild(bullet);
}
LK.getSound('shoot').play();
self.shootCooldown = 10;
}
};
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 = -18;
self.update = function () {
self.y += self.speed;
};
return self;
});
var PowerOrb = Container.expand(function () {
var self = Container.call(this);
var orbGraphics = self.attachAsset('powerOrb', {
anchorX: 0.5,
anchorY: 0.5
});
self.update = function () {
// Pulse effect
self.rotation += 0.1;
var scale = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
self.scaleX = scale;
self.scaleY = scale;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
var player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 - 150;
var playerBullets = [];
var enemyBullets = [];
var enemies = [];
var wave = 1;
var enemiesPerWave = 8;
var waveSpawnTimer = 0;
var enemiesSpawned = 0;
var gameStarted = false;
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 150;
scoreTxt.y = 50;
LK.gui.addChild(scoreTxt);
var waveTxt = new Text2('Wave: 1', {
size: 60,
fill: 0xFFFFFF
});
waveTxt.anchor.set(1, 0);
waveTxt.x = -150;
waveTxt.y = 50;
LK.gui.topRight.addChild(waveTxt);
var healthTxt = new Text2('Health: 100', {
size: 60,
fill: 0x00ff00
});
healthTxt.anchor.set(0.5, 0);
healthTxt.x = 0;
healthTxt.y = 50;
LK.gui.top.addChild(healthTxt);
var dragTarget = null;
var powerOrb = null;
var tripleShot = false;
var tripleShotTimer = 0;
var orbSpawned = false;
var healthOrbs = [];
var lastHealthBelowFifty = false;
var bombs = [];
var bossActive = false;
function spawnEnemyWave() {
// Check if boss should spawn (every 5th wave)
if (wave % 5 === 0 && !bossActive && enemies.length === 0) {
var boss = new Enemy(3);
boss.x = 2048 / 2;
boss.y = -200;
enemies.push(boss);
game.addChild(boss);
bossActive = true;
enemiesSpawned = enemiesPerWave; // Prevent other spawns
return;
}
// Don't spawn regular enemies if boss is active
if (bossActive) {
return;
}
if (enemiesSpawned < enemiesPerWave) {
if (waveSpawnTimer <= 0) {
var enemyType = Math.random() < 0.7 ? 1 : 2;
var enemy = new Enemy(enemyType);
enemy.x = 200 + enemiesSpawned * 200;
enemy.y = -100;
enemies.push(enemy);
game.addChild(enemy);
enemiesSpawned++;
waveSpawnTimer = 30;
} else {
waveSpawnTimer--;
}
}
}
function checkCollisions() {
// Player bullets vs enemies
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
LK.getSound('enemyHit').play();
bullet.destroy();
playerBullets.splice(i, 1);
var enemyDestroyed = enemy.takeDamage();
if (enemyDestroyed) {
LK.setScore(LK.getScore() + enemy.points);
scoreTxt.setText('Score: ' + LK.getScore());
enemy.destroy();
enemies.splice(j, 1);
}
break;
}
}
}
// Enemy bullets vs player
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (bullet.intersects(player)) {
player.health -= 20;
healthTxt.setText('Health: ' + player.health);
if (player.health <= 0) {
healthTxt.tint = 0xff0000;
} else if (player.health <= 30) {
healthTxt.tint = 0xff6600;
} else {
healthTxt.tint = 0x00ff00;
}
LK.effects.flashScreen(0xff0000, 500);
bullet.destroy();
enemyBullets.splice(i, 1);
LK.getSound('explosion').play();
if (player.health <= 0) {
LK.showGameOver();
return;
}
}
}
// Enemies vs player
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy.intersects(player)) {
player.health -= 30;
healthTxt.setText('Health: ' + player.health);
if (player.health <= 0) {
healthTxt.tint = 0xff0000;
} else if (player.health <= 30) {
healthTxt.tint = 0xff6600;
} else {
healthTxt.tint = 0x00ff00;
}
LK.effects.flashScreen(0xff0000, 500);
enemy.destroy();
enemies.splice(i, 1);
LK.getSound('explosion').play();
if (player.health <= 0) {
LK.showGameOver();
return;
}
}
}
// Player bullets vs bombs
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
for (var b = bombs.length - 1; b >= 0; b--) {
var bomb = bombs[b];
if (bullet.intersects(bomb)) {
bullet.destroy();
playerBullets.splice(i, 1);
bomb.explode();
bombs.splice(b, 1);
break;
}
}
}
// Bombs vs player
for (var b = bombs.length - 1; b >= 0; b--) {
var bomb = bombs[b];
if (bomb.intersects(player)) {
player.health -= 40;
healthTxt.setText('Health: ' + player.health);
if (player.health <= 0) {
healthTxt.tint = 0xff0000;
} else if (player.health <= 30) {
healthTxt.tint = 0xff6600;
} else {
healthTxt.tint = 0x00ff00;
}
bomb.explode();
bombs.splice(b, 1);
if (player.health <= 0) {
LK.showGameOver();
return;
}
}
}
}
function updateBullets() {
// Clean up player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.y < -50) {
bullet.destroy();
playerBullets.splice(i, 1);
}
}
// Clean up enemy bullets and award dodge points
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (bullet.y > 2732 + 50) {
// Award points for dodging bullet
LK.setScore(LK.getScore() + 5);
scoreTxt.setText('Score: ' + LK.getScore());
bullet.destroy();
enemyBullets.splice(i, 1);
}
}
// Check power orb collision
if (powerOrb) {
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.intersects(powerOrb)) {
// Activate triple shot
tripleShot = true;
tripleShotTimer = 600; // 10 seconds at 60fps
// Remove orb and bullet
powerOrb.destroy();
powerOrb = null;
bullet.destroy();
playerBullets.splice(i, 1);
// Flash screen blue
LK.effects.flashScreen(0x00ffff, 500);
break;
}
}
}
// Check health orb collisions
for (var h = healthOrbs.length - 1; h >= 0; h--) {
var healthOrb = healthOrbs[h];
for (var i = playerBullets.length - 1; i >= 0; i--) {
var bullet = playerBullets[i];
if (bullet.intersects(healthOrb)) {
// Restore health
player.health = Math.min(player.maxHealth, player.health + 25);
healthTxt.setText('Health: ' + player.health);
if (player.health <= 30) {
healthTxt.tint = 0xff6600;
} else {
healthTxt.tint = 0x00ff00;
}
// Remove orb and bullet
healthOrb.destroy();
healthOrbs.splice(h, 1);
bullet.destroy();
playerBullets.splice(i, 1);
// Flash screen green
LK.effects.flashScreen(0x00ff00, 500);
break;
}
}
}
// Clean up bombs that go off screen
for (var b = bombs.length - 1; b >= 0; b--) {
var bomb = bombs[b];
if (bomb.y > 2732 + 100 || bomb.y < -100 || bomb.x < -100 || bomb.x > 2148) {
bomb.destroy();
bombs.splice(b, 1);
}
}
}
function updateEnemies() {
// Clean up enemies that went off screen
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (enemy.y > 2732 + 100) {
enemy.destroy();
enemies.splice(i, 1);
}
// Reverse direction if hitting screen edges
if (enemy.x <= 50 || enemy.x >= 1998) {
enemy.direction *= -1;
}
}
}
function checkWaveComplete() {
if (enemies.length === 0 && enemiesSpawned >= enemiesPerWave) {
if (bossActive) {
bossActive = false;
// Extra bonus for defeating boss
LK.setScore(LK.getScore() + 500);
scoreTxt.setText('Score: ' + LK.getScore());
}
wave++;
enemiesPerWave += 2;
enemiesSpawned = 0;
waveSpawnTimer = 0;
waveTxt.setText('Wave: ' + wave);
// Bonus points for completing wave
LK.setScore(LK.getScore() + wave * 50);
scoreTxt.setText('Score: ' + LK.getScore());
}
}
game.down = function (x, y, obj) {
dragTarget = player;
player.x = x;
player.y = Math.max(100, Math.min(2632, y));
player.shoot();
};
game.move = function (x, y, obj) {
if (dragTarget) {
dragTarget.x = Math.max(40, Math.min(2008, x));
dragTarget.y = Math.max(100, Math.min(2632, y));
}
};
game.up = function (x, y, obj) {
dragTarget = null;
};
game.update = function () {
if (!gameStarted) {
gameStarted = true;
}
spawnEnemyWave();
updateBullets();
updateEnemies();
checkCollisions();
checkWaveComplete();
// Spawn power orb when score reaches 100
if (LK.getScore() >= 100 && !powerOrb && !orbSpawned) {
powerOrb = new PowerOrb();
powerOrb.x = 2048 / 2;
powerOrb.y = 2732 / 2;
game.addChild(powerOrb);
orbSpawned = true;
}
// Spawn health orbs when health drops below 50
var currentHealthBelowFifty = player.health < 50;
if (!lastHealthBelowFifty && currentHealthBelowFifty && healthOrbs.length === 0) {
// Spawn 2-3 health orbs
var numOrbs = 2 + Math.floor(Math.random() * 2);
for (var o = 0; o < numOrbs; o++) {
var healthOrb = new HealthOrb();
healthOrb.x = 300 + o * 400 + Math.random() * 200;
healthOrb.y = 500 + Math.random() * 1000;
healthOrbs.push(healthOrb);
game.addChild(healthOrb);
}
}
lastHealthBelowFifty = currentHealthBelowFifty;
// Clean up health orbs that go off screen
for (var h = healthOrbs.length - 1; h >= 0; h--) {
var healthOrb = healthOrbs[h];
if (healthOrb.y > 2732 + 100 || healthOrb.y < -100 || healthOrb.x < -100 || healthOrb.x > 2148) {
healthOrb.destroy();
healthOrbs.splice(h, 1);
}
}
// Manage triple shot timer
if (tripleShot) {
tripleShotTimer--;
if (tripleShotTimer <= 0) {
tripleShot = false;
}
}
// Auto-shoot for continuous fire
if (LK.ticks % 8 === 0) {
player.shoot();
}
};