/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Enemy Bullet
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bullet = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 18;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Enemy Ship
var EnemyShip = Container.expand(function () {
var self = Container.call(this);
var enemy = self.attachAsset('enemyShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = enemy.width;
self.height = enemy.height;
self.speedY = 6 + Math.random() * 4;
self.speedX = (Math.random() - 0.5) * 6;
self.shootCooldown = 60 + Math.floor(Math.random() * 60);
// Add health property for 2 hearts
self.health = 2;
self.update = function () {
self.y += self.speedY;
self.x += self.speedX;
if (self.x < self.width / 2) {
self.x = self.width / 2;
self.speedX *= -1;
}
if (self.x > 2048 - self.width / 2) {
self.x = 2048 - self.width / 2;
self.speedX *= -1;
}
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
// Method to take damage
self.takeDamage = function () {
self.health--;
if (self.health <= 0) {
return true; // destroyed
}
return false; // still alive
};
return self;
});
// Player Bullet
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bullet = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -32;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Player Ship
var PlayerShip = Container.expand(function () {
var self = Container.call(this);
var ship = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = ship.width;
self.height = ship.height;
self.shootCooldown = 0;
self.poweredUp = false;
self.powerupTimer = 0;
self.shielded = false;
self.shieldTimer = 0;
self.rapidFire = false;
self.rapidFireTimer = 0;
self.update = function () {
if (self.shootCooldown > 0) self.shootCooldown--;
if (self.poweredUp) {
self.powerupTimer--;
if (self.powerupTimer <= 0) {
self.poweredUp = false;
ship.tint = 0x33c1ff;
}
}
if (self.shielded) {
self.shieldTimer--;
if (self.shieldTimer <= 0) {
self.shielded = false;
ship.tint = 0x33c1ff;
}
}
if (self.rapidFire) {
self.rapidFireTimer--;
if (self.rapidFireTimer <= 0) {
self.rapidFire = false;
ship.tint = 0x33c1ff;
}
}
};
self.activatePowerup = function (type) {
if (!type || type === 'triple') {
self.poweredUp = true;
self.powerupTimer = 360; // 6 seconds at 60fps
ship.tint = 0x44ff44;
} else if (type === 'shield') {
self.shielded = true;
self.shieldTimer = 420; // 7 seconds
ship.tint = 0x33c1ff;
} else if (type === 'rapid') {
self.rapidFire = true;
self.rapidFireTimer = 300; // 5 seconds
ship.tint = 0xffe066;
}
};
return self;
});
// Powerup
var Powerup = Container.expand(function () {
var self = Container.call(this);
// Randomly choose a type: 'triple', 'shield', 'rapid'
var types = ['triple', 'shield', 'rapid'];
self.type = types[Math.floor(Math.random() * types.length)];
var color = 0x44ff44;
if (self.type === 'shield') color = 0x33c1ff;
if (self.type === 'rapid') color = 0xffe066;
var p = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5,
tint: color
});
self.speedY = 10;
self.update = function () {
self.y += self.speedY;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181828
});
/****
* Game Code
****/
// Play music
// Player ship: pixelated box
// Enemy: pixelated box
// Player bullet: small yellow box
// Enemy bullet: small red box
// Powerup: green ellipse
// Sound effects
// Music
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 1,
duration: 1200
}
});
// Score display
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Powerup display
var powerupTxt = new Text2('', {
size: 70,
fill: 0x44FF44
});
powerupTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(powerupTxt);
powerupTxt.y = 120;
// Game objects
var player = new PlayerShip();
game.addChild(player);
player.x = 2048 / 2;
player.y = 2732 - 180;
var playerBullets = [];
var enemies = [];
var enemyBullets = [];
var powerups = [];
var dragNode = null;
var lastPlayerHit = false;
var spawnTimer = 0;
var powerupSpawnTimer = 600; // 10 seconds
// Move handler for dragging player ship
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp to game area
var minX = player.width / 2 + 40;
var maxX = 2048 - player.width / 2 - 40;
dragNode.x = Math.max(minX, Math.min(maxX, x));
// Y is fixed at bottom
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Only allow drag if touch is near player
if (Math.abs(x - player.x) < player.width && Math.abs(y - player.y) < player.height) {
dragNode = player;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Touch anywhere to shoot
game.tap = function (x, y, obj) {
// Not used, as shooting is auto-fire
};
// Main update loop
game.update = function () {
// Player update
player.update();
// Player auto-fire
if (player.shootCooldown <= 0) {
var bullet = new PlayerBullet();
bullet.x = player.x;
bullet.y = player.y - player.height / 2 - 20;
playerBullets.push(bullet);
game.addChild(bullet);
if (player.rapidFire) {
player.shootCooldown = player.poweredUp ? 2 : 4;
} else {
player.shootCooldown = player.poweredUp ? 6 : 16;
}
LK.getSound('shoot').play();
if (player.poweredUp) {
// Side bullets
for (var i = -1; i <= 1; i += 2) {
var sideBullet = new PlayerBullet();
sideBullet.x = player.x + i * 50;
sideBullet.y = player.y - player.height / 2 - 20;
playerBullets.push(sideBullet);
game.addChild(sideBullet);
}
}
}
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var b = playerBullets[i];
b.update();
if (b.y < -60) {
b.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
if (b.intersects(e)) {
// Damage enemy
var destroyed = e.takeDamage();
LK.effects.flashObject(e, 0xffffff, 200);
b.destroy();
playerBullets.splice(i, 1);
if (destroyed) {
LK.setScore(LK.getScore() + 10);
scoreTxt.setText(LK.getScore());
LK.getSound('explosion').play();
e.destroy();
enemies.splice(j, 1);
} else {
LK.getSound('explosion').play();
}
break;
}
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
e.update();
if (e.y > 2732 + 100) {
e.destroy();
enemies.splice(i, 1);
continue;
}
// Enemy shooting
if (e.shootCooldown <= 0) {
var eb = new EnemyBullet();
eb.x = e.x;
eb.y = e.y + e.height / 2 + 10;
enemyBullets.push(eb);
game.addChild(eb);
e.shootCooldown = 90 + Math.floor(Math.random() * 60);
LK.getSound('enemyShoot').play();
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var eb = enemyBullets[i];
eb.update();
if (eb.y > 2732 + 60) {
eb.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (eb.intersects(player)) {
if (player.shielded) {
eb.destroy();
enemyBullets.splice(i, 1);
} else if (!player.poweredUp) {
if (!lastPlayerHit) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
lastPlayerHit = true;
}
} else {
eb.destroy();
enemyBullets.splice(i, 1);
}
}
}
// Update powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var p = powerups[i];
p.update();
if (p.y > 2732 + 80) {
p.destroy();
powerups.splice(i, 1);
continue;
}
if (p.intersects(player)) {
player.activatePowerup(p.type);
LK.getSound('powerup').play();
if (p.type === 'shield') {
powerupTxt.setText('SHIELD!');
} else if (p.type === 'rapid') {
powerupTxt.setText('RAPID FIRE!');
} else {
powerupTxt.setText('TRIPLE SHOT!');
}
tween(powerupTxt, {
alpha: 0
}, {
duration: 1200,
easing: tween.linear,
onFinish: function onFinish() {
powerupTxt.setText('');
powerupTxt.alpha = 1;
}
});
p.destroy();
powerups.splice(i, 1);
}
}
// Enemy spawn
spawnTimer--;
if (spawnTimer <= 0) {
var e = new EnemyShip();
e.x = 200 + Math.random() * (2048 - 400);
e.y = -100;
enemies.push(e);
game.addChild(e);
spawnTimer = Math.max(24, 90 - Math.floor(LK.getScore() / 100)); // Faster spawns as score increases
}
// Powerup spawn
powerupSpawnTimer--;
if (powerupSpawnTimer <= 0) {
var p = new Powerup();
p.x = 200 + Math.random() * (2048 - 400);
p.y = -80;
powerups.push(p);
game.addChild(p);
powerupSpawnTimer = 900 + Math.floor(Math.random() * 600); // 15-25 seconds
}
// Win condition: score 1000
if (LK.getScore() >= 1000) {
LK.showYouWin();
}
// Always reset lastPlayerHit at end of update (game will be reset by LK on game over)
lastPlayerHit = false;
};
// Initial score
LK.setScore(0);
scoreTxt.setText('0'); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Enemy Bullet
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bullet = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 18;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Enemy Ship
var EnemyShip = Container.expand(function () {
var self = Container.call(this);
var enemy = self.attachAsset('enemyShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = enemy.width;
self.height = enemy.height;
self.speedY = 6 + Math.random() * 4;
self.speedX = (Math.random() - 0.5) * 6;
self.shootCooldown = 60 + Math.floor(Math.random() * 60);
// Add health property for 2 hearts
self.health = 2;
self.update = function () {
self.y += self.speedY;
self.x += self.speedX;
if (self.x < self.width / 2) {
self.x = self.width / 2;
self.speedX *= -1;
}
if (self.x > 2048 - self.width / 2) {
self.x = 2048 - self.width / 2;
self.speedX *= -1;
}
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
// Method to take damage
self.takeDamage = function () {
self.health--;
if (self.health <= 0) {
return true; // destroyed
}
return false; // still alive
};
return self;
});
// Player Bullet
var PlayerBullet = Container.expand(function () {
var self = Container.call(this);
var bullet = self.attachAsset('playerBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -32;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Player Ship
var PlayerShip = Container.expand(function () {
var self = Container.call(this);
var ship = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = ship.width;
self.height = ship.height;
self.shootCooldown = 0;
self.poweredUp = false;
self.powerupTimer = 0;
self.shielded = false;
self.shieldTimer = 0;
self.rapidFire = false;
self.rapidFireTimer = 0;
self.update = function () {
if (self.shootCooldown > 0) self.shootCooldown--;
if (self.poweredUp) {
self.powerupTimer--;
if (self.powerupTimer <= 0) {
self.poweredUp = false;
ship.tint = 0x33c1ff;
}
}
if (self.shielded) {
self.shieldTimer--;
if (self.shieldTimer <= 0) {
self.shielded = false;
ship.tint = 0x33c1ff;
}
}
if (self.rapidFire) {
self.rapidFireTimer--;
if (self.rapidFireTimer <= 0) {
self.rapidFire = false;
ship.tint = 0x33c1ff;
}
}
};
self.activatePowerup = function (type) {
if (!type || type === 'triple') {
self.poweredUp = true;
self.powerupTimer = 360; // 6 seconds at 60fps
ship.tint = 0x44ff44;
} else if (type === 'shield') {
self.shielded = true;
self.shieldTimer = 420; // 7 seconds
ship.tint = 0x33c1ff;
} else if (type === 'rapid') {
self.rapidFire = true;
self.rapidFireTimer = 300; // 5 seconds
ship.tint = 0xffe066;
}
};
return self;
});
// Powerup
var Powerup = Container.expand(function () {
var self = Container.call(this);
// Randomly choose a type: 'triple', 'shield', 'rapid'
var types = ['triple', 'shield', 'rapid'];
self.type = types[Math.floor(Math.random() * types.length)];
var color = 0x44ff44;
if (self.type === 'shield') color = 0x33c1ff;
if (self.type === 'rapid') color = 0xffe066;
var p = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5,
tint: color
});
self.speedY = 10;
self.update = function () {
self.y += self.speedY;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181828
});
/****
* Game Code
****/
// Play music
// Player ship: pixelated box
// Enemy: pixelated box
// Player bullet: small yellow box
// Enemy bullet: small red box
// Powerup: green ellipse
// Sound effects
// Music
LK.playMusic('bgmusic', {
fade: {
start: 0,
end: 1,
duration: 1200
}
});
// Score display
var scoreTxt = new Text2('0', {
size: 120,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Powerup display
var powerupTxt = new Text2('', {
size: 70,
fill: 0x44FF44
});
powerupTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(powerupTxt);
powerupTxt.y = 120;
// Game objects
var player = new PlayerShip();
game.addChild(player);
player.x = 2048 / 2;
player.y = 2732 - 180;
var playerBullets = [];
var enemies = [];
var enemyBullets = [];
var powerups = [];
var dragNode = null;
var lastPlayerHit = false;
var spawnTimer = 0;
var powerupSpawnTimer = 600; // 10 seconds
// Move handler for dragging player ship
function handleMove(x, y, obj) {
if (dragNode) {
// Clamp to game area
var minX = player.width / 2 + 40;
var maxX = 2048 - player.width / 2 - 40;
dragNode.x = Math.max(minX, Math.min(maxX, x));
// Y is fixed at bottom
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
// Only allow drag if touch is near player
if (Math.abs(x - player.x) < player.width && Math.abs(y - player.y) < player.height) {
dragNode = player;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Touch anywhere to shoot
game.tap = function (x, y, obj) {
// Not used, as shooting is auto-fire
};
// Main update loop
game.update = function () {
// Player update
player.update();
// Player auto-fire
if (player.shootCooldown <= 0) {
var bullet = new PlayerBullet();
bullet.x = player.x;
bullet.y = player.y - player.height / 2 - 20;
playerBullets.push(bullet);
game.addChild(bullet);
if (player.rapidFire) {
player.shootCooldown = player.poweredUp ? 2 : 4;
} else {
player.shootCooldown = player.poweredUp ? 6 : 16;
}
LK.getSound('shoot').play();
if (player.poweredUp) {
// Side bullets
for (var i = -1; i <= 1; i += 2) {
var sideBullet = new PlayerBullet();
sideBullet.x = player.x + i * 50;
sideBullet.y = player.y - player.height / 2 - 20;
playerBullets.push(sideBullet);
game.addChild(sideBullet);
}
}
}
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var b = playerBullets[i];
b.update();
if (b.y < -60) {
b.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
if (b.intersects(e)) {
// Damage enemy
var destroyed = e.takeDamage();
LK.effects.flashObject(e, 0xffffff, 200);
b.destroy();
playerBullets.splice(i, 1);
if (destroyed) {
LK.setScore(LK.getScore() + 10);
scoreTxt.setText(LK.getScore());
LK.getSound('explosion').play();
e.destroy();
enemies.splice(j, 1);
} else {
LK.getSound('explosion').play();
}
break;
}
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
e.update();
if (e.y > 2732 + 100) {
e.destroy();
enemies.splice(i, 1);
continue;
}
// Enemy shooting
if (e.shootCooldown <= 0) {
var eb = new EnemyBullet();
eb.x = e.x;
eb.y = e.y + e.height / 2 + 10;
enemyBullets.push(eb);
game.addChild(eb);
e.shootCooldown = 90 + Math.floor(Math.random() * 60);
LK.getSound('enemyShoot').play();
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; i--) {
var eb = enemyBullets[i];
eb.update();
if (eb.y > 2732 + 60) {
eb.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
if (eb.intersects(player)) {
if (player.shielded) {
eb.destroy();
enemyBullets.splice(i, 1);
} else if (!player.poweredUp) {
if (!lastPlayerHit) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
lastPlayerHit = true;
}
} else {
eb.destroy();
enemyBullets.splice(i, 1);
}
}
}
// Update powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var p = powerups[i];
p.update();
if (p.y > 2732 + 80) {
p.destroy();
powerups.splice(i, 1);
continue;
}
if (p.intersects(player)) {
player.activatePowerup(p.type);
LK.getSound('powerup').play();
if (p.type === 'shield') {
powerupTxt.setText('SHIELD!');
} else if (p.type === 'rapid') {
powerupTxt.setText('RAPID FIRE!');
} else {
powerupTxt.setText('TRIPLE SHOT!');
}
tween(powerupTxt, {
alpha: 0
}, {
duration: 1200,
easing: tween.linear,
onFinish: function onFinish() {
powerupTxt.setText('');
powerupTxt.alpha = 1;
}
});
p.destroy();
powerups.splice(i, 1);
}
}
// Enemy spawn
spawnTimer--;
if (spawnTimer <= 0) {
var e = new EnemyShip();
e.x = 200 + Math.random() * (2048 - 400);
e.y = -100;
enemies.push(e);
game.addChild(e);
spawnTimer = Math.max(24, 90 - Math.floor(LK.getScore() / 100)); // Faster spawns as score increases
}
// Powerup spawn
powerupSpawnTimer--;
if (powerupSpawnTimer <= 0) {
var p = new Powerup();
p.x = 200 + Math.random() * (2048 - 400);
p.y = -80;
powerups.push(p);
game.addChild(p);
powerupSpawnTimer = 900 + Math.floor(Math.random() * 600); // 15-25 seconds
}
// Win condition: score 1000
if (LK.getScore() >= 1000) {
LK.showYouWin();
}
// Always reset lastPlayerHit at end of update (game will be reset by LK on game over)
lastPlayerHit = false;
};
// Initial score
LK.setScore(0);
scoreTxt.setText('0');