/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Boss = Container.expand(function (level) {
var self = Container.call(this);
var graphics = self.attachAsset('bossChristian', {
anchorX: 0.5,
anchorY: 0.5
});
self.level = level || 1;
self.maxHealth = 3 + level;
self.health = self.maxHealth;
self.speed = 2 + level * 0.5;
self.direction = Math.random() * Math.PI * 2;
self.attackTimer = 0;
self.attackCooldown = 2000; // 2 seconds
self.isDead = false;
self.chargeAttacking = false;
self.chargeSpeed = 12;
// Health bar
var healthBarBg = self.addChild(LK.getAsset('shape', {
width: 120,
height: 20,
color: 0x660000,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
y: -100
}));
var healthBar = self.addChild(LK.getAsset('shape', {
width: 120,
height: 16,
color: 0xff0000,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
y: -100
}));
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
healthBar.width = 120 * healthPercent;
};
self.update = function () {
if (self.isDead) return;
self.attackTimer += 16.67;
// Boss AI behavior
if (self.chargeAttacking) {
// Charge attack - move fast towards player
var deltaX = player.x - self.x;
var deltaY = player.y - self.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > 10) {
self.direction = Math.atan2(deltaY, deltaX);
var newX = self.x + Math.cos(self.direction) * self.chargeSpeed;
var newY = self.y + Math.sin(self.direction) * self.chargeSpeed;
// Keep within bounds
self.x = Math.max(shipBounds.left + 75, Math.min(shipBounds.right - 75, newX));
self.y = Math.max(shipBounds.top + 75, Math.min(shipBounds.bottom - 75, newY));
}
// End charge attack after 1 second
if (self.attackTimer >= 1000) {
self.chargeAttacking = false;
self.attackTimer = 0;
}
} else if (self.attackTimer >= self.attackCooldown) {
// Start charge attack
self.chargeAttacking = true;
self.attackTimer = 0;
LK.effects.flashObject(self, 0xffff00, 500);
} else {
// Normal movement - slower patrol
var deltaX = player.x - self.x;
var deltaY = player.y - self.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > 200) {
// Move towards player if far away
self.direction = Math.atan2(deltaY, deltaX);
} else {
// Random movement when close
if (Math.random() < 0.02) {
self.direction = Math.random() * Math.PI * 2;
}
}
var newX = self.x + Math.cos(self.direction) * self.speed;
var newY = self.y + Math.sin(self.direction) * self.speed;
// Bounce off boundaries
if (newX < shipBounds.left + 75 || newX > shipBounds.right - 75) {
self.direction = Math.PI - self.direction;
}
if (newY < shipBounds.top + 75 || newY > shipBounds.bottom - 75) {
self.direction = -self.direction;
}
// Keep within bounds
self.x = Math.max(shipBounds.left + 75, Math.min(shipBounds.right - 75, newX));
self.y = Math.max(shipBounds.top + 75, Math.min(shipBounds.bottom - 75, newY));
}
};
self.takeDamage = function () {
if (self.isDead) return false;
self.health--;
self.updateHealthBar();
LK.effects.flashObject(self, 0xffffff, 300);
if (self.health <= 0) {
self.isDead = true;
LK.setScore(LK.getScore() + 500);
LK.getSound('faithVictory').play();
scoreTxt.setText('Score: ' + LK.getScore());
return true;
}
return false;
};
return self;
});
var Christian = Container.expand(function (colorAsset) {
var self = Container.call(this);
var graphics = self.attachAsset(colorAsset || 'christian', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.direction = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.isIdentified = false;
self.update = function () {
if (self.isIdentified) return;
// Calculate direction towards player
var deltaX = player.x - self.x;
var deltaY = player.y - self.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// Only chase if player is alive and within reasonable distance
if (player.isAlive && distance > 10) {
// Calculate angle towards player
self.direction = Math.atan2(deltaY, deltaX);
// Add some randomness to make movement less predictable
var randomOffset = (Math.random() - 0.5) * 0.3;
self.direction += randomOffset;
}
// Move in current direction
var newX = self.x + Math.cos(self.direction) * self.speed;
var newY = self.y + Math.sin(self.direction) * self.speed;
// Bounce off ship boundaries
if (newX < shipBounds.left + 40 || newX > shipBounds.right - 40) {
self.direction = Math.PI - self.direction;
}
if (newY < shipBounds.top + 40 || newY > shipBounds.bottom - 40) {
self.direction = -self.direction;
}
// Keep within bounds
self.x = Math.max(shipBounds.left + 40, Math.min(shipBounds.right - 40, newX));
self.y = Math.max(shipBounds.top + 40, Math.min(shipBounds.bottom - 40, newY));
};
return self;
});
var Mosque = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('mosque', {
anchorX: 0.5,
anchorY: 0.5
});
self.isCompleted = false;
return self;
});
var Muslim = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('muslim', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.isAlive = true;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Game variables
var player;
var christians = [];
var mosques = [];
var mosqueArea = {};
var gameState = 'playing'; // 'playing', 'praying', 'roundEnd'
var roundNumber = 1;
var prayersCompleted = 0;
var prayingTimer = 0;
var prayingDuration = 5000; // 5 seconds for praying
var dragNode = null;
// Missing variables that are referenced in the code
var shipBounds = {};
var impostors = [];
var taskStations = [];
var tasksCompleted = 0;
// Level system variables
var currentLevel = 1;
var maxLevel = 4;
var currentBoss = null;
var levelNames = ['Main Mosque', 'Prayer Hall', 'Minaret', 'Sacred Courtyard'];
var levelBackgrounds = ['courtyard', 'mainMosque', 'prayerHall', 'minaret'];
var currentMosque = null;
var isLevelTransition = false;
var levelTransitionDuration = 8000; // 8 seconds pause between levels
var isLevelCompleted = false;
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var gameStateTxt = new Text2('Visit mosques to pray and avoid the pursuers!', {
size: 60,
fill: 0xFFFF00
});
gameStateTxt.anchor.set(0.5, 0);
gameStateTxt.y = 100;
LK.gui.top.addChild(gameStateTxt);
var roundTxt = new Text2('Round 1', {
size: 70,
fill: 0x00FFFF
});
roundTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(roundTxt);
roundTxt.x = 120; // Avoid the menu icon
var levelTxt = new Text2('Level 1: Main Mosque', {
size: 60,
fill: 0xff9900
});
levelTxt.anchor.set(0, 0);
levelTxt.y = 80;
LK.gui.topLeft.addChild(levelTxt);
levelTxt.x = 120;
var levelTransitionTxt = new Text2('', {
size: 120,
fill: 0xffff00
});
levelTransitionTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(levelTransitionTxt);
levelTransitionTxt.alpha = 0;
// Continue button for level completion
var continueBtn = new Text2('CONTINUE', {
size: 100,
fill: 0x00ff00
});
continueBtn.anchor.set(0.5, 0.5);
continueBtn.y = 200;
LK.gui.center.addChild(continueBtn);
continueBtn.alpha = 0;
continueBtn.interactive = true;
// Create level background
function createLevelBackground() {
if (currentMosque && currentMosque.parent) {
currentMosque.destroy();
}
var backgroundAsset = levelBackgrounds[currentLevel - 1] || 'courtyard';
currentMosque = game.attachAsset(backgroundAsset, {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
// Update mosque boundaries after creating new background
mosqueArea = {
left: currentMosque.x - currentMosque.width / 2,
right: currentMosque.x + currentMosque.width / 2,
top: currentMosque.y - currentMosque.height / 2,
bottom: currentMosque.y + currentMosque.height / 2
};
// Create fresh mosques for the new level
createMosques();
}
createLevelBackground();
// Set mosque boundaries
mosqueArea = {
left: currentMosque.x - currentMosque.width / 2,
right: currentMosque.x + currentMosque.width / 2,
top: currentMosque.y - currentMosque.height / 2,
bottom: currentMosque.y + currentMosque.height / 2
};
// Initialize shipBounds to match mosqueArea
shipBounds = {
left: mosqueArea.left,
right: mosqueArea.right,
top: mosqueArea.top,
bottom: mosqueArea.bottom
};
// Create player
player = game.addChild(new Muslim());
player.x = 1024;
player.y = 1600;
// Create mosques
function createMosques() {
// Destroy existing mosques first
for (var i = 0; i < mosques.length; i++) {
if (mosques[i].parent) {
mosques[i].destroy();
}
}
mosques = [];
var positions = [{
x: 400,
y: 800
}, {
x: 1600,
y: 800
}, {
x: 800,
y: 1000
}, {
x: 1200,
y: 1000
}, {
x: 600,
y: 1200
}];
for (var i = 0; i < positions.length; i++) {
var mosque = game.addChild(new Mosque());
mosque.x = positions[i].x;
mosque.y = positions[i].y;
mosque.isCompleted = false; // Ensure mosque starts uncompleted
mosques.push(mosque);
}
}
// Create boss for boss rounds
function createBoss() {
if (currentBoss && currentBoss.parent) {
currentBoss.destroy();
}
currentBoss = game.addChild(new Boss(currentLevel));
currentBoss.x = 1024;
currentBoss.y = 800;
}
// Create Christians for current round
function createChristians() {
christians = [];
// Boss levels (every 3rd round) have boss instead of regular Christians
if (roundNumber % 3 === 0) {
createBoss();
return; // No regular Christians on boss rounds
}
var christianCount = Math.min(roundNumber + 1, 4);
var colors = ['christian', 'christian2', 'christian3', 'christian'];
for (var i = 0; i < christianCount; i++) {
var christian = game.addChild(new Christian(colors[i % colors.length]));
christian.x = mosqueArea.left + 100 + Math.random() * (mosqueArea.right - mosqueArea.left - 200);
christian.y = mosqueArea.top + 100 + Math.random() * (mosqueArea.bottom - mosqueArea.top - 200);
christian.speed = 4 + roundNumber * 0.8;
christians.push(christian);
}
// Set impostors to reference christians for compatibility
impostors = christians;
// Set taskStations to reference mosques for compatibility
taskStations = mosques;
}
// Initialize first round
createMosques();
createChristians();
// Start level transition with pause
function startLevelTransition() {
isLevelTransition = true;
isLevelCompleted = true;
gameState = 'levelCompleted';
// Show level completion text
levelTransitionTxt.setText('Level ' + (currentLevel - 1) + ' Complete!');
tween(levelTransitionTxt, {
alpha: 1
}, {
duration: 1000,
onFinish: function onFinish() {
// Show continue button after text appears
tween(continueBtn, {
alpha: 1,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.easeOut
});
}
});
}
// Handle continue button click
continueBtn.down = function (x, y, obj) {
if (isLevelCompleted) {
// Fade out completion UI
tween(levelTransitionTxt, {
alpha: 0
}, {
duration: 500
});
tween(continueBtn, {
alpha: 0,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 500,
onFinish: function onFinish() {
isLevelCompleted = false;
isLevelTransition = false;
// Continue from level completion
gameState = 'playing';
continueNextRound();
}
});
}
};
// Continue next round after transition
function continueNextRound() {
prayersCompleted = 0; // Reset prayers completed for new round
roundTxt.setText('Round ' + roundNumber);
// Clean up old christians
for (var i = 0; i < christians.length; i++) {
if (christians[i].parent) {
christians[i].destroy();
}
}
// Clean up boss
if (currentBoss && currentBoss.parent) {
currentBoss.destroy();
currentBoss = null;
}
// Reset mosques
for (var i = 0; i < mosques.length; i++) {
mosques[i].isCompleted = false;
if (mosques[i].tint !== undefined) {
mosques[i].tint = 0xffffff;
}
}
// Create new christians or boss
createChristians();
// Update game state text based on round type
if (roundNumber % 3 === 0) {
gameStateTxt.setText('BOSS ROUND ' + roundNumber + ' - Complete prayers and prepare for final confrontation!');
} else {
gameStateTxt.setText('Round ' + roundNumber + ' - Complete prayers and avoid the pursuers!');
}
// Flash screen to indicate new round
LK.effects.flashScreen(0x0000ff, 500);
}
// Start next round
function startNextRound() {
roundNumber++;
tasksCompleted = 0;
prayersCompleted = 0; // Reset prayers completed for new round
// Level progression every 3 rounds
if (roundNumber % 3 === 1 && roundNumber > 1) {
currentLevel = Math.min(currentLevel + 1, maxLevel);
createLevelBackground();
levelTxt.setText('Level ' + currentLevel + ': ' + levelNames[currentLevel - 1]);
LK.getSound('levelComplete').play();
// Start level completion screen instead of immediately continuing
startLevelTransition();
return; // Exit early, transition will handle the rest
}
roundTxt.setText('Round ' + roundNumber);
// Clean up old christians
for (var i = 0; i < christians.length; i++) {
if (christians[i].parent) {
christians[i].destroy();
}
}
// Clean up boss
if (currentBoss && currentBoss.parent) {
currentBoss.destroy();
currentBoss = null;
}
// Reset mosques
for (var i = 0; i < mosques.length; i++) {
mosques[i].isCompleted = false;
if (mosques[i].tint !== undefined) {
mosques[i].tint = 0xffffff;
}
}
// Create new christians or boss
createChristians();
gameState = 'playing';
// Update game state text based on round type
if (roundNumber % 3 === 0) {
gameStateTxt.setText('BOSS ROUND ' + roundNumber + ' - Complete prayers and prepare for final confrontation!');
} else {
gameStateTxt.setText('Round ' + roundNumber + ' - Complete prayers and avoid the pursuers!');
}
// Flash screen to indicate new round
LK.effects.flashScreen(0x0000ff, 500);
}
// Handle player movement
function handleMove(x, y, obj) {
if (dragNode && player.isAlive && gameState === 'playing') {
var newX = Math.max(shipBounds.left + 40, Math.min(shipBounds.right - 40, x));
var newY = Math.max(shipBounds.top + 40, Math.min(shipBounds.bottom - 40, y));
dragNode.x = newX;
dragNode.y = newY;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
if (player.isAlive && gameState === 'playing') {
dragNode = player;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game update loop
game.update = function () {
if (!player.isAlive) return;
// Skip game logic during level transition or completion
if (isLevelTransition || gameState === 'transition' || gameState === 'levelCompleted') {
return;
}
if (gameState !== 'playing') return;
// Check collisions with christians (only non-identified ones)
for (var i = 0; i < christians.length; i++) {
if (!christians[i].isIdentified && player.intersects(christians[i])) {
// Player caught by christian
player.isAlive = false;
LK.effects.flashScreen(0xff0000, 1500);
LK.getSound('elimination').play();
LK.showGameOver();
return;
}
}
// Check collision with boss
if (currentBoss && !currentBoss.isDead && player.intersects(currentBoss)) {
// Player caught by boss
player.isAlive = false;
LK.effects.flashScreen(0xff0000, 1500);
LK.getSound('elimination').play();
LK.showGameOver();
return;
}
// Check mosque prayer completion
for (var i = 0; i < mosques.length; i++) {
var mosque = mosques[i];
if (!mosque.isCompleted && player.intersects(mosque)) {
mosque.isCompleted = true;
if (mosque.tint !== undefined) {
mosque.tint = 0x00ff00;
}
prayersCompleted++;
LK.setScore(LK.getScore() + 50);
LK.getSound('taskComplete').play();
scoreTxt.setText('Score: ' + LK.getScore());
// Check if all prayers completed
if (prayersCompleted >= mosques.length) {
startNextRound();
}
}
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Boss = Container.expand(function (level) {
var self = Container.call(this);
var graphics = self.attachAsset('bossChristian', {
anchorX: 0.5,
anchorY: 0.5
});
self.level = level || 1;
self.maxHealth = 3 + level;
self.health = self.maxHealth;
self.speed = 2 + level * 0.5;
self.direction = Math.random() * Math.PI * 2;
self.attackTimer = 0;
self.attackCooldown = 2000; // 2 seconds
self.isDead = false;
self.chargeAttacking = false;
self.chargeSpeed = 12;
// Health bar
var healthBarBg = self.addChild(LK.getAsset('shape', {
width: 120,
height: 20,
color: 0x660000,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
y: -100
}));
var healthBar = self.addChild(LK.getAsset('shape', {
width: 120,
height: 16,
color: 0xff0000,
shape: 'box',
anchorX: 0.5,
anchorY: 0.5,
y: -100
}));
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
healthBar.width = 120 * healthPercent;
};
self.update = function () {
if (self.isDead) return;
self.attackTimer += 16.67;
// Boss AI behavior
if (self.chargeAttacking) {
// Charge attack - move fast towards player
var deltaX = player.x - self.x;
var deltaY = player.y - self.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > 10) {
self.direction = Math.atan2(deltaY, deltaX);
var newX = self.x + Math.cos(self.direction) * self.chargeSpeed;
var newY = self.y + Math.sin(self.direction) * self.chargeSpeed;
// Keep within bounds
self.x = Math.max(shipBounds.left + 75, Math.min(shipBounds.right - 75, newX));
self.y = Math.max(shipBounds.top + 75, Math.min(shipBounds.bottom - 75, newY));
}
// End charge attack after 1 second
if (self.attackTimer >= 1000) {
self.chargeAttacking = false;
self.attackTimer = 0;
}
} else if (self.attackTimer >= self.attackCooldown) {
// Start charge attack
self.chargeAttacking = true;
self.attackTimer = 0;
LK.effects.flashObject(self, 0xffff00, 500);
} else {
// Normal movement - slower patrol
var deltaX = player.x - self.x;
var deltaY = player.y - self.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
if (distance > 200) {
// Move towards player if far away
self.direction = Math.atan2(deltaY, deltaX);
} else {
// Random movement when close
if (Math.random() < 0.02) {
self.direction = Math.random() * Math.PI * 2;
}
}
var newX = self.x + Math.cos(self.direction) * self.speed;
var newY = self.y + Math.sin(self.direction) * self.speed;
// Bounce off boundaries
if (newX < shipBounds.left + 75 || newX > shipBounds.right - 75) {
self.direction = Math.PI - self.direction;
}
if (newY < shipBounds.top + 75 || newY > shipBounds.bottom - 75) {
self.direction = -self.direction;
}
// Keep within bounds
self.x = Math.max(shipBounds.left + 75, Math.min(shipBounds.right - 75, newX));
self.y = Math.max(shipBounds.top + 75, Math.min(shipBounds.bottom - 75, newY));
}
};
self.takeDamage = function () {
if (self.isDead) return false;
self.health--;
self.updateHealthBar();
LK.effects.flashObject(self, 0xffffff, 300);
if (self.health <= 0) {
self.isDead = true;
LK.setScore(LK.getScore() + 500);
LK.getSound('faithVictory').play();
scoreTxt.setText('Score: ' + LK.getScore());
return true;
}
return false;
};
return self;
});
var Christian = Container.expand(function (colorAsset) {
var self = Container.call(this);
var graphics = self.attachAsset(colorAsset || 'christian', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 4;
self.direction = Math.random() * Math.PI * 2;
self.changeDirectionTimer = 0;
self.isIdentified = false;
self.update = function () {
if (self.isIdentified) return;
// Calculate direction towards player
var deltaX = player.x - self.x;
var deltaY = player.y - self.y;
var distance = Math.sqrt(deltaX * deltaX + deltaY * deltaY);
// Only chase if player is alive and within reasonable distance
if (player.isAlive && distance > 10) {
// Calculate angle towards player
self.direction = Math.atan2(deltaY, deltaX);
// Add some randomness to make movement less predictable
var randomOffset = (Math.random() - 0.5) * 0.3;
self.direction += randomOffset;
}
// Move in current direction
var newX = self.x + Math.cos(self.direction) * self.speed;
var newY = self.y + Math.sin(self.direction) * self.speed;
// Bounce off ship boundaries
if (newX < shipBounds.left + 40 || newX > shipBounds.right - 40) {
self.direction = Math.PI - self.direction;
}
if (newY < shipBounds.top + 40 || newY > shipBounds.bottom - 40) {
self.direction = -self.direction;
}
// Keep within bounds
self.x = Math.max(shipBounds.left + 40, Math.min(shipBounds.right - 40, newX));
self.y = Math.max(shipBounds.top + 40, Math.min(shipBounds.bottom - 40, newY));
};
return self;
});
var Mosque = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('mosque', {
anchorX: 0.5,
anchorY: 0.5
});
self.isCompleted = false;
return self;
});
var Muslim = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('muslim', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.isAlive = true;
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1a1a2e
});
/****
* Game Code
****/
// Game variables
var player;
var christians = [];
var mosques = [];
var mosqueArea = {};
var gameState = 'playing'; // 'playing', 'praying', 'roundEnd'
var roundNumber = 1;
var prayersCompleted = 0;
var prayingTimer = 0;
var prayingDuration = 5000; // 5 seconds for praying
var dragNode = null;
// Missing variables that are referenced in the code
var shipBounds = {};
var impostors = [];
var taskStations = [];
var tasksCompleted = 0;
// Level system variables
var currentLevel = 1;
var maxLevel = 4;
var currentBoss = null;
var levelNames = ['Main Mosque', 'Prayer Hall', 'Minaret', 'Sacred Courtyard'];
var levelBackgrounds = ['courtyard', 'mainMosque', 'prayerHall', 'minaret'];
var currentMosque = null;
var isLevelTransition = false;
var levelTransitionDuration = 8000; // 8 seconds pause between levels
var isLevelCompleted = false;
// UI Elements
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var gameStateTxt = new Text2('Visit mosques to pray and avoid the pursuers!', {
size: 60,
fill: 0xFFFF00
});
gameStateTxt.anchor.set(0.5, 0);
gameStateTxt.y = 100;
LK.gui.top.addChild(gameStateTxt);
var roundTxt = new Text2('Round 1', {
size: 70,
fill: 0x00FFFF
});
roundTxt.anchor.set(0, 0);
LK.gui.topLeft.addChild(roundTxt);
roundTxt.x = 120; // Avoid the menu icon
var levelTxt = new Text2('Level 1: Main Mosque', {
size: 60,
fill: 0xff9900
});
levelTxt.anchor.set(0, 0);
levelTxt.y = 80;
LK.gui.topLeft.addChild(levelTxt);
levelTxt.x = 120;
var levelTransitionTxt = new Text2('', {
size: 120,
fill: 0xffff00
});
levelTransitionTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(levelTransitionTxt);
levelTransitionTxt.alpha = 0;
// Continue button for level completion
var continueBtn = new Text2('CONTINUE', {
size: 100,
fill: 0x00ff00
});
continueBtn.anchor.set(0.5, 0.5);
continueBtn.y = 200;
LK.gui.center.addChild(continueBtn);
continueBtn.alpha = 0;
continueBtn.interactive = true;
// Create level background
function createLevelBackground() {
if (currentMosque && currentMosque.parent) {
currentMosque.destroy();
}
var backgroundAsset = levelBackgrounds[currentLevel - 1] || 'courtyard';
currentMosque = game.attachAsset(backgroundAsset, {
anchorX: 0.5,
anchorY: 0.5,
x: 1024,
y: 1366
});
// Update mosque boundaries after creating new background
mosqueArea = {
left: currentMosque.x - currentMosque.width / 2,
right: currentMosque.x + currentMosque.width / 2,
top: currentMosque.y - currentMosque.height / 2,
bottom: currentMosque.y + currentMosque.height / 2
};
// Create fresh mosques for the new level
createMosques();
}
createLevelBackground();
// Set mosque boundaries
mosqueArea = {
left: currentMosque.x - currentMosque.width / 2,
right: currentMosque.x + currentMosque.width / 2,
top: currentMosque.y - currentMosque.height / 2,
bottom: currentMosque.y + currentMosque.height / 2
};
// Initialize shipBounds to match mosqueArea
shipBounds = {
left: mosqueArea.left,
right: mosqueArea.right,
top: mosqueArea.top,
bottom: mosqueArea.bottom
};
// Create player
player = game.addChild(new Muslim());
player.x = 1024;
player.y = 1600;
// Create mosques
function createMosques() {
// Destroy existing mosques first
for (var i = 0; i < mosques.length; i++) {
if (mosques[i].parent) {
mosques[i].destroy();
}
}
mosques = [];
var positions = [{
x: 400,
y: 800
}, {
x: 1600,
y: 800
}, {
x: 800,
y: 1000
}, {
x: 1200,
y: 1000
}, {
x: 600,
y: 1200
}];
for (var i = 0; i < positions.length; i++) {
var mosque = game.addChild(new Mosque());
mosque.x = positions[i].x;
mosque.y = positions[i].y;
mosque.isCompleted = false; // Ensure mosque starts uncompleted
mosques.push(mosque);
}
}
// Create boss for boss rounds
function createBoss() {
if (currentBoss && currentBoss.parent) {
currentBoss.destroy();
}
currentBoss = game.addChild(new Boss(currentLevel));
currentBoss.x = 1024;
currentBoss.y = 800;
}
// Create Christians for current round
function createChristians() {
christians = [];
// Boss levels (every 3rd round) have boss instead of regular Christians
if (roundNumber % 3 === 0) {
createBoss();
return; // No regular Christians on boss rounds
}
var christianCount = Math.min(roundNumber + 1, 4);
var colors = ['christian', 'christian2', 'christian3', 'christian'];
for (var i = 0; i < christianCount; i++) {
var christian = game.addChild(new Christian(colors[i % colors.length]));
christian.x = mosqueArea.left + 100 + Math.random() * (mosqueArea.right - mosqueArea.left - 200);
christian.y = mosqueArea.top + 100 + Math.random() * (mosqueArea.bottom - mosqueArea.top - 200);
christian.speed = 4 + roundNumber * 0.8;
christians.push(christian);
}
// Set impostors to reference christians for compatibility
impostors = christians;
// Set taskStations to reference mosques for compatibility
taskStations = mosques;
}
// Initialize first round
createMosques();
createChristians();
// Start level transition with pause
function startLevelTransition() {
isLevelTransition = true;
isLevelCompleted = true;
gameState = 'levelCompleted';
// Show level completion text
levelTransitionTxt.setText('Level ' + (currentLevel - 1) + ' Complete!');
tween(levelTransitionTxt, {
alpha: 1
}, {
duration: 1000,
onFinish: function onFinish() {
// Show continue button after text appears
tween(continueBtn, {
alpha: 1,
scaleX: 1.1,
scaleY: 1.1
}, {
duration: 800,
easing: tween.easeOut
});
}
});
}
// Handle continue button click
continueBtn.down = function (x, y, obj) {
if (isLevelCompleted) {
// Fade out completion UI
tween(levelTransitionTxt, {
alpha: 0
}, {
duration: 500
});
tween(continueBtn, {
alpha: 0,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 500,
onFinish: function onFinish() {
isLevelCompleted = false;
isLevelTransition = false;
// Continue from level completion
gameState = 'playing';
continueNextRound();
}
});
}
};
// Continue next round after transition
function continueNextRound() {
prayersCompleted = 0; // Reset prayers completed for new round
roundTxt.setText('Round ' + roundNumber);
// Clean up old christians
for (var i = 0; i < christians.length; i++) {
if (christians[i].parent) {
christians[i].destroy();
}
}
// Clean up boss
if (currentBoss && currentBoss.parent) {
currentBoss.destroy();
currentBoss = null;
}
// Reset mosques
for (var i = 0; i < mosques.length; i++) {
mosques[i].isCompleted = false;
if (mosques[i].tint !== undefined) {
mosques[i].tint = 0xffffff;
}
}
// Create new christians or boss
createChristians();
// Update game state text based on round type
if (roundNumber % 3 === 0) {
gameStateTxt.setText('BOSS ROUND ' + roundNumber + ' - Complete prayers and prepare for final confrontation!');
} else {
gameStateTxt.setText('Round ' + roundNumber + ' - Complete prayers and avoid the pursuers!');
}
// Flash screen to indicate new round
LK.effects.flashScreen(0x0000ff, 500);
}
// Start next round
function startNextRound() {
roundNumber++;
tasksCompleted = 0;
prayersCompleted = 0; // Reset prayers completed for new round
// Level progression every 3 rounds
if (roundNumber % 3 === 1 && roundNumber > 1) {
currentLevel = Math.min(currentLevel + 1, maxLevel);
createLevelBackground();
levelTxt.setText('Level ' + currentLevel + ': ' + levelNames[currentLevel - 1]);
LK.getSound('levelComplete').play();
// Start level completion screen instead of immediately continuing
startLevelTransition();
return; // Exit early, transition will handle the rest
}
roundTxt.setText('Round ' + roundNumber);
// Clean up old christians
for (var i = 0; i < christians.length; i++) {
if (christians[i].parent) {
christians[i].destroy();
}
}
// Clean up boss
if (currentBoss && currentBoss.parent) {
currentBoss.destroy();
currentBoss = null;
}
// Reset mosques
for (var i = 0; i < mosques.length; i++) {
mosques[i].isCompleted = false;
if (mosques[i].tint !== undefined) {
mosques[i].tint = 0xffffff;
}
}
// Create new christians or boss
createChristians();
gameState = 'playing';
// Update game state text based on round type
if (roundNumber % 3 === 0) {
gameStateTxt.setText('BOSS ROUND ' + roundNumber + ' - Complete prayers and prepare for final confrontation!');
} else {
gameStateTxt.setText('Round ' + roundNumber + ' - Complete prayers and avoid the pursuers!');
}
// Flash screen to indicate new round
LK.effects.flashScreen(0x0000ff, 500);
}
// Handle player movement
function handleMove(x, y, obj) {
if (dragNode && player.isAlive && gameState === 'playing') {
var newX = Math.max(shipBounds.left + 40, Math.min(shipBounds.right - 40, x));
var newY = Math.max(shipBounds.top + 40, Math.min(shipBounds.bottom - 40, y));
dragNode.x = newX;
dragNode.y = newY;
}
}
game.move = handleMove;
game.down = function (x, y, obj) {
if (player.isAlive && gameState === 'playing') {
dragNode = player;
handleMove(x, y, obj);
}
};
game.up = function (x, y, obj) {
dragNode = null;
};
// Main game update loop
game.update = function () {
if (!player.isAlive) return;
// Skip game logic during level transition or completion
if (isLevelTransition || gameState === 'transition' || gameState === 'levelCompleted') {
return;
}
if (gameState !== 'playing') return;
// Check collisions with christians (only non-identified ones)
for (var i = 0; i < christians.length; i++) {
if (!christians[i].isIdentified && player.intersects(christians[i])) {
// Player caught by christian
player.isAlive = false;
LK.effects.flashScreen(0xff0000, 1500);
LK.getSound('elimination').play();
LK.showGameOver();
return;
}
}
// Check collision with boss
if (currentBoss && !currentBoss.isDead && player.intersects(currentBoss)) {
// Player caught by boss
player.isAlive = false;
LK.effects.flashScreen(0xff0000, 1500);
LK.getSound('elimination').play();
LK.showGameOver();
return;
}
// Check mosque prayer completion
for (var i = 0; i < mosques.length; i++) {
var mosque = mosques[i];
if (!mosque.isCompleted && player.intersects(mosque)) {
mosque.isCompleted = true;
if (mosque.tint !== undefined) {
mosque.tint = 0x00ff00;
}
prayersCompleted++;
LK.setScore(LK.getScore() + 50);
LK.getSound('taskComplete').play();
scoreTxt.setText('Score: ' + LK.getScore());
// Check if all prayers completed
if (prayersCompleted >= mosques.length) {
startNextRound();
}
}
}
};