/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Empire = Container.expand(function (empireType) {
var self = Container.call(this);
self.empireType = empireType;
self.health = 100;
self.maxHealth = 100;
self.resources = 50;
self.gold = 50;
self.units = [];
self.isDestroyed = false;
// Create base
var baseAsset = empireType + 'Base';
self.base = self.attachAsset(baseAsset, {
anchorX: 0.5,
anchorY: 0.5
});
// Create health bar background
self.healthBarBg = self.addChild(LK.getAsset('resource', {
anchorX: 0,
anchorY: 0,
scaleX: 4,
scaleY: 0.5
}));
self.healthBarBg.tint = 0x444444;
// Create health bar
self.healthBar = self.addChild(LK.getAsset('resource', {
anchorX: 0,
anchorY: 0,
scaleX: 4,
scaleY: 0.5
}));
self.healthBar.tint = 0x00FF00;
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
self.healthBar.scaleX = 4 * healthPercent;
if (healthPercent > 0.6) {
self.healthBar.tint = 0x00FF00;
} else if (healthPercent > 0.3) {
self.healthBar.tint = 0xFFFF00;
} else {
self.healthBar.tint = 0xFF0000;
}
};
self.positionHealthBar = function () {
self.healthBarBg.x = -60;
self.healthBarBg.y = -80;
self.healthBar.x = -60;
self.healthBar.y = -80;
};
self.takeDamage = function (damage) {
if (self.isDestroyed) {
return;
}
self.health -= damage;
self.updateHealthBar();
if (self.health <= 0) {
self.health = 0;
self.destroy();
}
};
self.destroy = function () {
if (self.isDestroyed) {
return;
}
self.isDestroyed = true;
LK.getSound('empireDestroyed').play();
// Remove from empires array
for (var i = empires.length - 1; i >= 0; i--) {
if (empires[i] === self) {
empires.splice(i, 1);
break;
}
}
// Destroy all units
for (var j = self.units.length - 1; j >= 0; j--) {
if (self.units[j] && self.units[j].parent) {
self.units[j].parent.removeChild(self.units[j]);
}
}
self.units = [];
// Visual destruction effect
tween(self, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 1000,
onFinish: function onFinish() {
if (self.parent) {
self.parent.removeChild(self);
}
}
});
};
self.spawnUnit = function (unitType) {
if (self.isDestroyed) {
return;
}
var cost = 0;
if (unitType === 'basic') {
cost = 10;
} else if (unitType === 'advanced') {
cost = 25;
} else if (unitType === 'elite') {
cost = 50;
}
if (self.gold < cost) {
return;
}
self.gold -= cost;
var unit = new Unit(self.empireType, self, unitType);
// Position unit near base
var angle = Math.random() * Math.PI * 2;
var distance = 80 + Math.random() * 40;
unit.x = self.x + Math.cos(angle) * distance;
unit.y = self.y + Math.sin(angle) * distance;
self.units.push(unit);
game.addChild(unit);
};
self.update = function () {
if (self.isDestroyed) {
return;
}
self.positionHealthBar();
// Auto spawn units with different types based on gold availability
if (LK.ticks % 120 === 0) {
if (self.gold >= 50) {
self.spawnUnit('elite');
} else if (self.gold >= 25) {
self.spawnUnit('advanced');
} else if (self.gold >= 10) {
self.spawnUnit('basic');
}
}
// Gain gold over time (5 gold per second)
if (LK.ticks % 60 === 0) {
self.gold += 5;
if (self.gold > 1000) {
self.gold = 1000;
}
}
};
return self;
});
var Projectile = Container.expand(function (startX, startY, targetX, targetY, damage, empireType) {
var self = Container.call(this);
self.damage = damage;
self.empireType = empireType;
self.speed = 5;
var projectileGraphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = startX;
self.y = startY;
// Calculate direction
var dx = targetX - startX;
var dy = targetY - startY;
var distance = Math.sqrt(dx * dx + dy * dy);
self.velocityX = dx / distance * self.speed;
self.velocityY = dy / distance * self.speed;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
// Check for hits
for (var i = 0; i < empires.length; i++) {
var empire = empires[i];
if (empire.empireType !== self.empireType && !empire.isDestroyed) {
if (self.intersects(empire)) {
empire.takeDamage(self.damage);
self.destroy();
return;
}
// Check units
for (var j = 0; j < empire.units.length; j++) {
var unit = empire.units[j];
if (unit && unit.parent && self.intersects(unit)) {
unit.takeDamage(self.damage);
self.destroy();
return;
}
}
}
}
// Remove if out of bounds
if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732) {
self.destroy();
}
};
self.destroy = function () {
if (self.parent) {
self.parent.removeChild(self);
}
};
return self;
});
var Resource = Container.expand(function () {
var self = Container.call(this);
self.resourceGraphics = self.attachAsset('resource', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.collect = function (empire) {
if (self.collected) {
return;
}
self.collected = true;
empire.resources += 10;
LK.getSound('resource').play();
tween(self, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
};
self.destroy = function () {
// Remove from resources array
for (var i = resources.length - 1; i >= 0; i--) {
if (resources[i] === self) {
resources.splice(i, 1);
break;
}
}
if (self.parent) {
self.parent.removeChild(self);
}
};
return self;
});
var Unit = Container.expand(function (empireType, ownerEmpire, unitType) {
var self = Container.call(this);
self.empireType = empireType;
self.ownerEmpire = ownerEmpire;
self.unitType = unitType || 'basic';
// Base stats
self.health = 30;
self.maxHealth = 30;
self.damage = 10;
self.speed = 1;
self.attackRange = 100;
self.target = null;
self.lastAttackTime = 0;
self.attackCooldown = 60; // 1 second at 60fps
self.playerDestination = null; // Player-commanded destination
self.destinationReached = false;
// Unit type bonuses
if (self.unitType === 'basic') {
// Basic units have standard stats
} else if (self.unitType === 'advanced') {
self.health = 50;
self.maxHealth = 50;
self.damage = 15;
self.speed = 1.3;
self.attackRange = 120;
} else if (self.unitType === 'elite') {
self.health = 80;
self.maxHealth = 80;
self.damage = 25;
self.speed = 1.6;
self.attackRange = 150;
self.attackCooldown = 45; // Faster attacks
}
var unitAsset = empireType + 'Unit';
self.unitGraphics = self.attachAsset(unitAsset, {
anchorX: 0.5,
anchorY: 0.5
});
// Empire-specific abilities (multiplied by unit type)
var typeMultiplier = 1;
if (self.unitType === 'advanced') {
typeMultiplier = 1.2;
} else if (self.unitType === 'elite') {
typeMultiplier = 1.5;
}
if (empireType === 'ottoman') {
self.speed *= 1.5 * typeMultiplier; // Cavalry speed
self.damage *= 1.2 * typeMultiplier;
} else if (empireType === 'roman') {
self.health *= 1.1 * typeMultiplier; // Formation strength
self.maxHealth *= 1.1 * typeMultiplier;
self.damage *= 0.6 * typeMultiplier;
} else if (empireType === 'safavid') {
self.attackRange *= 1.2 * typeMultiplier; // Gunpowder range
self.damage *= 1.5 * typeMultiplier;
} else if (empireType === 'english') {
self.attackRange *= 1.4 * typeMultiplier; // Naval superiority
self.damage *= 1.1 * typeMultiplier;
}
self.findTarget = function () {
var closestDistance = Infinity;
var closestTarget = null;
// Find closest enemy empire or unit
for (var i = 0; i < empires.length; i++) {
var empire = empires[i];
if (empire.empireType !== self.empireType && !empire.isDestroyed) {
var distance = Math.sqrt(Math.pow(empire.x - self.x, 2) + Math.pow(empire.y - self.y, 2));
if (distance < closestDistance) {
closestDistance = distance;
closestTarget = empire;
}
// Also check empire's units
for (var j = 0; j < empire.units.length; j++) {
var unit = empire.units[j];
if (unit && unit.parent) {
var unitDistance = Math.sqrt(Math.pow(unit.x - self.x, 2) + Math.pow(unit.y - self.y, 2));
if (unitDistance < closestDistance) {
closestDistance = unitDistance;
closestTarget = unit;
}
}
}
}
}
return closestTarget;
};
self.attack = function (target) {
if (LK.ticks - self.lastAttackTime < self.attackCooldown) {
return;
}
self.lastAttackTime = LK.ticks;
// Create projectile
var projectile = new Projectile(self.x, self.y, target.x, target.y, self.damage, self.empireType);
game.addChild(projectile);
LK.getSound('combat').play();
};
self.takeDamage = function (damage) {
self.health -= damage;
// Flash red when taking damage
tween(self.unitGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
tween(self.unitGraphics, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
});
if (self.health <= 0) {
self.destroy();
}
};
self.destroy = function () {
// Remove from owner's units array
if (self.ownerEmpire && self.ownerEmpire.units) {
for (var i = self.ownerEmpire.units.length - 1; i >= 0; i--) {
if (self.ownerEmpire.units[i] === self) {
self.ownerEmpire.units.splice(i, 1);
break;
}
}
}
if (self.parent) {
self.parent.removeChild(self);
}
};
self.update = function () {
// Check if we have a player destination to move to
if (self.playerDestination && !self.destinationReached) {
var dx = self.playerDestination.x - self.x;
var dy = self.playerDestination.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= 20) {
// Close enough to destination
self.destinationReached = true;
self.playerDestination = null;
} else {
// Move towards player destination
var moveX = dx / distance * self.speed;
var moveY = dy / distance * self.speed;
self.x += moveX;
self.y += moveY;
// Keep units within bounds
self.x = Math.max(50, Math.min(1998, self.x));
self.y = Math.max(50, Math.min(2682, self.y));
}
} else {
// Default AI behavior - find and attack targets
if (!self.target || self.target.isDestroyed || !self.target.parent) {
self.target = self.findTarget();
}
if (self.target) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.attackRange) {
// Attack
self.attack(self.target);
} else {
// Move towards target
var moveX = dx / distance * self.speed;
var moveY = dy / distance * self.speed;
self.x += moveX;
self.y += moveY;
// Keep units within bounds
self.x = Math.max(50, Math.min(1998, self.x));
self.y = Math.max(50, Math.min(2682, self.y));
}
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x228B22
});
/****
* Game Code
****/
var empires = [];
var resources = [];
var gameStarted = false;
var selectedEmpire = null;
var selectionPhase = false;
var showingMainMenu = true;
// Create main menu UI
var mainMenuContainer = new Container();
var gameTitle = new Text2('Empire\'s Last Stand', {
size: 150,
fill: 0xFFD700
});
gameTitle.anchor.set(0.5, 0.5);
gameTitle.y = -200;
mainMenuContainer.addChild(gameTitle);
var gameSubtitle = new Text2('Command historic empires in epic battle', {
size: 80,
fill: 0xFFFFFF
});
gameSubtitle.anchor.set(0.5, 0.5);
gameSubtitle.y = -50;
mainMenuContainer.addChild(gameSubtitle);
var startButton = new Container();
var startButtonBg = startButton.addChild(LK.getAsset('ottomanBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 1
}));
startButtonBg.tint = 0x4169E1;
var startButtonText = new Text2('START GAME', {
size: 80,
fill: 0xFFFFFF
});
startButtonText.anchor.set(0.5, 0.5);
startButton.addChild(startButtonText);
startButton.y = 150;
mainMenuContainer.addChild(startButton);
LK.gui.center.addChild(mainMenuContainer);
// Create empire selection UI (initially hidden)
var selectionText = new Text2('Choose Your Empire', {
size: 120,
fill: 0xFFFFFF
});
selectionText.anchor.set(0.5, 0.5);
selectionText.y = -300;
selectionText.visible = false;
LK.gui.center.addChild(selectionText);
// Create empire selection buttons
var empireButtons = [];
var empireNames = ['Ottoman Empire', 'Roman Empire', 'Safavid Empire', 'English Empire'];
var empireTypes = ['ottoman', 'roman', 'safavid', 'english'];
var empireDescriptions = ['Powerful cavalry charges and swift attacks', 'Strong defensive formations and endurance', 'Advanced gunpowder weapons and range', 'Naval superiority and long-range combat'];
for (var i = 0; i < 4; i++) {
var button = new Container();
var buttonBg = button.addChild(LK.getAsset(empireTypes[i] + 'Base', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
}));
var buttonText = new Text2(empireNames[i], {
size: 50,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
buttonText.y = 120;
button.addChild(buttonText);
var descriptionText = new Text2(empireDescriptions[i], {
size: 35,
fill: 0xFFD700
});
descriptionText.anchor.set(0.5, 0.5);
descriptionText.y = 170;
button.addChild(descriptionText);
button.x = (i - 1.5) * 400;
button.y = 0;
button.empireType = empireTypes[i];
button.visible = false;
empireButtons.push(button);
LK.gui.center.addChild(button);
}
function showEmpireSelection() {
showingMainMenu = false;
selectionPhase = true;
// Hide main menu
LK.gui.center.removeChild(mainMenuContainer);
// Show empire selection UI
selectionText.visible = true;
for (var i = 0; i < empireButtons.length; i++) {
empireButtons[i].visible = true;
}
}
function startGame(playerEmpireType) {
selectionPhase = false;
// Remove selection UI
LK.gui.center.removeChild(selectionText);
for (var i = 0; i < empireButtons.length; i++) {
LK.gui.center.removeChild(empireButtons[i]);
}
// Create empires
var empirePositions = [{
x: 400,
y: 400
},
// Top-left
{
x: 1648,
y: 400
},
// Top-right
{
x: 400,
y: 2332
},
// Bottom-left
{
x: 1648,
y: 2332
} // Bottom-right
];
for (var j = 0; j < 4; j++) {
var empire = new Empire(empireTypes[j]);
empire.x = empirePositions[j].x;
empire.y = empirePositions[j].y;
empire.updateHealthBar();
empires.push(empire);
game.addChild(empire);
if (empireTypes[j] === playerEmpireType) {
selectedEmpire = empire;
}
}
// Spawn initial resources
for (var k = 0; k < 20; k++) {
var resource = new Resource();
resource.x = 200 + Math.random() * 1648;
resource.y = 200 + Math.random() * 2332;
resources.push(resource);
game.addChild(resource);
}
gameStarted = true;
// Create UI
createGameUI();
}
function createGameUI() {
var empireText = new Text2('Empire: ' + (selectedEmpire ? selectedEmpire.empireType : 'None'), {
size: 60,
fill: 0xFFFFFF
});
empireText.anchor.set(0, 0);
empireText.x = 150;
empireText.y = 50;
LK.gui.topLeft.addChild(empireText);
var goldText = new Text2('Gold: 0', {
size: 50,
fill: 0xFFD700
});
goldText.anchor.set(0, 0);
goldText.x = 150;
goldText.y = 120;
LK.gui.topLeft.addChild(goldText);
// Store reference for updates
game.goldText = goldText;
}
// Handle main menu and empire selection
game.down = function (x, y, obj) {
if (showingMainMenu) {
// Check if start button was clicked
// Convert game coordinates to GUI coordinates
var gamePos = {
x: x,
y: y
}; // Use direct coordinates if obj.parent is undefined
if (obj && obj.parent && obj.position) {
gamePos = game.toLocal(obj.parent.toGlobal(obj.position));
}
var guiPos = LK.gui.center.toLocal(game.toGlobal(gamePos));
// Check if click is within start button bounds
var buttonCenterX = startButton.x;
var buttonCenterY = startButton.y;
var distance = Math.sqrt(Math.pow(guiPos.x - buttonCenterX, 2) + Math.pow(guiPos.y - buttonCenterY, 2));
if (distance < 150) {
showEmpireSelection();
}
} else if (selectionPhase) {
// Convert game coordinates to GUI coordinates
var gamePos = {
x: x,
y: y
}; // Use direct coordinates if obj.parent is undefined
if (obj && obj.parent && obj.position) {
gamePos = game.toLocal(obj.parent.toGlobal(obj.position));
}
var guiPos = LK.gui.center.toLocal(game.toGlobal(gamePos));
for (var i = 0; i < empireButtons.length; i++) {
var button = empireButtons[i];
var distance = Math.sqrt(Math.pow(guiPos.x - button.x, 2) + Math.pow(guiPos.y - button.y, 2));
if (distance < 100) {
startGame(button.empireType);
break;
}
}
} else if (gameStarted && selectedEmpire) {
// Player unit movement control
// Command all player units to move to the clicked position
for (var i = 0; i < selectedEmpire.units.length; i++) {
var unit = selectedEmpire.units[i];
if (unit && unit.parent) {
unit.playerDestination = {
x: x,
y: y
};
unit.destinationReached = false;
}
}
}
};
// Spawn resources periodically
var lastResourceSpawn = 0;
game.update = function () {
if (!gameStarted) {
return;
}
// Spawn resources
if (LK.ticks - lastResourceSpawn > 300) {
// Every 5 seconds
if (resources.length < 30) {
var resource = new Resource();
resource.x = 200 + Math.random() * 1648;
resource.y = 200 + Math.random() * 2332;
resources.push(resource);
game.addChild(resource);
}
lastResourceSpawn = LK.ticks;
}
// Check resource collection
for (var i = resources.length - 1; i >= 0; i--) {
var resource = resources[i];
if (resource.collected) {
continue;
}
for (var j = 0; j < empires.length; j++) {
var empire = empires[j];
if (empire.isDestroyed) {
continue;
}
var distance = Math.sqrt(Math.pow(empire.x - resource.x, 2) + Math.pow(empire.y - resource.y, 2));
if (distance < 80) {
resource.collect(empire);
break;
}
}
}
// Update gold display
if (game.goldText && selectedEmpire) {
game.goldText.setText('Gold: ' + selectedEmpire.gold);
}
// Check win condition
if (empires.length === 1) {
var winner = empires[0];
if (winner === selectedEmpire) {
LK.showYouWin();
} else {
LK.showGameOver();
}
} else if (empires.length === 0) {
LK.showGameOver();
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Empire = Container.expand(function (empireType) {
var self = Container.call(this);
self.empireType = empireType;
self.health = 100;
self.maxHealth = 100;
self.resources = 50;
self.gold = 50;
self.units = [];
self.isDestroyed = false;
// Create base
var baseAsset = empireType + 'Base';
self.base = self.attachAsset(baseAsset, {
anchorX: 0.5,
anchorY: 0.5
});
// Create health bar background
self.healthBarBg = self.addChild(LK.getAsset('resource', {
anchorX: 0,
anchorY: 0,
scaleX: 4,
scaleY: 0.5
}));
self.healthBarBg.tint = 0x444444;
// Create health bar
self.healthBar = self.addChild(LK.getAsset('resource', {
anchorX: 0,
anchorY: 0,
scaleX: 4,
scaleY: 0.5
}));
self.healthBar.tint = 0x00FF00;
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
self.healthBar.scaleX = 4 * healthPercent;
if (healthPercent > 0.6) {
self.healthBar.tint = 0x00FF00;
} else if (healthPercent > 0.3) {
self.healthBar.tint = 0xFFFF00;
} else {
self.healthBar.tint = 0xFF0000;
}
};
self.positionHealthBar = function () {
self.healthBarBg.x = -60;
self.healthBarBg.y = -80;
self.healthBar.x = -60;
self.healthBar.y = -80;
};
self.takeDamage = function (damage) {
if (self.isDestroyed) {
return;
}
self.health -= damage;
self.updateHealthBar();
if (self.health <= 0) {
self.health = 0;
self.destroy();
}
};
self.destroy = function () {
if (self.isDestroyed) {
return;
}
self.isDestroyed = true;
LK.getSound('empireDestroyed').play();
// Remove from empires array
for (var i = empires.length - 1; i >= 0; i--) {
if (empires[i] === self) {
empires.splice(i, 1);
break;
}
}
// Destroy all units
for (var j = self.units.length - 1; j >= 0; j--) {
if (self.units[j] && self.units[j].parent) {
self.units[j].parent.removeChild(self.units[j]);
}
}
self.units = [];
// Visual destruction effect
tween(self, {
alpha: 0,
scaleX: 0.1,
scaleY: 0.1
}, {
duration: 1000,
onFinish: function onFinish() {
if (self.parent) {
self.parent.removeChild(self);
}
}
});
};
self.spawnUnit = function (unitType) {
if (self.isDestroyed) {
return;
}
var cost = 0;
if (unitType === 'basic') {
cost = 10;
} else if (unitType === 'advanced') {
cost = 25;
} else if (unitType === 'elite') {
cost = 50;
}
if (self.gold < cost) {
return;
}
self.gold -= cost;
var unit = new Unit(self.empireType, self, unitType);
// Position unit near base
var angle = Math.random() * Math.PI * 2;
var distance = 80 + Math.random() * 40;
unit.x = self.x + Math.cos(angle) * distance;
unit.y = self.y + Math.sin(angle) * distance;
self.units.push(unit);
game.addChild(unit);
};
self.update = function () {
if (self.isDestroyed) {
return;
}
self.positionHealthBar();
// Auto spawn units with different types based on gold availability
if (LK.ticks % 120 === 0) {
if (self.gold >= 50) {
self.spawnUnit('elite');
} else if (self.gold >= 25) {
self.spawnUnit('advanced');
} else if (self.gold >= 10) {
self.spawnUnit('basic');
}
}
// Gain gold over time (5 gold per second)
if (LK.ticks % 60 === 0) {
self.gold += 5;
if (self.gold > 1000) {
self.gold = 1000;
}
}
};
return self;
});
var Projectile = Container.expand(function (startX, startY, targetX, targetY, damage, empireType) {
var self = Container.call(this);
self.damage = damage;
self.empireType = empireType;
self.speed = 5;
var projectileGraphics = self.attachAsset('projectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = startX;
self.y = startY;
// Calculate direction
var dx = targetX - startX;
var dy = targetY - startY;
var distance = Math.sqrt(dx * dx + dy * dy);
self.velocityX = dx / distance * self.speed;
self.velocityY = dy / distance * self.speed;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
// Check for hits
for (var i = 0; i < empires.length; i++) {
var empire = empires[i];
if (empire.empireType !== self.empireType && !empire.isDestroyed) {
if (self.intersects(empire)) {
empire.takeDamage(self.damage);
self.destroy();
return;
}
// Check units
for (var j = 0; j < empire.units.length; j++) {
var unit = empire.units[j];
if (unit && unit.parent && self.intersects(unit)) {
unit.takeDamage(self.damage);
self.destroy();
return;
}
}
}
}
// Remove if out of bounds
if (self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732) {
self.destroy();
}
};
self.destroy = function () {
if (self.parent) {
self.parent.removeChild(self);
}
};
return self;
});
var Resource = Container.expand(function () {
var self = Container.call(this);
self.resourceGraphics = self.attachAsset('resource', {
anchorX: 0.5,
anchorY: 0.5
});
self.collected = false;
self.collect = function (empire) {
if (self.collected) {
return;
}
self.collected = true;
empire.resources += 10;
LK.getSound('resource').play();
tween(self, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 300,
onFinish: function onFinish() {
self.destroy();
}
});
};
self.destroy = function () {
// Remove from resources array
for (var i = resources.length - 1; i >= 0; i--) {
if (resources[i] === self) {
resources.splice(i, 1);
break;
}
}
if (self.parent) {
self.parent.removeChild(self);
}
};
return self;
});
var Unit = Container.expand(function (empireType, ownerEmpire, unitType) {
var self = Container.call(this);
self.empireType = empireType;
self.ownerEmpire = ownerEmpire;
self.unitType = unitType || 'basic';
// Base stats
self.health = 30;
self.maxHealth = 30;
self.damage = 10;
self.speed = 1;
self.attackRange = 100;
self.target = null;
self.lastAttackTime = 0;
self.attackCooldown = 60; // 1 second at 60fps
self.playerDestination = null; // Player-commanded destination
self.destinationReached = false;
// Unit type bonuses
if (self.unitType === 'basic') {
// Basic units have standard stats
} else if (self.unitType === 'advanced') {
self.health = 50;
self.maxHealth = 50;
self.damage = 15;
self.speed = 1.3;
self.attackRange = 120;
} else if (self.unitType === 'elite') {
self.health = 80;
self.maxHealth = 80;
self.damage = 25;
self.speed = 1.6;
self.attackRange = 150;
self.attackCooldown = 45; // Faster attacks
}
var unitAsset = empireType + 'Unit';
self.unitGraphics = self.attachAsset(unitAsset, {
anchorX: 0.5,
anchorY: 0.5
});
// Empire-specific abilities (multiplied by unit type)
var typeMultiplier = 1;
if (self.unitType === 'advanced') {
typeMultiplier = 1.2;
} else if (self.unitType === 'elite') {
typeMultiplier = 1.5;
}
if (empireType === 'ottoman') {
self.speed *= 1.5 * typeMultiplier; // Cavalry speed
self.damage *= 1.2 * typeMultiplier;
} else if (empireType === 'roman') {
self.health *= 1.1 * typeMultiplier; // Formation strength
self.maxHealth *= 1.1 * typeMultiplier;
self.damage *= 0.6 * typeMultiplier;
} else if (empireType === 'safavid') {
self.attackRange *= 1.2 * typeMultiplier; // Gunpowder range
self.damage *= 1.5 * typeMultiplier;
} else if (empireType === 'english') {
self.attackRange *= 1.4 * typeMultiplier; // Naval superiority
self.damage *= 1.1 * typeMultiplier;
}
self.findTarget = function () {
var closestDistance = Infinity;
var closestTarget = null;
// Find closest enemy empire or unit
for (var i = 0; i < empires.length; i++) {
var empire = empires[i];
if (empire.empireType !== self.empireType && !empire.isDestroyed) {
var distance = Math.sqrt(Math.pow(empire.x - self.x, 2) + Math.pow(empire.y - self.y, 2));
if (distance < closestDistance) {
closestDistance = distance;
closestTarget = empire;
}
// Also check empire's units
for (var j = 0; j < empire.units.length; j++) {
var unit = empire.units[j];
if (unit && unit.parent) {
var unitDistance = Math.sqrt(Math.pow(unit.x - self.x, 2) + Math.pow(unit.y - self.y, 2));
if (unitDistance < closestDistance) {
closestDistance = unitDistance;
closestTarget = unit;
}
}
}
}
}
return closestTarget;
};
self.attack = function (target) {
if (LK.ticks - self.lastAttackTime < self.attackCooldown) {
return;
}
self.lastAttackTime = LK.ticks;
// Create projectile
var projectile = new Projectile(self.x, self.y, target.x, target.y, self.damage, self.empireType);
game.addChild(projectile);
LK.getSound('combat').play();
};
self.takeDamage = function (damage) {
self.health -= damage;
// Flash red when taking damage
tween(self.unitGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
tween(self.unitGraphics, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
});
if (self.health <= 0) {
self.destroy();
}
};
self.destroy = function () {
// Remove from owner's units array
if (self.ownerEmpire && self.ownerEmpire.units) {
for (var i = self.ownerEmpire.units.length - 1; i >= 0; i--) {
if (self.ownerEmpire.units[i] === self) {
self.ownerEmpire.units.splice(i, 1);
break;
}
}
}
if (self.parent) {
self.parent.removeChild(self);
}
};
self.update = function () {
// Check if we have a player destination to move to
if (self.playerDestination && !self.destinationReached) {
var dx = self.playerDestination.x - self.x;
var dy = self.playerDestination.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= 20) {
// Close enough to destination
self.destinationReached = true;
self.playerDestination = null;
} else {
// Move towards player destination
var moveX = dx / distance * self.speed;
var moveY = dy / distance * self.speed;
self.x += moveX;
self.y += moveY;
// Keep units within bounds
self.x = Math.max(50, Math.min(1998, self.x));
self.y = Math.max(50, Math.min(2682, self.y));
}
} else {
// Default AI behavior - find and attack targets
if (!self.target || self.target.isDestroyed || !self.target.parent) {
self.target = self.findTarget();
}
if (self.target) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.attackRange) {
// Attack
self.attack(self.target);
} else {
// Move towards target
var moveX = dx / distance * self.speed;
var moveY = dy / distance * self.speed;
self.x += moveX;
self.y += moveY;
// Keep units within bounds
self.x = Math.max(50, Math.min(1998, self.x));
self.y = Math.max(50, Math.min(2682, self.y));
}
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x228B22
});
/****
* Game Code
****/
var empires = [];
var resources = [];
var gameStarted = false;
var selectedEmpire = null;
var selectionPhase = false;
var showingMainMenu = true;
// Create main menu UI
var mainMenuContainer = new Container();
var gameTitle = new Text2('Empire\'s Last Stand', {
size: 150,
fill: 0xFFD700
});
gameTitle.anchor.set(0.5, 0.5);
gameTitle.y = -200;
mainMenuContainer.addChild(gameTitle);
var gameSubtitle = new Text2('Command historic empires in epic battle', {
size: 80,
fill: 0xFFFFFF
});
gameSubtitle.anchor.set(0.5, 0.5);
gameSubtitle.y = -50;
mainMenuContainer.addChild(gameSubtitle);
var startButton = new Container();
var startButtonBg = startButton.addChild(LK.getAsset('ottomanBase', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 1
}));
startButtonBg.tint = 0x4169E1;
var startButtonText = new Text2('START GAME', {
size: 80,
fill: 0xFFFFFF
});
startButtonText.anchor.set(0.5, 0.5);
startButton.addChild(startButtonText);
startButton.y = 150;
mainMenuContainer.addChild(startButton);
LK.gui.center.addChild(mainMenuContainer);
// Create empire selection UI (initially hidden)
var selectionText = new Text2('Choose Your Empire', {
size: 120,
fill: 0xFFFFFF
});
selectionText.anchor.set(0.5, 0.5);
selectionText.y = -300;
selectionText.visible = false;
LK.gui.center.addChild(selectionText);
// Create empire selection buttons
var empireButtons = [];
var empireNames = ['Ottoman Empire', 'Roman Empire', 'Safavid Empire', 'English Empire'];
var empireTypes = ['ottoman', 'roman', 'safavid', 'english'];
var empireDescriptions = ['Powerful cavalry charges and swift attacks', 'Strong defensive formations and endurance', 'Advanced gunpowder weapons and range', 'Naval superiority and long-range combat'];
for (var i = 0; i < 4; i++) {
var button = new Container();
var buttonBg = button.addChild(LK.getAsset(empireTypes[i] + 'Base', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5
}));
var buttonText = new Text2(empireNames[i], {
size: 50,
fill: 0xFFFFFF
});
buttonText.anchor.set(0.5, 0.5);
buttonText.y = 120;
button.addChild(buttonText);
var descriptionText = new Text2(empireDescriptions[i], {
size: 35,
fill: 0xFFD700
});
descriptionText.anchor.set(0.5, 0.5);
descriptionText.y = 170;
button.addChild(descriptionText);
button.x = (i - 1.5) * 400;
button.y = 0;
button.empireType = empireTypes[i];
button.visible = false;
empireButtons.push(button);
LK.gui.center.addChild(button);
}
function showEmpireSelection() {
showingMainMenu = false;
selectionPhase = true;
// Hide main menu
LK.gui.center.removeChild(mainMenuContainer);
// Show empire selection UI
selectionText.visible = true;
for (var i = 0; i < empireButtons.length; i++) {
empireButtons[i].visible = true;
}
}
function startGame(playerEmpireType) {
selectionPhase = false;
// Remove selection UI
LK.gui.center.removeChild(selectionText);
for (var i = 0; i < empireButtons.length; i++) {
LK.gui.center.removeChild(empireButtons[i]);
}
// Create empires
var empirePositions = [{
x: 400,
y: 400
},
// Top-left
{
x: 1648,
y: 400
},
// Top-right
{
x: 400,
y: 2332
},
// Bottom-left
{
x: 1648,
y: 2332
} // Bottom-right
];
for (var j = 0; j < 4; j++) {
var empire = new Empire(empireTypes[j]);
empire.x = empirePositions[j].x;
empire.y = empirePositions[j].y;
empire.updateHealthBar();
empires.push(empire);
game.addChild(empire);
if (empireTypes[j] === playerEmpireType) {
selectedEmpire = empire;
}
}
// Spawn initial resources
for (var k = 0; k < 20; k++) {
var resource = new Resource();
resource.x = 200 + Math.random() * 1648;
resource.y = 200 + Math.random() * 2332;
resources.push(resource);
game.addChild(resource);
}
gameStarted = true;
// Create UI
createGameUI();
}
function createGameUI() {
var empireText = new Text2('Empire: ' + (selectedEmpire ? selectedEmpire.empireType : 'None'), {
size: 60,
fill: 0xFFFFFF
});
empireText.anchor.set(0, 0);
empireText.x = 150;
empireText.y = 50;
LK.gui.topLeft.addChild(empireText);
var goldText = new Text2('Gold: 0', {
size: 50,
fill: 0xFFD700
});
goldText.anchor.set(0, 0);
goldText.x = 150;
goldText.y = 120;
LK.gui.topLeft.addChild(goldText);
// Store reference for updates
game.goldText = goldText;
}
// Handle main menu and empire selection
game.down = function (x, y, obj) {
if (showingMainMenu) {
// Check if start button was clicked
// Convert game coordinates to GUI coordinates
var gamePos = {
x: x,
y: y
}; // Use direct coordinates if obj.parent is undefined
if (obj && obj.parent && obj.position) {
gamePos = game.toLocal(obj.parent.toGlobal(obj.position));
}
var guiPos = LK.gui.center.toLocal(game.toGlobal(gamePos));
// Check if click is within start button bounds
var buttonCenterX = startButton.x;
var buttonCenterY = startButton.y;
var distance = Math.sqrt(Math.pow(guiPos.x - buttonCenterX, 2) + Math.pow(guiPos.y - buttonCenterY, 2));
if (distance < 150) {
showEmpireSelection();
}
} else if (selectionPhase) {
// Convert game coordinates to GUI coordinates
var gamePos = {
x: x,
y: y
}; // Use direct coordinates if obj.parent is undefined
if (obj && obj.parent && obj.position) {
gamePos = game.toLocal(obj.parent.toGlobal(obj.position));
}
var guiPos = LK.gui.center.toLocal(game.toGlobal(gamePos));
for (var i = 0; i < empireButtons.length; i++) {
var button = empireButtons[i];
var distance = Math.sqrt(Math.pow(guiPos.x - button.x, 2) + Math.pow(guiPos.y - button.y, 2));
if (distance < 100) {
startGame(button.empireType);
break;
}
}
} else if (gameStarted && selectedEmpire) {
// Player unit movement control
// Command all player units to move to the clicked position
for (var i = 0; i < selectedEmpire.units.length; i++) {
var unit = selectedEmpire.units[i];
if (unit && unit.parent) {
unit.playerDestination = {
x: x,
y: y
};
unit.destinationReached = false;
}
}
}
};
// Spawn resources periodically
var lastResourceSpawn = 0;
game.update = function () {
if (!gameStarted) {
return;
}
// Spawn resources
if (LK.ticks - lastResourceSpawn > 300) {
// Every 5 seconds
if (resources.length < 30) {
var resource = new Resource();
resource.x = 200 + Math.random() * 1648;
resource.y = 200 + Math.random() * 2332;
resources.push(resource);
game.addChild(resource);
}
lastResourceSpawn = LK.ticks;
}
// Check resource collection
for (var i = resources.length - 1; i >= 0; i--) {
var resource = resources[i];
if (resource.collected) {
continue;
}
for (var j = 0; j < empires.length; j++) {
var empire = empires[j];
if (empire.isDestroyed) {
continue;
}
var distance = Math.sqrt(Math.pow(empire.x - resource.x, 2) + Math.pow(empire.y - resource.y, 2));
if (distance < 80) {
resource.collect(empire);
break;
}
}
}
// Update gold display
if (game.goldText && selectedEmpire) {
game.goldText.setText('Gold: ' + selectedEmpire.gold);
}
// Check win condition
if (empires.length === 1) {
var winner = empires[0];
if (winner === selectedEmpire) {
LK.showYouWin();
} else {
LK.showGameOver();
}
} else if (empires.length === 0) {
LK.showGameOver();
}
};
Taştan ve dört tane kulesi olan kırmızı bayraklar asılı kale. In-Game asset. 2d. High contrast. No shadows
Osmanlı sarayı. In-Game asset. 2d. High contrast. No shadows
Mızraklı atlı ve yeşil deri zırh. In-Game asset. 2d. High contrast. No shadows
Mermi. In-Game asset. 2d. High contrast. No shadows
İngiliz okçusu. In-Game asset. 2d. High contrast. No shadows
Kılıçlı yeniçeri. In-Game asset. 2d. High contrast. No shadows
Safevi çadırı. In-Game asset. 2d. High contrast. No shadows
Roma imparatorluğu sarayı. In-Game asset. 2d. High contrast. No shadows
Vareg muhafızı. In-Game asset. 2d. High contrast. No shadows
Ağaç. In-Game asset. 2d. High contrast. No shadows