/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Alien enemy var Alien = Container.expand(function () { var self = Container.call(this); var alien = self.attachAsset('alien', { anchorX: 0.5, anchorY: 0.5 }); self.width = alien.width; self.height = alien.height; self.direction = 1; // 1: right, -1: left self.speed = 3; self.shootChance = 0.002; // increased chance per frame to shoot (4x more bullets) self.row = 0; self.col = 0; self.alive = true; self.update = function () { // Movement handled by game for all aliens together // Randomly shoot if (Math.random() < self.shootChance && self.alive) { self.shoot(); } }; self.shoot = function () { var bullet = new AlienBullet(); bullet.x = self.x; bullet.y = self.y + self.height / 2 + bullet.height / 2; alienBullets.push(bullet); game.addChild(bullet); LK.getSound('alienShoot').play(); }; self.hit = function () { if (!self.alive) { return; } self.alive = false; tween(self, { alpha: 0 }, { duration: 200, onFinish: function onFinish() { self.destroy(); } }); LK.getSound('explosion').play(); LK.setScore(LK.getScore() + 10); scoreTxt.setText(LK.getScore()); }; return self; }); // Alien bullet var AlienBullet = Container.expand(function () { var self = Container.call(this); var bullet = self.attachAsset('alienBullet', { anchorX: 0.5, anchorY: 0.5 }); self.width = bullet.width; self.height = bullet.height; self.speed = 12; // Faster alien bullets self.update = function () { self.y += self.speed; }; 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.width = bullet.width; self.height = bullet.height; self.speed = -32; self.update = function () { self.y += self.speed; }; return self; }); // Player spaceship 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.canShoot = true; self.shootCooldown = 20; // frames - longer cooldown between shots self.cooldownTimer = 0; self.lives = 3; // Reduced lives for harder gameplay self.invincible = false; self.invincibleTimer = 0; self.update = function () { if (!self.canShoot) { self.cooldownTimer--; if (self.cooldownTimer <= 0) { self.canShoot = true; } } if (self.invincible) { self.invincibleTimer--; // Add rotation effect to show invincibility ship.rotation = Math.sin(LK.ticks * 0.1) * 0.1; // Add flashing tint effect for invincibility visual feedback if (LK.ticks % 10 < 5) { ship.tint = 0xffe14d; // Yellow tint } else { ship.tint = 0xffffff; // Reset tint } if (self.invincibleTimer <= 0) { self.invincible = false; ship.alpha = 1; ship.rotation = 0; ship.tint = 0xffffff; // Reset tint when invincibility ends } } else { // Reset effects when not invincible ship.rotation = 0; ship.tint = 0xffffff; } }; self.shoot = function () { if (self.canShoot) { var bullet = new PlayerBullet(); bullet.x = self.x; bullet.y = self.y - self.height / 2 - bullet.height / 2; playerBullets.push(bullet); game.addChild(bullet); LK.getSound('shoot').play(); self.canShoot = false; self.cooldownTimer = self.shootCooldown; } }; self.hit = function () { if (self.invincible) { return; } self.lives--; self.invincible = true; self.invincibleTimer = 60; // Less invincibility time after getting hit ship.alpha = 0.4; LK.effects.flashObject(self, 0xff0000, 400); if (self.lives <= 0) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); } }; self.collectPowerup = function () { self.lives++; LK.getSound('powerup').play(); // Grant temporary invincibility for 3 seconds (180 frames) self.invincible = true; self.invincibleTimer = 180; ship.alpha = 0.6; // Create pulsing effect during invincibility tween(ship, { alpha: 0.3 }, { duration: 500, onFinish: function onFinish() { tween(ship, { alpha: 0.8 }, { duration: 500, onFinish: function onFinish() { tween(ship, { alpha: 0.3 }, { duration: 500, onFinish: function onFinish() { tween(ship, { alpha: 0.8 }, { duration: 500, onFinish: function onFinish() { tween(ship, { alpha: 0.3 }, { duration: 500, onFinish: function onFinish() { tween(ship, { alpha: 1 }, { duration: 500 }); } }); } }); } }); } }); } }); // Pulsing effect during invincibility }; return self; }); // Power-up var Powerup = Container.expand(function () { var self = Container.call(this); var p = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.width = p.width; self.height = p.height; self.speed = 10; self.update = function () { self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000010 }); /**** * Game Code ****/ // Play music // Spaceship (player) // Alien enemy // Player bullet // Alien bullet // Power-up // Sound effects // Music LK.playMusic('spaceMusic'); // Score display var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Lives display var livesTxt = new Text2('♥♥♥', { size: 90, fill: 0xFF4D4D }); livesTxt.anchor.set(1, 0); livesTxt.x = -40; LK.gui.topRight.addChild(livesTxt); // Game variables var player; var playerBullets = []; var alienBullets = []; var aliens = []; var powerups = []; var alienRows = 4; var alienCols = 8; var alienSpacingX = 180; var alienSpacingY = 140; var alienStartY = 300; var alienMoveDir = 1; // 1: right, -1: left var alienMoveDown = false; var alienMoveSpeed = 25; // faster horizontal movement var alienMoveTimer = 0; var alienMoveInterval = 20; // frames - quicker movement updates var wave = 1; var dragNode = null; var lastTouchX = 0; // Initialize player player = new PlayerShip(); player.x = 2048 / 2; player.y = 2732 - 180; game.addChild(player); // Initialize aliens function spawnAliens() { for (var row = 0; row < alienRows; row++) { for (var col = 0; col < alienCols; col++) { var alien = new Alien(); alien.x = 2048 / 2 - (alienCols - 1) * alienSpacingX / 2 + col * alienSpacingX; alien.y = alienStartY + row * alienSpacingY; alien.row = row; alien.col = col; aliens.push(alien); game.addChild(alien); } } } spawnAliens(); // Powerup spawn timer var powerupTimer = 0; var powerupInterval = 600; // frames - less frequent powerups // Touch/move controls game.down = function (x, y, obj) { // Always move ship X to cursor/touch X, regardless of Y player.x = x; // Clamp to screen if (player.x < player.width / 2) { player.x = player.width / 2; } if (player.x > 2048 - player.width / 2) { player.x = 2048 - player.width / 2; } }; // No dragNode needed for this control scheme game.move = function (x, y, obj) { // Always move ship X to cursor/touch X, regardless of Y player.x = x; // Clamp to screen if (player.x < player.width / 2) { player.x = player.width / 2; } if (player.x > 2048 - player.width / 2) { player.x = 2048 - player.width / 2; } }; // Tap to shoot if not in bottom 1/3 game.up = function (x, y, obj) { if (y <= 2732 * 0.7) { player.shoot(); } }; // Main update loop game.update = function () { // Update player player.update(); // Update lives display var livesStr = ''; for (var i = 0; i < player.lives; i++) { livesStr += '♥'; } livesTxt.setText(livesStr); // Update player bullets for (var i = playerBullets.length - 1; i >= 0; i--) { var b = playerBullets[i]; b.update(); // Remove if off screen if (b.y < -b.height) { b.destroy(); playerBullets.splice(i, 1); continue; } // Check collision with aliens for (var j = 0; j < aliens.length; j++) { var a = aliens[j]; if (a.alive && b.intersects(a)) { a.hit(); b.destroy(); playerBullets.splice(i, 1); break; } } } // Update alien bullets for (var i = alienBullets.length - 1; i >= 0; i--) { var ab = alienBullets[i]; ab.update(); // Remove if off screen if (ab.y > 2732 + ab.height) { ab.destroy(); alienBullets.splice(i, 1); continue; } // Check collision with player if (ab.intersects(player) && !player.invincible) { ab.destroy(); alienBullets.splice(i, 1); player.hit(); continue; } } // Update aliens var leftMost = 2048, rightMost = 0, bottomMost = 0; for (var i = 0; i < aliens.length; i++) { var a = aliens[i]; if (!a.alive) { continue; } a.update(); if (a.x < leftMost) { leftMost = a.x; } if (a.x > rightMost) { rightMost = a.x; } if (a.y > bottomMost) { bottomMost = a.y; } } // Aliens movement (all together) alienMoveTimer++; if (alienMoveTimer >= alienMoveInterval) { alienMoveTimer = 0; var moveX = alienMoveSpeed * alienMoveDir; var needReverse = false; // Check if any alien hits edge for (var i = 0; i < aliens.length; i++) { var a = aliens[i]; if (!a.alive) { continue; } var nextX = a.x + moveX; if (nextX < a.width / 2 + 40 || nextX > 2048 - a.width / 2 - 40) { needReverse = true; break; } } if (needReverse) { alienMoveDir *= -1; for (var i = 0; i < aliens.length; i++) { var a = aliens[i]; if (!a.alive) { continue; } a.y += 120; // Aliens move down more aggressively when changing direction // If any alien reaches bottom, game over if (a.y + a.height / 2 >= player.y - player.height / 2) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } } } else { for (var i = 0; i < aliens.length; i++) { var a = aliens[i]; if (!a.alive) { continue; } a.x += moveX; } } } // Remove dead aliens from array for (var i = aliens.length - 1; i >= 0; i--) { if (!aliens[i].alive && aliens[i].alpha === 0) { aliens.splice(i, 1); } } // If all aliens dead, next wave if (aliens.length === 0) { wave++; alienRows = Math.min(6, 3 + wave); alienCols = Math.min(10, 6 + wave); alienMoveSpeed = 10 + wave * 1.5; alienMoveInterval = Math.max(10, 30 - wave * 2); spawnAliens(); // Powerup drop var p = new Powerup(); p.x = 2048 / 2; p.y = 200; powerups.push(p); game.addChild(p); } // Powerup spawn powerupTimer++; if (powerupTimer >= powerupInterval) { powerupTimer = 0; var p = new Powerup(); p.x = 200 + Math.random() * (2048 - 400); p.y = 200; powerups.push(p); game.addChild(p); } // Update powerups for (var i = powerups.length - 1; i >= 0; i--) { var p = powerups[i]; p.update(); if (p.y > 2732 + p.height) { p.destroy(); powerups.splice(i, 1); continue; } if (p.intersects(player)) { player.collectPowerup(); // Flash the player ship yellow to indicate powerup LK.effects.flashObject(player, 0xffe14d, 400); // Create a shield effect around the player LK.effects.flashScreen(0xffe14d, 200); // Flash screen to show powerup effect // Show explosion at powerup location tween(p, { scaleX: 3, scaleY: 3, alpha: 0 }, { duration: 400 }); p.destroy(); powerups.splice(i, 1); continue; } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Alien enemy
var Alien = Container.expand(function () {
var self = Container.call(this);
var alien = self.attachAsset('alien', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = alien.width;
self.height = alien.height;
self.direction = 1; // 1: right, -1: left
self.speed = 3;
self.shootChance = 0.002; // increased chance per frame to shoot (4x more bullets)
self.row = 0;
self.col = 0;
self.alive = true;
self.update = function () {
// Movement handled by game for all aliens together
// Randomly shoot
if (Math.random() < self.shootChance && self.alive) {
self.shoot();
}
};
self.shoot = function () {
var bullet = new AlienBullet();
bullet.x = self.x;
bullet.y = self.y + self.height / 2 + bullet.height / 2;
alienBullets.push(bullet);
game.addChild(bullet);
LK.getSound('alienShoot').play();
};
self.hit = function () {
if (!self.alive) {
return;
}
self.alive = false;
tween(self, {
alpha: 0
}, {
duration: 200,
onFinish: function onFinish() {
self.destroy();
}
});
LK.getSound('explosion').play();
LK.setScore(LK.getScore() + 10);
scoreTxt.setText(LK.getScore());
};
return self;
});
// Alien bullet
var AlienBullet = Container.expand(function () {
var self = Container.call(this);
var bullet = self.attachAsset('alienBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = bullet.width;
self.height = bullet.height;
self.speed = 12; // Faster alien bullets
self.update = function () {
self.y += self.speed;
};
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.width = bullet.width;
self.height = bullet.height;
self.speed = -32;
self.update = function () {
self.y += self.speed;
};
return self;
});
// Player spaceship
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.canShoot = true;
self.shootCooldown = 20; // frames - longer cooldown between shots
self.cooldownTimer = 0;
self.lives = 3; // Reduced lives for harder gameplay
self.invincible = false;
self.invincibleTimer = 0;
self.update = function () {
if (!self.canShoot) {
self.cooldownTimer--;
if (self.cooldownTimer <= 0) {
self.canShoot = true;
}
}
if (self.invincible) {
self.invincibleTimer--;
// Add rotation effect to show invincibility
ship.rotation = Math.sin(LK.ticks * 0.1) * 0.1;
// Add flashing tint effect for invincibility visual feedback
if (LK.ticks % 10 < 5) {
ship.tint = 0xffe14d; // Yellow tint
} else {
ship.tint = 0xffffff; // Reset tint
}
if (self.invincibleTimer <= 0) {
self.invincible = false;
ship.alpha = 1;
ship.rotation = 0;
ship.tint = 0xffffff; // Reset tint when invincibility ends
}
} else {
// Reset effects when not invincible
ship.rotation = 0;
ship.tint = 0xffffff;
}
};
self.shoot = function () {
if (self.canShoot) {
var bullet = new PlayerBullet();
bullet.x = self.x;
bullet.y = self.y - self.height / 2 - bullet.height / 2;
playerBullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
self.canShoot = false;
self.cooldownTimer = self.shootCooldown;
}
};
self.hit = function () {
if (self.invincible) {
return;
}
self.lives--;
self.invincible = true;
self.invincibleTimer = 60; // Less invincibility time after getting hit
ship.alpha = 0.4;
LK.effects.flashObject(self, 0xff0000, 400);
if (self.lives <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
};
self.collectPowerup = function () {
self.lives++;
LK.getSound('powerup').play();
// Grant temporary invincibility for 3 seconds (180 frames)
self.invincible = true;
self.invincibleTimer = 180;
ship.alpha = 0.6;
// Create pulsing effect during invincibility
tween(ship, {
alpha: 0.3
}, {
duration: 500,
onFinish: function onFinish() {
tween(ship, {
alpha: 0.8
}, {
duration: 500,
onFinish: function onFinish() {
tween(ship, {
alpha: 0.3
}, {
duration: 500,
onFinish: function onFinish() {
tween(ship, {
alpha: 0.8
}, {
duration: 500,
onFinish: function onFinish() {
tween(ship, {
alpha: 0.3
}, {
duration: 500,
onFinish: function onFinish() {
tween(ship, {
alpha: 1
}, {
duration: 500
});
}
});
}
});
}
});
}
});
}
}); // Pulsing effect during invincibility
};
return self;
});
// Power-up
var Powerup = Container.expand(function () {
var self = Container.call(this);
var p = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.width = p.width;
self.height = p.height;
self.speed = 10;
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000010
});
/****
* Game Code
****/
// Play music
// Spaceship (player)
// Alien enemy
// Player bullet
// Alien bullet
// Power-up
// Sound effects
// Music
LK.playMusic('spaceMusic');
// Score display
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Lives display
var livesTxt = new Text2('♥♥♥', {
size: 90,
fill: 0xFF4D4D
});
livesTxt.anchor.set(1, 0);
livesTxt.x = -40;
LK.gui.topRight.addChild(livesTxt);
// Game variables
var player;
var playerBullets = [];
var alienBullets = [];
var aliens = [];
var powerups = [];
var alienRows = 4;
var alienCols = 8;
var alienSpacingX = 180;
var alienSpacingY = 140;
var alienStartY = 300;
var alienMoveDir = 1; // 1: right, -1: left
var alienMoveDown = false;
var alienMoveSpeed = 25; // faster horizontal movement
var alienMoveTimer = 0;
var alienMoveInterval = 20; // frames - quicker movement updates
var wave = 1;
var dragNode = null;
var lastTouchX = 0;
// Initialize player
player = new PlayerShip();
player.x = 2048 / 2;
player.y = 2732 - 180;
game.addChild(player);
// Initialize aliens
function spawnAliens() {
for (var row = 0; row < alienRows; row++) {
for (var col = 0; col < alienCols; col++) {
var alien = new Alien();
alien.x = 2048 / 2 - (alienCols - 1) * alienSpacingX / 2 + col * alienSpacingX;
alien.y = alienStartY + row * alienSpacingY;
alien.row = row;
alien.col = col;
aliens.push(alien);
game.addChild(alien);
}
}
}
spawnAliens();
// Powerup spawn timer
var powerupTimer = 0;
var powerupInterval = 600; // frames - less frequent powerups
// Touch/move controls
game.down = function (x, y, obj) {
// Always move ship X to cursor/touch X, regardless of Y
player.x = x;
// Clamp to screen
if (player.x < player.width / 2) {
player.x = player.width / 2;
}
if (player.x > 2048 - player.width / 2) {
player.x = 2048 - player.width / 2;
}
};
// No dragNode needed for this control scheme
game.move = function (x, y, obj) {
// Always move ship X to cursor/touch X, regardless of Y
player.x = x;
// Clamp to screen
if (player.x < player.width / 2) {
player.x = player.width / 2;
}
if (player.x > 2048 - player.width / 2) {
player.x = 2048 - player.width / 2;
}
};
// Tap to shoot if not in bottom 1/3
game.up = function (x, y, obj) {
if (y <= 2732 * 0.7) {
player.shoot();
}
};
// Main update loop
game.update = function () {
// Update player
player.update();
// Update lives display
var livesStr = '';
for (var i = 0; i < player.lives; i++) {
livesStr += '♥';
}
livesTxt.setText(livesStr);
// Update player bullets
for (var i = playerBullets.length - 1; i >= 0; i--) {
var b = playerBullets[i];
b.update();
// Remove if off screen
if (b.y < -b.height) {
b.destroy();
playerBullets.splice(i, 1);
continue;
}
// Check collision with aliens
for (var j = 0; j < aliens.length; j++) {
var a = aliens[j];
if (a.alive && b.intersects(a)) {
a.hit();
b.destroy();
playerBullets.splice(i, 1);
break;
}
}
}
// Update alien bullets
for (var i = alienBullets.length - 1; i >= 0; i--) {
var ab = alienBullets[i];
ab.update();
// Remove if off screen
if (ab.y > 2732 + ab.height) {
ab.destroy();
alienBullets.splice(i, 1);
continue;
}
// Check collision with player
if (ab.intersects(player) && !player.invincible) {
ab.destroy();
alienBullets.splice(i, 1);
player.hit();
continue;
}
}
// Update aliens
var leftMost = 2048,
rightMost = 0,
bottomMost = 0;
for (var i = 0; i < aliens.length; i++) {
var a = aliens[i];
if (!a.alive) {
continue;
}
a.update();
if (a.x < leftMost) {
leftMost = a.x;
}
if (a.x > rightMost) {
rightMost = a.x;
}
if (a.y > bottomMost) {
bottomMost = a.y;
}
}
// Aliens movement (all together)
alienMoveTimer++;
if (alienMoveTimer >= alienMoveInterval) {
alienMoveTimer = 0;
var moveX = alienMoveSpeed * alienMoveDir;
var needReverse = false;
// Check if any alien hits edge
for (var i = 0; i < aliens.length; i++) {
var a = aliens[i];
if (!a.alive) {
continue;
}
var nextX = a.x + moveX;
if (nextX < a.width / 2 + 40 || nextX > 2048 - a.width / 2 - 40) {
needReverse = true;
break;
}
}
if (needReverse) {
alienMoveDir *= -1;
for (var i = 0; i < aliens.length; i++) {
var a = aliens[i];
if (!a.alive) {
continue;
}
a.y += 120; // Aliens move down more aggressively when changing direction
// If any alien reaches bottom, game over
if (a.y + a.height / 2 >= player.y - player.height / 2) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
} else {
for (var i = 0; i < aliens.length; i++) {
var a = aliens[i];
if (!a.alive) {
continue;
}
a.x += moveX;
}
}
}
// Remove dead aliens from array
for (var i = aliens.length - 1; i >= 0; i--) {
if (!aliens[i].alive && aliens[i].alpha === 0) {
aliens.splice(i, 1);
}
}
// If all aliens dead, next wave
if (aliens.length === 0) {
wave++;
alienRows = Math.min(6, 3 + wave);
alienCols = Math.min(10, 6 + wave);
alienMoveSpeed = 10 + wave * 1.5;
alienMoveInterval = Math.max(10, 30 - wave * 2);
spawnAliens();
// Powerup drop
var p = new Powerup();
p.x = 2048 / 2;
p.y = 200;
powerups.push(p);
game.addChild(p);
}
// Powerup spawn
powerupTimer++;
if (powerupTimer >= powerupInterval) {
powerupTimer = 0;
var p = new Powerup();
p.x = 200 + Math.random() * (2048 - 400);
p.y = 200;
powerups.push(p);
game.addChild(p);
}
// Update powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var p = powerups[i];
p.update();
if (p.y > 2732 + p.height) {
p.destroy();
powerups.splice(i, 1);
continue;
}
if (p.intersects(player)) {
player.collectPowerup();
// Flash the player ship yellow to indicate powerup
LK.effects.flashObject(player, 0xffe14d, 400);
// Create a shield effect around the player
LK.effects.flashScreen(0xffe14d, 200); // Flash screen to show powerup effect
// Show explosion at powerup location
tween(p, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 400
});
p.destroy();
powerups.splice(i, 1);
continue;
}
}
};