/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Bullet class var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGfx = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = -48; // Fast upward self.update = function () { self.y += self.speed; }; return self; }); // Crosshair class (visual only) var Crosshair = Container.expand(function () { var self = Container.call(this); var crossGfx = self.attachAsset('crosshair', { anchorX: 0.5, anchorY: 0.5 }); crossGfx.alpha = 0.4; return self; }); // Enemy class var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGfx = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6 + Math.random() * 6; // Varying speed self.update = function () { self.y += self.speed; }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x181818 }); /**** * Game Code ****/ // Music (optional, will not play by default) // Sound for enemy escape // Sound for enemy hit // Sound for shooting // Crosshair: Green ellipse, thin // Bullet: Yellow box, small // Enemy: Red ellipse, medium size // Game variables var bullets = []; var enemies = []; var crosshair = null; var score = 0; var missed = 0; var maxMissed = 5; var spawnInterval = 60; // frames between spawns, will decrease var lastSpawnTick = 0; var dragAiming = false; // Score display var scoreTxt = new Text2('0', { size: 120, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Missed display (bottom center) var missedTxt = new Text2('', { size: 90, fill: 0xFF4444 }); missedTxt.anchor.set(0.5, 1); LK.gui.bottom.addChild(missedTxt); // Crosshair crosshair = new Crosshair(); game.addChild(crosshair); crosshair.x = 2048 / 2; crosshair.y = 2732 * 0.8; // Helper: update UI function updateUI() { scoreTxt.setText(score); missedTxt.setText(missed > 0 ? "Missed: " + missed + "/" + maxMissed : ""); } // Helper: spawn enemy at random x function spawnEnemy() { var enemy = new Enemy(); var margin = 120; enemy.x = margin + Math.random() * (2048 - 2 * margin); enemy.y = -80; enemies.push(enemy); game.addChild(enemy); } // Helper: fire bullet from crosshair function fireBullet(x, y) { var bullet = new Bullet(); bullet.x = x; bullet.y = y; bullets.push(bullet); game.addChild(bullet); LK.getSound('shoot').play(); } // Touch controls game.down = function (x, y, obj) { // Move crosshair to touch, fire crosshair.x = x; crosshair.y = y; fireBullet(x, y); dragAiming = true; }; game.move = function (x, y, obj) { if (dragAiming) { crosshair.x = x; crosshair.y = y; } }; game.up = function (x, y, obj) { dragAiming = false; }; // Main update loop game.update = function () { // Spawn enemies if (LK.ticks - lastSpawnTick >= spawnInterval) { spawnEnemy(); lastSpawnTick = LK.ticks; // Increase difficulty if (spawnInterval > 24) { spawnInterval -= 1; } } // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { var b = bullets[i]; b.update(); // Remove if off screen if (b.y < -100) { b.destroy(); bullets.splice(i, 1); continue; } } // Update enemies for (var j = enemies.length - 1; j >= 0; j--) { var e = enemies[j]; e.update(); // Check if enemy reached bottom if (e.y > 2732 + 100) { e.destroy(); enemies.splice(j, 1); missed += 1; updateUI(); LK.getSound('fail').play(); // Game over if too many missed if (missed >= maxMissed) { LK.effects.flashScreen(0xff0000, 800); LK.showGameOver(); return; } continue; } // Check collision with bullets var hit = false; for (var k = bullets.length - 1; k >= 0; k--) { var b2 = bullets[k]; if (e.intersects(b2)) { // Hit! hit = true; score += 1; updateUI(); LK.getSound('hit').play(); // Remove both e.destroy(); b2.destroy(); enemies.splice(j, 1); bullets.splice(k, 1); // Win condition if (score >= 30) { LK.effects.flashScreen(0x44ff44, 800); LK.showYouWin(); return; } break; } } if (hit) continue; } }; // Initial UI updateUI();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Bullet class
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGfx = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -48; // Fast upward
self.update = function () {
self.y += self.speed;
};
return self;
});
// Crosshair class (visual only)
var Crosshair = Container.expand(function () {
var self = Container.call(this);
var crossGfx = self.attachAsset('crosshair', {
anchorX: 0.5,
anchorY: 0.5
});
crossGfx.alpha = 0.4;
return self;
});
// Enemy class
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGfx = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6 + Math.random() * 6; // Varying speed
self.update = function () {
self.y += self.speed;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x181818
});
/****
* Game Code
****/
// Music (optional, will not play by default)
// Sound for enemy escape
// Sound for enemy hit
// Sound for shooting
// Crosshair: Green ellipse, thin
// Bullet: Yellow box, small
// Enemy: Red ellipse, medium size
// Game variables
var bullets = [];
var enemies = [];
var crosshair = null;
var score = 0;
var missed = 0;
var maxMissed = 5;
var spawnInterval = 60; // frames between spawns, will decrease
var lastSpawnTick = 0;
var dragAiming = false;
// Score display
var scoreTxt = new Text2('0', {
size: 120,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Missed display (bottom center)
var missedTxt = new Text2('', {
size: 90,
fill: 0xFF4444
});
missedTxt.anchor.set(0.5, 1);
LK.gui.bottom.addChild(missedTxt);
// Crosshair
crosshair = new Crosshair();
game.addChild(crosshair);
crosshair.x = 2048 / 2;
crosshair.y = 2732 * 0.8;
// Helper: update UI
function updateUI() {
scoreTxt.setText(score);
missedTxt.setText(missed > 0 ? "Missed: " + missed + "/" + maxMissed : "");
}
// Helper: spawn enemy at random x
function spawnEnemy() {
var enemy = new Enemy();
var margin = 120;
enemy.x = margin + Math.random() * (2048 - 2 * margin);
enemy.y = -80;
enemies.push(enemy);
game.addChild(enemy);
}
// Helper: fire bullet from crosshair
function fireBullet(x, y) {
var bullet = new Bullet();
bullet.x = x;
bullet.y = y;
bullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
}
// Touch controls
game.down = function (x, y, obj) {
// Move crosshair to touch, fire
crosshair.x = x;
crosshair.y = y;
fireBullet(x, y);
dragAiming = true;
};
game.move = function (x, y, obj) {
if (dragAiming) {
crosshair.x = x;
crosshair.y = y;
}
};
game.up = function (x, y, obj) {
dragAiming = false;
};
// Main update loop
game.update = function () {
// Spawn enemies
if (LK.ticks - lastSpawnTick >= spawnInterval) {
spawnEnemy();
lastSpawnTick = LK.ticks;
// Increase difficulty
if (spawnInterval > 24) {
spawnInterval -= 1;
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var b = bullets[i];
b.update();
// Remove if off screen
if (b.y < -100) {
b.destroy();
bullets.splice(i, 1);
continue;
}
}
// Update enemies
for (var j = enemies.length - 1; j >= 0; j--) {
var e = enemies[j];
e.update();
// Check if enemy reached bottom
if (e.y > 2732 + 100) {
e.destroy();
enemies.splice(j, 1);
missed += 1;
updateUI();
LK.getSound('fail').play();
// Game over if too many missed
if (missed >= maxMissed) {
LK.effects.flashScreen(0xff0000, 800);
LK.showGameOver();
return;
}
continue;
}
// Check collision with bullets
var hit = false;
for (var k = bullets.length - 1; k >= 0; k--) {
var b2 = bullets[k];
if (e.intersects(b2)) {
// Hit!
hit = true;
score += 1;
updateUI();
LK.getSound('hit').play();
// Remove both
e.destroy();
b2.destroy();
enemies.splice(j, 1);
bullets.splice(k, 1);
// Win condition
if (score >= 30) {
LK.effects.flashScreen(0x44ff44, 800);
LK.showYouWin();
return;
}
break;
}
}
if (hit) continue;
}
};
// Initial UI
updateUI();