/****
* 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;
};