/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var BigMonster = Container.expand(function () { var self = Container.call(this); var monsterGraphics = self.attachAsset('bigMonster', { anchorX: 0.5, anchorY: 0.5 }); // Make big monster different colored monsterGraphics.tint = 0xFF4444; // Red tint to distinguish from normal monsters self.health = 2; // Takes 2 waves to kill self.speed = 1.5; // Slightly slower than normal monsters self.damage = 10; // Takes 10 lives self.targetX = 0; self.targetY = 0; self.update = function () { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } }; return self; }); var KingMonster = Container.expand(function () { var self = Container.call(this); var monsterGraphics = self.attachAsset('kingMonster', { anchorX: 0.5, anchorY: 0.5 }); // Make king monster different colored monsterGraphics.tint = 0x8B008B; // Purple tint to distinguish from other monsters self.health = 5; // Takes 5 waves to kill self.speed = 1; // Slower than other monsters self.damage = 20; // Takes 20 lives self.targetX = 0; self.targetY = 0; self.update = function () { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } }; return self; }); var Monster = Container.expand(function () { var self = Container.call(this); var monsterGraphics = self.attachAsset('monster', { anchorX: 0.5, anchorY: 0.5 }); self.health = 1; self.speed = 2; self.damage = 10; self.targetX = 0; self.targetY = 0; self.update = function () { var dx = self.targetX - self.x; var dy = self.targetY - self.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { self.x += dx / distance * self.speed; self.y += dy / distance * self.speed; } }; return self; }); var Ship = Container.expand(function () { var self = Container.call(this); var shipGraphics = self.attachAsset('ship', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.maxHealth = 100; return self; }); var Wave = Container.expand(function () { var self = Container.call(this); var waveGraphics = self.attachAsset('wave', { anchorX: 0.5, anchorY: 0.5 }); self.damage = 1; self.maxRadius = 50; self.expansionSpeed = 4; self.currentRadius = 10; self.lifetime = 0; self.maxLifetime = 30; self.speed = 10; self.directionX = 0; self.directionY = 0; waveGraphics.alpha = 0.7; self.update = function () { self.lifetime++; // Move wave in direction self.x += self.directionX * self.speed; self.y += self.directionY * self.speed; if (self.currentRadius < self.maxRadius) { self.currentRadius += self.expansionSpeed; var scale = self.currentRadius / 10; waveGraphics.scaleX = scale; waveGraphics.scaleY = scale; } // Keep waves visible - no alpha fade }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x001133 }); /**** * Game Code ****/ var ship = game.addChild(new Ship()); ship.x = 2048 / 2; ship.y = 2732 / 2; var monsters = []; var bigMonsters = []; var kingMonsters = []; var waves = []; var monsterSpawnTimer = 0; var monsterSpawnRate = 120; var bigMonsterSpawnTimer = 0; var bigMonsterSpawnRate = 600; // Spawn big monsters every 10 seconds var kingMonsterSpawnTimer = 0; var kingMonsterSpawnRate = 1200; // Spawn king monsters every 20 seconds var difficultyTimer = 0; var gameStarted = true; var attackCooldown = 0; var maxAttackCooldown = 60; // 1 second at 60 FPS var cooldownIndicator = null; var lives = 100; var livesText = null; var currentRound = 1; var totalRounds = 5; var roundText = null; var roundMonstersSpawned = 0; var roundMonstersToSpawn = 0; var roundComplete = false; var gameComplete = false; // Create cooldown indicator cooldownIndicator = new Text2('READY', { size: 40, fill: 0x00FF00 }); cooldownIndicator.anchor.set(0.5, 0); cooldownIndicator.y = 80; LK.gui.top.addChild(cooldownIndicator); // Create lives display livesText = new Text2('Lives: 100', { size: 50, fill: 0xFFFFFF }); livesText.anchor.set(1, 0); livesText.x = -20; livesText.y = 20; LK.gui.topRight.addChild(livesText); // Create round display roundText = new Text2('Round 1', { size: 60, fill: 0xFFD700 }); roundText.anchor.set(0.5, 0); roundText.y = 20; LK.gui.top.addChild(roundText); // Initialize first round initializeRound(); function initializeRound() { roundComplete = false; roundMonstersSpawned = 0; switch (currentRound) { case 1: // Round 1: Normal Monsters (15 pieces) roundMonstersToSpawn = 15; break; case 2: // Round 2: Normal Monster and Big Monster (20 pieces: 15 Normal, 5 Big) roundMonstersToSpawn = 20; break; case 3: // Round 3: Big Monster (15 pieces) roundMonstersToSpawn = 15; break; case 4: // Round 4: Big and King Monster (20 pieces: 15 Big, 5 King) roundMonstersToSpawn = 20; break; case 5: // Round 5: King Monster (10 pieces) roundMonstersToSpawn = 10; break; } roundText.setText('Round ' + currentRound); } function spawnMonster() { var monster = new Monster(); var side = Math.floor(Math.random() * 4); switch (side) { case 0: // Top monster.x = Math.random() * 2048; monster.y = -30; break; case 1: // Right monster.x = 2048 + 30; monster.y = Math.random() * 2732; break; case 2: // Bottom monster.x = Math.random() * 2048; monster.y = 2732 + 30; break; case 3: // Left monster.x = -30; monster.y = Math.random() * 2732; break; } monster.targetX = ship.x; monster.targetY = ship.y; monsters.push(monster); game.addChild(monster); } function spawnBigMonster() { var bigMonster = new BigMonster(); var side = Math.floor(Math.random() * 4); switch (side) { case 0: // Top bigMonster.x = Math.random() * 2048; bigMonster.y = -30; break; case 1: // Right bigMonster.x = 2048 + 30; bigMonster.y = Math.random() * 2732; break; case 2: // Bottom bigMonster.x = Math.random() * 2048; bigMonster.y = 2732 + 30; break; case 3: // Left bigMonster.x = -30; bigMonster.y = Math.random() * 2732; break; } bigMonster.targetX = ship.x; bigMonster.targetY = ship.y; bigMonsters.push(bigMonster); game.addChild(bigMonster); } function spawnKingMonster() { var kingMonster = new KingMonster(); var side = Math.floor(Math.random() * 4); switch (side) { case 0: // Top kingMonster.x = Math.random() * 2048; kingMonster.y = -30; break; case 1: // Right kingMonster.x = 2048 + 30; kingMonster.y = Math.random() * 2732; break; case 2: // Bottom kingMonster.x = Math.random() * 2048; kingMonster.y = 2732 + 30; break; case 3: // Left kingMonster.x = -30; kingMonster.y = Math.random() * 2732; break; } kingMonster.targetX = ship.x; kingMonster.targetY = ship.y; kingMonsters.push(kingMonster); game.addChild(kingMonster); } function spawnRoundMonster() { if (roundMonstersSpawned >= roundMonstersToSpawn || roundComplete) { return; } switch (currentRound) { case 1: // Round 1: Only normal monsters spawnMonster(); break; case 2: // Round 2: 15 Normal, 5 Big if (roundMonstersSpawned < 15) { spawnMonster(); } else { spawnBigMonster(); } break; case 3: // Round 3: Only big monsters spawnBigMonster(); break; case 4: // Round 4: 15 Big, 5 King if (roundMonstersSpawned < 15) { spawnBigMonster(); } else { spawnKingMonster(); } break; case 5: // Round 5: Only king monsters spawnKingMonster(); break; } roundMonstersSpawned++; } function createWave(targetX, targetY) { var wave = new Wave(); wave.x = ship.x; wave.y = ship.y; // Calculate direction from ship to target var dx = targetX - ship.x; var dy = targetY - ship.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance > 0) { wave.directionX = dx / distance; wave.directionY = dy / distance; } else { wave.directionX = 0; wave.directionY = 0; } waves.push(wave); game.addChild(wave); LK.getSound('waveSound').play(); // Start cooldown attackCooldown = maxAttackCooldown; cooldownIndicator.setText('COOLDOWN'); tween(cooldownIndicator, { tint: 0xFF0000 }, { duration: 100 }); } function checkWaveMonsterCollisions() { for (var w = waves.length - 1; w >= 0; w--) { var wave = waves[w]; // Check collisions with normal monsters for (var m = monsters.length - 1; m >= 0; m--) { var monster = monsters[m]; var dx = wave.x - monster.x; var dy = wave.y - monster.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= wave.currentRadius) { monster.health -= wave.damage; if (monster.health <= 0) { LK.getSound('monsterHit').play(); monster.destroy(); monsters.splice(m, 1); } } } // Check collisions with big monsters for (var b = bigMonsters.length - 1; b >= 0; b--) { var bigMonster = bigMonsters[b]; var dx = wave.x - bigMonster.x; var dy = wave.y - bigMonster.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= wave.currentRadius) { bigMonster.health -= wave.damage; if (bigMonster.health <= 0) { LK.getSound('monsterHit').play(); bigMonster.destroy(); bigMonsters.splice(b, 1); } } } // Check collisions with king monsters for (var k = kingMonsters.length - 1; k >= 0; k--) { var kingMonster = kingMonsters[k]; var dx = wave.x - kingMonster.x; var dy = wave.y - kingMonster.y; var distance = Math.sqrt(dx * dx + dy * dy); if (distance <= wave.currentRadius) { kingMonster.health -= wave.damage; if (kingMonster.health <= 0) { LK.getSound('monsterHit').play(); kingMonster.destroy(); kingMonsters.splice(k, 1); } } } } } function checkRoundComplete() { // Check if all monsters for this round have been spawned and defeated if (roundMonstersSpawned >= roundMonstersToSpawn && monsters.length === 0 && bigMonsters.length === 0 && kingMonsters.length === 0) { if (!roundComplete) { roundComplete = true; if (currentRound < totalRounds) { // Advance to next round currentRound++; initializeRound(); // Show round transition effect LK.effects.flashScreen(0x00FF00, 1000); } else { // Game complete! gameComplete = true; LK.showYouWin(); } } } } function checkMonsterShipCollisions() { // Check collisions with normal monsters for (var m = monsters.length - 1; m >= 0; m--) { var monster = monsters[m]; if (ship.intersects(monster)) { lives -= 5; livesText.setText('Lives: ' + lives); LK.getSound('shipHit').play(); LK.effects.flashScreen(0xff0000, 500); monster.destroy(); monsters.splice(m, 1); if (lives <= 0) { LK.showGameOver(); return; } } } // Check collisions with big monsters for (var b = bigMonsters.length - 1; b >= 0; b--) { var bigMonster = bigMonsters[b]; if (ship.intersects(bigMonster)) { lives -= 10; // Big monsters take 10 lives livesText.setText('Lives: ' + lives); LK.getSound('shipHit').play(); LK.effects.flashScreen(0xff0000, 500); bigMonster.destroy(); bigMonsters.splice(b, 1); if (lives <= 0) { LK.showGameOver(); return; } } } // Check collisions with king monsters for (var k = kingMonsters.length - 1; k >= 0; k--) { var kingMonster = kingMonsters[k]; if (ship.intersects(kingMonster)) { lives -= 20; // King monsters take 20 lives livesText.setText('Lives: ' + lives); LK.getSound('shipHit').play(); LK.effects.flashScreen(0xff0000, 500); kingMonster.destroy(); kingMonsters.splice(k, 1); if (lives <= 0) { LK.showGameOver(); return; } } } } game.down = function (x, y, obj) { if (gameStarted && attackCooldown <= 0) { createWave(x, y); } }; game.update = function () { if (!gameStarted) return; // Update attack cooldown if (attackCooldown > 0) { attackCooldown--; if (attackCooldown === 0) { // Cooldown finished cooldownIndicator.setText('READY'); tween(cooldownIndicator, { tint: 0x00FF00 }, { duration: 200 }); } } difficultyTimer++; monsterSpawnTimer++; bigMonsterSpawnTimer++; kingMonsterSpawnTimer++; // Increase difficulty over time if (difficultyTimer % 1800 === 0) { // Every 30 seconds monsterSpawnRate = Math.max(60, monsterSpawnRate - 10); bigMonsterSpawnRate = Math.max(300, bigMonsterSpawnRate - 30); // Also increase big monster spawn rate kingMonsterSpawnRate = Math.max(600, kingMonsterSpawnRate - 60); // Also increase king monster spawn rate } // Spawn monsters based on current round if (monsterSpawnTimer >= monsterSpawnRate && !gameComplete) { spawnRoundMonster(); monsterSpawnTimer = 0; } // Update waves - no cleanup, they travel infinitely for (var w = waves.length - 1; w >= 0; w--) { var wave = waves[w]; // Waves now travel infinitely - no cleanup } // Update monster targets to current ship position for (var m = 0; m < monsters.length; m++) { var monster = monsters[m]; monster.targetX = ship.x; monster.targetY = ship.y; } // Update big monster targets to current ship position for (var b = 0; b < bigMonsters.length; b++) { var bigMonster = bigMonsters[b]; bigMonster.targetX = ship.x; bigMonster.targetY = ship.y; } // Update king monster targets to current ship position for (var k = 0; k < kingMonsters.length; k++) { var kingMonster = kingMonsters[k]; kingMonster.targetX = ship.x; kingMonster.targetY = ship.y; } // Check collisions checkWaveMonsterCollisions(); checkMonsterShipCollisions(); // Check if round is complete checkRoundComplete(); // Remove off-screen monsters (safety cleanup) for (var m = monsters.length - 1; m >= 0; m--) { var monster = monsters[m]; if (monster.x < -100 || monster.x > 2148 || monster.y < -100 || monster.y > 2832) { monster.destroy(); monsters.splice(m, 1); } } // Remove off-screen big monsters (safety cleanup) for (var b = bigMonsters.length - 1; b >= 0; b--) { var bigMonster = bigMonsters[b]; if (bigMonster.x < -100 || bigMonster.x > 2148 || bigMonster.y < -100 || bigMonster.y > 2832) { bigMonster.destroy(); bigMonsters.splice(b, 1); } } // Remove off-screen king monsters (safety cleanup) for (var k = kingMonsters.length - 1; k >= 0; k--) { var kingMonster = kingMonsters[k]; if (kingMonster.x < -100 || kingMonster.x > 2148 || kingMonster.y < -100 || kingMonster.y > 2832) { kingMonster.destroy(); kingMonsters.splice(k, 1); } } };
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BigMonster = Container.expand(function () {
var self = Container.call(this);
var monsterGraphics = self.attachAsset('bigMonster', {
anchorX: 0.5,
anchorY: 0.5
});
// Make big monster different colored
monsterGraphics.tint = 0xFF4444; // Red tint to distinguish from normal monsters
self.health = 2; // Takes 2 waves to kill
self.speed = 1.5; // Slightly slower than normal monsters
self.damage = 10; // Takes 10 lives
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
return self;
});
var KingMonster = Container.expand(function () {
var self = Container.call(this);
var monsterGraphics = self.attachAsset('kingMonster', {
anchorX: 0.5,
anchorY: 0.5
});
// Make king monster different colored
monsterGraphics.tint = 0x8B008B; // Purple tint to distinguish from other monsters
self.health = 5; // Takes 5 waves to kill
self.speed = 1; // Slower than other monsters
self.damage = 20; // Takes 20 lives
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
return self;
});
var Monster = Container.expand(function () {
var self = Container.call(this);
var monsterGraphics = self.attachAsset('monster', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1;
self.speed = 2;
self.damage = 10;
self.targetX = 0;
self.targetY = 0;
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
};
return self;
});
var Ship = Container.expand(function () {
var self = Container.call(this);
var shipGraphics = self.attachAsset('ship', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
return self;
});
var Wave = Container.expand(function () {
var self = Container.call(this);
var waveGraphics = self.attachAsset('wave', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 1;
self.maxRadius = 50;
self.expansionSpeed = 4;
self.currentRadius = 10;
self.lifetime = 0;
self.maxLifetime = 30;
self.speed = 10;
self.directionX = 0;
self.directionY = 0;
waveGraphics.alpha = 0.7;
self.update = function () {
self.lifetime++;
// Move wave in direction
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
if (self.currentRadius < self.maxRadius) {
self.currentRadius += self.expansionSpeed;
var scale = self.currentRadius / 10;
waveGraphics.scaleX = scale;
waveGraphics.scaleY = scale;
}
// Keep waves visible - no alpha fade
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x001133
});
/****
* Game Code
****/
var ship = game.addChild(new Ship());
ship.x = 2048 / 2;
ship.y = 2732 / 2;
var monsters = [];
var bigMonsters = [];
var kingMonsters = [];
var waves = [];
var monsterSpawnTimer = 0;
var monsterSpawnRate = 120;
var bigMonsterSpawnTimer = 0;
var bigMonsterSpawnRate = 600; // Spawn big monsters every 10 seconds
var kingMonsterSpawnTimer = 0;
var kingMonsterSpawnRate = 1200; // Spawn king monsters every 20 seconds
var difficultyTimer = 0;
var gameStarted = true;
var attackCooldown = 0;
var maxAttackCooldown = 60; // 1 second at 60 FPS
var cooldownIndicator = null;
var lives = 100;
var livesText = null;
var currentRound = 1;
var totalRounds = 5;
var roundText = null;
var roundMonstersSpawned = 0;
var roundMonstersToSpawn = 0;
var roundComplete = false;
var gameComplete = false;
// Create cooldown indicator
cooldownIndicator = new Text2('READY', {
size: 40,
fill: 0x00FF00
});
cooldownIndicator.anchor.set(0.5, 0);
cooldownIndicator.y = 80;
LK.gui.top.addChild(cooldownIndicator);
// Create lives display
livesText = new Text2('Lives: 100', {
size: 50,
fill: 0xFFFFFF
});
livesText.anchor.set(1, 0);
livesText.x = -20;
livesText.y = 20;
LK.gui.topRight.addChild(livesText);
// Create round display
roundText = new Text2('Round 1', {
size: 60,
fill: 0xFFD700
});
roundText.anchor.set(0.5, 0);
roundText.y = 20;
LK.gui.top.addChild(roundText);
// Initialize first round
initializeRound();
function initializeRound() {
roundComplete = false;
roundMonstersSpawned = 0;
switch (currentRound) {
case 1:
// Round 1: Normal Monsters (15 pieces)
roundMonstersToSpawn = 15;
break;
case 2:
// Round 2: Normal Monster and Big Monster (20 pieces: 15 Normal, 5 Big)
roundMonstersToSpawn = 20;
break;
case 3:
// Round 3: Big Monster (15 pieces)
roundMonstersToSpawn = 15;
break;
case 4:
// Round 4: Big and King Monster (20 pieces: 15 Big, 5 King)
roundMonstersToSpawn = 20;
break;
case 5:
// Round 5: King Monster (10 pieces)
roundMonstersToSpawn = 10;
break;
}
roundText.setText('Round ' + currentRound);
}
function spawnMonster() {
var monster = new Monster();
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
monster.x = Math.random() * 2048;
monster.y = -30;
break;
case 1:
// Right
monster.x = 2048 + 30;
monster.y = Math.random() * 2732;
break;
case 2:
// Bottom
monster.x = Math.random() * 2048;
monster.y = 2732 + 30;
break;
case 3:
// Left
monster.x = -30;
monster.y = Math.random() * 2732;
break;
}
monster.targetX = ship.x;
monster.targetY = ship.y;
monsters.push(monster);
game.addChild(monster);
}
function spawnBigMonster() {
var bigMonster = new BigMonster();
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
bigMonster.x = Math.random() * 2048;
bigMonster.y = -30;
break;
case 1:
// Right
bigMonster.x = 2048 + 30;
bigMonster.y = Math.random() * 2732;
break;
case 2:
// Bottom
bigMonster.x = Math.random() * 2048;
bigMonster.y = 2732 + 30;
break;
case 3:
// Left
bigMonster.x = -30;
bigMonster.y = Math.random() * 2732;
break;
}
bigMonster.targetX = ship.x;
bigMonster.targetY = ship.y;
bigMonsters.push(bigMonster);
game.addChild(bigMonster);
}
function spawnKingMonster() {
var kingMonster = new KingMonster();
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
kingMonster.x = Math.random() * 2048;
kingMonster.y = -30;
break;
case 1:
// Right
kingMonster.x = 2048 + 30;
kingMonster.y = Math.random() * 2732;
break;
case 2:
// Bottom
kingMonster.x = Math.random() * 2048;
kingMonster.y = 2732 + 30;
break;
case 3:
// Left
kingMonster.x = -30;
kingMonster.y = Math.random() * 2732;
break;
}
kingMonster.targetX = ship.x;
kingMonster.targetY = ship.y;
kingMonsters.push(kingMonster);
game.addChild(kingMonster);
}
function spawnRoundMonster() {
if (roundMonstersSpawned >= roundMonstersToSpawn || roundComplete) {
return;
}
switch (currentRound) {
case 1:
// Round 1: Only normal monsters
spawnMonster();
break;
case 2:
// Round 2: 15 Normal, 5 Big
if (roundMonstersSpawned < 15) {
spawnMonster();
} else {
spawnBigMonster();
}
break;
case 3:
// Round 3: Only big monsters
spawnBigMonster();
break;
case 4:
// Round 4: 15 Big, 5 King
if (roundMonstersSpawned < 15) {
spawnBigMonster();
} else {
spawnKingMonster();
}
break;
case 5:
// Round 5: Only king monsters
spawnKingMonster();
break;
}
roundMonstersSpawned++;
}
function createWave(targetX, targetY) {
var wave = new Wave();
wave.x = ship.x;
wave.y = ship.y;
// Calculate direction from ship to target
var dx = targetX - ship.x;
var dy = targetY - ship.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
wave.directionX = dx / distance;
wave.directionY = dy / distance;
} else {
wave.directionX = 0;
wave.directionY = 0;
}
waves.push(wave);
game.addChild(wave);
LK.getSound('waveSound').play();
// Start cooldown
attackCooldown = maxAttackCooldown;
cooldownIndicator.setText('COOLDOWN');
tween(cooldownIndicator, {
tint: 0xFF0000
}, {
duration: 100
});
}
function checkWaveMonsterCollisions() {
for (var w = waves.length - 1; w >= 0; w--) {
var wave = waves[w];
// Check collisions with normal monsters
for (var m = monsters.length - 1; m >= 0; m--) {
var monster = monsters[m];
var dx = wave.x - monster.x;
var dy = wave.y - monster.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= wave.currentRadius) {
monster.health -= wave.damage;
if (monster.health <= 0) {
LK.getSound('monsterHit').play();
monster.destroy();
monsters.splice(m, 1);
}
}
}
// Check collisions with big monsters
for (var b = bigMonsters.length - 1; b >= 0; b--) {
var bigMonster = bigMonsters[b];
var dx = wave.x - bigMonster.x;
var dy = wave.y - bigMonster.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= wave.currentRadius) {
bigMonster.health -= wave.damage;
if (bigMonster.health <= 0) {
LK.getSound('monsterHit').play();
bigMonster.destroy();
bigMonsters.splice(b, 1);
}
}
}
// Check collisions with king monsters
for (var k = kingMonsters.length - 1; k >= 0; k--) {
var kingMonster = kingMonsters[k];
var dx = wave.x - kingMonster.x;
var dy = wave.y - kingMonster.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= wave.currentRadius) {
kingMonster.health -= wave.damage;
if (kingMonster.health <= 0) {
LK.getSound('monsterHit').play();
kingMonster.destroy();
kingMonsters.splice(k, 1);
}
}
}
}
}
function checkRoundComplete() {
// Check if all monsters for this round have been spawned and defeated
if (roundMonstersSpawned >= roundMonstersToSpawn && monsters.length === 0 && bigMonsters.length === 0 && kingMonsters.length === 0) {
if (!roundComplete) {
roundComplete = true;
if (currentRound < totalRounds) {
// Advance to next round
currentRound++;
initializeRound();
// Show round transition effect
LK.effects.flashScreen(0x00FF00, 1000);
} else {
// Game complete!
gameComplete = true;
LK.showYouWin();
}
}
}
}
function checkMonsterShipCollisions() {
// Check collisions with normal monsters
for (var m = monsters.length - 1; m >= 0; m--) {
var monster = monsters[m];
if (ship.intersects(monster)) {
lives -= 5;
livesText.setText('Lives: ' + lives);
LK.getSound('shipHit').play();
LK.effects.flashScreen(0xff0000, 500);
monster.destroy();
monsters.splice(m, 1);
if (lives <= 0) {
LK.showGameOver();
return;
}
}
}
// Check collisions with big monsters
for (var b = bigMonsters.length - 1; b >= 0; b--) {
var bigMonster = bigMonsters[b];
if (ship.intersects(bigMonster)) {
lives -= 10; // Big monsters take 10 lives
livesText.setText('Lives: ' + lives);
LK.getSound('shipHit').play();
LK.effects.flashScreen(0xff0000, 500);
bigMonster.destroy();
bigMonsters.splice(b, 1);
if (lives <= 0) {
LK.showGameOver();
return;
}
}
}
// Check collisions with king monsters
for (var k = kingMonsters.length - 1; k >= 0; k--) {
var kingMonster = kingMonsters[k];
if (ship.intersects(kingMonster)) {
lives -= 20; // King monsters take 20 lives
livesText.setText('Lives: ' + lives);
LK.getSound('shipHit').play();
LK.effects.flashScreen(0xff0000, 500);
kingMonster.destroy();
kingMonsters.splice(k, 1);
if (lives <= 0) {
LK.showGameOver();
return;
}
}
}
}
game.down = function (x, y, obj) {
if (gameStarted && attackCooldown <= 0) {
createWave(x, y);
}
};
game.update = function () {
if (!gameStarted) return;
// Update attack cooldown
if (attackCooldown > 0) {
attackCooldown--;
if (attackCooldown === 0) {
// Cooldown finished
cooldownIndicator.setText('READY');
tween(cooldownIndicator, {
tint: 0x00FF00
}, {
duration: 200
});
}
}
difficultyTimer++;
monsterSpawnTimer++;
bigMonsterSpawnTimer++;
kingMonsterSpawnTimer++;
// Increase difficulty over time
if (difficultyTimer % 1800 === 0) {
// Every 30 seconds
monsterSpawnRate = Math.max(60, monsterSpawnRate - 10);
bigMonsterSpawnRate = Math.max(300, bigMonsterSpawnRate - 30); // Also increase big monster spawn rate
kingMonsterSpawnRate = Math.max(600, kingMonsterSpawnRate - 60); // Also increase king monster spawn rate
}
// Spawn monsters based on current round
if (monsterSpawnTimer >= monsterSpawnRate && !gameComplete) {
spawnRoundMonster();
monsterSpawnTimer = 0;
}
// Update waves - no cleanup, they travel infinitely
for (var w = waves.length - 1; w >= 0; w--) {
var wave = waves[w];
// Waves now travel infinitely - no cleanup
}
// Update monster targets to current ship position
for (var m = 0; m < monsters.length; m++) {
var monster = monsters[m];
monster.targetX = ship.x;
monster.targetY = ship.y;
}
// Update big monster targets to current ship position
for (var b = 0; b < bigMonsters.length; b++) {
var bigMonster = bigMonsters[b];
bigMonster.targetX = ship.x;
bigMonster.targetY = ship.y;
}
// Update king monster targets to current ship position
for (var k = 0; k < kingMonsters.length; k++) {
var kingMonster = kingMonsters[k];
kingMonster.targetX = ship.x;
kingMonster.targetY = ship.y;
}
// Check collisions
checkWaveMonsterCollisions();
checkMonsterShipCollisions();
// Check if round is complete
checkRoundComplete();
// Remove off-screen monsters (safety cleanup)
for (var m = monsters.length - 1; m >= 0; m--) {
var monster = monsters[m];
if (monster.x < -100 || monster.x > 2148 || monster.y < -100 || monster.y > 2832) {
monster.destroy();
monsters.splice(m, 1);
}
}
// Remove off-screen big monsters (safety cleanup)
for (var b = bigMonsters.length - 1; b >= 0; b--) {
var bigMonster = bigMonsters[b];
if (bigMonster.x < -100 || bigMonster.x > 2148 || bigMonster.y < -100 || bigMonster.y > 2832) {
bigMonster.destroy();
bigMonsters.splice(b, 1);
}
}
// Remove off-screen king monsters (safety cleanup)
for (var k = kingMonsters.length - 1; k >= 0; k--) {
var kingMonster = kingMonsters[k];
if (kingMonster.x < -100 || kingMonster.x > 2148 || kingMonster.y < -100 || kingMonster.y > 2832) {
kingMonster.destroy();
kingMonsters.splice(k, 1);
}
}
};