/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
level: 1
});
var facekit = LK.import("@upit/facekit.v1");
/****
* Classes
****/
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemyShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1;
self.score = 10;
self.speedX = 0;
self.speedY = 3;
self.type = 'normal';
self.update = function () {
// Basic movement
self.x += self.speedX;
self.y += self.speedY;
// Bounce off walls for some enemy types
if (self.type === 'bouncer') {
if (self.x < 100 || self.x > 2048 - 100) {
self.speedX *= -1;
}
}
// Remove if off screen
if (self.y > 2732 + 100) {
self.readyToRemove = true;
}
};
self.damage = function (amount) {
self.health -= amount;
if (self.health <= 0) {
self.explode();
return true;
}
// Flash red when hit
tween(enemyGraphics, {
alpha: 0.5
}, {
duration: 100,
onFinish: function onFinish() {
tween(enemyGraphics, {
alpha: 1
}, {
duration: 100
});
}
});
return false;
};
self.explode = function () {
self.readyToRemove = true;
LK.getSound('explosion').play();
// Create explosion effect
var explosion = new Explosion();
explosion.x = self.x;
explosion.y = self.y;
game.addChild(explosion);
};
return self;
});
var Asteroid = Enemy.expand(function () {
var self = Enemy.call(this);
// Remove the ship graphic
self.removeChildren();
// Add asteroid graphic
var asteroidGraphics = self.attachAsset('asteroid', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 2;
self.score = 15;
self.type = 'asteroid';
// Random rotation
self.rotationSpeed = (Math.random() - 0.5) * 0.1;
// Override update to add rotation
var parentUpdate = self.update;
self.update = function () {
parentUpdate.call(self);
self.rotation += self.rotationSpeed;
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var explosionGraphics = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9
});
self.lifespan = 15; // frames
self.age = 0;
self.update = function () {
self.age++;
// Grow effect
self.scale.x = 1 + self.age / 10;
self.scale.y = 1 + self.age / 10;
// Fade out over time
self.alpha = 1 - self.age / self.lifespan;
if (self.age >= self.lifespan) {
self.readyToRemove = true;
}
};
return self;
});
var Laser = Container.expand(function () {
var self = Container.call(this);
var laserGraphics = self.attachAsset('laser', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -15;
self.power = 1;
self.update = function () {
self.y += self.speed;
// Remove when off screen
if (self.y < -100) {
self.readyToRemove = true;
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 5;
self.maxHealth = 5;
self.fireRate = 20; // frames between shots
self.fireTimer = 0;
self.specialAttackReady = true;
self.specialAttackCooldown = 0;
self.invulnerable = false;
self.update = function () {
// Cooldowns
if (self.fireTimer > 0) {
self.fireTimer--;
}
if (self.specialAttackCooldown > 0) {
self.specialAttackCooldown--;
if (self.specialAttackCooldown <= 0) {
self.specialAttackReady = true;
}
}
};
self.fire = function () {
if (self.fireTimer <= 0) {
var laser = new Laser();
laser.x = self.x;
laser.y = self.y - 50;
game.addChild(laser);
lasers.push(laser);
LK.getSound('laserShot').play();
self.fireTimer = self.fireRate;
return true;
}
return false;
};
self.specialAttack = function () {
if (self.specialAttackReady) {
var attack = new SpecialAttack();
attack.x = self.x;
attack.y = self.y;
game.addChild(attack);
specialAttacks.push(attack);
LK.getSound('specialAttack').play();
self.specialAttackReady = false;
self.specialAttackCooldown = 120; // 2 seconds at 60fps
return true;
}
return false;
};
self.damage = function (amount) {
if (self.invulnerable) {
return false;
}
self.health -= amount;
// Flash player ship when hit
self.invulnerable = true;
var flashCount = 0;
var flashInterval = LK.setInterval(function () {
shipGraphics.alpha = shipGraphics.alpha === 1 ? 0.5 : 1;
flashCount++;
if (flashCount >= 6) {
LK.clearInterval(flashInterval);
shipGraphics.alpha = 1;
self.invulnerable = false;
}
}, 100);
// Update health bar
updateHealthBar();
if (self.health <= 0) {
return true; // Player is dead
}
return false;
};
self.addHealth = function (amount) {
self.health = Math.min(self.health + amount, self.maxHealth);
updateHealthBar();
LK.getSound('powerUp').play();
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'health'; // default type
self.speedY = 2;
self.update = function () {
self.y += self.speedY;
// Bob up and down
self.x += Math.sin(LK.ticks / 10) * 1;
// Remove if off screen
if (self.y > 2732 + 100) {
self.readyToRemove = true;
}
};
return self;
});
var SpecialAttack = Container.expand(function () {
var self = Container.call(this);
var attackGraphics = self.attachAsset('specialAttack', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
self.power = 5;
self.lifespan = 30; // frames
self.age = 0;
self.update = function () {
self.age++;
// Grow effect
self.scale.x = 1 + self.age / 15;
self.scale.y = 1 + self.age / 15;
// Fade out over time
self.alpha = 1 - self.age / self.lifespan;
if (self.age >= self.lifespan) {
self.readyToRemove = true;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000022
});
/****
* Game Code
****/
// Game variables
var player;
var lasers = [];
var enemies = [];
var powerUps = [];
var specialAttacks = [];
var score = 0;
var level = storage.level || 1;
var enemySpawnRate = 120 - level * 10; // frames between enemy spawns
var enemySpawnTimer = 60; // give player a short break at start
var waveSize = 10 + level * 5;
var enemiesDefeated = 0;
var gameActive = true;
var lastMouthOpen = false;
var healthBar;
var healthBarBg;
var scoreText;
var levelText;
var specialCooldownIndicator;
// Initialize game elements
function initGame() {
// Play background music
LK.playMusic('gameBgm');
// Create player
player = new Player();
player.x = 2048 / 2;
player.y = 2732 - 300;
game.addChild(player);
// Create health bar background
healthBarBg = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0.5,
x: 150,
y: 100,
tint: 0x444444
});
game.addChild(healthBarBg);
// Create health bar
healthBar = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0.5,
x: 150,
y: 100
});
game.addChild(healthBar);
// Create score text
scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
// Create level text
levelText = new Text2('Level: ' + level, {
size: 60,
fill: 0xFFFFFF
});
levelText.anchor.set(0, 0);
levelText.x = 150;
LK.gui.top.addChild(levelText);
// Special attack cooldown indicator
specialCooldownIndicator = LK.getAsset('specialAttack', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 - 100,
y: 2732 - 100,
scale: 0.3,
alpha: 0.6
});
game.addChild(specialCooldownIndicator);
}
// Update the health bar
function updateHealthBar() {
// Scale health bar based on current health
var healthPercent = player.health / player.maxHealth;
healthBar.scale.x = healthPercent;
}
// Update score display
function updateScore(points) {
score += points;
scoreText.setText('Score: ' + score);
// Update high score if needed
if (score > storage.highScore) {
storage.highScore = score;
}
}
// Spawn a new enemy
function spawnEnemy() {
var enemy;
var enemyType = Math.random();
if (enemyType < 0.7) {
// Normal enemy
enemy = new Enemy();
enemy.health = 1;
} else {
// Asteroid
enemy = new Asteroid();
enemy.health = 2;
}
// Set enemy position
enemy.x = Math.random() * (2048 - 200) + 100;
enemy.y = -100;
// For some enemies, set random X movement
if (Math.random() < 0.3) {
enemy.type = 'bouncer';
enemy.speedX = Math.random() * 4 - 2;
}
// Add to game
game.addChild(enemy);
enemies.push(enemy);
}
// Spawn a power-up
function spawnPowerUp() {
var powerUp = new PowerUp();
// Position randomly
powerUp.x = Math.random() * (2048 - 200) + 100;
powerUp.y = -100;
// Set type
var powerUpType = Math.random();
if (powerUpType < 0.7) {
powerUp.type = 'health';
} else {
powerUp.type = 'shield';
}
// Add to game
game.addChild(powerUp);
powerUps.push(powerUp);
}
// Check collisions between game elements
function checkCollisions() {
// Lasers hitting enemies
for (var i = lasers.length - 1; i >= 0; i--) {
var laser = lasers[i];
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (laser.intersects(enemy)) {
// Enemy hit
var destroyed = enemy.damage(laser.power);
if (destroyed) {
updateScore(enemy.score);
enemy.readyToRemove = true;
enemiesDefeated++;
// Chance to spawn power-up
if (Math.random() < 0.1) {
spawnPowerUp();
}
// Level up if enough enemies defeated
if (enemiesDefeated >= waveSize) {
level++;
storage.level = level;
enemiesDefeated = 0;
waveSize = 10 + level * 5;
enemySpawnRate = Math.max(20, 120 - level * 10);
levelText.setText('Level: ' + level);
// Flash level text
tween(levelText, {
scale: 1.5
}, {
duration: 300,
onFinish: function onFinish() {
tween(levelText, {
scale: 1
}, {
duration: 300
});
}
});
}
}
// Remove laser
laser.readyToRemove = true;
lasers.splice(i, 1);
break;
}
}
}
// Special attacks hitting enemies
for (var i = specialAttacks.length - 1; i >= 0; i--) {
var attack = specialAttacks[i];
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (attack.intersects(enemy)) {
// Enemy destroyed by special attack
updateScore(enemy.score);
enemy.explode();
enemies.splice(j, 1);
enemiesDefeated++;
// Chance to spawn power-up
if (Math.random() < 0.2) {
spawnPowerUp();
}
}
}
}
// Player colliding with enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (player.intersects(enemy)) {
// Player hit by enemy
if (player.damage(1)) {
// Player died
gameOver();
return;
}
// Enemy destroyed
enemy.explode();
enemies.splice(i, 1);
}
}
// Player collecting power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
if (player.intersects(powerUp)) {
// Apply power-up effect
if (powerUp.type === 'health') {
player.addHealth(1);
} else if (powerUp.type === 'shield') {
// Give temporary shield
player.invulnerable = true;
LK.setTimeout(function () {
player.invulnerable = false;
}, 5000);
}
// Remove power-up
powerUp.readyToRemove = true;
powerUps.splice(i, 1);
}
}
}
// Clean up game objects marked for removal
function cleanupObjects() {
for (var i = lasers.length - 1; i >= 0; i--) {
if (lasers[i].readyToRemove) {
lasers[i].destroy();
lasers.splice(i, 1);
}
}
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i].readyToRemove) {
enemies[i].destroy();
enemies.splice(i, 1);
}
}
for (var i = powerUps.length - 1; i >= 0; i--) {
if (powerUps[i].readyToRemove) {
powerUps[i].destroy();
powerUps.splice(i, 1);
}
}
for (var i = specialAttacks.length - 1; i >= 0; i--) {
if (specialAttacks[i].readyToRemove) {
specialAttacks[i].destroy();
specialAttacks.splice(i, 1);
}
}
}
// Game over function
function gameOver() {
gameActive = false;
LK.showGameOver();
}
// Initialize the game
initGame();
// Main game update function
game.update = function () {
if (!gameActive) {
return;
}
// Update player position based on face position
if (facekit.noseTip) {
// Map face position to game coordinates
var targetX = facekit.noseTip.x;
var targetY = Math.max(500, Math.min(2732 - 300, facekit.noseTip.y + 500));
// Smooth movement
player.x += (targetX - player.x) * 0.1;
player.y += (targetY - player.y) * 0.1;
}
// Fire laser when mouth opens
var mouthOpen = facekit.mouthOpen;
if (mouthOpen && !lastMouthOpen) {
player.fire();
}
lastMouthOpen = mouthOpen;
// Special attack with loud sound
if (facekit.volume > 0.6) {
player.specialAttack();
}
// Update special attack indicator
specialCooldownIndicator.alpha = player.specialAttackReady ? 1 : 0.3;
// Spawn enemies
enemySpawnTimer--;
if (enemySpawnTimer <= 0) {
spawnEnemy();
enemySpawnTimer = enemySpawnRate;
}
// Update game objects
player.update();
for (var i = 0; i < lasers.length; i++) {
lasers[i].update();
}
for (var i = 0; i < enemies.length; i++) {
enemies[i].update();
}
for (var i = 0; i < powerUps.length; i++) {
powerUps[i].update();
}
for (var i = 0; i < specialAttacks.length; i++) {
specialAttacks[i].update();
}
// Check for collisions
checkCollisions();
// Clean up objects
cleanupObjects();
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0,
level: 1
});
var facekit = LK.import("@upit/facekit.v1");
/****
* Classes
****/
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemyShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1;
self.score = 10;
self.speedX = 0;
self.speedY = 3;
self.type = 'normal';
self.update = function () {
// Basic movement
self.x += self.speedX;
self.y += self.speedY;
// Bounce off walls for some enemy types
if (self.type === 'bouncer') {
if (self.x < 100 || self.x > 2048 - 100) {
self.speedX *= -1;
}
}
// Remove if off screen
if (self.y > 2732 + 100) {
self.readyToRemove = true;
}
};
self.damage = function (amount) {
self.health -= amount;
if (self.health <= 0) {
self.explode();
return true;
}
// Flash red when hit
tween(enemyGraphics, {
alpha: 0.5
}, {
duration: 100,
onFinish: function onFinish() {
tween(enemyGraphics, {
alpha: 1
}, {
duration: 100
});
}
});
return false;
};
self.explode = function () {
self.readyToRemove = true;
LK.getSound('explosion').play();
// Create explosion effect
var explosion = new Explosion();
explosion.x = self.x;
explosion.y = self.y;
game.addChild(explosion);
};
return self;
});
var Asteroid = Enemy.expand(function () {
var self = Enemy.call(this);
// Remove the ship graphic
self.removeChildren();
// Add asteroid graphic
var asteroidGraphics = self.attachAsset('asteroid', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 2;
self.score = 15;
self.type = 'asteroid';
// Random rotation
self.rotationSpeed = (Math.random() - 0.5) * 0.1;
// Override update to add rotation
var parentUpdate = self.update;
self.update = function () {
parentUpdate.call(self);
self.rotation += self.rotationSpeed;
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var explosionGraphics = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9
});
self.lifespan = 15; // frames
self.age = 0;
self.update = function () {
self.age++;
// Grow effect
self.scale.x = 1 + self.age / 10;
self.scale.y = 1 + self.age / 10;
// Fade out over time
self.alpha = 1 - self.age / self.lifespan;
if (self.age >= self.lifespan) {
self.readyToRemove = true;
}
};
return self;
});
var Laser = Container.expand(function () {
var self = Container.call(this);
var laserGraphics = self.attachAsset('laser', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -15;
self.power = 1;
self.update = function () {
self.y += self.speed;
// Remove when off screen
if (self.y < -100) {
self.readyToRemove = true;
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('playerShip', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 5;
self.maxHealth = 5;
self.fireRate = 20; // frames between shots
self.fireTimer = 0;
self.specialAttackReady = true;
self.specialAttackCooldown = 0;
self.invulnerable = false;
self.update = function () {
// Cooldowns
if (self.fireTimer > 0) {
self.fireTimer--;
}
if (self.specialAttackCooldown > 0) {
self.specialAttackCooldown--;
if (self.specialAttackCooldown <= 0) {
self.specialAttackReady = true;
}
}
};
self.fire = function () {
if (self.fireTimer <= 0) {
var laser = new Laser();
laser.x = self.x;
laser.y = self.y - 50;
game.addChild(laser);
lasers.push(laser);
LK.getSound('laserShot').play();
self.fireTimer = self.fireRate;
return true;
}
return false;
};
self.specialAttack = function () {
if (self.specialAttackReady) {
var attack = new SpecialAttack();
attack.x = self.x;
attack.y = self.y;
game.addChild(attack);
specialAttacks.push(attack);
LK.getSound('specialAttack').play();
self.specialAttackReady = false;
self.specialAttackCooldown = 120; // 2 seconds at 60fps
return true;
}
return false;
};
self.damage = function (amount) {
if (self.invulnerable) {
return false;
}
self.health -= amount;
// Flash player ship when hit
self.invulnerable = true;
var flashCount = 0;
var flashInterval = LK.setInterval(function () {
shipGraphics.alpha = shipGraphics.alpha === 1 ? 0.5 : 1;
flashCount++;
if (flashCount >= 6) {
LK.clearInterval(flashInterval);
shipGraphics.alpha = 1;
self.invulnerable = false;
}
}, 100);
// Update health bar
updateHealthBar();
if (self.health <= 0) {
return true; // Player is dead
}
return false;
};
self.addHealth = function (amount) {
self.health = Math.min(self.health + amount, self.maxHealth);
updateHealthBar();
LK.getSound('powerUp').play();
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = 'health'; // default type
self.speedY = 2;
self.update = function () {
self.y += self.speedY;
// Bob up and down
self.x += Math.sin(LK.ticks / 10) * 1;
// Remove if off screen
if (self.y > 2732 + 100) {
self.readyToRemove = true;
}
};
return self;
});
var SpecialAttack = Container.expand(function () {
var self = Container.call(this);
var attackGraphics = self.attachAsset('specialAttack', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.7
});
self.power = 5;
self.lifespan = 30; // frames
self.age = 0;
self.update = function () {
self.age++;
// Grow effect
self.scale.x = 1 + self.age / 15;
self.scale.y = 1 + self.age / 15;
// Fade out over time
self.alpha = 1 - self.age / self.lifespan;
if (self.age >= self.lifespan) {
self.readyToRemove = true;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000022
});
/****
* Game Code
****/
// Game variables
var player;
var lasers = [];
var enemies = [];
var powerUps = [];
var specialAttacks = [];
var score = 0;
var level = storage.level || 1;
var enemySpawnRate = 120 - level * 10; // frames between enemy spawns
var enemySpawnTimer = 60; // give player a short break at start
var waveSize = 10 + level * 5;
var enemiesDefeated = 0;
var gameActive = true;
var lastMouthOpen = false;
var healthBar;
var healthBarBg;
var scoreText;
var levelText;
var specialCooldownIndicator;
// Initialize game elements
function initGame() {
// Play background music
LK.playMusic('gameBgm');
// Create player
player = new Player();
player.x = 2048 / 2;
player.y = 2732 - 300;
game.addChild(player);
// Create health bar background
healthBarBg = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0.5,
x: 150,
y: 100,
tint: 0x444444
});
game.addChild(healthBarBg);
// Create health bar
healthBar = LK.getAsset('healthBar', {
anchorX: 0,
anchorY: 0.5,
x: 150,
y: 100
});
game.addChild(healthBar);
// Create score text
scoreText = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
// Create level text
levelText = new Text2('Level: ' + level, {
size: 60,
fill: 0xFFFFFF
});
levelText.anchor.set(0, 0);
levelText.x = 150;
LK.gui.top.addChild(levelText);
// Special attack cooldown indicator
specialCooldownIndicator = LK.getAsset('specialAttack', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 - 100,
y: 2732 - 100,
scale: 0.3,
alpha: 0.6
});
game.addChild(specialCooldownIndicator);
}
// Update the health bar
function updateHealthBar() {
// Scale health bar based on current health
var healthPercent = player.health / player.maxHealth;
healthBar.scale.x = healthPercent;
}
// Update score display
function updateScore(points) {
score += points;
scoreText.setText('Score: ' + score);
// Update high score if needed
if (score > storage.highScore) {
storage.highScore = score;
}
}
// Spawn a new enemy
function spawnEnemy() {
var enemy;
var enemyType = Math.random();
if (enemyType < 0.7) {
// Normal enemy
enemy = new Enemy();
enemy.health = 1;
} else {
// Asteroid
enemy = new Asteroid();
enemy.health = 2;
}
// Set enemy position
enemy.x = Math.random() * (2048 - 200) + 100;
enemy.y = -100;
// For some enemies, set random X movement
if (Math.random() < 0.3) {
enemy.type = 'bouncer';
enemy.speedX = Math.random() * 4 - 2;
}
// Add to game
game.addChild(enemy);
enemies.push(enemy);
}
// Spawn a power-up
function spawnPowerUp() {
var powerUp = new PowerUp();
// Position randomly
powerUp.x = Math.random() * (2048 - 200) + 100;
powerUp.y = -100;
// Set type
var powerUpType = Math.random();
if (powerUpType < 0.7) {
powerUp.type = 'health';
} else {
powerUp.type = 'shield';
}
// Add to game
game.addChild(powerUp);
powerUps.push(powerUp);
}
// Check collisions between game elements
function checkCollisions() {
// Lasers hitting enemies
for (var i = lasers.length - 1; i >= 0; i--) {
var laser = lasers[i];
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (laser.intersects(enemy)) {
// Enemy hit
var destroyed = enemy.damage(laser.power);
if (destroyed) {
updateScore(enemy.score);
enemy.readyToRemove = true;
enemiesDefeated++;
// Chance to spawn power-up
if (Math.random() < 0.1) {
spawnPowerUp();
}
// Level up if enough enemies defeated
if (enemiesDefeated >= waveSize) {
level++;
storage.level = level;
enemiesDefeated = 0;
waveSize = 10 + level * 5;
enemySpawnRate = Math.max(20, 120 - level * 10);
levelText.setText('Level: ' + level);
// Flash level text
tween(levelText, {
scale: 1.5
}, {
duration: 300,
onFinish: function onFinish() {
tween(levelText, {
scale: 1
}, {
duration: 300
});
}
});
}
}
// Remove laser
laser.readyToRemove = true;
lasers.splice(i, 1);
break;
}
}
}
// Special attacks hitting enemies
for (var i = specialAttacks.length - 1; i >= 0; i--) {
var attack = specialAttacks[i];
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (attack.intersects(enemy)) {
// Enemy destroyed by special attack
updateScore(enemy.score);
enemy.explode();
enemies.splice(j, 1);
enemiesDefeated++;
// Chance to spawn power-up
if (Math.random() < 0.2) {
spawnPowerUp();
}
}
}
}
// Player colliding with enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
if (player.intersects(enemy)) {
// Player hit by enemy
if (player.damage(1)) {
// Player died
gameOver();
return;
}
// Enemy destroyed
enemy.explode();
enemies.splice(i, 1);
}
}
// Player collecting power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
if (player.intersects(powerUp)) {
// Apply power-up effect
if (powerUp.type === 'health') {
player.addHealth(1);
} else if (powerUp.type === 'shield') {
// Give temporary shield
player.invulnerable = true;
LK.setTimeout(function () {
player.invulnerable = false;
}, 5000);
}
// Remove power-up
powerUp.readyToRemove = true;
powerUps.splice(i, 1);
}
}
}
// Clean up game objects marked for removal
function cleanupObjects() {
for (var i = lasers.length - 1; i >= 0; i--) {
if (lasers[i].readyToRemove) {
lasers[i].destroy();
lasers.splice(i, 1);
}
}
for (var i = enemies.length - 1; i >= 0; i--) {
if (enemies[i].readyToRemove) {
enemies[i].destroy();
enemies.splice(i, 1);
}
}
for (var i = powerUps.length - 1; i >= 0; i--) {
if (powerUps[i].readyToRemove) {
powerUps[i].destroy();
powerUps.splice(i, 1);
}
}
for (var i = specialAttacks.length - 1; i >= 0; i--) {
if (specialAttacks[i].readyToRemove) {
specialAttacks[i].destroy();
specialAttacks.splice(i, 1);
}
}
}
// Game over function
function gameOver() {
gameActive = false;
LK.showGameOver();
}
// Initialize the game
initGame();
// Main game update function
game.update = function () {
if (!gameActive) {
return;
}
// Update player position based on face position
if (facekit.noseTip) {
// Map face position to game coordinates
var targetX = facekit.noseTip.x;
var targetY = Math.max(500, Math.min(2732 - 300, facekit.noseTip.y + 500));
// Smooth movement
player.x += (targetX - player.x) * 0.1;
player.y += (targetY - player.y) * 0.1;
}
// Fire laser when mouth opens
var mouthOpen = facekit.mouthOpen;
if (mouthOpen && !lastMouthOpen) {
player.fire();
}
lastMouthOpen = mouthOpen;
// Special attack with loud sound
if (facekit.volume > 0.6) {
player.specialAttack();
}
// Update special attack indicator
specialCooldownIndicator.alpha = player.specialAttackReady ? 1 : 0.3;
// Spawn enemies
enemySpawnTimer--;
if (enemySpawnTimer <= 0) {
spawnEnemy();
enemySpawnTimer = enemySpawnRate;
}
// Update game objects
player.update();
for (var i = 0; i < lasers.length; i++) {
lasers[i].update();
}
for (var i = 0; i < enemies.length; i++) {
enemies[i].update();
}
for (var i = 0; i < powerUps.length; i++) {
powerUps[i].update();
}
for (var i = 0; i < specialAttacks.length; i++) {
specialAttacks[i].update();
}
// Check for collisions
checkCollisions();
// Clean up objects
cleanupObjects();
};