User prompt
delete enemy ship that got hit when shot
User prompt
kill enemy ship when shot by bullet
User prompt
when player hits enemy with bullet kill enemy and add to score
Code edit (1 edits merged)
Please save this source code
User prompt
Face Invaders: Cosmic Guardian
Initial prompt
make a facekit game
/****
* 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);
enemies.splice(j, 1);
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();
}; ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,582 @@
-/****
+/****
+* 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: 0x000000
-});
\ No newline at end of file
+ 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);
+ enemies.splice(j, 1);
+ 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();
+};
\ No newline at end of file