/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Asteroid = Container.expand(function () {
var self = Container.call(this);
var asteroid = self.attachAsset('asteroid', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 2;
self.speed = {
y: 2 + Math.random() * 2,
x: (Math.random() - 0.5) * 2
};
self.rotation = Math.random() * 0.1 - 0.05;
self.scoreValue = 15;
// Random size variation
var scale = 0.7 + Math.random() * 0.8;
asteroid.scale.set(scale, scale);
self.damage = function (amount) {
self.health -= amount || 1;
tween(asteroid, {
tint: 0xffffff
}, {
duration: 200,
onFinish: function onFinish() {
asteroid.tint = 0x95a5a6;
}
});
return self.health <= 0;
};
self.update = function () {
self.y += self.speed.y;
self.x += self.speed.x;
asteroid.rotation += self.rotation;
};
return self;
});
var Boss = Container.expand(function (level) {
var self = Container.call(this);
var ship = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
self.level = level || 1;
self.maxHealth = 20 * self.level;
self.health = self.maxHealth;
self.scoreValue = 200 * self.level;
self.phase = 0;
self.phaseTime = 0;
self.patterns = ['side-to-side', 'charge', 'retreat'];
self.currentPattern = 0;
self.targetX = 0;
self.targetY = 0;
// Adjust boss based on level
if (self.level > 1) {
ship.tint = 0xcc00cc;
}
// Health bar
self.healthBar = new Container();
self.addChild(self.healthBar);
var healthBarBg = self.healthBar.attachAsset('playerLaser', {
anchorX: 0,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.5
});
healthBarBg.tint = 0x333333;
healthBarBg.width = 200;
self.healthBarFill = self.healthBar.attachAsset('playerLaser', {
anchorX: 0,
anchorY: 0.5,
scaleX: 2,
scaleY: 0.4
});
self.healthBarFill.tint = 0xff3333;
self.healthBarFill.width = 200;
self.healthBar.y = -120;
self.damage = function (amount) {
self.health -= amount || 1;
// Update health bar
var healthPercent = self.health / self.maxHealth;
self.healthBarFill.width = 200 * healthPercent;
tween(ship, {
tint: 0xffffff
}, {
duration: 100,
onFinish: function onFinish() {
ship.tint = self.level > 1 ? 0xcc00cc : 0x9b59b6;
}
});
// Change patterns more quickly when damaged
if (self.health < self.maxHealth * 0.5 && self.phaseTime > 150) {
self.changePattern();
}
return self.health <= 0;
};
self.changePattern = function () {
self.currentPattern = (self.currentPattern + 1) % self.patterns.length;
self.phaseTime = 0;
self.phase = 0;
};
self.update = function () {
self.phaseTime++;
// Change pattern every so often
if (self.phaseTime > 300) {
self.changePattern();
}
var pattern = self.patterns[self.currentPattern];
switch (pattern) {
case 'side-to-side':
// Move side to side
self.targetX = 1024 + Math.sin(self.phaseTime * 0.02) * 800;
if (self.phaseTime < 60) {
self.targetY = Math.min(self.y + 2, 400);
} else {
self.targetY = 400;
}
break;
case 'charge':
// Charge down then back up
if (self.phase === 0) {
self.targetY = self.y + 5;
if (self.y > 800) {
self.phase = 1;
}
} else {
self.targetY = Math.max(self.y - 3, 300);
if (self.y <= 300) {
self.phase = 0;
}
}
self.targetX = 1024 + Math.sin(self.phaseTime * 0.03) * 500;
break;
case 'retreat':
// Stay near top and move quickly
self.targetY = 300;
self.targetX = 1024 + Math.sin(self.phaseTime * 0.05) * 900;
break;
}
// Move toward target position
self.x += (self.targetX - self.x) * 0.05;
self.y += (self.targetY - self.y) * 0.05;
};
return self;
});
var Enemy = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'basic';
var assetType = self.type === 'fast' ? 'enemy' : 'enemy';
var ship = self.attachAsset(assetType, {
anchorX: 0.5,
anchorY: 0.5
});
// Different enemy types
if (self.type === 'basic') {
self.health = 1;
self.speed = 2;
self.scoreValue = 10;
self.shootChance = 0.01;
} else if (self.type === 'fast') {
self.health = 1;
self.speed = 3.5;
self.scoreValue = 15;
ship.scaleX = 0.8;
ship.scaleY = 0.8;
self.shootChance = 0.005;
ship.tint = 0xff9966;
} else if (self.type === 'tank') {
self.health = 3;
self.speed = 1.5;
self.scoreValue = 25;
ship.scaleX = 1.2;
ship.scaleY = 1.2;
self.shootChance = 0.015;
ship.tint = 0x66ff66;
}
self.movement = {
pattern: 'straight',
phase: Math.random() * Math.PI * 2,
amplitude: 60 + Math.random() * 60
};
self.initialX = 0;
self.damage = function (amount) {
self.health -= amount || 1;
tween(ship, {
tint: 0xffffff
}, {
duration: 200,
onFinish: function onFinish() {
ship.tint = self.type === 'fast' ? 0xff9966 : self.type === 'tank' ? 0x66ff66 : 0xe74c3c;
}
});
return self.health <= 0;
};
self.update = function () {
// Basic movement
self.y += self.speed;
// Pattern movement
if (self.movement.pattern === 'sine') {
self.x = self.initialX + Math.sin(LK.ticks * 0.05 + self.movement.phase) * self.movement.amplitude;
} else if (self.movement.pattern === 'zigzag') {
var timeScale = 0.02;
var t = LK.ticks * timeScale + self.movement.phase;
var triangleWave = Math.abs(t % 2 - 1) * 2 - 1;
self.x = self.initialX + triangleWave * self.movement.amplitude;
}
};
return self;
});
var EnemyLaser = Container.expand(function () {
var self = Container.call(this);
var laser = self.attachAsset('enemyLaser', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var explosion = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9
});
// Set up fade and scale
tween(explosion, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 500,
onFinish: function onFinish() {
self.destroy();
}
});
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var ship = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.shield = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
self.lives = 3;
self.shieldActive = false;
self.fireRate = 20;
self.lastShot = 0;
self.canShoot = true;
self.power = 1;
self.invulnerable = false;
self.activateShield = function (duration) {
self.shieldActive = true;
self.shield.alpha = 0.4;
LK.setTimeout(function () {
self.shieldActive = false;
tween(self.shield, {
alpha: 0
}, {
duration: 500
});
}, duration);
};
self.damage = function () {
if (self.invulnerable || self.shieldActive) {
return;
}
self.lives--;
LK.getSound('playerDamage').play();
// Make player temporarily invulnerable
self.invulnerable = true;
// Flash the player to show invulnerability
var flashCount = 0;
var flashInterval = LK.setInterval(function () {
ship.alpha = ship.alpha === 0.3 ? 1 : 0.3;
flashCount++;
if (flashCount >= 10) {
LK.clearInterval(flashInterval);
ship.alpha = 1;
self.invulnerable = false;
}
}, 150);
};
self.upgrade = function (type) {
LK.getSound('powerup').play();
if (type === 'shield') {
self.activateShield(8000);
} else if (type === 'power') {
self.power = Math.min(self.power + 1, 3);
// Reset power after some time
LK.setTimeout(function () {
self.power = Math.max(1, self.power - 1);
}, 10000);
} else if (type === 'life') {
self.lives = Math.min(self.lives + 1, 5);
} else if (type === 'speed') {
var oldFireRate = self.fireRate;
self.fireRate = Math.max(self.fireRate - 5, 10);
// Reset fire rate after some time
LK.setTimeout(function () {
self.fireRate = oldFireRate;
}, 10000);
}
};
return self;
});
var PlayerLaser = Container.expand(function () {
var self = Container.call(this);
var laser = self.attachAsset('playerLaser', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -15;
self.power = 1;
self.update = function () {
self.y += self.speed;
};
return self;
});
var Powerup = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || ['shield', 'power', 'life', 'speed'][Math.floor(Math.random() * 4)];
var powerup = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
// Set color based on type
if (self.type === 'shield') {
powerup.tint = 0x3498db; // Blue
} else if (self.type === 'power') {
powerup.tint = 0xe74c3c; // Red
} else if (self.type === 'life') {
powerup.tint = 0x2ecc71; // Green
} else if (self.type === 'speed') {
powerup.tint = 0xf1c40f; // Yellow
}
self.speed = 3;
self.update = function () {
self.y += self.speed;
powerup.rotation += 0.05;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000022
});
/****
* Game Code
****/
// Game variables
var player;
var playerLasers = [];
var enemies = [];
var enemyLasers = [];
var asteroids = [];
var powerups = [];
var explosions = [];
var boss = null;
var gameState = 'playing';
var score = 0;
var waveNumber = 1;
var enemiesThisWave = 0;
var enemiesDefeated = 0;
var waveDelay = 0;
var bossWave = false;
var dragStartPosition = {
x: 0,
y: 0
};
// UI elements
var scoreTxt = new Text2('SCORE: 0', {
size: 40,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreTxt);
scoreTxt.x = -250;
scoreTxt.y = 50;
var waveText = new Text2('WAVE: 1', {
size: 40,
fill: 0xFFFFFF
});
waveText.anchor.set(0.5, 0);
LK.gui.top.addChild(waveText);
waveText.y = 50;
var livesText = new Text2('LIVES: 3', {
size: 40,
fill: 0xFFFFFF
});
livesText.anchor.set(0, 0);
LK.gui.topLeft.addChild(livesText);
livesText.x = 150; // Keep away from the top-left menu icon
livesText.y = 50;
// Create game elements
function initGame() {
// Reset game variables
playerLasers = [];
enemies = [];
enemyLasers = [];
asteroids = [];
powerups = [];
explosions = [];
boss = null;
gameState = 'playing';
score = 0;
waveNumber = 1;
enemiesThisWave = 10;
enemiesDefeated = 0;
waveDelay = 0;
bossWave = false;
// Update UI
scoreTxt.setText('SCORE: ' + score);
waveText.setText('WAVE: ' + waveNumber);
// Create player
player = new Player();
player.x = 1024;
player.y = 2200;
game.addChild(player);
livesText.setText('LIVES: ' + player.lives);
// Start with player moving up
tween(player, {
y: 2000
}, {
duration: 1000
});
// Start the music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.7,
duration: 1000
}
});
// Create first wave
createWave();
}
// Create a new wave of enemies
function createWave() {
waveNumber++;
waveText.setText('WAVE: ' + waveNumber);
// Every 5 waves is a boss wave
bossWave = waveNumber % 5 === 0;
if (bossWave) {
// Create a boss
var bossLevel = Math.ceil(waveNumber / 5);
LK.getSound('bossAlert').play();
boss = new Boss(bossLevel);
boss.x = 1024;
boss.y = -200;
game.addChild(boss);
tween(boss, {
y: 300
}, {
duration: 2000
});
// Show boss wave text
var bossText = new Text2('BOSS WAVE!', {
size: 80,
fill: 0xFF0000
});
bossText.anchor.set(0.5, 0.5);
bossText.x = 1024;
bossText.y = 800;
game.addChild(bossText);
tween(bossText, {
alpha: 0,
y: 700
}, {
duration: 2000,
onFinish: function onFinish() {
bossText.destroy();
}
});
return;
}
// Regular wave
enemiesThisWave = 10 + waveNumber * 2;
enemiesDefeated = 0;
// Show wave text
var newWaveText = new Text2('WAVE ' + waveNumber, {
size: 80,
fill: 0xFFFFFF
});
newWaveText.anchor.set(0.5, 0.5);
newWaveText.x = 1024;
newWaveText.y = 800;
game.addChild(newWaveText);
tween(newWaveText, {
alpha: 0,
y: 700
}, {
duration: 2000,
onFinish: function onFinish() {
newWaveText.destroy();
}
});
// Start spawning enemies after a short delay
waveDelay = 120;
}
// Create a new enemy
function spawnEnemy() {
var types = ['basic'];
// Add more enemy types as waves progress
if (waveNumber >= 2) {
types.push('fast');
}
if (waveNumber >= 3) {
types.push('tank');
}
var type = types[Math.floor(Math.random() * types.length)];
var enemy = new Enemy(type);
// Position the enemy
enemy.x = Math.random() * 1800 + 124;
enemy.y = -100;
enemy.initialX = enemy.x;
// Set random movement pattern
var patterns = ['straight'];
if (waveNumber >= 2) {
patterns.push('sine');
}
if (waveNumber >= 4) {
patterns.push('zigzag');
}
enemy.movement.pattern = patterns[Math.floor(Math.random() * patterns.length)];
// Add to game
enemies.push(enemy);
game.addChild(enemy);
}
// Create a new asteroid
function spawnAsteroid() {
var asteroid = new Asteroid();
// Position the asteroid
asteroid.x = Math.random() * 1800 + 124;
asteroid.y = -100;
// Add to game
asteroids.push(asteroid);
game.addChild(asteroid);
}
// Create a player laser
function firePlayerLaser() {
if (!player || !player.canShoot || player.lastShot + player.fireRate > LK.ticks) {
return;
}
player.lastShot = LK.ticks;
LK.getSound('playerShoot').play();
// Fire based on power level
if (player.power === 1) {
var laser = new PlayerLaser();
laser.x = player.x;
laser.y = player.y - 50;
laser.power = player.power;
playerLasers.push(laser);
game.addChild(laser);
} else if (player.power === 2) {
for (var i = -1; i <= 1; i += 2) {
var laser = new PlayerLaser();
laser.x = player.x + i * 30;
laser.y = player.y - 40;
laser.power = player.power;
playerLasers.push(laser);
game.addChild(laser);
}
} else if (player.power >= 3) {
var centerLaser = new PlayerLaser();
centerLaser.x = player.x;
centerLaser.y = player.y - 50;
centerLaser.power = player.power;
playerLasers.push(centerLaser);
game.addChild(centerLaser);
for (var i = -1; i <= 1; i += 2) {
var sideLaser = new PlayerLaser();
sideLaser.x = player.x + i * 40;
sideLaser.y = player.y - 30;
sideLaser.power = player.power - 1;
playerLasers.push(sideLaser);
game.addChild(sideLaser);
}
}
}
// Create an enemy laser
function fireEnemyLaser(enemy) {
var laser = new EnemyLaser();
laser.x = enemy.x;
laser.y = enemy.y + 40;
enemyLasers.push(laser);
game.addChild(laser);
LK.getSound('enemyShoot').play({
volume: 0.2
});
}
// Fire boss laser pattern
function fireBossLasers() {
if (!boss) {
return;
}
// Different patterns based on boss level and health
var healthPercent = boss.health / boss.maxHealth;
var pattern = 'spread';
if (boss.level >= 2 && healthPercent < 0.5) {
pattern = 'circle';
}
if (pattern === 'spread') {
for (var i = -2; i <= 2; i++) {
var laser = new EnemyLaser();
laser.x = boss.x + i * 50;
laser.y = boss.y + 80;
enemyLasers.push(laser);
game.addChild(laser);
}
} else if (pattern === 'circle') {
var numLasers = 8;
for (var i = 0; i < numLasers; i++) {
var angle = i / numLasers * Math.PI * 2;
var laser = new EnemyLaser();
laser.x = boss.x + Math.cos(angle) * 100;
laser.y = boss.y + Math.sin(angle) * 100;
enemyLasers.push(laser);
game.addChild(laser);
// Add directional motion
laser.update = function () {
var dx = this.x - boss.x;
var dy = this.y - boss.y;
var length = Math.sqrt(dx * dx + dy * dy);
this.x += dx / length * 5;
this.y += dy / length * 5;
};
}
}
LK.getSound('enemyShoot').play({
volume: 0.4
});
}
// Create explosion animation
function createExplosion(x, y, scale) {
var explosion = new Explosion();
explosion.x = x;
explosion.y = y;
if (scale) {
explosion.scale.set(scale, scale);
}
explosions.push(explosion);
game.addChild(explosion);
LK.getSound('explosion').play();
}
// Create a powerup
function spawnPowerup(x, y, type) {
var powerup = new Powerup(type);
powerup.x = x;
powerup.y = y;
powerups.push(powerup);
game.addChild(powerup);
}
// Handle player shooting and movement
function handlePlayerInput() {
// Keep player in bounds
player.x = Math.max(100, Math.min(player.x, 2048 - 100));
player.y = Math.max(100, Math.min(player.y, 2732 - 100));
// Auto-fire
if (LK.ticks % 10 === 0) {
firePlayerLaser();
}
}
// Handle collisions between game objects
function handleCollisions() {
// Player lasers vs enemies
for (var i = playerLasers.length - 1; i >= 0; i--) {
var laser = playerLasers[i];
var hitSomething = false;
// Check against enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (laser.intersects(enemy)) {
// Damage enemy
if (enemy.damage(laser.power)) {
// Enemy destroyed
createExplosion(enemy.x, enemy.y);
// Add score
score += enemy.scoreValue;
scoreTxt.setText('SCORE: ' + score);
// Count enemy as defeated
enemiesDefeated++;
// Chance to spawn powerup
if (Math.random() < 0.1) {
spawnPowerup(enemy.x, enemy.y);
}
enemy.destroy();
enemies.splice(j, 1);
}
// Remove laser
laser.destroy();
playerLasers.splice(i, 1);
hitSomething = true;
break;
}
}
// Only check other collisions if we haven't hit an enemy
if (!hitSomething) {
// Check against boss
if (boss && laser.intersects(boss)) {
// Damage boss
if (boss.damage(laser.power)) {
// Boss destroyed
createExplosion(boss.x, boss.y, 2);
// Add score
score += boss.scoreValue;
scoreTxt.setText('SCORE: ' + score);
// Spawn multiple powerups
for (var p = 0; p < 3; p++) {
var powerupType = ['shield', 'power', 'life', 'speed'][Math.floor(Math.random() * 4)];
spawnPowerup(boss.x + (Math.random() * 200 - 100), boss.y + (Math.random() * 200 - 100), powerupType);
}
boss.destroy();
boss = null;
// Move to next wave
createWave();
}
// Remove laser
laser.destroy();
playerLasers.splice(i, 1);
hitSomething = true;
}
// Check against asteroids
for (var k = asteroids.length - 1; k >= 0; k--) {
var asteroid = asteroids[k];
if (laser.intersects(asteroid)) {
// Damage asteroid
if (asteroid.damage(laser.power)) {
// Asteroid destroyed
createExplosion(asteroid.x, asteroid.y, 0.7);
// Add score
score += asteroid.scoreValue;
scoreTxt.setText('SCORE: ' + score);
asteroid.destroy();
asteroids.splice(k, 1);
}
// Remove laser
laser.destroy();
playerLasers.splice(i, 1);
hitSomething = true;
break;
}
}
}
// Remove laser if it's off screen
if (!hitSomething && laser.y < -50) {
laser.destroy();
playerLasers.splice(i, 1);
}
}
// Enemy lasers vs player
for (var i = enemyLasers.length - 1; i >= 0; i--) {
var laser = enemyLasers[i];
if (player && laser.intersects(player)) {
// Damage player
player.damage();
// Update UI
livesText.setText('LIVES: ' + player.lives);
// Check for game over
if (player.lives <= 0) {
// Game over
createExplosion(player.x, player.y, 1.5);
player.destroy();
player = null;
// Save high score if needed
if (score > storage.highScore) {
storage.highScore = score;
}
// Show game over after a delay
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
// Remove laser
laser.destroy();
enemyLasers.splice(i, 1);
} else if (laser.y > 2732 + 50) {
// Remove laser if it's off screen
laser.destroy();
enemyLasers.splice(i, 1);
}
}
// Player vs enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (player && player.intersects(enemy)) {
// Damage player
player.damage();
// Damage enemy
enemy.damage(1);
// Update UI
livesText.setText('LIVES: ' + player.lives);
// Check for enemy death
if (enemy.health <= 0) {
// Enemy destroyed
createExplosion(enemy.x, enemy.y);
// Add score
score += enemy.scoreValue;
scoreTxt.setText('SCORE: ' + score);
// Count enemy as defeated
enemiesDefeated++;
enemy.destroy();
enemies.splice(i, 1);
}
// Check for game over
if (player.lives <= 0) {
// Game over
createExplosion(player.x, player.y, 1.5);
player.destroy();
player = null;
// Save high score if needed
if (score > storage.highScore) {
storage.highScore = score;
}
// Show game over after a delay
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
// Remove enemy if it's off screen
if (enemy.y > 2732 + 100) {
enemy.destroy();
enemies.splice(i, 1);
}
}
// Player vs asteroids
for (var i = asteroids.length - 1; i >= 0; i--) {
var asteroid = asteroids[i];
if (player && player.intersects(asteroid)) {
// Damage player
player.damage();
// Damage asteroid
asteroid.damage(1);
// Update UI
livesText.setText('LIVES: ' + player.lives);
// Check for asteroid death
if (asteroid.health <= 0) {
// Asteroid destroyed
createExplosion(asteroid.x, asteroid.y, 0.7);
// Add score
score += asteroid.scoreValue;
scoreTxt.setText('SCORE: ' + score);
asteroid.destroy();
asteroids.splice(i, 1);
}
// Check for game over
if (player.lives <= 0) {
// Game over
createExplosion(player.x, player.y, 1.5);
player.destroy();
player = null;
// Save high score if needed
if (score > storage.highScore) {
storage.highScore = score;
}
// Show game over after a delay
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
// Remove asteroid if it's off screen
if (asteroid.y > 2732 + 100 || asteroid.x < -100 || asteroid.x > 2048 + 100) {
asteroid.destroy();
asteroids.splice(i, 1);
}
}
// Player vs powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
if (player && player.intersects(powerup)) {
// Apply powerup
player.upgrade(powerup.type);
// Update UI if life powerup
if (powerup.type === 'life') {
livesText.setText('LIVES: ' + player.lives);
}
// Remove powerup
powerup.destroy();
powerups.splice(i, 1);
} else if (powerup.y > 2732 + 50) {
// Remove powerup if it's off screen
powerup.destroy();
powerups.splice(i, 1);
}
}
// Player vs boss
if (player && boss && player.intersects(boss)) {
// Damage player
player.damage();
// Update UI
livesText.setText('LIVES: ' + player.lives);
// Check for game over
if (player.lives <= 0) {
// Game over
createExplosion(player.x, player.y, 1.5);
player.destroy();
player = null;
// Save high score if needed
if (score > storage.highScore) {
storage.highScore = score;
}
// Show game over after a delay
LK.setTimeout(function () {
LK.showGameOver();
}, 1000);
}
}
}
// Initialize the game
initGame();
// Game down event handler
game.down = function (x, y, obj) {
if (!player) {
return;
}
dragStartPosition.x = x;
dragStartPosition.y = y;
// Fire lasers on tap
firePlayerLaser();
};
// Game move event handler
game.move = function (x, y, obj) {
if (!player) {
return;
}
// Move player with drag
player.x = x;
player.y = y;
};
// Game update handler
game.update = function () {
if (gameState !== 'playing') {
return;
}
// Handle player input
if (player) {
handlePlayerInput();
}
// Handle wave creation
if (waveDelay > 0) {
waveDelay--;
} else if (!bossWave && enemies.length === 0 && enemiesDefeated >= enemiesThisWave) {
// All enemies for this wave defeated, create next wave
createWave();
} else if (!bossWave && enemies.length < 5 && enemiesDefeated < enemiesThisWave && LK.ticks % 30 === 0) {
// Spawn more enemies for this wave
spawnEnemy();
}
// Spawn asteroids occasionally
if (LK.ticks % 180 === 0 && Math.random() < 0.7) {
spawnAsteroid();
}
// Boss shooting
if (boss && LK.ticks % 90 === 0) {
fireBossLasers();
}
// Enemy shooting
for (var i = 0; i < enemies.length; i++) {
if (Math.random() < enemies[i].shootChance) {
fireEnemyLaser(enemies[i]);
}
}
// Collision detection
handleCollisions();
}; ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,988 @@
-/****
+/****
+* Plugins
+****/
+var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1", {
+ highScore: 0
+});
+
+/****
+* Classes
+****/
+var Asteroid = Container.expand(function () {
+ var self = Container.call(this);
+ var asteroid = self.attachAsset('asteroid', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.health = 2;
+ self.speed = {
+ y: 2 + Math.random() * 2,
+ x: (Math.random() - 0.5) * 2
+ };
+ self.rotation = Math.random() * 0.1 - 0.05;
+ self.scoreValue = 15;
+ // Random size variation
+ var scale = 0.7 + Math.random() * 0.8;
+ asteroid.scale.set(scale, scale);
+ self.damage = function (amount) {
+ self.health -= amount || 1;
+ tween(asteroid, {
+ tint: 0xffffff
+ }, {
+ duration: 200,
+ onFinish: function onFinish() {
+ asteroid.tint = 0x95a5a6;
+ }
+ });
+ return self.health <= 0;
+ };
+ self.update = function () {
+ self.y += self.speed.y;
+ self.x += self.speed.x;
+ asteroid.rotation += self.rotation;
+ };
+ return self;
+});
+var Boss = Container.expand(function (level) {
+ var self = Container.call(this);
+ var ship = self.attachAsset('boss', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.level = level || 1;
+ self.maxHealth = 20 * self.level;
+ self.health = self.maxHealth;
+ self.scoreValue = 200 * self.level;
+ self.phase = 0;
+ self.phaseTime = 0;
+ self.patterns = ['side-to-side', 'charge', 'retreat'];
+ self.currentPattern = 0;
+ self.targetX = 0;
+ self.targetY = 0;
+ // Adjust boss based on level
+ if (self.level > 1) {
+ ship.tint = 0xcc00cc;
+ }
+ // Health bar
+ self.healthBar = new Container();
+ self.addChild(self.healthBar);
+ var healthBarBg = self.healthBar.attachAsset('playerLaser', {
+ anchorX: 0,
+ anchorY: 0.5,
+ scaleX: 2,
+ scaleY: 0.5
+ });
+ healthBarBg.tint = 0x333333;
+ healthBarBg.width = 200;
+ self.healthBarFill = self.healthBar.attachAsset('playerLaser', {
+ anchorX: 0,
+ anchorY: 0.5,
+ scaleX: 2,
+ scaleY: 0.4
+ });
+ self.healthBarFill.tint = 0xff3333;
+ self.healthBarFill.width = 200;
+ self.healthBar.y = -120;
+ self.damage = function (amount) {
+ self.health -= amount || 1;
+ // Update health bar
+ var healthPercent = self.health / self.maxHealth;
+ self.healthBarFill.width = 200 * healthPercent;
+ tween(ship, {
+ tint: 0xffffff
+ }, {
+ duration: 100,
+ onFinish: function onFinish() {
+ ship.tint = self.level > 1 ? 0xcc00cc : 0x9b59b6;
+ }
+ });
+ // Change patterns more quickly when damaged
+ if (self.health < self.maxHealth * 0.5 && self.phaseTime > 150) {
+ self.changePattern();
+ }
+ return self.health <= 0;
+ };
+ self.changePattern = function () {
+ self.currentPattern = (self.currentPattern + 1) % self.patterns.length;
+ self.phaseTime = 0;
+ self.phase = 0;
+ };
+ self.update = function () {
+ self.phaseTime++;
+ // Change pattern every so often
+ if (self.phaseTime > 300) {
+ self.changePattern();
+ }
+ var pattern = self.patterns[self.currentPattern];
+ switch (pattern) {
+ case 'side-to-side':
+ // Move side to side
+ self.targetX = 1024 + Math.sin(self.phaseTime * 0.02) * 800;
+ if (self.phaseTime < 60) {
+ self.targetY = Math.min(self.y + 2, 400);
+ } else {
+ self.targetY = 400;
+ }
+ break;
+ case 'charge':
+ // Charge down then back up
+ if (self.phase === 0) {
+ self.targetY = self.y + 5;
+ if (self.y > 800) {
+ self.phase = 1;
+ }
+ } else {
+ self.targetY = Math.max(self.y - 3, 300);
+ if (self.y <= 300) {
+ self.phase = 0;
+ }
+ }
+ self.targetX = 1024 + Math.sin(self.phaseTime * 0.03) * 500;
+ break;
+ case 'retreat':
+ // Stay near top and move quickly
+ self.targetY = 300;
+ self.targetX = 1024 + Math.sin(self.phaseTime * 0.05) * 900;
+ break;
+ }
+ // Move toward target position
+ self.x += (self.targetX - self.x) * 0.05;
+ self.y += (self.targetY - self.y) * 0.05;
+ };
+ return self;
+});
+var Enemy = Container.expand(function (type) {
+ var self = Container.call(this);
+ self.type = type || 'basic';
+ var assetType = self.type === 'fast' ? 'enemy' : 'enemy';
+ var ship = self.attachAsset(assetType, {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Different enemy types
+ if (self.type === 'basic') {
+ self.health = 1;
+ self.speed = 2;
+ self.scoreValue = 10;
+ self.shootChance = 0.01;
+ } else if (self.type === 'fast') {
+ self.health = 1;
+ self.speed = 3.5;
+ self.scoreValue = 15;
+ ship.scaleX = 0.8;
+ ship.scaleY = 0.8;
+ self.shootChance = 0.005;
+ ship.tint = 0xff9966;
+ } else if (self.type === 'tank') {
+ self.health = 3;
+ self.speed = 1.5;
+ self.scoreValue = 25;
+ ship.scaleX = 1.2;
+ ship.scaleY = 1.2;
+ self.shootChance = 0.015;
+ ship.tint = 0x66ff66;
+ }
+ self.movement = {
+ pattern: 'straight',
+ phase: Math.random() * Math.PI * 2,
+ amplitude: 60 + Math.random() * 60
+ };
+ self.initialX = 0;
+ self.damage = function (amount) {
+ self.health -= amount || 1;
+ tween(ship, {
+ tint: 0xffffff
+ }, {
+ duration: 200,
+ onFinish: function onFinish() {
+ ship.tint = self.type === 'fast' ? 0xff9966 : self.type === 'tank' ? 0x66ff66 : 0xe74c3c;
+ }
+ });
+ return self.health <= 0;
+ };
+ self.update = function () {
+ // Basic movement
+ self.y += self.speed;
+ // Pattern movement
+ if (self.movement.pattern === 'sine') {
+ self.x = self.initialX + Math.sin(LK.ticks * 0.05 + self.movement.phase) * self.movement.amplitude;
+ } else if (self.movement.pattern === 'zigzag') {
+ var timeScale = 0.02;
+ var t = LK.ticks * timeScale + self.movement.phase;
+ var triangleWave = Math.abs(t % 2 - 1) * 2 - 1;
+ self.x = self.initialX + triangleWave * self.movement.amplitude;
+ }
+ };
+ return self;
+});
+var EnemyLaser = Container.expand(function () {
+ var self = Container.call(this);
+ var laser = self.attachAsset('enemyLaser', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 8;
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+var Explosion = Container.expand(function () {
+ var self = Container.call(this);
+ var explosion = self.attachAsset('explosion', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0.9
+ });
+ // Set up fade and scale
+ tween(explosion, {
+ alpha: 0,
+ scaleX: 2,
+ scaleY: 2
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ self.destroy();
+ }
+ });
+ return self;
+});
+var Player = Container.expand(function () {
+ var self = Container.call(this);
+ var ship = self.attachAsset('player', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.shield = self.attachAsset('shield', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ alpha: 0
+ });
+ self.lives = 3;
+ self.shieldActive = false;
+ self.fireRate = 20;
+ self.lastShot = 0;
+ self.canShoot = true;
+ self.power = 1;
+ self.invulnerable = false;
+ self.activateShield = function (duration) {
+ self.shieldActive = true;
+ self.shield.alpha = 0.4;
+ LK.setTimeout(function () {
+ self.shieldActive = false;
+ tween(self.shield, {
+ alpha: 0
+ }, {
+ duration: 500
+ });
+ }, duration);
+ };
+ self.damage = function () {
+ if (self.invulnerable || self.shieldActive) {
+ return;
+ }
+ self.lives--;
+ LK.getSound('playerDamage').play();
+ // Make player temporarily invulnerable
+ self.invulnerable = true;
+ // Flash the player to show invulnerability
+ var flashCount = 0;
+ var flashInterval = LK.setInterval(function () {
+ ship.alpha = ship.alpha === 0.3 ? 1 : 0.3;
+ flashCount++;
+ if (flashCount >= 10) {
+ LK.clearInterval(flashInterval);
+ ship.alpha = 1;
+ self.invulnerable = false;
+ }
+ }, 150);
+ };
+ self.upgrade = function (type) {
+ LK.getSound('powerup').play();
+ if (type === 'shield') {
+ self.activateShield(8000);
+ } else if (type === 'power') {
+ self.power = Math.min(self.power + 1, 3);
+ // Reset power after some time
+ LK.setTimeout(function () {
+ self.power = Math.max(1, self.power - 1);
+ }, 10000);
+ } else if (type === 'life') {
+ self.lives = Math.min(self.lives + 1, 5);
+ } else if (type === 'speed') {
+ var oldFireRate = self.fireRate;
+ self.fireRate = Math.max(self.fireRate - 5, 10);
+ // Reset fire rate after some time
+ LK.setTimeout(function () {
+ self.fireRate = oldFireRate;
+ }, 10000);
+ }
+ };
+ return self;
+});
+var PlayerLaser = Container.expand(function () {
+ var self = Container.call(this);
+ var laser = self.attachAsset('playerLaser', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = -15;
+ self.power = 1;
+ self.update = function () {
+ self.y += self.speed;
+ };
+ return self;
+});
+var Powerup = Container.expand(function (type) {
+ var self = Container.call(this);
+ self.type = type || ['shield', 'power', 'life', 'speed'][Math.floor(Math.random() * 4)];
+ var powerup = self.attachAsset('powerup', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Set color based on type
+ if (self.type === 'shield') {
+ powerup.tint = 0x3498db; // Blue
+ } else if (self.type === 'power') {
+ powerup.tint = 0xe74c3c; // Red
+ } else if (self.type === 'life') {
+ powerup.tint = 0x2ecc71; // Green
+ } else if (self.type === 'speed') {
+ powerup.tint = 0xf1c40f; // Yellow
+ }
+ self.speed = 3;
+ self.update = function () {
+ self.y += self.speed;
+ powerup.rotation += 0.05;
+ };
+ return self;
+});
+
+/****
* Initialize Game
-****/
+****/
var game = new LK.Game({
- backgroundColor: 0x000000
-});
\ No newline at end of file
+ backgroundColor: 0x000022
+});
+
+/****
+* Game Code
+****/
+// Game variables
+var player;
+var playerLasers = [];
+var enemies = [];
+var enemyLasers = [];
+var asteroids = [];
+var powerups = [];
+var explosions = [];
+var boss = null;
+var gameState = 'playing';
+var score = 0;
+var waveNumber = 1;
+var enemiesThisWave = 0;
+var enemiesDefeated = 0;
+var waveDelay = 0;
+var bossWave = false;
+var dragStartPosition = {
+ x: 0,
+ y: 0
+};
+// UI elements
+var scoreTxt = new Text2('SCORE: 0', {
+ size: 40,
+ fill: 0xFFFFFF
+});
+scoreTxt.anchor.set(0, 0);
+LK.gui.topRight.addChild(scoreTxt);
+scoreTxt.x = -250;
+scoreTxt.y = 50;
+var waveText = new Text2('WAVE: 1', {
+ size: 40,
+ fill: 0xFFFFFF
+});
+waveText.anchor.set(0.5, 0);
+LK.gui.top.addChild(waveText);
+waveText.y = 50;
+var livesText = new Text2('LIVES: 3', {
+ size: 40,
+ fill: 0xFFFFFF
+});
+livesText.anchor.set(0, 0);
+LK.gui.topLeft.addChild(livesText);
+livesText.x = 150; // Keep away from the top-left menu icon
+livesText.y = 50;
+// Create game elements
+function initGame() {
+ // Reset game variables
+ playerLasers = [];
+ enemies = [];
+ enemyLasers = [];
+ asteroids = [];
+ powerups = [];
+ explosions = [];
+ boss = null;
+ gameState = 'playing';
+ score = 0;
+ waveNumber = 1;
+ enemiesThisWave = 10;
+ enemiesDefeated = 0;
+ waveDelay = 0;
+ bossWave = false;
+ // Update UI
+ scoreTxt.setText('SCORE: ' + score);
+ waveText.setText('WAVE: ' + waveNumber);
+ // Create player
+ player = new Player();
+ player.x = 1024;
+ player.y = 2200;
+ game.addChild(player);
+ livesText.setText('LIVES: ' + player.lives);
+ // Start with player moving up
+ tween(player, {
+ y: 2000
+ }, {
+ duration: 1000
+ });
+ // Start the music
+ LK.playMusic('gameMusic', {
+ fade: {
+ start: 0,
+ end: 0.7,
+ duration: 1000
+ }
+ });
+ // Create first wave
+ createWave();
+}
+// Create a new wave of enemies
+function createWave() {
+ waveNumber++;
+ waveText.setText('WAVE: ' + waveNumber);
+ // Every 5 waves is a boss wave
+ bossWave = waveNumber % 5 === 0;
+ if (bossWave) {
+ // Create a boss
+ var bossLevel = Math.ceil(waveNumber / 5);
+ LK.getSound('bossAlert').play();
+ boss = new Boss(bossLevel);
+ boss.x = 1024;
+ boss.y = -200;
+ game.addChild(boss);
+ tween(boss, {
+ y: 300
+ }, {
+ duration: 2000
+ });
+ // Show boss wave text
+ var bossText = new Text2('BOSS WAVE!', {
+ size: 80,
+ fill: 0xFF0000
+ });
+ bossText.anchor.set(0.5, 0.5);
+ bossText.x = 1024;
+ bossText.y = 800;
+ game.addChild(bossText);
+ tween(bossText, {
+ alpha: 0,
+ y: 700
+ }, {
+ duration: 2000,
+ onFinish: function onFinish() {
+ bossText.destroy();
+ }
+ });
+ return;
+ }
+ // Regular wave
+ enemiesThisWave = 10 + waveNumber * 2;
+ enemiesDefeated = 0;
+ // Show wave text
+ var newWaveText = new Text2('WAVE ' + waveNumber, {
+ size: 80,
+ fill: 0xFFFFFF
+ });
+ newWaveText.anchor.set(0.5, 0.5);
+ newWaveText.x = 1024;
+ newWaveText.y = 800;
+ game.addChild(newWaveText);
+ tween(newWaveText, {
+ alpha: 0,
+ y: 700
+ }, {
+ duration: 2000,
+ onFinish: function onFinish() {
+ newWaveText.destroy();
+ }
+ });
+ // Start spawning enemies after a short delay
+ waveDelay = 120;
+}
+// Create a new enemy
+function spawnEnemy() {
+ var types = ['basic'];
+ // Add more enemy types as waves progress
+ if (waveNumber >= 2) {
+ types.push('fast');
+ }
+ if (waveNumber >= 3) {
+ types.push('tank');
+ }
+ var type = types[Math.floor(Math.random() * types.length)];
+ var enemy = new Enemy(type);
+ // Position the enemy
+ enemy.x = Math.random() * 1800 + 124;
+ enemy.y = -100;
+ enemy.initialX = enemy.x;
+ // Set random movement pattern
+ var patterns = ['straight'];
+ if (waveNumber >= 2) {
+ patterns.push('sine');
+ }
+ if (waveNumber >= 4) {
+ patterns.push('zigzag');
+ }
+ enemy.movement.pattern = patterns[Math.floor(Math.random() * patterns.length)];
+ // Add to game
+ enemies.push(enemy);
+ game.addChild(enemy);
+}
+// Create a new asteroid
+function spawnAsteroid() {
+ var asteroid = new Asteroid();
+ // Position the asteroid
+ asteroid.x = Math.random() * 1800 + 124;
+ asteroid.y = -100;
+ // Add to game
+ asteroids.push(asteroid);
+ game.addChild(asteroid);
+}
+// Create a player laser
+function firePlayerLaser() {
+ if (!player || !player.canShoot || player.lastShot + player.fireRate > LK.ticks) {
+ return;
+ }
+ player.lastShot = LK.ticks;
+ LK.getSound('playerShoot').play();
+ // Fire based on power level
+ if (player.power === 1) {
+ var laser = new PlayerLaser();
+ laser.x = player.x;
+ laser.y = player.y - 50;
+ laser.power = player.power;
+ playerLasers.push(laser);
+ game.addChild(laser);
+ } else if (player.power === 2) {
+ for (var i = -1; i <= 1; i += 2) {
+ var laser = new PlayerLaser();
+ laser.x = player.x + i * 30;
+ laser.y = player.y - 40;
+ laser.power = player.power;
+ playerLasers.push(laser);
+ game.addChild(laser);
+ }
+ } else if (player.power >= 3) {
+ var centerLaser = new PlayerLaser();
+ centerLaser.x = player.x;
+ centerLaser.y = player.y - 50;
+ centerLaser.power = player.power;
+ playerLasers.push(centerLaser);
+ game.addChild(centerLaser);
+ for (var i = -1; i <= 1; i += 2) {
+ var sideLaser = new PlayerLaser();
+ sideLaser.x = player.x + i * 40;
+ sideLaser.y = player.y - 30;
+ sideLaser.power = player.power - 1;
+ playerLasers.push(sideLaser);
+ game.addChild(sideLaser);
+ }
+ }
+}
+// Create an enemy laser
+function fireEnemyLaser(enemy) {
+ var laser = new EnemyLaser();
+ laser.x = enemy.x;
+ laser.y = enemy.y + 40;
+ enemyLasers.push(laser);
+ game.addChild(laser);
+ LK.getSound('enemyShoot').play({
+ volume: 0.2
+ });
+}
+// Fire boss laser pattern
+function fireBossLasers() {
+ if (!boss) {
+ return;
+ }
+ // Different patterns based on boss level and health
+ var healthPercent = boss.health / boss.maxHealth;
+ var pattern = 'spread';
+ if (boss.level >= 2 && healthPercent < 0.5) {
+ pattern = 'circle';
+ }
+ if (pattern === 'spread') {
+ for (var i = -2; i <= 2; i++) {
+ var laser = new EnemyLaser();
+ laser.x = boss.x + i * 50;
+ laser.y = boss.y + 80;
+ enemyLasers.push(laser);
+ game.addChild(laser);
+ }
+ } else if (pattern === 'circle') {
+ var numLasers = 8;
+ for (var i = 0; i < numLasers; i++) {
+ var angle = i / numLasers * Math.PI * 2;
+ var laser = new EnemyLaser();
+ laser.x = boss.x + Math.cos(angle) * 100;
+ laser.y = boss.y + Math.sin(angle) * 100;
+ enemyLasers.push(laser);
+ game.addChild(laser);
+ // Add directional motion
+ laser.update = function () {
+ var dx = this.x - boss.x;
+ var dy = this.y - boss.y;
+ var length = Math.sqrt(dx * dx + dy * dy);
+ this.x += dx / length * 5;
+ this.y += dy / length * 5;
+ };
+ }
+ }
+ LK.getSound('enemyShoot').play({
+ volume: 0.4
+ });
+}
+// Create explosion animation
+function createExplosion(x, y, scale) {
+ var explosion = new Explosion();
+ explosion.x = x;
+ explosion.y = y;
+ if (scale) {
+ explosion.scale.set(scale, scale);
+ }
+ explosions.push(explosion);
+ game.addChild(explosion);
+ LK.getSound('explosion').play();
+}
+// Create a powerup
+function spawnPowerup(x, y, type) {
+ var powerup = new Powerup(type);
+ powerup.x = x;
+ powerup.y = y;
+ powerups.push(powerup);
+ game.addChild(powerup);
+}
+// Handle player shooting and movement
+function handlePlayerInput() {
+ // Keep player in bounds
+ player.x = Math.max(100, Math.min(player.x, 2048 - 100));
+ player.y = Math.max(100, Math.min(player.y, 2732 - 100));
+ // Auto-fire
+ if (LK.ticks % 10 === 0) {
+ firePlayerLaser();
+ }
+}
+// Handle collisions between game objects
+function handleCollisions() {
+ // Player lasers vs enemies
+ for (var i = playerLasers.length - 1; i >= 0; i--) {
+ var laser = playerLasers[i];
+ var hitSomething = false;
+ // Check against enemies
+ for (var j = enemies.length - 1; j >= 0; j--) {
+ var enemy = enemies[j];
+ if (laser.intersects(enemy)) {
+ // Damage enemy
+ if (enemy.damage(laser.power)) {
+ // Enemy destroyed
+ createExplosion(enemy.x, enemy.y);
+ // Add score
+ score += enemy.scoreValue;
+ scoreTxt.setText('SCORE: ' + score);
+ // Count enemy as defeated
+ enemiesDefeated++;
+ // Chance to spawn powerup
+ if (Math.random() < 0.1) {
+ spawnPowerup(enemy.x, enemy.y);
+ }
+ enemy.destroy();
+ enemies.splice(j, 1);
+ }
+ // Remove laser
+ laser.destroy();
+ playerLasers.splice(i, 1);
+ hitSomething = true;
+ break;
+ }
+ }
+ // Only check other collisions if we haven't hit an enemy
+ if (!hitSomething) {
+ // Check against boss
+ if (boss && laser.intersects(boss)) {
+ // Damage boss
+ if (boss.damage(laser.power)) {
+ // Boss destroyed
+ createExplosion(boss.x, boss.y, 2);
+ // Add score
+ score += boss.scoreValue;
+ scoreTxt.setText('SCORE: ' + score);
+ // Spawn multiple powerups
+ for (var p = 0; p < 3; p++) {
+ var powerupType = ['shield', 'power', 'life', 'speed'][Math.floor(Math.random() * 4)];
+ spawnPowerup(boss.x + (Math.random() * 200 - 100), boss.y + (Math.random() * 200 - 100), powerupType);
+ }
+ boss.destroy();
+ boss = null;
+ // Move to next wave
+ createWave();
+ }
+ // Remove laser
+ laser.destroy();
+ playerLasers.splice(i, 1);
+ hitSomething = true;
+ }
+ // Check against asteroids
+ for (var k = asteroids.length - 1; k >= 0; k--) {
+ var asteroid = asteroids[k];
+ if (laser.intersects(asteroid)) {
+ // Damage asteroid
+ if (asteroid.damage(laser.power)) {
+ // Asteroid destroyed
+ createExplosion(asteroid.x, asteroid.y, 0.7);
+ // Add score
+ score += asteroid.scoreValue;
+ scoreTxt.setText('SCORE: ' + score);
+ asteroid.destroy();
+ asteroids.splice(k, 1);
+ }
+ // Remove laser
+ laser.destroy();
+ playerLasers.splice(i, 1);
+ hitSomething = true;
+ break;
+ }
+ }
+ }
+ // Remove laser if it's off screen
+ if (!hitSomething && laser.y < -50) {
+ laser.destroy();
+ playerLasers.splice(i, 1);
+ }
+ }
+ // Enemy lasers vs player
+ for (var i = enemyLasers.length - 1; i >= 0; i--) {
+ var laser = enemyLasers[i];
+ if (player && laser.intersects(player)) {
+ // Damage player
+ player.damage();
+ // Update UI
+ livesText.setText('LIVES: ' + player.lives);
+ // Check for game over
+ if (player.lives <= 0) {
+ // Game over
+ createExplosion(player.x, player.y, 1.5);
+ player.destroy();
+ player = null;
+ // Save high score if needed
+ if (score > storage.highScore) {
+ storage.highScore = score;
+ }
+ // Show game over after a delay
+ LK.setTimeout(function () {
+ LK.showGameOver();
+ }, 1000);
+ }
+ // Remove laser
+ laser.destroy();
+ enemyLasers.splice(i, 1);
+ } else if (laser.y > 2732 + 50) {
+ // Remove laser if it's off screen
+ laser.destroy();
+ enemyLasers.splice(i, 1);
+ }
+ }
+ // Player vs enemies
+ for (var i = enemies.length - 1; i >= 0; i--) {
+ var enemy = enemies[i];
+ if (player && player.intersects(enemy)) {
+ // Damage player
+ player.damage();
+ // Damage enemy
+ enemy.damage(1);
+ // Update UI
+ livesText.setText('LIVES: ' + player.lives);
+ // Check for enemy death
+ if (enemy.health <= 0) {
+ // Enemy destroyed
+ createExplosion(enemy.x, enemy.y);
+ // Add score
+ score += enemy.scoreValue;
+ scoreTxt.setText('SCORE: ' + score);
+ // Count enemy as defeated
+ enemiesDefeated++;
+ enemy.destroy();
+ enemies.splice(i, 1);
+ }
+ // Check for game over
+ if (player.lives <= 0) {
+ // Game over
+ createExplosion(player.x, player.y, 1.5);
+ player.destroy();
+ player = null;
+ // Save high score if needed
+ if (score > storage.highScore) {
+ storage.highScore = score;
+ }
+ // Show game over after a delay
+ LK.setTimeout(function () {
+ LK.showGameOver();
+ }, 1000);
+ }
+ }
+ // Remove enemy if it's off screen
+ if (enemy.y > 2732 + 100) {
+ enemy.destroy();
+ enemies.splice(i, 1);
+ }
+ }
+ // Player vs asteroids
+ for (var i = asteroids.length - 1; i >= 0; i--) {
+ var asteroid = asteroids[i];
+ if (player && player.intersects(asteroid)) {
+ // Damage player
+ player.damage();
+ // Damage asteroid
+ asteroid.damage(1);
+ // Update UI
+ livesText.setText('LIVES: ' + player.lives);
+ // Check for asteroid death
+ if (asteroid.health <= 0) {
+ // Asteroid destroyed
+ createExplosion(asteroid.x, asteroid.y, 0.7);
+ // Add score
+ score += asteroid.scoreValue;
+ scoreTxt.setText('SCORE: ' + score);
+ asteroid.destroy();
+ asteroids.splice(i, 1);
+ }
+ // Check for game over
+ if (player.lives <= 0) {
+ // Game over
+ createExplosion(player.x, player.y, 1.5);
+ player.destroy();
+ player = null;
+ // Save high score if needed
+ if (score > storage.highScore) {
+ storage.highScore = score;
+ }
+ // Show game over after a delay
+ LK.setTimeout(function () {
+ LK.showGameOver();
+ }, 1000);
+ }
+ }
+ // Remove asteroid if it's off screen
+ if (asteroid.y > 2732 + 100 || asteroid.x < -100 || asteroid.x > 2048 + 100) {
+ asteroid.destroy();
+ asteroids.splice(i, 1);
+ }
+ }
+ // Player vs powerups
+ for (var i = powerups.length - 1; i >= 0; i--) {
+ var powerup = powerups[i];
+ if (player && player.intersects(powerup)) {
+ // Apply powerup
+ player.upgrade(powerup.type);
+ // Update UI if life powerup
+ if (powerup.type === 'life') {
+ livesText.setText('LIVES: ' + player.lives);
+ }
+ // Remove powerup
+ powerup.destroy();
+ powerups.splice(i, 1);
+ } else if (powerup.y > 2732 + 50) {
+ // Remove powerup if it's off screen
+ powerup.destroy();
+ powerups.splice(i, 1);
+ }
+ }
+ // Player vs boss
+ if (player && boss && player.intersects(boss)) {
+ // Damage player
+ player.damage();
+ // Update UI
+ livesText.setText('LIVES: ' + player.lives);
+ // Check for game over
+ if (player.lives <= 0) {
+ // Game over
+ createExplosion(player.x, player.y, 1.5);
+ player.destroy();
+ player = null;
+ // Save high score if needed
+ if (score > storage.highScore) {
+ storage.highScore = score;
+ }
+ // Show game over after a delay
+ LK.setTimeout(function () {
+ LK.showGameOver();
+ }, 1000);
+ }
+ }
+}
+// Initialize the game
+initGame();
+// Game down event handler
+game.down = function (x, y, obj) {
+ if (!player) {
+ return;
+ }
+ dragStartPosition.x = x;
+ dragStartPosition.y = y;
+ // Fire lasers on tap
+ firePlayerLaser();
+};
+// Game move event handler
+game.move = function (x, y, obj) {
+ if (!player) {
+ return;
+ }
+ // Move player with drag
+ player.x = x;
+ player.y = y;
+};
+// Game update handler
+game.update = function () {
+ if (gameState !== 'playing') {
+ return;
+ }
+ // Handle player input
+ if (player) {
+ handlePlayerInput();
+ }
+ // Handle wave creation
+ if (waveDelay > 0) {
+ waveDelay--;
+ } else if (!bossWave && enemies.length === 0 && enemiesDefeated >= enemiesThisWave) {
+ // All enemies for this wave defeated, create next wave
+ createWave();
+ } else if (!bossWave && enemies.length < 5 && enemiesDefeated < enemiesThisWave && LK.ticks % 30 === 0) {
+ // Spawn more enemies for this wave
+ spawnEnemy();
+ }
+ // Spawn asteroids occasionally
+ if (LK.ticks % 180 === 0 && Math.random() < 0.7) {
+ spawnAsteroid();
+ }
+ // Boss shooting
+ if (boss && LK.ticks % 90 === 0) {
+ fireBossLasers();
+ }
+ // Enemy shooting
+ for (var i = 0; i < enemies.length; i++) {
+ if (Math.random() < enemies[i].shootChance) {
+ fireEnemyLaser(enemies[i]);
+ }
+ }
+ // Collision detection
+ handleCollisions();
+};
\ No newline at end of file
space ship. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
asteroid. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
space enemy. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
explosion. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
shield. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
powerup. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
space boss ufo. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
green laser. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
red laser. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat