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