/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
level: 1
});
/****
* Classes
****/
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
self.health = 300;
self.maxHealth = 300;
self.pointValue = 100;
self.phase = 1;
self.shootCooldown = 0;
self.shootDelay = 60; // 1 second at 60 fps
self.movementCounter = 0;
self.speed = 1;
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 200);
// Phase transitions
if (self.health < self.maxHealth * 0.7 && self.phase === 1) {
self.phase = 2;
self.shootDelay = 45; // Faster attacks in phase 2
} else if (self.health < self.maxHealth * 0.3 && self.phase === 2) {
self.phase = 3;
self.shootDelay = 30; // Even faster attacks in phase 3
bossGraphics.tint = 0xff5555; // Visual indicator for final phase
}
};
self.update = function () {
// Boss movement pattern
if (self.phase === 1) {
self.x += Math.sin(self.movementCounter * 0.02) * 2;
if (self.y < 400) {
self.y += 0.5;
}
} else if (self.phase === 2) {
self.x += Math.sin(self.movementCounter * 0.03) * 3;
self.y += Math.sin(self.movementCounter * 0.01) * 1;
} else {
self.x += Math.sin(self.movementCounter * 0.04) * 5;
self.y += Math.sin(self.movementCounter * 0.02) * 2;
}
self.movementCounter++;
// Update shoot cooldown
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 12;
self.damage = 10;
self.direction = {
x: 0,
y: -1
};
self.update = function () {
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 30;
self.speed = 2;
self.pointValue = 10;
self.movementPattern = 'direct'; // direct, zigzag, circle
self.movementCounter = 0;
self.shootCooldown = 0;
self.shootDelay = 360; // 6 seconds at 60 fps
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 200);
};
self.update = function () {
// Movement patterns
switch (self.movementPattern) {
case 'direct':
self.y += self.speed;
break;
case 'zigzag':
self.y += self.speed;
self.x += Math.sin(self.movementCounter * 0.05) * 3;
self.movementCounter++;
break;
case 'circle':
self.y += self.speed * 0.7;
self.x += Math.sin(self.movementCounter * 0.03) * 4;
self.movementCounter++;
break;
}
// Update shoot cooldown
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
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.damage = 5;
self.direction = {
x: 0,
y: 1
};
self.update = function () {
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
self.health = 100;
self.maxHealth = 100;
self.shootCooldown = 0;
self.shootDelay = 15;
self.speed = 10;
self.powerUpActive = false;
self.powerUpTimer = 0;
self.powerUpDuration = 300; // 5 seconds at 60 fps
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health <= 0) {
self.health = 0;
}
LK.getSound('playerDamage').play();
LK.effects.flashObject(self, 0xff0000, 500);
tween(playerGraphics, {
alpha: 0.3
}, {
duration: 100,
onFinish: function onFinish() {
tween(playerGraphics, {
alpha: 1
}, {
duration: 100
});
}
});
};
self.activatePowerUp = function () {
self.powerUpActive = true;
self.powerUpTimer = self.powerUpDuration;
playerGraphics.tint = 0x2ecc71;
self.shootDelay = 7; // Faster shooting with power-up
};
self.update = function () {
// Update power-up status
if (self.powerUpActive) {
self.powerUpTimer--;
if (self.powerUpTimer <= 0) {
self.powerUpActive = false;
playerGraphics.tint = 0xffffff; // Reset tint
self.shootDelay = 15; // Reset shooting speed
}
}
// Update shoot cooldown
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.rotationSpeed = 0.05;
self.update = function () {
self.y += self.speed;
self.rotation += self.rotationSpeed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
/****
* Game Description
*
* Welcome to the Ultimate Space Battle! In this thrilling game, you are the pilot of a powerful spaceship tasked with defending the galaxy from waves of enemy ships and formidable bosses.
* Navigate through the arena, dodge enemy fire, and strategically shoot down foes to earn points.
* Collect power-ups to enhance your ship's capabilities and survive the relentless onslaught.
* Every fifth wave brings a challenging boss fight, testing your skills and reflexes.
* Aim for the highest score and see if you can beat your personal best!
****/
game.setBackgroundColor(0x2c3e50);
// Game variables
var player;
var bullets = [];
var enemyBullets = [];
var enemies = [];
var powerUps = [];
var boss = null;
var isBossFight = false;
var gameLevel = storage.level || 1;
var score = 0;
var wave = 1;
var waveSize = 5 + (gameLevel - 1) * 2;
var waveDelay = 180; // 3 seconds at 60fps
var waveTimer = waveDelay;
var lastMouseX = 0;
var lastMouseY = 0;
// Create arena background
var arena = LK.getAsset('arena', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
arena.x = 2048 / 2;
arena.y = 2732 / 2;
game.addChild(arena);
// Create player
player = new Player();
player.x = 2048 / 2;
player.y = 2732 - 300;
game.addChild(player);
// UI Elements
var scoreTxt = new Text2('SCORE: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
var waveTxt = new Text2('WAVE: 1', {
size: 80,
fill: 0xFFFFFF
});
waveTxt.anchor.set(1, 0);
LK.gui.topLeft.addChild(waveTxt);
waveTxt.x = 150; // Move away from the corner
// Player Health Bar
var healthBar = new Container();
var healthBarBg = LK.getAsset('bullet', {
anchorX: 0,
anchorY: 0.5,
scaleX: 20,
scaleY: 0.8
});
healthBarBg.tint = 0x333333;
var healthBarFill = LK.getAsset('bullet', {
anchorX: 0,
anchorY: 0.5,
scaleX: 20,
scaleY: 0.8
});
healthBarFill.tint = 0x2ecc71;
healthBar.addChild(healthBarBg);
healthBar.addChild(healthBarFill);
healthBar.y = 100;
LK.gui.bottom.addChild(healthBar);
var healthBar = new Container();
var healthBarBg = LK.getAsset('bullet', {
anchorX: 0,
anchorY: 0.5,
scaleX: 20,
scaleY: 0.8
});
healthBarBg.tint = 0x333333;
var healthBarFill = LK.getAsset('bullet', {
anchorX: 0,
anchorY: 0.5,
scaleX: 20,
scaleY: 0.8
});
healthBarFill.tint = 0x2ecc71;
healthBar.addChild(healthBarBg);
healthBar.addChild(healthBarFill);
healthBar.y = 100;
LK.gui.bottom.addChild(healthBar);
// Boss health bar (only visible during boss fights)
var bossHealthBar = new Container();
var bossHealthBarBg = LK.getAsset('bullet', {
anchorX: 0,
anchorY: 0.5,
scaleX: 30,
scaleY: 1
});
bossHealthBarBg.tint = 0x333333;
var bossHealthBarFill = LK.getAsset('bullet', {
anchorX: 0,
anchorY: 0.5,
scaleX: 30,
scaleY: 1
});
bossHealthBarFill.tint = 0xe74c3c;
var bossLabel = new Text2('BOSS', {
size: 60,
fill: 0xFF0000
});
bossLabel.anchor.set(0.5, 0.5);
bossLabel.y = -40;
bossHealthBar.addChild(bossHealthBarBg);
bossHealthBar.addChild(bossHealthBarFill);
bossHealthBar.addChild(bossLabel);
bossHealthBar.visible = false;
bossHealthBar.y = 250;
LK.gui.top.addChild(bossHealthBar);
// Game functions
function spawnWave() {
var currentWaveSize = isBossFight ? 0 : waveSize;
if (isBossFight) {
// Spawn boss
boss = new Boss();
boss.x = 2048 / 2;
boss.y = 300;
game.addChild(boss);
// Show boss health bar
bossHealthBar.visible = true;
// Boss intro effect
tween(boss, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
onFinish: function onFinish() {
tween(boss, {
scaleX: 1,
scaleY: 1
}, {
duration: 300
});
}
});
} else {
// Spawn regular enemies
for (var i = 0; i < currentWaveSize; i++) {
var enemy = new Enemy();
enemy.x = 200 + Math.random() * (2048 - 400);
enemy.y = -100 - Math.random() * 300;
// Assign random movement pattern
var patterns = ['direct', 'zigzag', 'circle'];
enemy.movementPattern = patterns[Math.floor(Math.random() * patterns.length)];
// Increase enemy difficulty with wave
enemy.health += Math.floor(wave * 0.5);
enemy.pointValue += Math.floor(wave * 0.2);
if (wave > 3) {
enemy.shootDelay = Math.max(60, 120 - wave * 5); // Enemies shoot faster in later waves
}
game.addChild(enemy);
enemies.push(enemy);
}
}
wave++;
waveSize = 5 + Math.floor((wave - 1) * 1.5);
waveTimer = waveDelay;
// Update wave text
waveTxt.setText('WAVE: ' + wave);
}
function spawnPowerUp() {
if (Math.random() < 0.3) {
// 30% chance to spawn power-up
var powerUp = new PowerUp();
powerUp.x = 200 + Math.random() * (2048 - 400);
powerUp.y = -50;
game.addChild(powerUp);
powerUps.push(powerUp);
}
}
function playerShoot() {
if (player.shootCooldown <= 0) {
// Create bullet
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y - 50;
if (player.powerUpActive) {
// Triple shot when powered up
var bulletLeft = new Bullet();
bulletLeft.x = player.x - 40;
bulletLeft.y = player.y - 30;
bulletLeft.direction = {
x: -0.2,
y: -0.8
};
var bulletRight = new Bullet();
bulletRight.x = player.x + 40;
bulletRight.y = player.y - 30;
bulletRight.direction = {
x: 0.2,
y: -0.8
};
game.addChild(bulletLeft);
game.addChild(bulletRight);
bullets.push(bulletLeft);
bullets.push(bulletRight);
}
game.addChild(bullet);
bullets.push(bullet);
// Set cooldown
player.shootCooldown = player.shootDelay;
// Play sound
LK.getSound('shoot').play();
}
}
function enemyShoot(enemy) {
if (enemy.shootCooldown <= 0) {
// Fire two bullets
for (var i = 0; i < 2; i++) {
var bullet = new EnemyBullet();
bullet.x = enemy.x;
bullet.y = enemy.y + 50;
// Aim at player
var dx = player.x - enemy.x;
var dy = player.y - enemy.y;
var distance = Math.sqrt(dx * dx + dy * dy);
bullet.direction = {
x: dx / distance,
y: dy / distance
};
game.addChild(bullet);
enemyBullets.push(bullet);
}
// Set cooldown
enemy.shootCooldown = enemy.shootDelay;
}
}
function bossShoot() {
if (boss && boss.shootCooldown <= 0) {
// Pattern depends on boss phase
if (boss.phase === 1) {
// Simple triple shot
for (var i = -1; i <= 1; i++) {
var bullet = new EnemyBullet();
bullet.x = boss.x + i * 60;
bullet.y = boss.y + 60;
game.addChild(bullet);
enemyBullets.push(bullet);
}
} else if (boss.phase === 2) {
// Spread shot
for (var i = -2; i <= 2; i++) {
var bullet = new EnemyBullet();
bullet.x = boss.x + i * 50;
bullet.y = boss.y + 60;
bullet.direction = {
x: i * 0.2,
y: 1
};
game.addChild(bullet);
enemyBullets.push(bullet);
}
} else {
// Circular burst
for (var i = 0; i < 8; i++) {
var angle = Math.PI * 2 / 8 * i;
var bullet = new EnemyBullet();
bullet.x = boss.x;
bullet.y = boss.y;
bullet.direction = {
x: Math.sin(angle),
y: Math.cos(angle)
};
game.addChild(bullet);
enemyBullets.push(bullet);
}
// Also shoot directly at player
var targetBullet = new EnemyBullet();
targetBullet.x = boss.x;
targetBullet.y = boss.y;
var dx = player.x - boss.x;
var dy = player.y - boss.y;
var distance = Math.sqrt(dx * dx + dy * dy);
targetBullet.direction = {
x: dx / distance,
y: dy / distance
};
game.addChild(targetBullet);
enemyBullets.push(targetBullet);
}
// Set cooldown
boss.shootCooldown = boss.shootDelay;
}
}
// Handle player movement
game.move = function (x, y, obj) {
lastMouseX = x;
lastMouseY = y;
};
game.down = function (x, y, obj) {
lastMouseX = x;
lastMouseY = y;
playerShoot();
};
game.up = function (x, y, obj) {
// Nothing needed here
};
// Main game update
game.update = function () {
// Play music if not already playing
if (LK.ticks === 1) {
LK.playMusic('battleMusic');
}
// Move player toward touch/mouse position, but with smoothing
if (lastMouseX !== 0 && lastMouseY !== 0) {
var dx = lastMouseX - player.x;
var dy = lastMouseY - player.y;
// Apply movement with speed limit
player.x += Math.min(Math.max(dx, -player.speed), player.speed);
player.y += Math.min(Math.max(dy, -player.speed), player.speed);
// Keep player in bounds
player.x = Math.max(100, Math.min(2048 - 100, player.x));
player.y = Math.max(100, Math.min(2732 - 100, player.y));
}
// Automatic shooting
if (LK.ticks % player.shootDelay === 0) {
playerShoot();
}
// Update player
player.update();
// Update player health bar
healthBarFill.scaleX = 20 * (player.health / player.maxHealth);
healthBarFill.tint = player.health > player.maxHealth * 0.6 ? 0x2ecc71 : player.health > player.maxHealth * 0.3 ? 0xf39c12 : 0xe74c3c;
// Boss health bar update
if (boss && bossHealthBar.visible) {
bossHealthBarFill.scaleX = 30 * (boss.health / boss.maxHealth);
}
// Wave management
if (enemies.length === 0 && !isBossFight && boss === null) {
waveTimer--;
if (waveTimer <= 0) {
// Every 5 waves is a boss
if (wave % 5 === 0) {
isBossFight = true;
}
spawnWave();
// Chance to spawn power-up on new wave
spawnPowerUp();
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
bullet.update();
// Check if bullet is off screen
if (bullet.y < -50 || bullet.y > 2732 + 50 || bullet.x < -50 || bullet.x > 2048 + 50) {
bullet.destroy();
bullets.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)) {
enemy.takeDamage(bullet.damage);
bullet.destroy();
bullets.splice(i, 1);
// Check if enemy is dead
if (enemy.health <= 0) {
score += enemy.pointValue;
scoreTxt.setText('SCORE: ' + score);
// Play enemy death sound
LK.getSound('enemyDeath').play();
// Spawn power-up chance on enemy death
if (Math.random() < 0.1) {
// 10% chance
var powerUp = new PowerUp();
powerUp.x = enemy.x;
powerUp.y = enemy.y;
game.addChild(powerUp);
powerUps.push(powerUp);
}
// Remove enemy
enemy.destroy();
enemies.splice(j, 1);
}
// Skip checking other enemies since this bullet is destroyed
break;
}
}
// Check for collision with boss
if (!bullet.destroyed && boss && bullet.intersects(boss)) {
boss.takeDamage(bullet.damage);
bullet.destroy();
bullets.splice(i, 1);
// Check if boss is dead
if (boss.health <= 0) {
score += boss.pointValue;
scoreTxt.setText('SCORE: ' + score);
// Play enemy death sound at higher volume
var deathSound = LK.getSound('enemyDeath');
deathSound.volume = 0.8;
deathSound.play();
// Boss death effect
LK.effects.flashScreen(0xffffff, 500);
// Remove boss
boss.destroy();
boss = null;
isBossFight = false;
bossHealthBar.visible = false;
// Level up!
gameLevel++;
storage.level = gameLevel;
// If high score is beaten, save it
if (score > storage.highScore) {
storage.highScore = score;
}
}
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
bullet.update();
// Check if bullet is off screen
if (bullet.y < -50 || bullet.y > 2732 + 50 || bullet.x < -50 || bullet.x > 2048 + 50) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check for collision with player
if (bullet.intersects(player)) {
player.takeDamage(bullet.damage);
bullet.destroy();
enemyBullets.splice(i, 1);
// Check if player is dead
if (player.health <= 0) {
// Game over!
LK.effects.flashScreen(0xff0000, 1000);
// If high score is beaten, save it
if (score > storage.highScore) {
storage.highScore = score;
}
LK.showGameOver();
return;
}
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
enemy.update();
// Check if enemy is off bottom of screen
if (enemy.y > 2732 + 100) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Enemy shooting
if (enemy.shootCooldown <= 0 && enemy.y > 0) {
enemyShoot(enemy);
}
// Check for collision with player
if (enemy.intersects(player)) {
player.takeDamage(20);
enemy.takeDamage(30);
// Check if enemy is dead from collision
if (enemy.health <= 0) {
score += enemy.pointValue;
scoreTxt.setText('SCORE: ' + score);
// Play enemy death sound
LK.getSound('enemyDeath').play();
// Remove enemy
enemy.destroy();
enemies.splice(i, 1);
}
// Check if player is dead
if (player.health <= 0) {
// Game over!
LK.effects.flashScreen(0xff0000, 1000);
// If high score is beaten, save it
if (score > storage.highScore) {
storage.highScore = score;
}
LK.showGameOver();
return;
}
}
}
// Update power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
powerUp.update();
// Check if power-up is off bottom of screen
if (powerUp.y > 2732 + 50) {
powerUp.destroy();
powerUps.splice(i, 1);
continue;
}
// Check for collision with player
if (powerUp.intersects(player)) {
// Activate power-up
player.activatePowerUp();
// Play power-up sound
LK.getSound('powerup').play();
// Remove power-up
powerUp.destroy();
powerUps.splice(i, 1);
}
}
// Update boss
if (boss) {
boss.update();
// Boss shooting
bossShoot();
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
level: 1
});
/****
* Classes
****/
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
self.health = 300;
self.maxHealth = 300;
self.pointValue = 100;
self.phase = 1;
self.shootCooldown = 0;
self.shootDelay = 60; // 1 second at 60 fps
self.movementCounter = 0;
self.speed = 1;
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 200);
// Phase transitions
if (self.health < self.maxHealth * 0.7 && self.phase === 1) {
self.phase = 2;
self.shootDelay = 45; // Faster attacks in phase 2
} else if (self.health < self.maxHealth * 0.3 && self.phase === 2) {
self.phase = 3;
self.shootDelay = 30; // Even faster attacks in phase 3
bossGraphics.tint = 0xff5555; // Visual indicator for final phase
}
};
self.update = function () {
// Boss movement pattern
if (self.phase === 1) {
self.x += Math.sin(self.movementCounter * 0.02) * 2;
if (self.y < 400) {
self.y += 0.5;
}
} else if (self.phase === 2) {
self.x += Math.sin(self.movementCounter * 0.03) * 3;
self.y += Math.sin(self.movementCounter * 0.01) * 1;
} else {
self.x += Math.sin(self.movementCounter * 0.04) * 5;
self.y += Math.sin(self.movementCounter * 0.02) * 2;
}
self.movementCounter++;
// Update shoot cooldown
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 12;
self.damage = 10;
self.direction = {
x: 0,
y: -1
};
self.update = function () {
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 30;
self.speed = 2;
self.pointValue = 10;
self.movementPattern = 'direct'; // direct, zigzag, circle
self.movementCounter = 0;
self.shootCooldown = 0;
self.shootDelay = 360; // 6 seconds at 60 fps
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xff0000, 200);
};
self.update = function () {
// Movement patterns
switch (self.movementPattern) {
case 'direct':
self.y += self.speed;
break;
case 'zigzag':
self.y += self.speed;
self.x += Math.sin(self.movementCounter * 0.05) * 3;
self.movementCounter++;
break;
case 'circle':
self.y += self.speed * 0.7;
self.x += Math.sin(self.movementCounter * 0.03) * 4;
self.movementCounter++;
break;
}
// Update shoot cooldown
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
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.damage = 5;
self.direction = {
x: 0,
y: 1
};
self.update = function () {
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
});
self.health = 100;
self.maxHealth = 100;
self.shootCooldown = 0;
self.shootDelay = 15;
self.speed = 10;
self.powerUpActive = false;
self.powerUpTimer = 0;
self.powerUpDuration = 300; // 5 seconds at 60 fps
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health <= 0) {
self.health = 0;
}
LK.getSound('playerDamage').play();
LK.effects.flashObject(self, 0xff0000, 500);
tween(playerGraphics, {
alpha: 0.3
}, {
duration: 100,
onFinish: function onFinish() {
tween(playerGraphics, {
alpha: 1
}, {
duration: 100
});
}
});
};
self.activatePowerUp = function () {
self.powerUpActive = true;
self.powerUpTimer = self.powerUpDuration;
playerGraphics.tint = 0x2ecc71;
self.shootDelay = 7; // Faster shooting with power-up
};
self.update = function () {
// Update power-up status
if (self.powerUpActive) {
self.powerUpTimer--;
if (self.powerUpTimer <= 0) {
self.powerUpActive = false;
playerGraphics.tint = 0xffffff; // Reset tint
self.shootDelay = 15; // Reset shooting speed
}
}
// Update shoot cooldown
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.rotationSpeed = 0.05;
self.update = function () {
self.y += self.speed;
self.rotation += self.rotationSpeed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
/****
* Game Description
*
* Welcome to the Ultimate Space Battle! In this thrilling game, you are the pilot of a powerful spaceship tasked with defending the galaxy from waves of enemy ships and formidable bosses.
* Navigate through the arena, dodge enemy fire, and strategically shoot down foes to earn points.
* Collect power-ups to enhance your ship's capabilities and survive the relentless onslaught.
* Every fifth wave brings a challenging boss fight, testing your skills and reflexes.
* Aim for the highest score and see if you can beat your personal best!
****/
game.setBackgroundColor(0x2c3e50);
// Game variables
var player;
var bullets = [];
var enemyBullets = [];
var enemies = [];
var powerUps = [];
var boss = null;
var isBossFight = false;
var gameLevel = storage.level || 1;
var score = 0;
var wave = 1;
var waveSize = 5 + (gameLevel - 1) * 2;
var waveDelay = 180; // 3 seconds at 60fps
var waveTimer = waveDelay;
var lastMouseX = 0;
var lastMouseY = 0;
// Create arena background
var arena = LK.getAsset('arena', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
arena.x = 2048 / 2;
arena.y = 2732 / 2;
game.addChild(arena);
// Create player
player = new Player();
player.x = 2048 / 2;
player.y = 2732 - 300;
game.addChild(player);
// UI Elements
var scoreTxt = new Text2('SCORE: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
var waveTxt = new Text2('WAVE: 1', {
size: 80,
fill: 0xFFFFFF
});
waveTxt.anchor.set(1, 0);
LK.gui.topLeft.addChild(waveTxt);
waveTxt.x = 150; // Move away from the corner
// Player Health Bar
var healthBar = new Container();
var healthBarBg = LK.getAsset('bullet', {
anchorX: 0,
anchorY: 0.5,
scaleX: 20,
scaleY: 0.8
});
healthBarBg.tint = 0x333333;
var healthBarFill = LK.getAsset('bullet', {
anchorX: 0,
anchorY: 0.5,
scaleX: 20,
scaleY: 0.8
});
healthBarFill.tint = 0x2ecc71;
healthBar.addChild(healthBarBg);
healthBar.addChild(healthBarFill);
healthBar.y = 100;
LK.gui.bottom.addChild(healthBar);
var healthBar = new Container();
var healthBarBg = LK.getAsset('bullet', {
anchorX: 0,
anchorY: 0.5,
scaleX: 20,
scaleY: 0.8
});
healthBarBg.tint = 0x333333;
var healthBarFill = LK.getAsset('bullet', {
anchorX: 0,
anchorY: 0.5,
scaleX: 20,
scaleY: 0.8
});
healthBarFill.tint = 0x2ecc71;
healthBar.addChild(healthBarBg);
healthBar.addChild(healthBarFill);
healthBar.y = 100;
LK.gui.bottom.addChild(healthBar);
// Boss health bar (only visible during boss fights)
var bossHealthBar = new Container();
var bossHealthBarBg = LK.getAsset('bullet', {
anchorX: 0,
anchorY: 0.5,
scaleX: 30,
scaleY: 1
});
bossHealthBarBg.tint = 0x333333;
var bossHealthBarFill = LK.getAsset('bullet', {
anchorX: 0,
anchorY: 0.5,
scaleX: 30,
scaleY: 1
});
bossHealthBarFill.tint = 0xe74c3c;
var bossLabel = new Text2('BOSS', {
size: 60,
fill: 0xFF0000
});
bossLabel.anchor.set(0.5, 0.5);
bossLabel.y = -40;
bossHealthBar.addChild(bossHealthBarBg);
bossHealthBar.addChild(bossHealthBarFill);
bossHealthBar.addChild(bossLabel);
bossHealthBar.visible = false;
bossHealthBar.y = 250;
LK.gui.top.addChild(bossHealthBar);
// Game functions
function spawnWave() {
var currentWaveSize = isBossFight ? 0 : waveSize;
if (isBossFight) {
// Spawn boss
boss = new Boss();
boss.x = 2048 / 2;
boss.y = 300;
game.addChild(boss);
// Show boss health bar
bossHealthBar.visible = true;
// Boss intro effect
tween(boss, {
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
onFinish: function onFinish() {
tween(boss, {
scaleX: 1,
scaleY: 1
}, {
duration: 300
});
}
});
} else {
// Spawn regular enemies
for (var i = 0; i < currentWaveSize; i++) {
var enemy = new Enemy();
enemy.x = 200 + Math.random() * (2048 - 400);
enemy.y = -100 - Math.random() * 300;
// Assign random movement pattern
var patterns = ['direct', 'zigzag', 'circle'];
enemy.movementPattern = patterns[Math.floor(Math.random() * patterns.length)];
// Increase enemy difficulty with wave
enemy.health += Math.floor(wave * 0.5);
enemy.pointValue += Math.floor(wave * 0.2);
if (wave > 3) {
enemy.shootDelay = Math.max(60, 120 - wave * 5); // Enemies shoot faster in later waves
}
game.addChild(enemy);
enemies.push(enemy);
}
}
wave++;
waveSize = 5 + Math.floor((wave - 1) * 1.5);
waveTimer = waveDelay;
// Update wave text
waveTxt.setText('WAVE: ' + wave);
}
function spawnPowerUp() {
if (Math.random() < 0.3) {
// 30% chance to spawn power-up
var powerUp = new PowerUp();
powerUp.x = 200 + Math.random() * (2048 - 400);
powerUp.y = -50;
game.addChild(powerUp);
powerUps.push(powerUp);
}
}
function playerShoot() {
if (player.shootCooldown <= 0) {
// Create bullet
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y - 50;
if (player.powerUpActive) {
// Triple shot when powered up
var bulletLeft = new Bullet();
bulletLeft.x = player.x - 40;
bulletLeft.y = player.y - 30;
bulletLeft.direction = {
x: -0.2,
y: -0.8
};
var bulletRight = new Bullet();
bulletRight.x = player.x + 40;
bulletRight.y = player.y - 30;
bulletRight.direction = {
x: 0.2,
y: -0.8
};
game.addChild(bulletLeft);
game.addChild(bulletRight);
bullets.push(bulletLeft);
bullets.push(bulletRight);
}
game.addChild(bullet);
bullets.push(bullet);
// Set cooldown
player.shootCooldown = player.shootDelay;
// Play sound
LK.getSound('shoot').play();
}
}
function enemyShoot(enemy) {
if (enemy.shootCooldown <= 0) {
// Fire two bullets
for (var i = 0; i < 2; i++) {
var bullet = new EnemyBullet();
bullet.x = enemy.x;
bullet.y = enemy.y + 50;
// Aim at player
var dx = player.x - enemy.x;
var dy = player.y - enemy.y;
var distance = Math.sqrt(dx * dx + dy * dy);
bullet.direction = {
x: dx / distance,
y: dy / distance
};
game.addChild(bullet);
enemyBullets.push(bullet);
}
// Set cooldown
enemy.shootCooldown = enemy.shootDelay;
}
}
function bossShoot() {
if (boss && boss.shootCooldown <= 0) {
// Pattern depends on boss phase
if (boss.phase === 1) {
// Simple triple shot
for (var i = -1; i <= 1; i++) {
var bullet = new EnemyBullet();
bullet.x = boss.x + i * 60;
bullet.y = boss.y + 60;
game.addChild(bullet);
enemyBullets.push(bullet);
}
} else if (boss.phase === 2) {
// Spread shot
for (var i = -2; i <= 2; i++) {
var bullet = new EnemyBullet();
bullet.x = boss.x + i * 50;
bullet.y = boss.y + 60;
bullet.direction = {
x: i * 0.2,
y: 1
};
game.addChild(bullet);
enemyBullets.push(bullet);
}
} else {
// Circular burst
for (var i = 0; i < 8; i++) {
var angle = Math.PI * 2 / 8 * i;
var bullet = new EnemyBullet();
bullet.x = boss.x;
bullet.y = boss.y;
bullet.direction = {
x: Math.sin(angle),
y: Math.cos(angle)
};
game.addChild(bullet);
enemyBullets.push(bullet);
}
// Also shoot directly at player
var targetBullet = new EnemyBullet();
targetBullet.x = boss.x;
targetBullet.y = boss.y;
var dx = player.x - boss.x;
var dy = player.y - boss.y;
var distance = Math.sqrt(dx * dx + dy * dy);
targetBullet.direction = {
x: dx / distance,
y: dy / distance
};
game.addChild(targetBullet);
enemyBullets.push(targetBullet);
}
// Set cooldown
boss.shootCooldown = boss.shootDelay;
}
}
// Handle player movement
game.move = function (x, y, obj) {
lastMouseX = x;
lastMouseY = y;
};
game.down = function (x, y, obj) {
lastMouseX = x;
lastMouseY = y;
playerShoot();
};
game.up = function (x, y, obj) {
// Nothing needed here
};
// Main game update
game.update = function () {
// Play music if not already playing
if (LK.ticks === 1) {
LK.playMusic('battleMusic');
}
// Move player toward touch/mouse position, but with smoothing
if (lastMouseX !== 0 && lastMouseY !== 0) {
var dx = lastMouseX - player.x;
var dy = lastMouseY - player.y;
// Apply movement with speed limit
player.x += Math.min(Math.max(dx, -player.speed), player.speed);
player.y += Math.min(Math.max(dy, -player.speed), player.speed);
// Keep player in bounds
player.x = Math.max(100, Math.min(2048 - 100, player.x));
player.y = Math.max(100, Math.min(2732 - 100, player.y));
}
// Automatic shooting
if (LK.ticks % player.shootDelay === 0) {
playerShoot();
}
// Update player
player.update();
// Update player health bar
healthBarFill.scaleX = 20 * (player.health / player.maxHealth);
healthBarFill.tint = player.health > player.maxHealth * 0.6 ? 0x2ecc71 : player.health > player.maxHealth * 0.3 ? 0xf39c12 : 0xe74c3c;
// Boss health bar update
if (boss && bossHealthBar.visible) {
bossHealthBarFill.scaleX = 30 * (boss.health / boss.maxHealth);
}
// Wave management
if (enemies.length === 0 && !isBossFight && boss === null) {
waveTimer--;
if (waveTimer <= 0) {
// Every 5 waves is a boss
if (wave % 5 === 0) {
isBossFight = true;
}
spawnWave();
// Chance to spawn power-up on new wave
spawnPowerUp();
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
bullet.update();
// Check if bullet is off screen
if (bullet.y < -50 || bullet.y > 2732 + 50 || bullet.x < -50 || bullet.x > 2048 + 50) {
bullet.destroy();
bullets.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)) {
enemy.takeDamage(bullet.damage);
bullet.destroy();
bullets.splice(i, 1);
// Check if enemy is dead
if (enemy.health <= 0) {
score += enemy.pointValue;
scoreTxt.setText('SCORE: ' + score);
// Play enemy death sound
LK.getSound('enemyDeath').play();
// Spawn power-up chance on enemy death
if (Math.random() < 0.1) {
// 10% chance
var powerUp = new PowerUp();
powerUp.x = enemy.x;
powerUp.y = enemy.y;
game.addChild(powerUp);
powerUps.push(powerUp);
}
// Remove enemy
enemy.destroy();
enemies.splice(j, 1);
}
// Skip checking other enemies since this bullet is destroyed
break;
}
}
// Check for collision with boss
if (!bullet.destroyed && boss && bullet.intersects(boss)) {
boss.takeDamage(bullet.damage);
bullet.destroy();
bullets.splice(i, 1);
// Check if boss is dead
if (boss.health <= 0) {
score += boss.pointValue;
scoreTxt.setText('SCORE: ' + score);
// Play enemy death sound at higher volume
var deathSound = LK.getSound('enemyDeath');
deathSound.volume = 0.8;
deathSound.play();
// Boss death effect
LK.effects.flashScreen(0xffffff, 500);
// Remove boss
boss.destroy();
boss = null;
isBossFight = false;
bossHealthBar.visible = false;
// Level up!
gameLevel++;
storage.level = gameLevel;
// If high score is beaten, save it
if (score > storage.highScore) {
storage.highScore = score;
}
}
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
bullet.update();
// Check if bullet is off screen
if (bullet.y < -50 || bullet.y > 2732 + 50 || bullet.x < -50 || bullet.x > 2048 + 50) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check for collision with player
if (bullet.intersects(player)) {
player.takeDamage(bullet.damage);
bullet.destroy();
enemyBullets.splice(i, 1);
// Check if player is dead
if (player.health <= 0) {
// Game over!
LK.effects.flashScreen(0xff0000, 1000);
// If high score is beaten, save it
if (score > storage.highScore) {
storage.highScore = score;
}
LK.showGameOver();
return;
}
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
enemy.update();
// Check if enemy is off bottom of screen
if (enemy.y > 2732 + 100) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Enemy shooting
if (enemy.shootCooldown <= 0 && enemy.y > 0) {
enemyShoot(enemy);
}
// Check for collision with player
if (enemy.intersects(player)) {
player.takeDamage(20);
enemy.takeDamage(30);
// Check if enemy is dead from collision
if (enemy.health <= 0) {
score += enemy.pointValue;
scoreTxt.setText('SCORE: ' + score);
// Play enemy death sound
LK.getSound('enemyDeath').play();
// Remove enemy
enemy.destroy();
enemies.splice(i, 1);
}
// Check if player is dead
if (player.health <= 0) {
// Game over!
LK.effects.flashScreen(0xff0000, 1000);
// If high score is beaten, save it
if (score > storage.highScore) {
storage.highScore = score;
}
LK.showGameOver();
return;
}
}
}
// Update power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
powerUp.update();
// Check if power-up is off bottom of screen
if (powerUp.y > 2732 + 50) {
powerUp.destroy();
powerUps.splice(i, 1);
continue;
}
// Check for collision with player
if (powerUp.intersects(player)) {
// Activate power-up
player.activatePowerUp();
// Play power-up sound
LK.getSound('powerup').play();
// Remove power-up
powerUp.destroy();
powerUps.splice(i, 1);
}
}
// Update boss
if (boss) {
boss.update();
// Boss shooting
bossShoot();
}
};
Arena. Single Game Texture. High contrast. Arena
Boss. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Power up bullet. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
Enemy plane. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows