/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Arrow = Container.expand(function () {
var self = Container.call(this);
var arrowGraphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetX = 0;
self.targetY = 0;
self.speed = 15;
self.directionX = 0;
self.directionY = 0;
self.setTarget = function (targetX, targetY) {
self.targetX = targetX;
self.targetY = targetY;
var dx = targetX - self.x;
var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
self.directionX = dx / distance;
self.directionY = dy / distance;
// Rotate arrow to face target
arrowGraphics.rotation = Math.atan2(dy, dx);
};
self.update = function () {
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2 + Math.random() * 3;
self.directionX = (Math.random() - 0.5) * 2;
self.directionY = (Math.random() - 0.5) * 2;
self.update = function () {
// Move towards player if player exists
if (player) {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.directionX = dx / distance;
self.directionY = dy / distance;
}
}
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
// Keep in bounds
self.x = Math.max(40, Math.min(2008, self.x));
self.y = Math.max(40, Math.min(2692, self.y));
};
self.down = function (x, y, obj) {
// Enemy clicked - kill it
killEnemy(self);
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.targetX = 1024;
self.targetY = 2600;
self.update = function () {
// Move towards target position smoothly
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000011
});
/****
* Game Code
****/
var gameState = 'genderSelection'; // 'genderSelection', 'playing', 'gameOver', 'victory'
var score = 0;
var enemies = [];
var arrows = [];
var player = null;
var spawnPoints = [{
x: 400,
y: 100
},
// Left spawn
{
x: 1024,
y: 100
},
// Center spawn
{
x: 1648,
y: 100
} // Right spawn
];
var lastSpawnPoint = -1;
// UI Elements
var titleText = new Text2('Age of Ignorance', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
var instructionText = new Text2('Choose your gender to begin:', {
size: 50,
fill: 0xCCCCCC
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = 600;
var boyButton = new Text2('Boy', {
size: 60,
fill: 0x4CAF50
});
boyButton.anchor.set(0.5, 0.5);
boyButton.x = 824;
boyButton.y = 800;
var girlButton = new Text2('Girl', {
size: 60,
fill: 0xE91E63
});
girlButton.anchor.set(0.5, 0.5);
girlButton.x = 1224;
girlButton.y = 800;
var gameOverText = new Text2('', {
size: 50,
fill: 0xFF4444
});
gameOverText.anchor.set(0.5, 0.5);
gameOverText.x = 1024;
gameOverText.y = 1000;
var restartText = new Text2('Touch to restart', {
size: 40,
fill: 0x888888
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 1024;
restartText.y = 1200;
var scoreText = new Text2('Score: 0', {
size: 50,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
var victoryText = new Text2('Victory! You survived the Age of Ignorance!', {
size: 60,
fill: 0x00FF00
});
victoryText.anchor.set(0.5, 0.5);
victoryText.x = 1024;
victoryText.y = 1366;
// Add background
var background = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Add stars to background
var stars = [];
for (var i = 0; i < 200; i++) {
var star = LK.getAsset('arrow', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
x: Math.random() * 2048,
y: Math.random() * 2732
});
star.tint = 0xffffff;
star.alpha = Math.random() * 0.8 + 0.2;
stars.push(star);
game.addChild(star);
}
// Initialize gender selection screen
function showGenderSelection() {
gameState = 'genderSelection';
game.addChild(titleText);
game.addChild(instructionText);
game.addChild(boyButton);
game.addChild(girlButton);
// Clear any existing game elements
clearGame();
}
function showGameOverScreen(message) {
gameState = 'gameOver';
gameOverText.setText(message);
game.addChild(gameOverText);
game.addChild(restartText);
}
function startGame() {
gameState = 'playing';
score = 0;
// Clear gender selection UI
game.removeChild(titleText);
game.removeChild(instructionText);
game.removeChild(boyButton);
game.removeChild(girlButton);
game.removeChild(gameOverText);
game.removeChild(restartText);
game.removeChild(victoryText);
// Create player
player = new Player();
player.x = 1024;
player.y = 2600;
game.addChild(player);
// Add game UI
LK.gui.top.addChild(scoreText);
updateScore();
// Spawn initial enemies
spawnEnemies(2);
}
function clearGame() {
// Remove all enemies
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].destroy();
}
enemies = [];
// Remove all arrows
for (var j = arrows.length - 1; j >= 0; j--) {
arrows[j].destroy();
}
arrows = [];
// Remove player
if (player && player.parent) {
player.destroy();
player = null;
}
// Remove score from GUI
if (scoreText.parent) {
LK.gui.top.removeChild(scoreText);
}
}
function spawnEnemies(count) {
for (var i = 0; i < count; i++) {
var enemy = new Enemy();
// Select next spawn point (avoid consecutive same spawn point)
var spawnIndex = lastSpawnPoint;
while (spawnIndex === lastSpawnPoint) {
spawnIndex = Math.floor(Math.random() * spawnPoints.length);
}
lastSpawnPoint = spawnIndex;
var spawnPoint = spawnPoints[spawnIndex];
// Spawn from selected point with slight variation
enemy.x = spawnPoint.x + (Math.random() - 0.5) * 100;
enemy.y = spawnPoint.y;
enemies.push(enemy);
game.addChild(enemy);
}
}
function killEnemy(enemy) {
if (gameState !== 'playing') return;
// Play sound
LK.getSound('enemyHit').play();
// Remove enemy
var index = enemies.indexOf(enemy);
if (index > -1) {
enemies.splice(index, 1);
enemy.destroy();
// Update score
score += 1;
updateScore();
// Check victory condition
if (score >= 30) {
showVictory();
return;
}
// Spawn 2 new enemies
spawnEnemies(2);
}
}
function updateScore() {
scoreText.setText('Score: ' + score + '/30');
LK.setScore(score);
}
function showVictory() {
gameState = 'victory';
clearGame();
game.addChild(victoryText);
game.addChild(restartText);
LK.showYouWin();
}
function shootArrow(targetX, targetY) {
if (gameState !== 'playing' || !player) return;
var arrow = new Arrow();
arrow.x = player.x;
arrow.y = player.y;
arrow.setTarget(targetX, targetY);
arrows.push(arrow);
game.addChild(arrow);
LK.getSound('bowShoot').play();
// Remove arrow after 3 seconds
LK.setTimeout(function () {
var index = arrows.indexOf(arrow);
if (index > -1) {
arrows.splice(index, 1);
if (arrow.parent) {
arrow.destroy();
}
}
}, 3000);
}
// Event handlers
game.down = function (x, y, obj) {
if (gameState === 'genderSelection') {
// Check button clicks
var boyBounds = {
left: boyButton.x - 100,
right: boyButton.x + 100,
top: boyButton.y - 40,
bottom: boyButton.y + 40
};
var girlBounds = {
left: girlButton.x - 100,
right: girlButton.x + 100,
top: girlButton.y - 40,
bottom: girlButton.y + 40
};
if (x >= boyBounds.left && x <= boyBounds.right && y >= boyBounds.top && y <= boyBounds.bottom) {
startGame();
} else if (x >= girlBounds.left && x <= girlBounds.right && y >= girlBounds.top && y <= girlBounds.bottom) {
showGameOverScreen('You were buried alive. The Age of Ignorance claims another victim.');
}
} else if (gameState === 'playing') {
// Left click shoots arrow
if (!obj.event || obj.event.button === 0) {
// Left click or touch - shoot arrow
shootArrow(x, y);
}
} else if (gameState === 'gameOver' || gameState === 'victory') {
showGenderSelection();
}
};
game.update = function () {
if (gameState === 'playing') {
// Check player-enemy collisions
if (player) {
for (var e = 0; e < enemies.length; e++) {
var enemy = enemies[e];
if (player.intersects(enemy)) {
showGameOverScreen('You were killed by European enemies! The Age of Ignorance continues...');
return;
}
}
}
// Update arrows
for (var i = arrows.length - 1; i >= 0; i--) {
var arrow = arrows[i];
// Check if arrow hit any enemy
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (arrow.intersects(enemy)) {
// Remove arrow
arrows.splice(i, 1);
arrow.destroy();
// Kill enemy
killEnemy(enemy);
break;
}
}
// Remove arrows that go off screen
if (arrow && (arrow.x < -100 || arrow.x > 2148 || arrow.y < -100 || arrow.y > 2832)) {
arrows.splice(i, 1);
arrow.destroy();
}
}
// Check for game over condition (too many enemies)
if (enemies.length > 100) {
showGameOverScreen('Overwhelmed by enemies! The Age of Ignorance continues...');
}
}
// Animate stars
for (var k = 0; k < stars.length; k++) {
stars[k].alpha = 0.2 + Math.sin(LK.ticks * 0.01 + k) * 0.3;
}
};
// Handle right-click for player movement
game.on('rightdown', function (x, y, obj) {
if (obj.event) {
obj.event.preventDefault();
}
if (gameState === 'playing') {
// Right click - move player
if (player) {
player.targetX = Math.max(30, Math.min(2018, x));
player.targetY = Math.max(30, Math.min(2702, y));
}
}
});
// Prevent context menu on right click
game.on('contextmenu', function (x, y, obj) {
if (obj.event) {
obj.event.preventDefault();
}
});
// Start with gender selection
showGenderSelection(); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Arrow = Container.expand(function () {
var self = Container.call(this);
var arrowGraphics = self.attachAsset('arrow', {
anchorX: 0.5,
anchorY: 0.5
});
self.targetX = 0;
self.targetY = 0;
self.speed = 15;
self.directionX = 0;
self.directionY = 0;
self.setTarget = function (targetX, targetY) {
self.targetX = targetX;
self.targetY = targetY;
var dx = targetX - self.x;
var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
self.directionX = dx / distance;
self.directionY = dy / distance;
// Rotate arrow to face target
arrowGraphics.rotation = Math.atan2(dy, dx);
};
self.update = function () {
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2 + Math.random() * 3;
self.directionX = (Math.random() - 0.5) * 2;
self.directionY = (Math.random() - 0.5) * 2;
self.update = function () {
// Move towards player if player exists
if (player) {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.directionX = dx / distance;
self.directionY = dy / distance;
}
}
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
// Keep in bounds
self.x = Math.max(40, Math.min(2008, self.x));
self.y = Math.max(40, Math.min(2692, self.y));
};
self.down = function (x, y, obj) {
// Enemy clicked - kill it
killEnemy(self);
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.targetX = 1024;
self.targetY = 2600;
self.update = function () {
// Move towards target position smoothly
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000011
});
/****
* Game Code
****/
var gameState = 'genderSelection'; // 'genderSelection', 'playing', 'gameOver', 'victory'
var score = 0;
var enemies = [];
var arrows = [];
var player = null;
var spawnPoints = [{
x: 400,
y: 100
},
// Left spawn
{
x: 1024,
y: 100
},
// Center spawn
{
x: 1648,
y: 100
} // Right spawn
];
var lastSpawnPoint = -1;
// UI Elements
var titleText = new Text2('Age of Ignorance', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 400;
var instructionText = new Text2('Choose your gender to begin:', {
size: 50,
fill: 0xCCCCCC
});
instructionText.anchor.set(0.5, 0.5);
instructionText.x = 1024;
instructionText.y = 600;
var boyButton = new Text2('Boy', {
size: 60,
fill: 0x4CAF50
});
boyButton.anchor.set(0.5, 0.5);
boyButton.x = 824;
boyButton.y = 800;
var girlButton = new Text2('Girl', {
size: 60,
fill: 0xE91E63
});
girlButton.anchor.set(0.5, 0.5);
girlButton.x = 1224;
girlButton.y = 800;
var gameOverText = new Text2('', {
size: 50,
fill: 0xFF4444
});
gameOverText.anchor.set(0.5, 0.5);
gameOverText.x = 1024;
gameOverText.y = 1000;
var restartText = new Text2('Touch to restart', {
size: 40,
fill: 0x888888
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 1024;
restartText.y = 1200;
var scoreText = new Text2('Score: 0', {
size: 50,
fill: 0xFFFFFF
});
scoreText.anchor.set(0.5, 0);
var victoryText = new Text2('Victory! You survived the Age of Ignorance!', {
size: 60,
fill: 0x00FF00
});
victoryText.anchor.set(0.5, 0.5);
victoryText.x = 1024;
victoryText.y = 1366;
// Add background
var background = game.addChild(LK.getAsset('background', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
}));
// Add stars to background
var stars = [];
for (var i = 0; i < 200; i++) {
var star = LK.getAsset('arrow', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.1,
scaleY: 0.1,
x: Math.random() * 2048,
y: Math.random() * 2732
});
star.tint = 0xffffff;
star.alpha = Math.random() * 0.8 + 0.2;
stars.push(star);
game.addChild(star);
}
// Initialize gender selection screen
function showGenderSelection() {
gameState = 'genderSelection';
game.addChild(titleText);
game.addChild(instructionText);
game.addChild(boyButton);
game.addChild(girlButton);
// Clear any existing game elements
clearGame();
}
function showGameOverScreen(message) {
gameState = 'gameOver';
gameOverText.setText(message);
game.addChild(gameOverText);
game.addChild(restartText);
}
function startGame() {
gameState = 'playing';
score = 0;
// Clear gender selection UI
game.removeChild(titleText);
game.removeChild(instructionText);
game.removeChild(boyButton);
game.removeChild(girlButton);
game.removeChild(gameOverText);
game.removeChild(restartText);
game.removeChild(victoryText);
// Create player
player = new Player();
player.x = 1024;
player.y = 2600;
game.addChild(player);
// Add game UI
LK.gui.top.addChild(scoreText);
updateScore();
// Spawn initial enemies
spawnEnemies(2);
}
function clearGame() {
// Remove all enemies
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].destroy();
}
enemies = [];
// Remove all arrows
for (var j = arrows.length - 1; j >= 0; j--) {
arrows[j].destroy();
}
arrows = [];
// Remove player
if (player && player.parent) {
player.destroy();
player = null;
}
// Remove score from GUI
if (scoreText.parent) {
LK.gui.top.removeChild(scoreText);
}
}
function spawnEnemies(count) {
for (var i = 0; i < count; i++) {
var enemy = new Enemy();
// Select next spawn point (avoid consecutive same spawn point)
var spawnIndex = lastSpawnPoint;
while (spawnIndex === lastSpawnPoint) {
spawnIndex = Math.floor(Math.random() * spawnPoints.length);
}
lastSpawnPoint = spawnIndex;
var spawnPoint = spawnPoints[spawnIndex];
// Spawn from selected point with slight variation
enemy.x = spawnPoint.x + (Math.random() - 0.5) * 100;
enemy.y = spawnPoint.y;
enemies.push(enemy);
game.addChild(enemy);
}
}
function killEnemy(enemy) {
if (gameState !== 'playing') return;
// Play sound
LK.getSound('enemyHit').play();
// Remove enemy
var index = enemies.indexOf(enemy);
if (index > -1) {
enemies.splice(index, 1);
enemy.destroy();
// Update score
score += 1;
updateScore();
// Check victory condition
if (score >= 30) {
showVictory();
return;
}
// Spawn 2 new enemies
spawnEnemies(2);
}
}
function updateScore() {
scoreText.setText('Score: ' + score + '/30');
LK.setScore(score);
}
function showVictory() {
gameState = 'victory';
clearGame();
game.addChild(victoryText);
game.addChild(restartText);
LK.showYouWin();
}
function shootArrow(targetX, targetY) {
if (gameState !== 'playing' || !player) return;
var arrow = new Arrow();
arrow.x = player.x;
arrow.y = player.y;
arrow.setTarget(targetX, targetY);
arrows.push(arrow);
game.addChild(arrow);
LK.getSound('bowShoot').play();
// Remove arrow after 3 seconds
LK.setTimeout(function () {
var index = arrows.indexOf(arrow);
if (index > -1) {
arrows.splice(index, 1);
if (arrow.parent) {
arrow.destroy();
}
}
}, 3000);
}
// Event handlers
game.down = function (x, y, obj) {
if (gameState === 'genderSelection') {
// Check button clicks
var boyBounds = {
left: boyButton.x - 100,
right: boyButton.x + 100,
top: boyButton.y - 40,
bottom: boyButton.y + 40
};
var girlBounds = {
left: girlButton.x - 100,
right: girlButton.x + 100,
top: girlButton.y - 40,
bottom: girlButton.y + 40
};
if (x >= boyBounds.left && x <= boyBounds.right && y >= boyBounds.top && y <= boyBounds.bottom) {
startGame();
} else if (x >= girlBounds.left && x <= girlBounds.right && y >= girlBounds.top && y <= girlBounds.bottom) {
showGameOverScreen('You were buried alive. The Age of Ignorance claims another victim.');
}
} else if (gameState === 'playing') {
// Left click shoots arrow
if (!obj.event || obj.event.button === 0) {
// Left click or touch - shoot arrow
shootArrow(x, y);
}
} else if (gameState === 'gameOver' || gameState === 'victory') {
showGenderSelection();
}
};
game.update = function () {
if (gameState === 'playing') {
// Check player-enemy collisions
if (player) {
for (var e = 0; e < enemies.length; e++) {
var enemy = enemies[e];
if (player.intersects(enemy)) {
showGameOverScreen('You were killed by European enemies! The Age of Ignorance continues...');
return;
}
}
}
// Update arrows
for (var i = arrows.length - 1; i >= 0; i--) {
var arrow = arrows[i];
// Check if arrow hit any enemy
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (arrow.intersects(enemy)) {
// Remove arrow
arrows.splice(i, 1);
arrow.destroy();
// Kill enemy
killEnemy(enemy);
break;
}
}
// Remove arrows that go off screen
if (arrow && (arrow.x < -100 || arrow.x > 2148 || arrow.y < -100 || arrow.y > 2832)) {
arrows.splice(i, 1);
arrow.destroy();
}
}
// Check for game over condition (too many enemies)
if (enemies.length > 100) {
showGameOverScreen('Overwhelmed by enemies! The Age of Ignorance continues...');
}
}
// Animate stars
for (var k = 0; k < stars.length; k++) {
stars[k].alpha = 0.2 + Math.sin(LK.ticks * 0.01 + k) * 0.3;
}
};
// Handle right-click for player movement
game.on('rightdown', function (x, y, obj) {
if (obj.event) {
obj.event.preventDefault();
}
if (gameState === 'playing') {
// Right click - move player
if (player) {
player.targetX = Math.max(30, Math.min(2018, x));
player.targetY = Math.max(30, Math.min(2702, y));
}
}
});
// Prevent context menu on right click
game.on('contextmenu', function (x, y, obj) {
if (obj.event) {
obj.event.preventDefault();
}
});
// Start with gender selection
showGenderSelection();