/****
* 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);
}
}
};