/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Enemy = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 2;
self.maxHealth = 2;
self.speed = 2;
self.fireRate = 120; // Fire every 2 seconds
self.fireTimer = Math.random() * 120; // Random initial fire delay
self.moveDirection = 1;
self.points = 100;
// Health bar setup
var healthBarBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.y = -50; // Position above enemy
var healthBarFill = self.attachAsset('healthBarFill', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarFill.y = -50; // Position above enemy
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
healthBarFill.width = 80 * healthPercent;
// Change color based on health
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00ff00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xffff00; // Yellow
} else {
healthBarFill.tint = 0xff0000; // Red
}
};
// Initialize health bar
self.updateHealthBar();
self.takeDamage = function () {
self.health--;
// Update health bar
self.updateHealthBar();
// Tint red briefly when hit
tween(graphics, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
graphics.tint = 0xffffff;
}
});
LK.getSound('enemyHit').play();
if (self.health <= 0) {
// Chance to drop powerup
if (Math.random() < 0.15) {
var powerup = new Powerup();
powerup.x = self.x;
powerup.y = self.y;
powerups.push(powerup);
game.addChild(powerup);
}
return true; // Enemy destroyed
}
return false;
};
self.update = function () {
self.y += self.speed;
// Fire at player occasionally
self.fireTimer--;
if (self.fireTimer <= 0) {
self.fireTimer = self.fireRate + Math.random() * 60;
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 40;
enemyBullets.push(bullet);
game.addChild(bullet);
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.update = function () {
self.y += self.speed;
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -12;
self.update = function () {
self.y += self.speed;
};
return self;
});
var PlayerShip = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 3;
self.maxHealth = 3;
self.speed = 8;
self.fireRate = 30; // Fire every 30 ticks (slower shooting)
self.fireTimer = 0;
self.invulnerable = false;
self.invulnerabilityTimer = 0;
self.takeDamage = function () {
if (self.invulnerable) return false;
self.health--;
self.invulnerable = true;
self.invulnerabilityTimer = 120; // 2 seconds of invulnerability
// Flash effect
LK.effects.flashObject(self, 0xff0000, 500);
LK.getSound('playerHit').play();
if (self.health <= 0) {
return true; // Player died
}
return false;
};
self.update = function () {
// Handle invulnerability
if (self.invulnerable) {
self.invulnerabilityTimer--;
if (self.invulnerabilityTimer <= 0) {
self.invulnerable = false;
}
// Flicker effect
graphics.alpha = self.invulnerabilityTimer % 10 < 5 ? 0.3 : 1.0;
} else {
graphics.alpha = 1.0;
}
// Auto-fire
self.fireTimer--;
if (self.fireTimer <= 0) {
self.fireTimer = self.fireRate;
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - 50;
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
}
};
return self;
});
var Powerup = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.bobTimer = 0;
self.initialY = 0;
self.update = function () {
self.y += self.speed;
// Bobbing animation
self.bobTimer += 0.2;
if (self.initialY === 0) self.initialY = self.y;
graphics.y = Math.sin(self.bobTimer) * 10;
// Rotate slowly
graphics.rotation += 0.1;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000022
});
/****
* Game Code
****/
// Game variables
var player;
var playerBullets = [];
var enemies = [];
var enemyBullets = [];
var powerups = [];
var currentWave = 1;
var enemiesInWave = 0;
var enemiesDestroyed = 0;
var waveSpawnTimer = 0;
var gameStarted = false;
var lives = 3;
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 100;
scoreTxt.y = 50;
LK.gui.topLeft.addChild(scoreTxt);
var wavesTxt = new Text2('Wave: 1', {
size: 60,
fill: 0xFFFFFF
});
wavesTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(wavesTxt);
var livesTxt = new Text2('Lives: 3', {
size: 60,
fill: 0xFFFFFF
});
livesTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(livesTxt);
// Initialize player
player = game.addChild(new PlayerShip());
player.x = 2048 / 2;
player.y = 2732 - 150;
// Touch controls
var touchStartX = 0;
var isDragging = false;
game.down = function (x, y, obj) {
touchStartX = x;
isDragging = true;
};
game.move = function (x, y, obj) {
if (isDragging) {
var deltaX = x - touchStartX;
player.x += deltaX * 0.8;
// Keep player within screen bounds
var halfWidth = 60;
if (player.x < halfWidth) player.x = halfWidth;
if (player.x > 2048 - halfWidth) player.x = 2048 - halfWidth;
touchStartX = x;
}
};
game.up = function (x, y, obj) {
isDragging = false;
};
// Wave management
function startNewWave() {
currentWave++;
enemiesInWave = Math.min(5 + currentWave * 2, 20);
enemiesDestroyed = 0;
waveSpawnTimer = 0;
wavesTxt.setText('Wave: ' + currentWave);
// Flash screen to indicate new wave
LK.effects.flashScreen(0x0044ff, 800);
}
function spawnEnemy() {
var enemy = new Enemy();
var formation = Math.floor(Math.random() * 3);
if (formation === 0) {
// Single enemy
enemy.x = Math.random() * (2048 - 200) + 100;
enemy.y = -50;
} else if (formation === 1) {
// Side formation
enemy.x = Math.random() < 0.5 ? 100 : 2048 - 100;
enemy.y = -50;
} else {
// Center formation
enemy.x = 2048 / 2 + (Math.random() - 0.5) * 400;
enemy.y = -50;
}
// Increase difficulty with waves
enemy.health += Math.floor(currentWave / 3);
enemy.maxHealth = enemy.health; // Update max health for proper health bar display
enemy.updateHealthBar(); // Refresh health bar after health changes
enemy.speed += currentWave * 0.3;
enemy.fireRate = Math.max(60, enemy.fireRate - currentWave * 5);
enemies.push(enemy);
game.addChild(enemy);
}
// Main game update
game.update = function () {
// Update score display
scoreTxt.setText('Score: ' + LK.getScore());
livesTxt.setText('Lives: ' + lives);
// Spawn enemies for current wave
if (enemies.length + enemiesDestroyed < enemiesInWave) {
waveSpawnTimer--;
if (waveSpawnTimer <= 0) {
spawnEnemy();
waveSpawnTimer = Math.max(30, 90 - currentWave * 3);
}
}
// Check if wave is complete
if (enemies.length === 0 && enemiesDestroyed >= enemiesInWave) {
LK.setTimeout(function () {
startNewWave();
}, 2000);
}
// Update 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);
continue;
}
// Check collision with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
bullet.destroy();
playerBullets.splice(i, 1);
if (enemy.takeDamage()) {
LK.setScore(LK.getScore() + enemy.points);
enemy.destroy();
enemies.splice(j, 1);
enemiesDestroyed++;
}
break;
}
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
// Remove enemies that go off screen
if (enemy.y > 2732 + 100) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check collision with player
if (enemy.intersects(player)) {
if (player.takeDamage()) {
lives--;
if (lives <= 0) {
LK.showGameOver();
return;
}
}
enemy.destroy();
enemies.splice(i, 1);
enemiesDestroyed++;
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (bullet.y > 2732 + 50) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (bullet.intersects(player)) {
bullet.destroy();
enemyBullets.splice(i, 1);
if (player.takeDamage()) {
lives--;
if (lives <= 0) {
LK.showGameOver();
return;
}
}
}
}
// Update powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
if (powerup.y > 2732 + 50) {
powerup.destroy();
powerups.splice(i, 1);
continue;
}
// Check collision with player
if (powerup.intersects(player)) {
powerup.destroy();
powerups.splice(i, 1);
// Apply powerup effect
LK.setScore(LK.getScore() + 500);
player.fireRate = Math.max(3, player.fireRate - 2); // Faster firing
LK.getSound('powerupCollect').play();
// Visual effect
LK.effects.flashObject(player, 0x00ffff, 1000);
}
}
};
// Start background music
LK.playMusic('bgmusic');
// Initialize first wave
enemiesInWave = 5;
waveSpawnTimer = 60; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Enemy = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 2;
self.maxHealth = 2;
self.speed = 2;
self.fireRate = 120; // Fire every 2 seconds
self.fireTimer = Math.random() * 120; // Random initial fire delay
self.moveDirection = 1;
self.points = 100;
// Health bar setup
var healthBarBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.y = -50; // Position above enemy
var healthBarFill = self.attachAsset('healthBarFill', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarFill.y = -50; // Position above enemy
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
healthBarFill.width = 80 * healthPercent;
// Change color based on health
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00ff00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xffff00; // Yellow
} else {
healthBarFill.tint = 0xff0000; // Red
}
};
// Initialize health bar
self.updateHealthBar();
self.takeDamage = function () {
self.health--;
// Update health bar
self.updateHealthBar();
// Tint red briefly when hit
tween(graphics, {
tint: 0xff0000
}, {
duration: 200,
onFinish: function onFinish() {
graphics.tint = 0xffffff;
}
});
LK.getSound('enemyHit').play();
if (self.health <= 0) {
// Chance to drop powerup
if (Math.random() < 0.15) {
var powerup = new Powerup();
powerup.x = self.x;
powerup.y = self.y;
powerups.push(powerup);
game.addChild(powerup);
}
return true; // Enemy destroyed
}
return false;
};
self.update = function () {
self.y += self.speed;
// Fire at player occasionally
self.fireTimer--;
if (self.fireTimer <= 0) {
self.fireTimer = self.fireRate + Math.random() * 60;
var bullet = new EnemyBullet();
bullet.x = self.x;
bullet.y = self.y + 40;
enemyBullets.push(bullet);
game.addChild(bullet);
}
};
return self;
});
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.update = function () {
self.y += self.speed;
};
return self;
});
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -12;
self.update = function () {
self.y += self.speed;
};
return self;
});
var PlayerShip = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 3;
self.maxHealth = 3;
self.speed = 8;
self.fireRate = 30; // Fire every 30 ticks (slower shooting)
self.fireTimer = 0;
self.invulnerable = false;
self.invulnerabilityTimer = 0;
self.takeDamage = function () {
if (self.invulnerable) return false;
self.health--;
self.invulnerable = true;
self.invulnerabilityTimer = 120; // 2 seconds of invulnerability
// Flash effect
LK.effects.flashObject(self, 0xff0000, 500);
LK.getSound('playerHit').play();
if (self.health <= 0) {
return true; // Player died
}
return false;
};
self.update = function () {
// Handle invulnerability
if (self.invulnerable) {
self.invulnerabilityTimer--;
if (self.invulnerabilityTimer <= 0) {
self.invulnerable = false;
}
// Flicker effect
graphics.alpha = self.invulnerabilityTimer % 10 < 5 ? 0.3 : 1.0;
} else {
graphics.alpha = 1.0;
}
// Auto-fire
self.fireTimer--;
if (self.fireTimer <= 0) {
self.fireTimer = self.fireRate;
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - 50;
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
}
};
return self;
});
var Powerup = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.bobTimer = 0;
self.initialY = 0;
self.update = function () {
self.y += self.speed;
// Bobbing animation
self.bobTimer += 0.2;
if (self.initialY === 0) self.initialY = self.y;
graphics.y = Math.sin(self.bobTimer) * 10;
// Rotate slowly
graphics.rotation += 0.1;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000022
});
/****
* Game Code
****/
// Game variables
var player;
var playerBullets = [];
var enemies = [];
var enemyBullets = [];
var powerups = [];
var currentWave = 1;
var enemiesInWave = 0;
var enemiesDestroyed = 0;
var waveSpawnTimer = 0;
var gameStarted = false;
var lives = 3;
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0, 0);
scoreTxt.x = 100;
scoreTxt.y = 50;
LK.gui.topLeft.addChild(scoreTxt);
var wavesTxt = new Text2('Wave: 1', {
size: 60,
fill: 0xFFFFFF
});
wavesTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(wavesTxt);
var livesTxt = new Text2('Lives: 3', {
size: 60,
fill: 0xFFFFFF
});
livesTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(livesTxt);
// Initialize player
player = game.addChild(new PlayerShip());
player.x = 2048 / 2;
player.y = 2732 - 150;
// Touch controls
var touchStartX = 0;
var isDragging = false;
game.down = function (x, y, obj) {
touchStartX = x;
isDragging = true;
};
game.move = function (x, y, obj) {
if (isDragging) {
var deltaX = x - touchStartX;
player.x += deltaX * 0.8;
// Keep player within screen bounds
var halfWidth = 60;
if (player.x < halfWidth) player.x = halfWidth;
if (player.x > 2048 - halfWidth) player.x = 2048 - halfWidth;
touchStartX = x;
}
};
game.up = function (x, y, obj) {
isDragging = false;
};
// Wave management
function startNewWave() {
currentWave++;
enemiesInWave = Math.min(5 + currentWave * 2, 20);
enemiesDestroyed = 0;
waveSpawnTimer = 0;
wavesTxt.setText('Wave: ' + currentWave);
// Flash screen to indicate new wave
LK.effects.flashScreen(0x0044ff, 800);
}
function spawnEnemy() {
var enemy = new Enemy();
var formation = Math.floor(Math.random() * 3);
if (formation === 0) {
// Single enemy
enemy.x = Math.random() * (2048 - 200) + 100;
enemy.y = -50;
} else if (formation === 1) {
// Side formation
enemy.x = Math.random() < 0.5 ? 100 : 2048 - 100;
enemy.y = -50;
} else {
// Center formation
enemy.x = 2048 / 2 + (Math.random() - 0.5) * 400;
enemy.y = -50;
}
// Increase difficulty with waves
enemy.health += Math.floor(currentWave / 3);
enemy.maxHealth = enemy.health; // Update max health for proper health bar display
enemy.updateHealthBar(); // Refresh health bar after health changes
enemy.speed += currentWave * 0.3;
enemy.fireRate = Math.max(60, enemy.fireRate - currentWave * 5);
enemies.push(enemy);
game.addChild(enemy);
}
// Main game update
game.update = function () {
// Update score display
scoreTxt.setText('Score: ' + LK.getScore());
livesTxt.setText('Lives: ' + lives);
// Spawn enemies for current wave
if (enemies.length + enemiesDestroyed < enemiesInWave) {
waveSpawnTimer--;
if (waveSpawnTimer <= 0) {
spawnEnemy();
waveSpawnTimer = Math.max(30, 90 - currentWave * 3);
}
}
// Check if wave is complete
if (enemies.length === 0 && enemiesDestroyed >= enemiesInWave) {
LK.setTimeout(function () {
startNewWave();
}, 2000);
}
// Update 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);
continue;
}
// Check collision with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy)) {
bullet.destroy();
playerBullets.splice(i, 1);
if (enemy.takeDamage()) {
LK.setScore(LK.getScore() + enemy.points);
enemy.destroy();
enemies.splice(j, 1);
enemiesDestroyed++;
}
break;
}
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
// Remove enemies that go off screen
if (enemy.y > 2732 + 100) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Check collision with player
if (enemy.intersects(player)) {
if (player.takeDamage()) {
lives--;
if (lives <= 0) {
LK.showGameOver();
return;
}
}
enemy.destroy();
enemies.splice(i, 1);
enemiesDestroyed++;
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var bullet = enemyBullets[i];
if (bullet.y > 2732 + 50) {
bullet.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (bullet.intersects(player)) {
bullet.destroy();
enemyBullets.splice(i, 1);
if (player.takeDamage()) {
lives--;
if (lives <= 0) {
LK.showGameOver();
return;
}
}
}
}
// Update powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
if (powerup.y > 2732 + 50) {
powerup.destroy();
powerups.splice(i, 1);
continue;
}
// Check collision with player
if (powerup.intersects(player)) {
powerup.destroy();
powerups.splice(i, 1);
// Apply powerup effect
LK.setScore(LK.getScore() + 500);
player.fireRate = Math.max(3, player.fireRate - 2); // Faster firing
LK.getSound('powerupCollect').play();
// Visual effect
LK.effects.flashObject(player, 0x00ffff, 1000);
}
}
};
// Start background music
LK.playMusic('bgmusic');
// Initialize first wave
enemiesInWave = 5;
waveSpawnTimer = 60;