/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 40;
self.speed = 2 + Math.random() * 2;
self.lastY = 0;
self.lastIntersecting = false;
self.update = function () {
self.lastY = self.y;
self.y += self.speed;
// Add slight horizontal movement
self.x += Math.sin(LK.ticks / 20 + self.y / 100) * 2;
};
self.damage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xFFFF00, 200);
if (self.health <= 0) {
return true; // Enemy is dead
}
return false;
};
return self;
});
var FireParticle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifetime = 20 + Math.random() * 20;
self.speedX = Math.random() * 4 - 2;
self.speedY = Math.random() * 2 + 1;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
self.lifetime--;
particleGraphics.alpha = self.lifetime / 40;
particleGraphics.scaleX = particleGraphics.scaleY = self.lifetime / 40;
};
return self;
});
var Fireball = Container.expand(function () {
var self = Container.call(this);
var fireballGraphics = self.attachAsset('fireball', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.damage = 20;
self.particles = [];
self.speedX = 0;
self.speedY = -15; // Default is upward
self.targetX = 0;
self.targetY = 0;
self.lastY = 0;
self.update = function () {
self.lastY = self.y;
// Use directional movement if speedX and speedY are set, otherwise fall back to default vertical movement
if (self.speedX !== undefined && self.speedY !== undefined) {
self.x += self.speedX;
self.y += self.speedY;
} else {
self.y -= self.speed;
}
// Create fire trail particles
if (LK.ticks % 3 === 0) {
self.createParticle();
}
// Rotate the fireball
fireballGraphics.rotation += 0.1;
};
self.createParticle = function () {
var particle = new FireParticle();
particle.x = self.x + (Math.random() * 20 - 10);
particle.y = self.y + (Math.random() * 20 - 10);
game.addChild(particle);
particles.push(particle);
};
return self;
});
var Flame = Container.expand(function () {
var self = Container.call(this);
var flameGraphics = self.attachAsset('flame', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifetime = 300;
self.power = 1;
self.selected = false;
self.originX = 0;
self.originY = 0;
self.lastIntersecting = false;
self.init = function (x, y) {
self.x = x;
self.y = y;
self.originX = x;
self.originY = y;
};
self.update = function () {
// Animate flame
if (!self.selected) {
flameGraphics.scaleX = 0.8 + Math.sin(LK.ticks / 10) * 0.2;
flameGraphics.scaleY = 0.8 + Math.cos(LK.ticks / 8) * 0.2;
// Random movement around origin
self.x = self.originX + Math.sin(LK.ticks / 15) * 10;
self.y = self.originY + Math.cos(LK.ticks / 12) * 10;
}
// Decrease lifetime
self.lifetime--;
if (self.lifetime <= 50) {
// Fade out when about to disappear
flameGraphics.alpha = self.lifetime / 50;
}
};
self.select = function () {
self.selected = true;
tween(flameGraphics, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeOut
});
};
self.deselect = function () {
self.selected = false;
tween(flameGraphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300,
easing: tween.easeOut
});
};
self.move = function (x, y) {
if (self.selected) {
self.x = x;
self.y = y;
}
};
return self;
});
var FlameTrap = Container.expand(function () {
var self = Container.call(this);
var trapGraphics = self.attachAsset('flameTrap', {
anchorX: 0.5,
anchorY: 0.5
});
self.active = false;
self.cooldown = 0;
self.lastIntersecting = false;
self.activate = function () {
if (!self.active && self.cooldown <= 0) {
self.active = true;
LK.effects.flashObject(self, 0xFF6600, 500);
LK.getSound('flameWhoosh').play();
// Create flames
for (var i = 0; i < 5; i++) {
var flame = new Flame();
flame.init(self.x + i * 40 - 80, self.y - 50);
game.addChild(flame);
flames.push(flame);
}
// Set cooldown
self.cooldown = 300;
self.active = false;
}
};
self.update = function () {
if (self.cooldown > 0) {
self.cooldown--;
trapGraphics.alpha = 0.3 + (1 - self.cooldown / 300) * 0.7;
}
};
return self;
});
var Pyromancer = Container.expand(function () {
var self = Container.call(this);
var pyromancerGraphics = self.attachAsset('pyromancer', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.fireballCooldown = 0;
self.fireballCooldownMax = 15;
self.flameManipulationActive = false;
self.targetFlame = null;
self.shoot = function () {
if (self.fireballCooldown <= 0) {
var fireball = new Fireball();
fireball.x = self.x;
fireball.y = self.y - 50;
// Modify fireball's trajectory to go above the red line
fireball.targetY = Math.random() * (2732 / 2 - 200) + 100; // Random position in upper half
fireball.targetX = Math.random() * 2048; // Random horizontal position
// Calculate direction vector
var dirX = fireball.targetX - fireball.x;
var dirY = fireball.targetY - fireball.y;
var length = Math.sqrt(dirX * dirX + dirY * dirY);
// Normalize and set velocity
fireball.speedX = dirX / length * 15;
fireball.speedY = dirY / length * 15;
game.addChild(fireball);
fireballs.push(fireball);
self.fireballCooldown = self.fireballCooldownMax;
LK.getSound('fireballLaunch').play();
}
};
self.update = function () {
if (self.fireballCooldown > 0) {
self.fireballCooldown--;
}
};
self.damage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xFF0000, 300);
if (self.health <= 0) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Set background to dark blue
game.setBackgroundColor(0x1A1A2E);
// Create a red line divider
var redLine = game.addChild(LK.getAsset('flameTrap', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10.24,
// Cover the full width of the screen
scaleY: 0.5,
tint: 0xFF0000 // Red color
}));
redLine.y = 2732 / 2; // Middle of the screen
redLine.x = 2048 / 2; // Center horizontally
// Game variables
var pyromancer;
var fireballs = [];
var enemies = [];
var flames = [];
var particles = [];
var flameTraps = [];
var wave = 1;
var enemiesDefeated = 0;
var enemiesInWave = 5;
var waveInterval = 600; // 10 seconds between waves
var waveTimer = 0;
var dragTarget = null;
var selectedFlame = null;
// Create UI
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFF9900
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var waveTxt = new Text2('Wave: 1', {
size: 80,
fill: 0xFFFFFF
});
waveTxt.anchor.set(0.5, 0);
waveTxt.y = 100;
LK.gui.top.addChild(waveTxt);
var healthTxt = new Text2('Health: 100', {
size: 80,
fill: 0xFF5555
});
healthTxt.anchor.set(0, 0);
healthTxt.x = 50;
healthTxt.y = 50;
LK.gui.topRight.addChild(healthTxt);
// Create pyromancer
pyromancer = new Pyromancer();
pyromancer.x = 2048 / 2;
pyromancer.y = 2732 - 200;
game.addChild(pyromancer);
// Create flame traps
for (var i = 0; i < 3; i++) {
var trap = new FlameTrap();
trap.x = (i + 1) * (2048 / 4);
trap.y = 2732 / 2;
game.addChild(trap);
flameTraps.push(trap);
}
// Play background music
LK.playMusic('battleTheme', {
fade: {
start: 0,
end: 0.7,
duration: 2000
}
});
// Handle touch input for moving pyromancer
function handleMove(x, y, obj) {
if (dragTarget === pyromancer) {
// Limit pyromancer to bottom half of screen
pyromancer.x = x;
pyromancer.y = Math.max(2732 / 2, Math.min(y, 2732 - 100));
} else if (selectedFlame) {
// Move selected flame
selectedFlame.move(x, y);
}
}
game.down = function (x, y, obj) {
// Check if tapping on an existing flame to control it
var flameSelected = false;
for (var i = 0; i < flames.length; i++) {
var flame = flames[i];
var localPos = flame.toLocal({
x: x,
y: y
});
if (Math.abs(localPos.x) < 40 && Math.abs(localPos.y) < 60) {
// Select this flame
if (selectedFlame) {
selectedFlame.deselect();
}
selectedFlame = flame;
selectedFlame.select();
flameSelected = true;
LK.getSound('flameWhoosh').play();
break;
}
}
// Check if tapping a flame trap
for (var i = 0; i < flameTraps.length; i++) {
var trap = flameTraps[i];
if (Math.abs(x - trap.x) < 100 && Math.abs(y - trap.y) < 30) {
trap.activate();
return;
}
}
// If not selecting a flame and in lower half of screen, control pyromancer
if (!flameSelected && y > 2732 / 2) {
dragTarget = pyromancer;
handleMove(x, y, obj);
} else if (!flameSelected && !selectedFlame && y < 2732 / 2) {
// Shoot fireball when tapping in upper half, and make it target that location
pyromancer.shoot();
// Set the target for the most recently shot fireball
if (fireballs.length > 0) {
var lastFireball = fireballs[fireballs.length - 1];
lastFireball.targetX = x;
lastFireball.targetY = y;
// Recalculate direction vector
var dirX = lastFireball.targetX - lastFireball.x;
var dirY = lastFireball.targetY - lastFireball.y;
var length = Math.sqrt(dirX * dirX + dirY * dirY);
// Normalize and set velocity
lastFireball.speedX = dirX / length * 15;
lastFireball.speedY = dirY / length * 15;
}
}
};
game.up = function (x, y, obj) {
dragTarget = null;
// Deselect flame if we have one
if (selectedFlame) {
selectedFlame.deselect();
selectedFlame = null;
}
};
game.move = handleMove;
// Create a new enemy
function spawnEnemy() {
var enemy = new Enemy();
enemy.x = Math.random() * (2048 - 200) + 100;
enemy.y = -100;
game.addChild(enemy);
enemies.push(enemy);
}
// Start a new wave
function startNewWave() {
wave++;
waveTxt.setText('Wave: ' + wave);
enemiesInWave = 5 + wave * 2;
waveTimer = 0;
// Spawn first enemy of wave
spawnEnemy();
}
// Update game every frame
game.update = function () {
// Update UI
scoreTxt.setText('Score: ' + LK.getScore());
healthTxt.setText('Health: ' + pyromancer.health);
// Update pyromancer
pyromancer.update();
// Enemy wave management
waveTimer++;
if (enemies.length === 0 && waveTimer >= waveInterval) {
startNewWave();
} else if (enemies.length < enemiesInWave && waveTimer % 60 === 0 && waveTimer < waveInterval) {
spawnEnemy();
}
// Update fireballs
for (var i = fireballs.length - 1; i >= 0; i--) {
var fireball = fireballs[i];
fireball.update();
// Remove fireballs that go off screen
if (fireball.y < -100) {
fireball.destroy();
fireballs.splice(i, 1);
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
enemy.lastY = enemy.y;
enemy.update();
// Check for collision with fireballs
for (var j = fireballs.length - 1; j >= 0; j--) {
var fireball = fireballs[j];
if (enemy.intersects(fireball)) {
// Enemy hit by fireball
if (enemy.damage(fireball.damage)) {
// Enemy destroyed
LK.getSound('enemyHit').play();
enemy.destroy();
enemies.splice(i, 1);
LK.setScore(LK.getScore() + 100);
enemiesDefeated++;
// Create flames where enemy was destroyed
var flame = new Flame();
flame.init(enemy.x, enemy.y);
game.addChild(flame);
flames.push(flame);
i--;
break;
}
// Remove fireball
fireball.destroy();
fireballs.splice(j, 1);
}
}
// Check for enemies that reach bottom of screen
if (enemy.y > 2732 + 50) {
pyromancer.damage(10);
enemy.destroy();
enemies.splice(i, 1);
}
// Check for collision with flames
if (enemy && selectedFlame && enemy.intersects(selectedFlame)) {
if (enemy.damage(0.5)) {
// Enemy destroyed by flame
LK.getSound('enemyHit').play();
enemy.destroy();
enemies.splice(i, 1);
LK.setScore(LK.getScore() + 150);
enemiesDefeated++;
}
}
// Check for collision with pyromancer
if (enemy && enemy.intersects(pyromancer)) {
pyromancer.damage(20);
enemy.destroy();
enemies.splice(i, 1);
}
}
// Update flames
for (var i = flames.length - 1; i >= 0; i--) {
var flame = flames[i];
flame.update();
// Remove flames that have expired
if (flame.lifetime <= 0) {
// Don't remove if it's currently selected
if (flame === selectedFlame) {
flame.lifetime = 60; // Give it a little more time
} else {
flame.destroy();
flames.splice(i, 1);
}
}
}
// Update flame traps
for (var i = 0; i < flameTraps.length; i++) {
flameTraps[i].update();
}
// Update particles
for (var i = particles.length - 1; i >= 0; i--) {
var particle = particles[i];
particle.update();
// Remove particles that have expired
if (particle.lifetime <= 0) {
particle.destroy();
particles.splice(i, 1);
}
}
// Check for win condition
if (enemiesDefeated >= 50) {
LK.showYouWin();
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 40;
self.speed = 2 + Math.random() * 2;
self.lastY = 0;
self.lastIntersecting = false;
self.update = function () {
self.lastY = self.y;
self.y += self.speed;
// Add slight horizontal movement
self.x += Math.sin(LK.ticks / 20 + self.y / 100) * 2;
};
self.damage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xFFFF00, 200);
if (self.health <= 0) {
return true; // Enemy is dead
}
return false;
};
return self;
});
var FireParticle = Container.expand(function () {
var self = Container.call(this);
var particleGraphics = self.attachAsset('particle', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifetime = 20 + Math.random() * 20;
self.speedX = Math.random() * 4 - 2;
self.speedY = Math.random() * 2 + 1;
self.update = function () {
self.x += self.speedX;
self.y += self.speedY;
self.lifetime--;
particleGraphics.alpha = self.lifetime / 40;
particleGraphics.scaleX = particleGraphics.scaleY = self.lifetime / 40;
};
return self;
});
var Fireball = Container.expand(function () {
var self = Container.call(this);
var fireballGraphics = self.attachAsset('fireball', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.damage = 20;
self.particles = [];
self.speedX = 0;
self.speedY = -15; // Default is upward
self.targetX = 0;
self.targetY = 0;
self.lastY = 0;
self.update = function () {
self.lastY = self.y;
// Use directional movement if speedX and speedY are set, otherwise fall back to default vertical movement
if (self.speedX !== undefined && self.speedY !== undefined) {
self.x += self.speedX;
self.y += self.speedY;
} else {
self.y -= self.speed;
}
// Create fire trail particles
if (LK.ticks % 3 === 0) {
self.createParticle();
}
// Rotate the fireball
fireballGraphics.rotation += 0.1;
};
self.createParticle = function () {
var particle = new FireParticle();
particle.x = self.x + (Math.random() * 20 - 10);
particle.y = self.y + (Math.random() * 20 - 10);
game.addChild(particle);
particles.push(particle);
};
return self;
});
var Flame = Container.expand(function () {
var self = Container.call(this);
var flameGraphics = self.attachAsset('flame', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifetime = 300;
self.power = 1;
self.selected = false;
self.originX = 0;
self.originY = 0;
self.lastIntersecting = false;
self.init = function (x, y) {
self.x = x;
self.y = y;
self.originX = x;
self.originY = y;
};
self.update = function () {
// Animate flame
if (!self.selected) {
flameGraphics.scaleX = 0.8 + Math.sin(LK.ticks / 10) * 0.2;
flameGraphics.scaleY = 0.8 + Math.cos(LK.ticks / 8) * 0.2;
// Random movement around origin
self.x = self.originX + Math.sin(LK.ticks / 15) * 10;
self.y = self.originY + Math.cos(LK.ticks / 12) * 10;
}
// Decrease lifetime
self.lifetime--;
if (self.lifetime <= 50) {
// Fade out when about to disappear
flameGraphics.alpha = self.lifetime / 50;
}
};
self.select = function () {
self.selected = true;
tween(flameGraphics, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 300,
easing: tween.easeOut
});
};
self.deselect = function () {
self.selected = false;
tween(flameGraphics, {
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300,
easing: tween.easeOut
});
};
self.move = function (x, y) {
if (self.selected) {
self.x = x;
self.y = y;
}
};
return self;
});
var FlameTrap = Container.expand(function () {
var self = Container.call(this);
var trapGraphics = self.attachAsset('flameTrap', {
anchorX: 0.5,
anchorY: 0.5
});
self.active = false;
self.cooldown = 0;
self.lastIntersecting = false;
self.activate = function () {
if (!self.active && self.cooldown <= 0) {
self.active = true;
LK.effects.flashObject(self, 0xFF6600, 500);
LK.getSound('flameWhoosh').play();
// Create flames
for (var i = 0; i < 5; i++) {
var flame = new Flame();
flame.init(self.x + i * 40 - 80, self.y - 50);
game.addChild(flame);
flames.push(flame);
}
// Set cooldown
self.cooldown = 300;
self.active = false;
}
};
self.update = function () {
if (self.cooldown > 0) {
self.cooldown--;
trapGraphics.alpha = 0.3 + (1 - self.cooldown / 300) * 0.7;
}
};
return self;
});
var Pyromancer = Container.expand(function () {
var self = Container.call(this);
var pyromancerGraphics = self.attachAsset('pyromancer', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.fireballCooldown = 0;
self.fireballCooldownMax = 15;
self.flameManipulationActive = false;
self.targetFlame = null;
self.shoot = function () {
if (self.fireballCooldown <= 0) {
var fireball = new Fireball();
fireball.x = self.x;
fireball.y = self.y - 50;
// Modify fireball's trajectory to go above the red line
fireball.targetY = Math.random() * (2732 / 2 - 200) + 100; // Random position in upper half
fireball.targetX = Math.random() * 2048; // Random horizontal position
// Calculate direction vector
var dirX = fireball.targetX - fireball.x;
var dirY = fireball.targetY - fireball.y;
var length = Math.sqrt(dirX * dirX + dirY * dirY);
// Normalize and set velocity
fireball.speedX = dirX / length * 15;
fireball.speedY = dirY / length * 15;
game.addChild(fireball);
fireballs.push(fireball);
self.fireballCooldown = self.fireballCooldownMax;
LK.getSound('fireballLaunch').play();
}
};
self.update = function () {
if (self.fireballCooldown > 0) {
self.fireballCooldown--;
}
};
self.damage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xFF0000, 300);
if (self.health <= 0) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000000
});
/****
* Game Code
****/
// Set background to dark blue
game.setBackgroundColor(0x1A1A2E);
// Create a red line divider
var redLine = game.addChild(LK.getAsset('flameTrap', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 10.24,
// Cover the full width of the screen
scaleY: 0.5,
tint: 0xFF0000 // Red color
}));
redLine.y = 2732 / 2; // Middle of the screen
redLine.x = 2048 / 2; // Center horizontally
// Game variables
var pyromancer;
var fireballs = [];
var enemies = [];
var flames = [];
var particles = [];
var flameTraps = [];
var wave = 1;
var enemiesDefeated = 0;
var enemiesInWave = 5;
var waveInterval = 600; // 10 seconds between waves
var waveTimer = 0;
var dragTarget = null;
var selectedFlame = null;
// Create UI
var scoreTxt = new Text2('Score: 0', {
size: 80,
fill: 0xFF9900
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var waveTxt = new Text2('Wave: 1', {
size: 80,
fill: 0xFFFFFF
});
waveTxt.anchor.set(0.5, 0);
waveTxt.y = 100;
LK.gui.top.addChild(waveTxt);
var healthTxt = new Text2('Health: 100', {
size: 80,
fill: 0xFF5555
});
healthTxt.anchor.set(0, 0);
healthTxt.x = 50;
healthTxt.y = 50;
LK.gui.topRight.addChild(healthTxt);
// Create pyromancer
pyromancer = new Pyromancer();
pyromancer.x = 2048 / 2;
pyromancer.y = 2732 - 200;
game.addChild(pyromancer);
// Create flame traps
for (var i = 0; i < 3; i++) {
var trap = new FlameTrap();
trap.x = (i + 1) * (2048 / 4);
trap.y = 2732 / 2;
game.addChild(trap);
flameTraps.push(trap);
}
// Play background music
LK.playMusic('battleTheme', {
fade: {
start: 0,
end: 0.7,
duration: 2000
}
});
// Handle touch input for moving pyromancer
function handleMove(x, y, obj) {
if (dragTarget === pyromancer) {
// Limit pyromancer to bottom half of screen
pyromancer.x = x;
pyromancer.y = Math.max(2732 / 2, Math.min(y, 2732 - 100));
} else if (selectedFlame) {
// Move selected flame
selectedFlame.move(x, y);
}
}
game.down = function (x, y, obj) {
// Check if tapping on an existing flame to control it
var flameSelected = false;
for (var i = 0; i < flames.length; i++) {
var flame = flames[i];
var localPos = flame.toLocal({
x: x,
y: y
});
if (Math.abs(localPos.x) < 40 && Math.abs(localPos.y) < 60) {
// Select this flame
if (selectedFlame) {
selectedFlame.deselect();
}
selectedFlame = flame;
selectedFlame.select();
flameSelected = true;
LK.getSound('flameWhoosh').play();
break;
}
}
// Check if tapping a flame trap
for (var i = 0; i < flameTraps.length; i++) {
var trap = flameTraps[i];
if (Math.abs(x - trap.x) < 100 && Math.abs(y - trap.y) < 30) {
trap.activate();
return;
}
}
// If not selecting a flame and in lower half of screen, control pyromancer
if (!flameSelected && y > 2732 / 2) {
dragTarget = pyromancer;
handleMove(x, y, obj);
} else if (!flameSelected && !selectedFlame && y < 2732 / 2) {
// Shoot fireball when tapping in upper half, and make it target that location
pyromancer.shoot();
// Set the target for the most recently shot fireball
if (fireballs.length > 0) {
var lastFireball = fireballs[fireballs.length - 1];
lastFireball.targetX = x;
lastFireball.targetY = y;
// Recalculate direction vector
var dirX = lastFireball.targetX - lastFireball.x;
var dirY = lastFireball.targetY - lastFireball.y;
var length = Math.sqrt(dirX * dirX + dirY * dirY);
// Normalize and set velocity
lastFireball.speedX = dirX / length * 15;
lastFireball.speedY = dirY / length * 15;
}
}
};
game.up = function (x, y, obj) {
dragTarget = null;
// Deselect flame if we have one
if (selectedFlame) {
selectedFlame.deselect();
selectedFlame = null;
}
};
game.move = handleMove;
// Create a new enemy
function spawnEnemy() {
var enemy = new Enemy();
enemy.x = Math.random() * (2048 - 200) + 100;
enemy.y = -100;
game.addChild(enemy);
enemies.push(enemy);
}
// Start a new wave
function startNewWave() {
wave++;
waveTxt.setText('Wave: ' + wave);
enemiesInWave = 5 + wave * 2;
waveTimer = 0;
// Spawn first enemy of wave
spawnEnemy();
}
// Update game every frame
game.update = function () {
// Update UI
scoreTxt.setText('Score: ' + LK.getScore());
healthTxt.setText('Health: ' + pyromancer.health);
// Update pyromancer
pyromancer.update();
// Enemy wave management
waveTimer++;
if (enemies.length === 0 && waveTimer >= waveInterval) {
startNewWave();
} else if (enemies.length < enemiesInWave && waveTimer % 60 === 0 && waveTimer < waveInterval) {
spawnEnemy();
}
// Update fireballs
for (var i = fireballs.length - 1; i >= 0; i--) {
var fireball = fireballs[i];
fireball.update();
// Remove fireballs that go off screen
if (fireball.y < -100) {
fireball.destroy();
fireballs.splice(i, 1);
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
enemy.lastY = enemy.y;
enemy.update();
// Check for collision with fireballs
for (var j = fireballs.length - 1; j >= 0; j--) {
var fireball = fireballs[j];
if (enemy.intersects(fireball)) {
// Enemy hit by fireball
if (enemy.damage(fireball.damage)) {
// Enemy destroyed
LK.getSound('enemyHit').play();
enemy.destroy();
enemies.splice(i, 1);
LK.setScore(LK.getScore() + 100);
enemiesDefeated++;
// Create flames where enemy was destroyed
var flame = new Flame();
flame.init(enemy.x, enemy.y);
game.addChild(flame);
flames.push(flame);
i--;
break;
}
// Remove fireball
fireball.destroy();
fireballs.splice(j, 1);
}
}
// Check for enemies that reach bottom of screen
if (enemy.y > 2732 + 50) {
pyromancer.damage(10);
enemy.destroy();
enemies.splice(i, 1);
}
// Check for collision with flames
if (enemy && selectedFlame && enemy.intersects(selectedFlame)) {
if (enemy.damage(0.5)) {
// Enemy destroyed by flame
LK.getSound('enemyHit').play();
enemy.destroy();
enemies.splice(i, 1);
LK.setScore(LK.getScore() + 150);
enemiesDefeated++;
}
}
// Check for collision with pyromancer
if (enemy && enemy.intersects(pyromancer)) {
pyromancer.damage(20);
enemy.destroy();
enemies.splice(i, 1);
}
}
// Update flames
for (var i = flames.length - 1; i >= 0; i--) {
var flame = flames[i];
flame.update();
// Remove flames that have expired
if (flame.lifetime <= 0) {
// Don't remove if it's currently selected
if (flame === selectedFlame) {
flame.lifetime = 60; // Give it a little more time
} else {
flame.destroy();
flames.splice(i, 1);
}
}
}
// Update flame traps
for (var i = 0; i < flameTraps.length; i++) {
flameTraps[i].update();
}
// Update particles
for (var i = particles.length - 1; i >= 0; i--) {
var particle = particles[i];
particle.update();
// Remove particles that have expired
if (particle.lifetime <= 0) {
particle.destroy();
particles.splice(i, 1);
}
}
// Check for win condition
if (enemiesDefeated >= 50) {
LK.showYouWin();
}
};