/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var Meteor = Container.expand(function () { var self = Container.call(this); var meteorGraphics = self.attachAsset('meteor', { anchorX: 0.5, anchorY: 0.5 }); self.speedX = (Math.random() - 0.5) * 4; // Random horizontal drift self.speedY = Math.random() * 3 + 2; // Downward speed self.rotationSpeed = (Math.random() - 0.5) * 0.2; self.update = function () { self.x += self.speedX; self.y += self.speedY; self.rotation += self.rotationSpeed; }; return self; }); var Particle = Container.expand(function () { var self = Container.call(this); var particleGraphics = self.attachAsset('particle', { anchorX: 0.5, anchorY: 0.5 }); self.velocityX = (Math.random() - 0.5) * 10; self.velocityY = (Math.random() - 0.5) * 10; self.life = 1.0; self.decay = Math.random() * 0.02 + 0.01; self.update = function () { self.x += self.velocityX; self.y += self.velocityY; self.life -= self.decay; self.alpha = self.life; if (self.life <= 0) { self.destroy(); } }; return self; }); var Shield = Container.expand(function () { var self = Container.call(this); var shieldGraphics = self.attachAsset('shield', { anchorX: 0.5, anchorY: 0.5 }); // Glow effect shieldGraphics.alpha = 0.9; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x0a0a20 }); /**** * Game Code ****/ game.setBackgroundColor(0x0a0a20); // Game variables var meteors = []; var particles = []; var shield; var spaceStation; var meteorSpawnTimer = 0; var meteorSpawnDelay = 120; // Start with 2 seconds at 60fps var waveNumber = 1; var consecutiveHits = 0; var screenShakeTimer = 0; var gameStarted = false; // UI Elements var scoreTxt = new Text2('0', { size: 100, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var waveTxt = new Text2('Wave 1', { size: 60, fill: 0x00D9FF }); waveTxt.anchor.set(0, 0); waveTxt.x = 100; waveTxt.y = 150; LK.gui.topLeft.addChild(waveTxt); // Create space station spaceStation = game.addChild(LK.getAsset('spaceStation', { anchorX: 0.5, anchorY: 1.0 })); spaceStation.x = 2048 / 2; spaceStation.y = 2732 - 50; // Create shield shield = game.addChild(new Shield()); shield.x = 2048 / 2; shield.y = 2732 - 400; // Screen shake effect function applyScreenShake() { if (screenShakeTimer > 0) { game.x = (Math.random() - 0.5) * screenShakeTimer * 2; game.y = (Math.random() - 0.5) * screenShakeTimer * 2; screenShakeTimer--; } else { game.x = 0; game.y = 0; } } // Create explosion particles function createExplosion(x, y, count) { for (var i = 0; i < count; i++) { var particle = new Particle(); particle.x = x + (Math.random() - 0.5) * 50; particle.y = y + (Math.random() - 0.5) * 50; particles.push(particle); game.addChild(particle); } } // Spawn meteor function spawnMeteor() { var meteor = new Meteor(); meteor.x = Math.random() * 2048; meteor.y = -100; // Increase speed based on wave meteor.speedY += waveNumber * 0.5; meteors.push(meteor); game.addChild(meteor); } // Handle dragging var dragOffset = 0; function handleMove(x, y, obj) { if (gameStarted) { shield.x = x; // Keep shield within screen bounds if (shield.x < 150) shield.x = 150; if (shield.x > 2048 - 150) shield.x = 2048 - 150; } } game.move = handleMove; game.down = function (x, y, obj) { if (!gameStarted) { gameStarted = true; } dragOffset = shield.x - x; handleMove(x + dragOffset, y, obj); }; game.up = function (x, y, obj) { // Nothing specific on release }; // Main game update loop game.update = function () { applyScreenShake(); if (!gameStarted) { return; } // Spawn meteors meteorSpawnTimer++; if (meteorSpawnTimer >= meteorSpawnDelay) { spawnMeteor(); meteorSpawnTimer = 0; // Gradually increase spawn rate if (meteorSpawnDelay > 30) { meteorSpawnDelay -= 0.5; } } // Update meteors for (var i = meteors.length - 1; i >= 0; i--) { var meteor = meteors[i]; if (meteor.lastY === undefined) meteor.lastY = meteor.y; if (meteor.lastIntersectingShield === undefined) meteor.lastIntersectingShield = false; if (meteor.lastIntersectingStation === undefined) meteor.lastIntersectingStation = false; // Check collision with shield var currentIntersectingShield = meteor.intersects(shield); if (!meteor.lastIntersectingShield && currentIntersectingShield) { // Meteor hit shield - deflect it meteor.speedY = -Math.abs(meteor.speedY) * 0.8; // Bounce up meteor.speedX += (Math.random() - 0.5) * 6; // Add random horizontal velocity // Score and effects consecutiveHits++; var points = 10 + consecutiveHits * 5; LK.setScore(LK.getScore() + points); scoreTxt.setText(LK.getScore()); // Visual effects LK.effects.flashScreen(0x00d9ff, 200); screenShakeTimer = 5; createExplosion(meteor.x, meteor.y, 8); LK.getSound('deflect').play(); } // Check collision with space station var currentIntersectingStation = meteor.intersects(spaceStation); if (!meteor.lastIntersectingStation && currentIntersectingStation) { // Game Over LK.effects.flashScreen(0xff0000, 1500); screenShakeTimer = 20; createExplosion(meteor.x, meteor.y, 15); LK.getSound('explode').play(); LK.showGameOver(); return; } // Remove meteors that are off screen if (meteor.y > 2732 + 100 || meteor.y < -200) { if (meteor.y > 2732 + 100) { consecutiveHits = 0; // Reset combo if meteor reaches bottom } meteor.destroy(); meteors.splice(i, 1); continue; } // Remove meteors that are too far horizontally if (meteor.x < -200 || meteor.x > 2048 + 200) { meteor.destroy(); meteors.splice(i, 1); continue; } meteor.lastY = meteor.y; meteor.lastIntersectingShield = currentIntersectingShield; meteor.lastIntersectingStation = currentIntersectingStation; } // Update particles for (var j = particles.length - 1; j >= 0; j--) { var particle = particles[j]; if (particle.life <= 0) { particles.splice(j, 1); } } // Wave progression if (LK.ticks % 1800 === 0 && LK.ticks > 0) { // Every 30 seconds waveNumber++; waveTxt.setText('Wave ' + waveNumber); // Flash wave indicator tween(waveTxt, { scaleX: 1.5, scaleY: 1.5 }, { duration: 300, easing: tween.easeOut }); tween(waveTxt, { scaleX: 1.0, scaleY: 1.0 }, { duration: 300, easing: tween.easeIn }); } // Shield glow effect var glowIntensity = 0.7 + Math.sin(LK.ticks * 0.1) * 0.2; shield.alpha = glowIntensity; };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Meteor = Container.expand(function () {
var self = Container.call(this);
var meteorGraphics = self.attachAsset('meteor', {
anchorX: 0.5,
anchorY: 0.5
});
self.speedX = (Math.random() - 0.5) * 4; // Random horizontal drift
self.speedY = Math.random() * 3 + 2; // Downward speed
self.rotationSpeed = (Math.random() - 0.5) * 0.2;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
self.rotation += self.rotationSpeed;
};
return self;
});
var Particle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = (Math.random() - 0.5) * 10;
self.velocityY = (Math.random() - 0.5) * 10;
self.life = 1.0;
self.decay = Math.random() * 0.02 + 0.01;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.life -= self.decay;
self.alpha = self.life;
if (self.life <= 0) {
self.destroy();
}
};
return self;
});
var Shield = Container.expand(function () {
var self = Container.call(this);
var shieldGraphics = self.attachAsset('shield', {
anchorX: 0.5,
anchorY: 0.5
});
// Glow effect
shieldGraphics.alpha = 0.9;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0a0a20
});
/****
* Game Code
****/
game.setBackgroundColor(0x0a0a20);
// Game variables
var meteors = [];
var particles = [];
var shield;
var spaceStation;
var meteorSpawnTimer = 0;
var meteorSpawnDelay = 120; // Start with 2 seconds at 60fps
var waveNumber = 1;
var consecutiveHits = 0;
var screenShakeTimer = 0;
var gameStarted = false;
// UI Elements
var scoreTxt = new Text2('0', {
size: 100,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var waveTxt = new Text2('Wave 1', {
size: 60,
fill: 0x00D9FF
});
waveTxt.anchor.set(0, 0);
waveTxt.x = 100;
waveTxt.y = 150;
LK.gui.topLeft.addChild(waveTxt);
// Create space station
spaceStation = game.addChild(LK.getAsset('spaceStation', {
anchorX: 0.5,
anchorY: 1.0
}));
spaceStation.x = 2048 / 2;
spaceStation.y = 2732 - 50;
// Create shield
shield = game.addChild(new Shield());
shield.x = 2048 / 2;
shield.y = 2732 - 400;
// Screen shake effect
function applyScreenShake() {
if (screenShakeTimer > 0) {
game.x = (Math.random() - 0.5) * screenShakeTimer * 2;
game.y = (Math.random() - 0.5) * screenShakeTimer * 2;
screenShakeTimer--;
} else {
game.x = 0;
game.y = 0;
}
}
// Create explosion particles
function createExplosion(x, y, count) {
for (var i = 0; i < count; i++) {
var particle = new Particle();
particle.x = x + (Math.random() - 0.5) * 50;
particle.y = y + (Math.random() - 0.5) * 50;
particles.push(particle);
game.addChild(particle);
}
}
// Spawn meteor
function spawnMeteor() {
var meteor = new Meteor();
meteor.x = Math.random() * 2048;
meteor.y = -100;
// Increase speed based on wave
meteor.speedY += waveNumber * 0.5;
meteors.push(meteor);
game.addChild(meteor);
}
// Handle dragging
var dragOffset = 0;
function handleMove(x, y, obj) {
if (gameStarted) {
shield.x = x;
// Keep shield within screen bounds
if (shield.x < 150) shield.x = 150;
if (shield.x > 2048 - 150) shield.x = 2048 - 150;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
if (!gameStarted) {
gameStarted = true;
}
dragOffset = shield.x - x;
handleMove(x + dragOffset, y, obj);
};
game.up = function (x, y, obj) {
// Nothing specific on release
};
// Main game update loop
game.update = function () {
applyScreenShake();
if (!gameStarted) {
return;
}
// Spawn meteors
meteorSpawnTimer++;
if (meteorSpawnTimer >= meteorSpawnDelay) {
spawnMeteor();
meteorSpawnTimer = 0;
// Gradually increase spawn rate
if (meteorSpawnDelay > 30) {
meteorSpawnDelay -= 0.5;
}
}
// Update meteors
for (var i = meteors.length - 1; i >= 0; i--) {
var meteor = meteors[i];
if (meteor.lastY === undefined) meteor.lastY = meteor.y;
if (meteor.lastIntersectingShield === undefined) meteor.lastIntersectingShield = false;
if (meteor.lastIntersectingStation === undefined) meteor.lastIntersectingStation = false;
// Check collision with shield
var currentIntersectingShield = meteor.intersects(shield);
if (!meteor.lastIntersectingShield && currentIntersectingShield) {
// Meteor hit shield - deflect it
meteor.speedY = -Math.abs(meteor.speedY) * 0.8; // Bounce up
meteor.speedX += (Math.random() - 0.5) * 6; // Add random horizontal velocity
// Score and effects
consecutiveHits++;
var points = 10 + consecutiveHits * 5;
LK.setScore(LK.getScore() + points);
scoreTxt.setText(LK.getScore());
// Visual effects
LK.effects.flashScreen(0x00d9ff, 200);
screenShakeTimer = 5;
createExplosion(meteor.x, meteor.y, 8);
LK.getSound('deflect').play();
}
// Check collision with space station
var currentIntersectingStation = meteor.intersects(spaceStation);
if (!meteor.lastIntersectingStation && currentIntersectingStation) {
// Game Over
LK.effects.flashScreen(0xff0000, 1500);
screenShakeTimer = 20;
createExplosion(meteor.x, meteor.y, 15);
LK.getSound('explode').play();
LK.showGameOver();
return;
}
// Remove meteors that are off screen
if (meteor.y > 2732 + 100 || meteor.y < -200) {
if (meteor.y > 2732 + 100) {
consecutiveHits = 0; // Reset combo if meteor reaches bottom
}
meteor.destroy();
meteors.splice(i, 1);
continue;
}
// Remove meteors that are too far horizontally
if (meteor.x < -200 || meteor.x > 2048 + 200) {
meteor.destroy();
meteors.splice(i, 1);
continue;
}
meteor.lastY = meteor.y;
meteor.lastIntersectingShield = currentIntersectingShield;
meteor.lastIntersectingStation = currentIntersectingStation;
}
// Update particles
for (var j = particles.length - 1; j >= 0; j--) {
var particle = particles[j];
if (particle.life <= 0) {
particles.splice(j, 1);
}
}
// Wave progression
if (LK.ticks % 1800 === 0 && LK.ticks > 0) {
// Every 30 seconds
waveNumber++;
waveTxt.setText('Wave ' + waveNumber);
// Flash wave indicator
tween(waveTxt, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeOut
});
tween(waveTxt, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300,
easing: tween.easeIn
});
}
// Shield glow effect
var glowIntensity = 0.7 + Math.sin(LK.ticks * 0.1) * 0.2;
shield.alpha = glowIntensity;
};