/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1", { bestScore: 0 }); var facekit = LK.import("@upit/facekit.v1"); /**** * Classes ****/ var Base = Container.expand(function () { var self = Container.call(this); self.graphics = self.attachAsset('base', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.isPlayerBase = true; // Health bar background self.healthBarBg = self.attachAsset('unit', { width: 300, height: 20, color: 0x000000, anchorX: 0.5, anchorY: 0.5, y: -180 }); // Health bar foreground self.healthBar = self.attachAsset('unit', { width: 300, height: 20, color: 0x00ff00, anchorX: 0, anchorY: 0.5, y: -180, x: -150 }); self.takeDamage = function (amount) { self.health -= amount; if (self.health < 0) { self.health = 0; } // Update health bar width self.healthBar.width = self.health / 100 * 300; if (self.health <= 0 && self.isPlayerBase) { LK.showGameOver(); } else if (self.health <= 0 && !self.isPlayerBase) { // Player wins LK.setScore(LK.getScore() + 1000); LK.showYouWin(); } }; return self; }); var EnemyBase = Base.expand(function () { var self = Base.call(this); // Override base graphics with enemy base self.graphics.destroy(); self.graphics = self.attachAsset('enemyBase', { anchorX: 0.5, anchorY: 0.5 }); self.healthBar.tint = 0xff0000; self.isPlayerBase = false; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); self.graphics = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 3; self.alive = true; self.targetUnit = null; self.lastPosition = { x: 0, y: 0 }; self.update = function () { if (!self.alive) { return; } self.lastPosition.x = self.x; self.lastPosition.y = self.y; // If we have a target unit, move toward it if (self.targetUnit && self.targetUnit.alive) { var dx = self.targetUnit.x - self.x; var dy = self.targetUnit.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > self.speed) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } } else { // No target or target is dead, find new target self.findNewTarget(); } }; self.findNewTarget = function () { var closestUnit = null; var closestDistance = Infinity; // Find the closest military unit for (var i = 0; i < units.length; i++) { var unit = units[i]; if (!unit.alive) { continue; } var dx = unit.x - self.x; var dy = unit.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); // If target is in stealth mode and not super close, can't detect it if (unit.state === "stealth" && distance > 100) { continue; } if (distance < closestDistance) { closestDistance = distance; closestUnit = unit; } } self.targetUnit = closestUnit; }; self.kill = function () { if (!self.alive) { return; } self.alive = false; tween(self, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { self.destroy(); } }); }; return self; }); var MilitaryUnit = Container.expand(function () { var self = Container.call(this); // Default state is normal self.state = "normal"; self.targetPosition = null; self.speed = 5; self.alive = true; self.score = 0; // Normal unit representation self.normalGraphics = self.attachAsset('unit', { anchorX: 0.5, anchorY: 0.5 }); // Stealth unit representation (initially hidden) self.stealthGraphics = self.attachAsset('stealth', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); // Attack unit representation (initially hidden) self.attackGraphics = self.attachAsset('attack', { anchorX: 0.5, anchorY: 0.5, alpha: 0 }); // Set initial state self.setState = function (newState) { if (newState === self.state) { return; } // Hide all graphics first self.normalGraphics.alpha = 0; self.stealthGraphics.alpha = 0; self.attackGraphics.alpha = 0; // Show the appropriate graphics if (newState === "normal") { self.normalGraphics.alpha = 1; self.speed = 5; } else if (newState === "stealth") { self.stealthGraphics.alpha = 1; self.speed = 3; // Slower in stealth mode } else if (newState === "attack") { self.attackGraphics.alpha = 1; self.speed = 7; // Faster in attack mode } self.state = newState; }; // Move toward target if one is set self.update = function () { if (!self.alive) { return; } if (self.targetPosition) { var dx = self.targetPosition.x - self.x; var dy = self.targetPosition.y - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > self.speed) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } else { self.x = self.targetPosition.x; self.y = self.targetPosition.y; self.targetPosition = null; } } }; // Destroy unit self.kill = function () { if (!self.alive) { return; } self.alive = false; tween(self, { alpha: 0 }, { duration: 500, onFinish: function onFinish() { self.destroy(); } }); }; return self; }); var Target = Container.expand(function () { var self = Container.call(this); self.graphics = self.attachAsset('target', { anchorX: 0.5, anchorY: 0.5, alpha: 0.5 }); // Pulse animation self.pulse = function () { tween(self.graphics, { alpha: 0.8, scaleX: 1.2, scaleY: 1.2 }, { duration: 500, easing: tween.easeOut, onFinish: function onFinish() { tween(self.graphics, { alpha: 0.5, scaleX: 1, scaleY: 1 }, { duration: 500, easing: tween.easeIn }); } }); }; self.pulse(); return self; }); var VoiceIndicator = Container.expand(function () { var self = Container.call(this); // Background self.bg = self.attachAsset('unit', { width: 400, height: 100, color: 0x000000, anchorX: 0.5, anchorY: 0.5, alpha: 0.5 }); // Voice level indicator self.level = self.attachAsset('unit', { width: 0, height: 80, color: 0x00ff00, anchorX: 0, anchorY: 0.5, x: -190 }); // Text labels self.whisperText = new Text2("Whisper", { size: 40, fill: 0xFFFFFF }); self.whisperText.anchor.set(0.5); self.whisperText.x = -135; self.whisperText.y = 50; self.addChild(self.whisperText); self.normalText = new Text2("Normal", { size: 40, fill: 0xFFFFFF }); self.normalText.anchor.set(0.5); self.normalText.x = 0; self.normalText.y = 50; self.addChild(self.normalText); self.shoutText = new Text2("Shout", { size: 40, fill: 0xFFFFFF }); self.shoutText.anchor.set(0.5); self.shoutText.x = 135; self.shoutText.y = 50; self.addChild(self.shoutText); // Update the indicator based on volume self.update = function () { var volume = facekit.volume; // Calculate width based on volume (0-1) var width = volume * 380; self.level.width = width; // Change color based on volume if (volume < 0.3) { self.level.tint = 0x33cc33; // Green for whisper } else if (volume > 0.7) { self.level.tint = 0xcc3333; // Red for shout } else { self.level.tint = 0x3366cc; // Blue for normal } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Game state variables var units = []; var enemies = []; var target = null; var playerBase = null; var enemyBase = null; var voiceIndicator = null; var voiceMode = "normal"; var lastVoiceMode = "normal"; var lastSpawnTime = 0; var currentWave = 1; var gameStarted = false; // Setup GUI var scoreTxt = new Text2("Score: 0", { size: 60, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var waveTxt = new Text2("Wave: 1", { size: 60, fill: 0xFFFFFF }); waveTxt.anchor.set(1, 0); waveTxt.x = -50; LK.gui.topRight.addChild(waveTxt); var instructionsTxt = new Text2("Use your voice to command units:\nWhisper - Stealth Mode\nNormal Voice - Normal Mode\nShout - Attack Mode\n\nTap to place target location", { size: 50, fill: 0xFFFFFF }); instructionsTxt.anchor.set(0.5, 0.5); LK.gui.center.addChild(instructionsTxt); var startButton = LK.getAsset('unit', { width: 300, height: 100, color: 0x3366cc, anchorX: 0.5, anchorY: 0.5 }); LK.gui.center.addChild(startButton); startButton.y = 200; var startText = new Text2("START", { size: 60, fill: 0xFFFFFF }); startText.anchor.set(0.5, 0.5); startButton.addChild(startText); // Start game when button is pressed startButton.down = function () { startGame(); }; function startGame() { gameStarted = true; LK.gui.center.removeChild(instructionsTxt); LK.gui.center.removeChild(startButton); // Create bases playerBase = new Base(); playerBase.x = 1024; playerBase.y = 2300; game.addChild(playerBase); enemyBase = new EnemyBase(); enemyBase.x = 1024; enemyBase.y = 400; game.addChild(enemyBase); // Create voice indicator voiceIndicator = new VoiceIndicator(); voiceIndicator.x = 1024; voiceIndicator.y = 2600; game.addChild(voiceIndicator); // Create initial units createUnit(900, 2000); createUnit(1150, 2000); // Start background music LK.playMusic('bgmusic'); } function createUnit(x, y) { var unit = new MilitaryUnit(); unit.x = x; unit.y = y; game.addChild(unit); units.push(unit); return unit; } function createEnemy(x, y) { var enemy = new Enemy(); enemy.x = x; enemy.y = y; game.addChild(enemy); enemies.push(enemy); return enemy; } function spawnEnemies() { var now = Date.now(); if (now - lastSpawnTime > 5000) { // Spawn every 5 seconds lastSpawnTime = now; // Spawn enemies based on wave var count = Math.min(2 + currentWave, 8); for (var i = 0; i < count; i++) { var x = 400 + Math.random() * 1248; var y = 400 + Math.random() * 200; createEnemy(x, y); } // Increase wave currentWave++; waveTxt.setText("Wave: " + currentWave); } } function createTarget(x, y) { // Remove existing target if there is one if (target) { target.destroy(); } // Create new target target = new Target(); target.x = x; target.y = y; game.addChild(target); // Command all units to move to target for (var i = 0; i < units.length; i++) { if (units[i].alive) { units[i].targetPosition = { x: x, y: y }; } } // Play sound based on voice mode if (voiceMode === "stealth") { LK.getSound('stealth').play(); } else if (voiceMode === "attack") { LK.getSound('attack').play(); } else { LK.getSound('order').play(); } } function checkCollisions() { // Check for enemy-unit collisions for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (!enemy.alive) { continue; } // Check collision with player base if (playerBase && enemy.intersects(playerBase)) { playerBase.takeDamage(1); enemy.kill(); enemies.splice(i, 1); continue; } // Check collision with units for (var j = units.length - 1; j >= 0; j--) { var unit = units[j]; if (!unit.alive) { continue; } if (unit.intersects(enemy)) { // Combat outcome depends on unit state if (unit.state === "attack") { // Unit is in attack mode, more likely to win enemy.kill(); enemies.splice(i, 1); LK.setScore(LK.getScore() + 100); break; } else if (unit.state === "stealth") { // Stealth units can sometimes evade if (Math.random() > 0.7) { // Unit escapes unit.x += Math.random() * 100 - 50; unit.y += Math.random() * 100 - 50; } else { unit.kill(); units.splice(j, 1); } } else { // Normal combat, 50/50 chance if (Math.random() > 0.5) { enemy.kill(); enemies.splice(i, 1); LK.setScore(LK.getScore() + 50); } else { unit.kill(); units.splice(j, 1); } break; } } } } // Check for units reaching enemy base for (var k = units.length - 1; k >= 0; k--) { var unit = units[k]; if (!unit.alive) { continue; } if (enemyBase && unit.intersects(enemyBase)) { // Unit is attacking enemy base var damage = unit.state === "attack" ? 20 : 10; enemyBase.takeDamage(damage); unit.kill(); units.splice(k, 1); LK.setScore(LK.getScore() + 200); } } } function determineVoiceMode() { var volume = facekit.volume; if (volume < 0.1) { // No sound, keep previous mode return voiceMode; } else if (volume < 0.3) { return "stealth"; } else if (volume > 0.7) { return "attack"; } else { return "normal"; } } function spawnNewUnits() { // Spawn new units every 10 seconds if we have fewer than 5 if (LK.ticks % 600 === 0 && units.length < 5) { createUnit(900 + Math.random() * 250, 2000 + Math.random() * 200); } } function updateScore() { scoreTxt.setText("Score: " + LK.getScore()); // Store best score if current score is higher if (LK.getScore() > storage.bestScore) { storage.bestScore = LK.getScore(); } } // Game down event - place target game.down = function (x, y) { if (!gameStarted) { return; } // Don't place target too close to enemy base or on bases var distToEnemyBase = Math.sqrt(Math.pow(x - enemyBase.x, 2) + Math.pow(y - enemyBase.y, 2)); var distToPlayerBase = Math.sqrt(Math.pow(x - playerBase.x, 2) + Math.pow(y - playerBase.y, 2)); if (distToEnemyBase > 350 && distToPlayerBase > 350) { createTarget(x, y); } }; // Game tick event game.update = function () { if (!gameStarted) { return; } // Update voice mode based on audio input voiceMode = determineVoiceMode(); // Update voice indicator if (voiceIndicator) { voiceIndicator.update(); } // Update all units with current voice mode if (voiceMode !== lastVoiceMode) { for (var i = 0; i < units.length; i++) { if (units[i].alive) { units[i].setState(voiceMode); } } lastVoiceMode = voiceMode; } // Check for collisions checkCollisions(); // Spawn enemies spawnEnemies(); // Spawn new units if needed spawnNewUnits(); // Update score display updateScore(); };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
bestScore: 0
});
var facekit = LK.import("@upit/facekit.v1");
/****
* Classes
****/
var Base = Container.expand(function () {
var self = Container.call(this);
self.graphics = self.attachAsset('base', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.isPlayerBase = true;
// Health bar background
self.healthBarBg = self.attachAsset('unit', {
width: 300,
height: 20,
color: 0x000000,
anchorX: 0.5,
anchorY: 0.5,
y: -180
});
// Health bar foreground
self.healthBar = self.attachAsset('unit', {
width: 300,
height: 20,
color: 0x00ff00,
anchorX: 0,
anchorY: 0.5,
y: -180,
x: -150
});
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health < 0) {
self.health = 0;
}
// Update health bar width
self.healthBar.width = self.health / 100 * 300;
if (self.health <= 0 && self.isPlayerBase) {
LK.showGameOver();
} else if (self.health <= 0 && !self.isPlayerBase) {
// Player wins
LK.setScore(LK.getScore() + 1000);
LK.showYouWin();
}
};
return self;
});
var EnemyBase = Base.expand(function () {
var self = Base.call(this);
// Override base graphics with enemy base
self.graphics.destroy();
self.graphics = self.attachAsset('enemyBase', {
anchorX: 0.5,
anchorY: 0.5
});
self.healthBar.tint = 0xff0000;
self.isPlayerBase = false;
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
self.graphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.alive = true;
self.targetUnit = null;
self.lastPosition = {
x: 0,
y: 0
};
self.update = function () {
if (!self.alive) {
return;
}
self.lastPosition.x = self.x;
self.lastPosition.y = self.y;
// If we have a target unit, move toward it
if (self.targetUnit && self.targetUnit.alive) {
var dx = self.targetUnit.x - self.x;
var dy = self.targetUnit.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.speed) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
} else {
// No target or target is dead, find new target
self.findNewTarget();
}
};
self.findNewTarget = function () {
var closestUnit = null;
var closestDistance = Infinity;
// Find the closest military unit
for (var i = 0; i < units.length; i++) {
var unit = units[i];
if (!unit.alive) {
continue;
}
var dx = unit.x - self.x;
var dy = unit.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// If target is in stealth mode and not super close, can't detect it
if (unit.state === "stealth" && distance > 100) {
continue;
}
if (distance < closestDistance) {
closestDistance = distance;
closestUnit = unit;
}
}
self.targetUnit = closestUnit;
};
self.kill = function () {
if (!self.alive) {
return;
}
self.alive = false;
tween(self, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var MilitaryUnit = Container.expand(function () {
var self = Container.call(this);
// Default state is normal
self.state = "normal";
self.targetPosition = null;
self.speed = 5;
self.alive = true;
self.score = 0;
// Normal unit representation
self.normalGraphics = self.attachAsset('unit', {
anchorX: 0.5,
anchorY: 0.5
});
// Stealth unit representation (initially hidden)
self.stealthGraphics = self.attachAsset('stealth', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
// Attack unit representation (initially hidden)
self.attackGraphics = self.attachAsset('attack', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0
});
// Set initial state
self.setState = function (newState) {
if (newState === self.state) {
return;
}
// Hide all graphics first
self.normalGraphics.alpha = 0;
self.stealthGraphics.alpha = 0;
self.attackGraphics.alpha = 0;
// Show the appropriate graphics
if (newState === "normal") {
self.normalGraphics.alpha = 1;
self.speed = 5;
} else if (newState === "stealth") {
self.stealthGraphics.alpha = 1;
self.speed = 3; // Slower in stealth mode
} else if (newState === "attack") {
self.attackGraphics.alpha = 1;
self.speed = 7; // Faster in attack mode
}
self.state = newState;
};
// Move toward target if one is set
self.update = function () {
if (!self.alive) {
return;
}
if (self.targetPosition) {
var dx = self.targetPosition.x - self.x;
var dy = self.targetPosition.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > self.speed) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
self.x = self.targetPosition.x;
self.y = self.targetPosition.y;
self.targetPosition = null;
}
}
};
// Destroy unit
self.kill = function () {
if (!self.alive) {
return;
}
self.alive = false;
tween(self, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
self.destroy();
}
});
};
return self;
});
var Target = Container.expand(function () {
var self = Container.call(this);
self.graphics = self.attachAsset('target', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
// Pulse animation
self.pulse = function () {
tween(self.graphics, {
alpha: 0.8,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self.graphics, {
alpha: 0.5,
scaleX: 1,
scaleY: 1
}, {
duration: 500,
easing: tween.easeIn
});
}
});
};
self.pulse();
return self;
});
var VoiceIndicator = Container.expand(function () {
var self = Container.call(this);
// Background
self.bg = self.attachAsset('unit', {
width: 400,
height: 100,
color: 0x000000,
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.5
});
// Voice level indicator
self.level = self.attachAsset('unit', {
width: 0,
height: 80,
color: 0x00ff00,
anchorX: 0,
anchorY: 0.5,
x: -190
});
// Text labels
self.whisperText = new Text2("Whisper", {
size: 40,
fill: 0xFFFFFF
});
self.whisperText.anchor.set(0.5);
self.whisperText.x = -135;
self.whisperText.y = 50;
self.addChild(self.whisperText);
self.normalText = new Text2("Normal", {
size: 40,
fill: 0xFFFFFF
});
self.normalText.anchor.set(0.5);
self.normalText.x = 0;
self.normalText.y = 50;
self.addChild(self.normalText);
self.shoutText = new Text2("Shout", {
size: 40,
fill: 0xFFFFFF
});
self.shoutText.anchor.set(0.5);
self.shoutText.x = 135;
self.shoutText.y = 50;
self.addChild(self.shoutText);
// Update the indicator based on volume
self.update = function () {
var volume = facekit.volume;
// Calculate width based on volume (0-1)
var width = volume * 380;
self.level.width = width;
// Change color based on volume
if (volume < 0.3) {
self.level.tint = 0x33cc33; // Green for whisper
} else if (volume > 0.7) {
self.level.tint = 0xcc3333; // Red for shout
} else {
self.level.tint = 0x3366cc; // Blue for normal
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Game state variables
var units = [];
var enemies = [];
var target = null;
var playerBase = null;
var enemyBase = null;
var voiceIndicator = null;
var voiceMode = "normal";
var lastVoiceMode = "normal";
var lastSpawnTime = 0;
var currentWave = 1;
var gameStarted = false;
// Setup GUI
var scoreTxt = new Text2("Score: 0", {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var waveTxt = new Text2("Wave: 1", {
size: 60,
fill: 0xFFFFFF
});
waveTxt.anchor.set(1, 0);
waveTxt.x = -50;
LK.gui.topRight.addChild(waveTxt);
var instructionsTxt = new Text2("Use your voice to command units:\nWhisper - Stealth Mode\nNormal Voice - Normal Mode\nShout - Attack Mode\n\nTap to place target location", {
size: 50,
fill: 0xFFFFFF
});
instructionsTxt.anchor.set(0.5, 0.5);
LK.gui.center.addChild(instructionsTxt);
var startButton = LK.getAsset('unit', {
width: 300,
height: 100,
color: 0x3366cc,
anchorX: 0.5,
anchorY: 0.5
});
LK.gui.center.addChild(startButton);
startButton.y = 200;
var startText = new Text2("START", {
size: 60,
fill: 0xFFFFFF
});
startText.anchor.set(0.5, 0.5);
startButton.addChild(startText);
// Start game when button is pressed
startButton.down = function () {
startGame();
};
function startGame() {
gameStarted = true;
LK.gui.center.removeChild(instructionsTxt);
LK.gui.center.removeChild(startButton);
// Create bases
playerBase = new Base();
playerBase.x = 1024;
playerBase.y = 2300;
game.addChild(playerBase);
enemyBase = new EnemyBase();
enemyBase.x = 1024;
enemyBase.y = 400;
game.addChild(enemyBase);
// Create voice indicator
voiceIndicator = new VoiceIndicator();
voiceIndicator.x = 1024;
voiceIndicator.y = 2600;
game.addChild(voiceIndicator);
// Create initial units
createUnit(900, 2000);
createUnit(1150, 2000);
// Start background music
LK.playMusic('bgmusic');
}
function createUnit(x, y) {
var unit = new MilitaryUnit();
unit.x = x;
unit.y = y;
game.addChild(unit);
units.push(unit);
return unit;
}
function createEnemy(x, y) {
var enemy = new Enemy();
enemy.x = x;
enemy.y = y;
game.addChild(enemy);
enemies.push(enemy);
return enemy;
}
function spawnEnemies() {
var now = Date.now();
if (now - lastSpawnTime > 5000) {
// Spawn every 5 seconds
lastSpawnTime = now;
// Spawn enemies based on wave
var count = Math.min(2 + currentWave, 8);
for (var i = 0; i < count; i++) {
var x = 400 + Math.random() * 1248;
var y = 400 + Math.random() * 200;
createEnemy(x, y);
}
// Increase wave
currentWave++;
waveTxt.setText("Wave: " + currentWave);
}
}
function createTarget(x, y) {
// Remove existing target if there is one
if (target) {
target.destroy();
}
// Create new target
target = new Target();
target.x = x;
target.y = y;
game.addChild(target);
// Command all units to move to target
for (var i = 0; i < units.length; i++) {
if (units[i].alive) {
units[i].targetPosition = {
x: x,
y: y
};
}
}
// Play sound based on voice mode
if (voiceMode === "stealth") {
LK.getSound('stealth').play();
} else if (voiceMode === "attack") {
LK.getSound('attack').play();
} else {
LK.getSound('order').play();
}
}
function checkCollisions() {
// Check for enemy-unit collisions
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (!enemy.alive) {
continue;
}
// Check collision with player base
if (playerBase && enemy.intersects(playerBase)) {
playerBase.takeDamage(1);
enemy.kill();
enemies.splice(i, 1);
continue;
}
// Check collision with units
for (var j = units.length - 1; j >= 0; j--) {
var unit = units[j];
if (!unit.alive) {
continue;
}
if (unit.intersects(enemy)) {
// Combat outcome depends on unit state
if (unit.state === "attack") {
// Unit is in attack mode, more likely to win
enemy.kill();
enemies.splice(i, 1);
LK.setScore(LK.getScore() + 100);
break;
} else if (unit.state === "stealth") {
// Stealth units can sometimes evade
if (Math.random() > 0.7) {
// Unit escapes
unit.x += Math.random() * 100 - 50;
unit.y += Math.random() * 100 - 50;
} else {
unit.kill();
units.splice(j, 1);
}
} else {
// Normal combat, 50/50 chance
if (Math.random() > 0.5) {
enemy.kill();
enemies.splice(i, 1);
LK.setScore(LK.getScore() + 50);
} else {
unit.kill();
units.splice(j, 1);
}
break;
}
}
}
}
// Check for units reaching enemy base
for (var k = units.length - 1; k >= 0; k--) {
var unit = units[k];
if (!unit.alive) {
continue;
}
if (enemyBase && unit.intersects(enemyBase)) {
// Unit is attacking enemy base
var damage = unit.state === "attack" ? 20 : 10;
enemyBase.takeDamage(damage);
unit.kill();
units.splice(k, 1);
LK.setScore(LK.getScore() + 200);
}
}
}
function determineVoiceMode() {
var volume = facekit.volume;
if (volume < 0.1) {
// No sound, keep previous mode
return voiceMode;
} else if (volume < 0.3) {
return "stealth";
} else if (volume > 0.7) {
return "attack";
} else {
return "normal";
}
}
function spawnNewUnits() {
// Spawn new units every 10 seconds if we have fewer than 5
if (LK.ticks % 600 === 0 && units.length < 5) {
createUnit(900 + Math.random() * 250, 2000 + Math.random() * 200);
}
}
function updateScore() {
scoreTxt.setText("Score: " + LK.getScore());
// Store best score if current score is higher
if (LK.getScore() > storage.bestScore) {
storage.bestScore = LK.getScore();
}
}
// Game down event - place target
game.down = function (x, y) {
if (!gameStarted) {
return;
}
// Don't place target too close to enemy base or on bases
var distToEnemyBase = Math.sqrt(Math.pow(x - enemyBase.x, 2) + Math.pow(y - enemyBase.y, 2));
var distToPlayerBase = Math.sqrt(Math.pow(x - playerBase.x, 2) + Math.pow(y - playerBase.y, 2));
if (distToEnemyBase > 350 && distToPlayerBase > 350) {
createTarget(x, y);
}
};
// Game tick event
game.update = function () {
if (!gameStarted) {
return;
}
// Update voice mode based on audio input
voiceMode = determineVoiceMode();
// Update voice indicator
if (voiceIndicator) {
voiceIndicator.update();
}
// Update all units with current voice mode
if (voiceMode !== lastVoiceMode) {
for (var i = 0; i < units.length; i++) {
if (units[i].alive) {
units[i].setState(voiceMode);
}
}
lastVoiceMode = voiceMode;
}
// Check for collisions
checkCollisions();
// Spawn enemies
spawnEnemies();
// Spawn new units if needed
spawnNewUnits();
// Update score display
updateScore();
};