/**** * Classes ****/ // Archer class: ranged unit, attacks enemies in range var Archer = Container.expand(function () { var self = Container.call(this); var archerSprite = self.attachAsset('archer', { anchorX: 0.5, anchorY: 0.5 }); self.range = 500; self.attackCooldown = 60; self.cooldown = 0; self.update = function () { if (self.cooldown > 0) self.cooldown--; for (var i = 0; i < enemies.length; i++) { var e = enemies[i]; var dx = e.x - self.x; var dy = e.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < self.range && self.cooldown === 0) { // Remove enemy e.destroy(); enemies.splice(i, 1); LK.setScore(LK.getScore() + 1); self.cooldown = self.attackCooldown; break; } } }; return self; }); // Arrays to track all units and enemies // Enemy class: moves from top to bottom, tracks lastY for event triggers var Enemy = Container.expand(function () { var self = Container.call(this); var enemySprite = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 6 + Math.random() * 2; // Vary speed a bit self.lastY = self.y; self.update = function () { self.lastY = self.y; self.y += self.speed; }; return self; }); // Legionnaire class: melee unit, attacks enemies in range var Legionnaire = Container.expand(function () { var self = Container.call(this); var legionSprite = self.attachAsset('legionnaire', { anchorX: 0.5, anchorY: 0.5 }); self.range = 180; self.attackCooldown = 30; self.cooldown = 0; self.update = function () { if (self.cooldown > 0) self.cooldown--; for (var i = 0; i < enemies.length; i++) { var e = enemies[i]; var dx = e.x - self.x; var dy = e.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < self.range && self.cooldown === 0) { // Remove enemy e.destroy(); enemies.splice(i, 1); LK.setScore(LK.getScore() + 1); self.cooldown = self.attackCooldown; break; } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000000 }); /**** * Game Code ****/ // Add background image to the game scene var background = LK.getAsset('background', { anchorX: 0, anchorY: 0, x: 0, y: 0 }); game.addChild(background); // Arrays to track all units and enemies var enemies = []; var legionnaires = []; var archers = []; var fortressHealth = 10; var spawnTimer = 0; var deployMode = null; // 'legionnaire' or 'archer' var draggingUnit = null; var reserveLegionnaires = 3; var reserveArchers = 2; // Score display var scoreTxt = new Text2('0', { size: 100, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); scoreTxt.y = 0; LK.gui.top.addChild(scoreTxt); // Fortress health display var healthTxt = new Text2('Fortress: ' + fortressHealth, { size: 80, fill: 0xFFB300 }); healthTxt.anchor.set(0, 0); healthTxt.y = 110; // Add vertical spacing below score LK.gui.top.addChild(healthTxt); healthTxt.x = 120; // Unit reserve display var legionReserveTxt = new Text2('Legionnaires: ' + reserveLegionnaires, { size: 70, fill: "#fff" }); legionReserveTxt.anchor.set(0, 0); legionReserveTxt.y = 200; // Add vertical spacing below health LK.gui.top.addChild(legionReserveTxt); legionReserveTxt.x = 400; var archerReserveTxt = new Text2('Archers: ' + reserveArchers, { size: 70, fill: "#fff" }); archerReserveTxt.anchor.set(0, 0); archerReserveTxt.y = 200; // Align with legionReserveTxt LK.gui.top.addChild(archerReserveTxt); archerReserveTxt.x = 900; // Reserve area for dragging units var legionReserveIcon = LK.getAsset('legionnaire', { anchorX: 0.5, anchorY: 0.5, x: 200, y: 2400 //{1i} // moved up to ensure visibility }); game.addChild(legionReserveIcon); var archerReserveIcon = LK.getAsset('archer', { anchorX: 0.5, anchorY: 0.5, x: 400, y: 2400 //{1m} // moved up to ensure visibility }); game.addChild(archerReserveIcon); // Drag logic game.down = function (x, y, obj) { // Only allow dragging from reserve if units available if (Math.abs(x - legionReserveIcon.x) < 100 && Math.abs(y - legionReserveIcon.y) < 100 && reserveLegionnaires > 0) { deployMode = 'legionnaire'; draggingUnit = LK.getAsset('legionnaire', { anchorX: 0.5, anchorY: 0.5, x: x, y: y }); game.addChild(draggingUnit); } else if (Math.abs(x - archerReserveIcon.x) < 100 && Math.abs(y - archerReserveIcon.y) < 100 && reserveArchers > 0) { deployMode = 'archer'; draggingUnit = LK.getAsset('archer', { anchorX: 0.5, anchorY: 0.5, x: x, y: y }); game.addChild(draggingUnit); } }; game.move = function (x, y, obj) { if (draggingUnit) { draggingUnit.x = x; draggingUnit.y = y; } }; game.up = function (x, y, obj) { if (draggingUnit && deployMode) { // Only allow deployment in battlefield area (not on reserve) if (y < 2400) { if (deployMode === 'legionnaire' && reserveLegionnaires > 0) { var l = new Legionnaire(); l.x = x; l.y = y; legionnaires.push(l); game.addChild(l); reserveLegionnaires--; legionReserveTxt.setText('Legionnaires: ' + reserveLegionnaires); } else if (deployMode === 'archer' && reserveArchers > 0) { var a = new Archer(); a.x = x; a.y = y; archers.push(a); game.addChild(a); reserveArchers--; archerReserveTxt.setText('Archers: ' + reserveArchers); } } draggingUnit.destroy(); draggingUnit = null; deployMode = null; } }; game.update = function () { // Spawn enemies every 60 ticks spawnTimer++; if (spawnTimer >= 60) { spawnTimer = 0; var e = new Enemy(); e.x = 200 + Math.random() * 1648; e.y = -60; enemies.push(e); game.addChild(e); } // Update all enemies for (var i = enemies.length - 1; i >= 0; i--) { var e = enemies[i]; e.update(); // Check if enemy reached fortress (bottom) if (e.lastY < 2650 && e.y >= 2650) { fortressHealth--; healthTxt.setText('Fortress: ' + fortressHealth); e.destroy(); enemies.splice(i, 1); if (fortressHealth <= 0) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } } } // Update all legionnaires for (var i = 0; i < legionnaires.length; i++) { legionnaires[i].update(); } // Update all archers for (var i = 0; i < archers.length; i++) { archers[i].update(); } // Update score scoreTxt.setText(LK.getScore()); // Win condition: 30 points if (LK.getScore() >= 30) { LK.effects.flashScreen(0x00ff00, 1000); LK.showYouWin(); } };
/****
* Classes
****/
// Archer class: ranged unit, attacks enemies in range
var Archer = Container.expand(function () {
var self = Container.call(this);
var archerSprite = self.attachAsset('archer', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 500;
self.attackCooldown = 60;
self.cooldown = 0;
self.update = function () {
if (self.cooldown > 0) self.cooldown--;
for (var i = 0; i < enemies.length; i++) {
var e = enemies[i];
var dx = e.x - self.x;
var dy = e.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < self.range && self.cooldown === 0) {
// Remove enemy
e.destroy();
enemies.splice(i, 1);
LK.setScore(LK.getScore() + 1);
self.cooldown = self.attackCooldown;
break;
}
}
};
return self;
});
// Arrays to track all units and enemies
// Enemy class: moves from top to bottom, tracks lastY for event triggers
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemySprite = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6 + Math.random() * 2; // Vary speed a bit
self.lastY = self.y;
self.update = function () {
self.lastY = self.y;
self.y += self.speed;
};
return self;
});
// Legionnaire class: melee unit, attacks enemies in range
var Legionnaire = Container.expand(function () {
var self = Container.call(this);
var legionSprite = self.attachAsset('legionnaire', {
anchorX: 0.5,
anchorY: 0.5
});
self.range = 180;
self.attackCooldown = 30;
self.cooldown = 0;
self.update = function () {
if (self.cooldown > 0) self.cooldown--;
for (var i = 0; i < enemies.length; i++) {
var e = enemies[i];
var dx = e.x - self.x;
var dy = e.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < self.range && self.cooldown === 0) {
// Remove enemy
e.destroy();
enemies.splice(i, 1);
LK.setScore(LK.getScore() + 1);
self.cooldown = self.attackCooldown;
break;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Add background image to the game scene
var background = LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
game.addChild(background);
// Arrays to track all units and enemies
var enemies = [];
var legionnaires = [];
var archers = [];
var fortressHealth = 10;
var spawnTimer = 0;
var deployMode = null; // 'legionnaire' or 'archer'
var draggingUnit = null;
var reserveLegionnaires = 3;
var reserveArchers = 2;
// Score display
var scoreTxt = new Text2('0', {
size: 100,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
scoreTxt.y = 0;
LK.gui.top.addChild(scoreTxt);
// Fortress health display
var healthTxt = new Text2('Fortress: ' + fortressHealth, {
size: 80,
fill: 0xFFB300
});
healthTxt.anchor.set(0, 0);
healthTxt.y = 110; // Add vertical spacing below score
LK.gui.top.addChild(healthTxt);
healthTxt.x = 120;
// Unit reserve display
var legionReserveTxt = new Text2('Legionnaires: ' + reserveLegionnaires, {
size: 70,
fill: "#fff"
});
legionReserveTxt.anchor.set(0, 0);
legionReserveTxt.y = 200; // Add vertical spacing below health
LK.gui.top.addChild(legionReserveTxt);
legionReserveTxt.x = 400;
var archerReserveTxt = new Text2('Archers: ' + reserveArchers, {
size: 70,
fill: "#fff"
});
archerReserveTxt.anchor.set(0, 0);
archerReserveTxt.y = 200; // Align with legionReserveTxt
LK.gui.top.addChild(archerReserveTxt);
archerReserveTxt.x = 900;
// Reserve area for dragging units
var legionReserveIcon = LK.getAsset('legionnaire', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: 2400 //{1i} // moved up to ensure visibility
});
game.addChild(legionReserveIcon);
var archerReserveIcon = LK.getAsset('archer', {
anchorX: 0.5,
anchorY: 0.5,
x: 400,
y: 2400 //{1m} // moved up to ensure visibility
});
game.addChild(archerReserveIcon);
// Drag logic
game.down = function (x, y, obj) {
// Only allow dragging from reserve if units available
if (Math.abs(x - legionReserveIcon.x) < 100 && Math.abs(y - legionReserveIcon.y) < 100 && reserveLegionnaires > 0) {
deployMode = 'legionnaire';
draggingUnit = LK.getAsset('legionnaire', {
anchorX: 0.5,
anchorY: 0.5,
x: x,
y: y
});
game.addChild(draggingUnit);
} else if (Math.abs(x - archerReserveIcon.x) < 100 && Math.abs(y - archerReserveIcon.y) < 100 && reserveArchers > 0) {
deployMode = 'archer';
draggingUnit = LK.getAsset('archer', {
anchorX: 0.5,
anchorY: 0.5,
x: x,
y: y
});
game.addChild(draggingUnit);
}
};
game.move = function (x, y, obj) {
if (draggingUnit) {
draggingUnit.x = x;
draggingUnit.y = y;
}
};
game.up = function (x, y, obj) {
if (draggingUnit && deployMode) {
// Only allow deployment in battlefield area (not on reserve)
if (y < 2400) {
if (deployMode === 'legionnaire' && reserveLegionnaires > 0) {
var l = new Legionnaire();
l.x = x;
l.y = y;
legionnaires.push(l);
game.addChild(l);
reserveLegionnaires--;
legionReserveTxt.setText('Legionnaires: ' + reserveLegionnaires);
} else if (deployMode === 'archer' && reserveArchers > 0) {
var a = new Archer();
a.x = x;
a.y = y;
archers.push(a);
game.addChild(a);
reserveArchers--;
archerReserveTxt.setText('Archers: ' + reserveArchers);
}
}
draggingUnit.destroy();
draggingUnit = null;
deployMode = null;
}
};
game.update = function () {
// Spawn enemies every 60 ticks
spawnTimer++;
if (spawnTimer >= 60) {
spawnTimer = 0;
var e = new Enemy();
e.x = 200 + Math.random() * 1648;
e.y = -60;
enemies.push(e);
game.addChild(e);
}
// Update all enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var e = enemies[i];
e.update();
// Check if enemy reached fortress (bottom)
if (e.lastY < 2650 && e.y >= 2650) {
fortressHealth--;
healthTxt.setText('Fortress: ' + fortressHealth);
e.destroy();
enemies.splice(i, 1);
if (fortressHealth <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
}
// Update all legionnaires
for (var i = 0; i < legionnaires.length; i++) {
legionnaires[i].update();
}
// Update all archers
for (var i = 0; i < archers.length; i++) {
archers[i].update();
}
// Update score
scoreTxt.setText(LK.getScore());
// Win condition: 30 points
if (LK.getScore() >= 30) {
LK.effects.flashScreen(0x00ff00, 1000);
LK.showYouWin();
}
};