/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Enemy = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2 + Math.random() * 1.5;
self.health = 1;
self.points = 10;
self.canShoot = Math.random() > 0.7;
self.shotDelay = 60 + Math.floor(Math.random() * 120);
self.shotTimer = self.shotDelay;
self.movePattern = Math.floor(Math.random() * 3);
self.amplitude = 30 + Math.random() * 50;
self.frequency = 0.01 + Math.random() * 0.02;
self.baseX = 0;
self.angle = Math.random() * Math.PI * 2;
self.init = function (x, y) {
self.x = x;
self.y = y;
self.baseX = x;
};
self.hit = function (power) {
self.health -= power;
// Visual feedback for hit
tween(graphic, {
alpha: 0.2
}, {
duration: 100,
easing: tween.linear,
onFinish: function onFinish() {
tween(graphic, {
alpha: 1
}, {
duration: 100,
easing: tween.linear
});
}
});
return self.health <= 0;
};
self.update = function () {
self.y += self.speed;
// Different movement patterns
if (self.movePattern === 0) {
// Sine wave movement
self.x = self.baseX + Math.sin(self.angle) * self.amplitude;
self.angle += self.frequency;
} else if (self.movePattern === 1) {
// Zig-zag movement
if (Math.abs(self.x - self.baseX) > self.amplitude) {
self.frequency = -self.frequency;
}
self.x += self.frequency * 5;
}
// Handle shooting
if (self.canShoot) {
self.shotTimer--;
if (self.shotTimer <= 0) {
self.shotTimer = self.shotDelay;
return true; // Signal to create projectile
}
}
return false;
};
return self;
});
var BossEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Replace the graphic with boss graphic
self.removeChildren();
var graphic = self.attachAsset('enemyBoss', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 10;
self.points = 100;
self.speed = 1;
self.canShoot = true;
self.shotDelay = 40;
self.shotTimer = self.shotDelay;
self.movePattern = 0;
// Override the update method to add boss-specific behavior
var parentUpdate = self.update;
self.update = function () {
// First few seconds, boss moves down slowly
if (self.y < 300) {
self.y += self.speed;
return false;
}
// Then use parent update logic for movement and shooting
return parentUpdate.call(self);
};
return self;
});
var EnemyProjectile = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('enemyProjectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.angle = 0;
self.init = function (x, y, targetX, targetY) {
self.x = x;
self.y = y;
// Calculate angle to target (usually the player)
if (targetX !== undefined && targetY !== undefined) {
var dx = targetX - x;
var dy = targetY - y;
self.angle = Math.atan2(dy, dx);
} else {
self.angle = Math.PI / 2; // Default: straight down
}
};
self.update = function () {
self.x += Math.cos(self.angle) * self.speed;
self.y += Math.sin(self.angle) * self.speed;
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9
});
self.lifetime = 20;
self.init = function (x, y, size) {
self.x = x;
self.y = y;
if (size) {
graphic.scale.set(size, size);
}
// Start with small scale and grow quickly
graphic.scale.set(0.2, 0.2);
tween(graphic.scale, {
x: 1,
y: 1
}, {
duration: 300,
easing: tween.easeOut
});
// Fade out
tween(graphic, {
alpha: 0
}, {
duration: 500,
easing: tween.linear
});
};
self.update = function () {
self.lifetime--;
return self.lifetime <= 0;
};
return self;
});
var Lightning = Container.expand(function () {
var self = Container.call(this);
var bolt = self.attachAsset('lightning', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0.9
});
self.speed = -15;
self.power = 1;
self.chainLightningEnabled = false;
// Branch lightning for power attacks
self.createBranches = function (numBranches) {
for (var i = 0; i < numBranches; i++) {
var branch = self.attachAsset('lightningBranch', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0.7,
rotation: Math.random() * 0.5 - 0.25 + (i % 2 ? 0.3 : -0.3)
});
branch.x = Math.random() * 20 - 10;
branch.y = bolt.height * (0.3 + Math.random() * 0.4);
}
};
self.update = function () {
self.y += self.speed;
// Add flicker effect to lightning
bolt.alpha = 0.7 + Math.random() * 0.3;
// Add slight random movement for natural feel
bolt.rotation = Math.random() * 0.1 - 0.05;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.type = Math.floor(Math.random() * 3); // 0: chain lightning, 1: increased power, 2: rapid fire
// Set different colors based on powerup type
if (self.type === 0) {
graphic.tint = 0x00ffff; // Cyan for chain lightning
} else if (self.type === 1) {
graphic.tint = 0xff00ff; // Purple for increased power
} else {
graphic.tint = 0xffff00; // Yellow for rapid fire
}
self.init = function (x, y) {
self.x = x;
self.y = y;
};
self.update = function () {
self.y += self.speed;
// Pulsate effect
var scale = 0.9 + 0.2 * Math.sin(LK.ticks * 0.1);
graphic.scale.set(scale, scale);
};
return self;
});
var Wizard = Container.expand(function () {
var self = Container.call(this);
// Create wizard body
var body = self.attachAsset('wizard', {
anchorX: 0.5,
anchorY: 0.5
});
// Create wizard hat
var hat = self.attachAsset('wizardHat', {
anchorX: 0.5,
anchorY: 1.0,
y: -body.height / 2
});
self.fireCooldown = 0;
self.fireRate = 20; // Lower = faster firing
self.powerLevel = 1;
self.chainLightning = false;
self.powerupTimer = 0;
self.invulnerable = false;
self.invulnerableTimer = 0;
self.update = function () {
if (self.fireCooldown > 0) {
self.fireCooldown--;
}
if (self.powerupTimer > 0) {
self.powerupTimer--;
// Visual indicator for active powerup
body.alpha = 0.7 + 0.3 * Math.sin(LK.ticks * 0.2);
// Reset powerups when timer expires
if (self.powerupTimer === 0) {
self.powerLevel = 1;
self.chainLightning = false;
self.fireRate = 20;
body.alpha = 1;
}
}
if (self.invulnerable) {
self.invulnerableTimer--;
if (self.invulnerableTimer <= 0) {
self.invulnerable = false;
body.alpha = 1;
hat.alpha = 1;
} else {
// Flicker effect for invulnerability
body.alpha = hat.alpha = LK.ticks % 4 < 2 ? 0.3 : 0.8;
}
}
};
self.fire = function () {
if (self.fireCooldown <= 0) {
self.fireCooldown = self.fireRate;
return true;
}
return false;
};
self.applyPowerup = function (type) {
self.powerupTimer = 600; // 10 seconds at 60fps
if (type === 0) {
// Chain lightning
self.chainLightning = true;
} else if (type === 1) {
// Increased power
self.powerLevel += 1;
} else if (type === 2) {
// Rapid fire
self.fireRate = Math.max(5, self.fireRate - 5);
}
};
self.hit = function () {
if (!self.invulnerable) {
self.invulnerable = true;
self.invulnerableTimer = 120; // 2 seconds invulnerability
return true;
}
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000022
});
/****
* Game Code
****/
// Game state variables
var wizard;
var lightnings = [];
var enemies = [];
var explosions = [];
var powerups = [];
var enemyProjectiles = [];
var lives = 3;
var score = 0;
var highScore = storage.highScore || 0;
var level = 1;
var enemiesDefeated = 0;
var enemySpawnTimer = 0;
var bossActive = false;
var levelClearDelay = 0;
var gameActive = true;
var shakeIntensity = 0;
// UI elements
var scoreText;
var livesText;
var levelText;
// Game initialization
function initGame() {
// Add background
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5
});
background.x = 2048 / 2;
background.y = 2732 / 2;
game.addChild(background);
// Initialize wizard
wizard = new Wizard();
wizard.fireRate = 30; // Set fireRate to 30 ticks, equivalent to 0.5 seconds at 60 FPS
wizard.x = 2048 / 2;
wizard.y = 2732 - 200;
game.addChild(wizard);
// Setup UI
scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreText);
livesText = new Text2('Lives: ' + lives, {
size: 80,
fill: 0xFFFFFF
});
livesText.anchor.set(0, 0);
LK.gui.top.addChild(livesText);
levelText = new Text2('Level: ' + level, {
size: 80,
fill: 0xFFFFFF
});
levelText.anchor.set(1, 0);
LK.gui.topLeft.addChild(levelText);
levelText.x = 200; // Move away from top-left corner
// Start initial enemy spawn
enemySpawnTimer = 60;
// Start game music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.7,
duration: 1000
}
});
}
function updateScore(points) {
score += points;
scoreText.setText('Score: ' + score);
// Update high score if needed
if (score > highScore) {
highScore = score;
storage.highScore = highScore;
}
}
function spawnEnemy() {
// Determine if we should spawn a boss
if (enemiesDefeated >= 20 * level && !bossActive) {
var boss = new BossEnemy();
boss.init(2048 / 2, -100);
enemies.push(boss);
game.addChild(boss);
bossActive = true;
// Screen shake effect for boss entrance
shakeIntensity = 10;
return;
}
// Regular enemy spawn
var enemy = new Enemy();
var x = 100 + Math.random() * (2048 - 200);
var y = -100;
enemy.init(x, y);
enemies.push(enemy);
game.addChild(enemy);
}
function nextLevel() {
level++;
levelText.setText('Level: ' + level);
// Reset level variables
enemiesDefeated = 0;
bossActive = false;
// Increase difficulty
Enemy.prototype.speed += 0.3;
// Visual effect for level transition
LK.effects.flashScreen(0x0000ff, 500);
}
function createLightning(x, y) {
var lightning = new Lightning();
lightning.x = x;
lightning.y = y;
lightning.power = wizard.powerLevel;
lightning.chainLightningEnabled = wizard.chainLightning;
// Add branches for higher power levels
if (wizard.powerLevel > 1) {
lightning.createBranches(wizard.powerLevel - 1);
}
lightnings.push(lightning);
game.addChild(lightning);
// Play lightning sound
LK.getSound('lightning').play();
}
function createExplosion(x, y, size) {
var explosion = new Explosion();
explosion.init(x, y, size);
explosions.push(explosion);
game.addChild(explosion);
// Play explosion sound
LK.getSound('explosion').play();
}
// Initialize the game
initGame();
// Touch/mouse handlers
var dragging = false;
var lastX = null;
game.down = function (x, y) {
dragging = true;
lastX = x;
};
game.move = function (x, y) {
if (dragging) {
var deltaX = x - lastX;
wizard.x += deltaX;
// Keep wizard within bounds
wizard.x = Math.max(50, Math.min(2048 - 50, wizard.x));
lastX = x;
}
};
game.up = function () {
dragging = false;
lastX = null;
};
// Main game update
game.update = function () {
if (!gameActive) {
return;
}
// Screen shake effect
if (shakeIntensity > 0) {
game.x = (Math.random() * 2 - 1) * shakeIntensity;
game.y = (Math.random() * 2 - 1) * shakeIntensity;
shakeIntensity *= 0.9;
if (shakeIntensity < 0.5) {
shakeIntensity = 0;
game.x = 0;
game.y = 0;
}
}
// Update wizard
wizard.update();
// Auto-fire
if (wizard.fire()) {
createLightning(wizard.x, wizard.y - 50);
}
// Level transition
if (levelClearDelay > 0) {
levelClearDelay--;
if (levelClearDelay === 0) {
nextLevel();
}
return; // Pause other updates during level transition
}
// Enemy spawn logic
if (enemySpawnTimer > 0) {
enemySpawnTimer--;
} else {
spawnEnemy();
// Adjust spawn rate based on level
enemySpawnTimer = bossActive ? 120 : Math.max(20, 60 - level * 5);
}
// Update lightnings
for (var i = lightnings.length - 1; i >= 0; i--) {
var lightning = lightnings[i];
lightning.update();
// Remove lightning if off screen
if (lightning.y < -100) {
lightning.destroy();
lightnings.splice(i, 1);
continue;
}
// Check for hits with enemies
var hitEnemy = false;
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (lightning.intersects(enemy)) {
hitEnemy = true;
// Enemy takes damage
if (enemy.hit(lightning.power)) {
// Enemy defeated
createExplosion(enemy.x, enemy.y, enemy instanceof BossEnemy ? 2 : 1);
updateScore(enemy.points);
enemiesDefeated++;
// Check if boss was defeated
if (enemy instanceof BossEnemy) {
bossActive = false;
levelClearDelay = 120; // 2 second delay before next level
LK.effects.flashScreen(0xffffff, 300);
}
// Chance to drop power-up
if (Math.random() < 0.2) {
var powerup = new PowerUp();
powerup.init(enemy.x, enemy.y);
powerups.push(powerup);
game.addChild(powerup);
}
enemy.destroy();
enemies.splice(j, 1);
} else {
// Enemy hit but not defeated
LK.getSound('enemyHit').play();
}
// Remove lightning unless it has chain lightning
if (!lightning.chainLightningEnabled) {
lightning.destroy();
lightnings.splice(i, 1);
continue; // Use continue to check other enemies
}
}
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
var shouldShoot = enemy.update();
// Check if enemy has moved off screen
if (enemy.y > 2732 + 100) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Enemy shoots projectile
if (shouldShoot) {
var projectile = new EnemyProjectile();
projectile.init(enemy.x, enemy.y, wizard.x, wizard.y);
enemyProjectiles.push(projectile);
game.addChild(projectile);
}
}
// Update enemy projectiles
for (var i = enemyProjectiles.length - 1; i >= 0; i--) {
var projectile = enemyProjectiles[i];
projectile.update();
// Check if projectile is off screen
if (projectile.y > 2732 + 20 || projectile.y < -20 || projectile.x > 2048 + 20 || projectile.x < -20) {
projectile.destroy();
enemyProjectiles.splice(i, 1);
continue;
}
// Check for collision with wizard
if (projectile.intersects(wizard)) {
if (wizard.hit()) {
// Player was hit
LK.getSound('playerHit').play();
lives--;
livesText.setText('Lives: ' + lives);
// Create explosion effect
createExplosion(projectile.x, projectile.y, 0.5);
// Screen shake
shakeIntensity = 5;
// Check for game over
if (lives <= 0) {
gameActive = false;
LK.effects.flashScreen(0xff0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1500);
}
}
// Remove projectile
projectile.destroy();
enemyProjectiles.splice(i, 1);
}
}
// Update powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
powerup.update();
// Check if powerup is off screen
if (powerup.y > 2732 + 30) {
powerup.destroy();
powerups.splice(i, 1);
continue;
}
// Check for collision with wizard
if (powerup.intersects(wizard)) {
// Apply powerup effect
wizard.applyPowerup(powerup.type);
// Play sound
LK.getSound('powerupCollect').play();
// Visual feedback
LK.effects.flashObject(wizard, 0x00ffff, 500);
// Remove powerup
powerup.destroy();
powerups.splice(i, 1);
}
}
// Update explosions
for (var i = explosions.length - 1; i >= 0; i--) {
if (explosions[i].update()) {
explosions[i].destroy();
explosions.splice(i, 1);
}
}
}; /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
highScore: 0
});
/****
* Classes
****/
var Enemy = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 2 + Math.random() * 1.5;
self.health = 1;
self.points = 10;
self.canShoot = Math.random() > 0.7;
self.shotDelay = 60 + Math.floor(Math.random() * 120);
self.shotTimer = self.shotDelay;
self.movePattern = Math.floor(Math.random() * 3);
self.amplitude = 30 + Math.random() * 50;
self.frequency = 0.01 + Math.random() * 0.02;
self.baseX = 0;
self.angle = Math.random() * Math.PI * 2;
self.init = function (x, y) {
self.x = x;
self.y = y;
self.baseX = x;
};
self.hit = function (power) {
self.health -= power;
// Visual feedback for hit
tween(graphic, {
alpha: 0.2
}, {
duration: 100,
easing: tween.linear,
onFinish: function onFinish() {
tween(graphic, {
alpha: 1
}, {
duration: 100,
easing: tween.linear
});
}
});
return self.health <= 0;
};
self.update = function () {
self.y += self.speed;
// Different movement patterns
if (self.movePattern === 0) {
// Sine wave movement
self.x = self.baseX + Math.sin(self.angle) * self.amplitude;
self.angle += self.frequency;
} else if (self.movePattern === 1) {
// Zig-zag movement
if (Math.abs(self.x - self.baseX) > self.amplitude) {
self.frequency = -self.frequency;
}
self.x += self.frequency * 5;
}
// Handle shooting
if (self.canShoot) {
self.shotTimer--;
if (self.shotTimer <= 0) {
self.shotTimer = self.shotDelay;
return true; // Signal to create projectile
}
}
return false;
};
return self;
});
var BossEnemy = Enemy.expand(function () {
var self = Enemy.call(this);
// Replace the graphic with boss graphic
self.removeChildren();
var graphic = self.attachAsset('enemyBoss', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 10;
self.points = 100;
self.speed = 1;
self.canShoot = true;
self.shotDelay = 40;
self.shotTimer = self.shotDelay;
self.movePattern = 0;
// Override the update method to add boss-specific behavior
var parentUpdate = self.update;
self.update = function () {
// First few seconds, boss moves down slowly
if (self.y < 300) {
self.y += self.speed;
return false;
}
// Then use parent update logic for movement and shooting
return parentUpdate.call(self);
};
return self;
});
var EnemyProjectile = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('enemyProjectile', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 6;
self.angle = 0;
self.init = function (x, y, targetX, targetY) {
self.x = x;
self.y = y;
// Calculate angle to target (usually the player)
if (targetX !== undefined && targetY !== undefined) {
var dx = targetX - x;
var dy = targetY - y;
self.angle = Math.atan2(dy, dx);
} else {
self.angle = Math.PI / 2; // Default: straight down
}
};
self.update = function () {
self.x += Math.cos(self.angle) * self.speed;
self.y += Math.sin(self.angle) * self.speed;
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.9
});
self.lifetime = 20;
self.init = function (x, y, size) {
self.x = x;
self.y = y;
if (size) {
graphic.scale.set(size, size);
}
// Start with small scale and grow quickly
graphic.scale.set(0.2, 0.2);
tween(graphic.scale, {
x: 1,
y: 1
}, {
duration: 300,
easing: tween.easeOut
});
// Fade out
tween(graphic, {
alpha: 0
}, {
duration: 500,
easing: tween.linear
});
};
self.update = function () {
self.lifetime--;
return self.lifetime <= 0;
};
return self;
});
var Lightning = Container.expand(function () {
var self = Container.call(this);
var bolt = self.attachAsset('lightning', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0.9
});
self.speed = -15;
self.power = 1;
self.chainLightningEnabled = false;
// Branch lightning for power attacks
self.createBranches = function (numBranches) {
for (var i = 0; i < numBranches; i++) {
var branch = self.attachAsset('lightningBranch', {
anchorX: 0.5,
anchorY: 1.0,
alpha: 0.7,
rotation: Math.random() * 0.5 - 0.25 + (i % 2 ? 0.3 : -0.3)
});
branch.x = Math.random() * 20 - 10;
branch.y = bolt.height * (0.3 + Math.random() * 0.4);
}
};
self.update = function () {
self.y += self.speed;
// Add flicker effect to lightning
bolt.alpha = 0.7 + Math.random() * 0.3;
// Add slight random movement for natural feel
bolt.rotation = Math.random() * 0.1 - 0.05;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var graphic = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 3;
self.type = Math.floor(Math.random() * 3); // 0: chain lightning, 1: increased power, 2: rapid fire
// Set different colors based on powerup type
if (self.type === 0) {
graphic.tint = 0x00ffff; // Cyan for chain lightning
} else if (self.type === 1) {
graphic.tint = 0xff00ff; // Purple for increased power
} else {
graphic.tint = 0xffff00; // Yellow for rapid fire
}
self.init = function (x, y) {
self.x = x;
self.y = y;
};
self.update = function () {
self.y += self.speed;
// Pulsate effect
var scale = 0.9 + 0.2 * Math.sin(LK.ticks * 0.1);
graphic.scale.set(scale, scale);
};
return self;
});
var Wizard = Container.expand(function () {
var self = Container.call(this);
// Create wizard body
var body = self.attachAsset('wizard', {
anchorX: 0.5,
anchorY: 0.5
});
// Create wizard hat
var hat = self.attachAsset('wizardHat', {
anchorX: 0.5,
anchorY: 1.0,
y: -body.height / 2
});
self.fireCooldown = 0;
self.fireRate = 20; // Lower = faster firing
self.powerLevel = 1;
self.chainLightning = false;
self.powerupTimer = 0;
self.invulnerable = false;
self.invulnerableTimer = 0;
self.update = function () {
if (self.fireCooldown > 0) {
self.fireCooldown--;
}
if (self.powerupTimer > 0) {
self.powerupTimer--;
// Visual indicator for active powerup
body.alpha = 0.7 + 0.3 * Math.sin(LK.ticks * 0.2);
// Reset powerups when timer expires
if (self.powerupTimer === 0) {
self.powerLevel = 1;
self.chainLightning = false;
self.fireRate = 20;
body.alpha = 1;
}
}
if (self.invulnerable) {
self.invulnerableTimer--;
if (self.invulnerableTimer <= 0) {
self.invulnerable = false;
body.alpha = 1;
hat.alpha = 1;
} else {
// Flicker effect for invulnerability
body.alpha = hat.alpha = LK.ticks % 4 < 2 ? 0.3 : 0.8;
}
}
};
self.fire = function () {
if (self.fireCooldown <= 0) {
self.fireCooldown = self.fireRate;
return true;
}
return false;
};
self.applyPowerup = function (type) {
self.powerupTimer = 600; // 10 seconds at 60fps
if (type === 0) {
// Chain lightning
self.chainLightning = true;
} else if (type === 1) {
// Increased power
self.powerLevel += 1;
} else if (type === 2) {
// Rapid fire
self.fireRate = Math.max(5, self.fireRate - 5);
}
};
self.hit = function () {
if (!self.invulnerable) {
self.invulnerable = true;
self.invulnerableTimer = 120; // 2 seconds invulnerability
return true;
}
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000022
});
/****
* Game Code
****/
// Game state variables
var wizard;
var lightnings = [];
var enemies = [];
var explosions = [];
var powerups = [];
var enemyProjectiles = [];
var lives = 3;
var score = 0;
var highScore = storage.highScore || 0;
var level = 1;
var enemiesDefeated = 0;
var enemySpawnTimer = 0;
var bossActive = false;
var levelClearDelay = 0;
var gameActive = true;
var shakeIntensity = 0;
// UI elements
var scoreText;
var livesText;
var levelText;
// Game initialization
function initGame() {
// Add background
var background = LK.getAsset('background', {
anchorX: 0.5,
anchorY: 0.5
});
background.x = 2048 / 2;
background.y = 2732 / 2;
game.addChild(background);
// Initialize wizard
wizard = new Wizard();
wizard.fireRate = 30; // Set fireRate to 30 ticks, equivalent to 0.5 seconds at 60 FPS
wizard.x = 2048 / 2;
wizard.y = 2732 - 200;
game.addChild(wizard);
// Setup UI
scoreText = new Text2('Score: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreText.anchor.set(0, 0);
LK.gui.topRight.addChild(scoreText);
livesText = new Text2('Lives: ' + lives, {
size: 80,
fill: 0xFFFFFF
});
livesText.anchor.set(0, 0);
LK.gui.top.addChild(livesText);
levelText = new Text2('Level: ' + level, {
size: 80,
fill: 0xFFFFFF
});
levelText.anchor.set(1, 0);
LK.gui.topLeft.addChild(levelText);
levelText.x = 200; // Move away from top-left corner
// Start initial enemy spawn
enemySpawnTimer = 60;
// Start game music
LK.playMusic('gameMusic', {
fade: {
start: 0,
end: 0.7,
duration: 1000
}
});
}
function updateScore(points) {
score += points;
scoreText.setText('Score: ' + score);
// Update high score if needed
if (score > highScore) {
highScore = score;
storage.highScore = highScore;
}
}
function spawnEnemy() {
// Determine if we should spawn a boss
if (enemiesDefeated >= 20 * level && !bossActive) {
var boss = new BossEnemy();
boss.init(2048 / 2, -100);
enemies.push(boss);
game.addChild(boss);
bossActive = true;
// Screen shake effect for boss entrance
shakeIntensity = 10;
return;
}
// Regular enemy spawn
var enemy = new Enemy();
var x = 100 + Math.random() * (2048 - 200);
var y = -100;
enemy.init(x, y);
enemies.push(enemy);
game.addChild(enemy);
}
function nextLevel() {
level++;
levelText.setText('Level: ' + level);
// Reset level variables
enemiesDefeated = 0;
bossActive = false;
// Increase difficulty
Enemy.prototype.speed += 0.3;
// Visual effect for level transition
LK.effects.flashScreen(0x0000ff, 500);
}
function createLightning(x, y) {
var lightning = new Lightning();
lightning.x = x;
lightning.y = y;
lightning.power = wizard.powerLevel;
lightning.chainLightningEnabled = wizard.chainLightning;
// Add branches for higher power levels
if (wizard.powerLevel > 1) {
lightning.createBranches(wizard.powerLevel - 1);
}
lightnings.push(lightning);
game.addChild(lightning);
// Play lightning sound
LK.getSound('lightning').play();
}
function createExplosion(x, y, size) {
var explosion = new Explosion();
explosion.init(x, y, size);
explosions.push(explosion);
game.addChild(explosion);
// Play explosion sound
LK.getSound('explosion').play();
}
// Initialize the game
initGame();
// Touch/mouse handlers
var dragging = false;
var lastX = null;
game.down = function (x, y) {
dragging = true;
lastX = x;
};
game.move = function (x, y) {
if (dragging) {
var deltaX = x - lastX;
wizard.x += deltaX;
// Keep wizard within bounds
wizard.x = Math.max(50, Math.min(2048 - 50, wizard.x));
lastX = x;
}
};
game.up = function () {
dragging = false;
lastX = null;
};
// Main game update
game.update = function () {
if (!gameActive) {
return;
}
// Screen shake effect
if (shakeIntensity > 0) {
game.x = (Math.random() * 2 - 1) * shakeIntensity;
game.y = (Math.random() * 2 - 1) * shakeIntensity;
shakeIntensity *= 0.9;
if (shakeIntensity < 0.5) {
shakeIntensity = 0;
game.x = 0;
game.y = 0;
}
}
// Update wizard
wizard.update();
// Auto-fire
if (wizard.fire()) {
createLightning(wizard.x, wizard.y - 50);
}
// Level transition
if (levelClearDelay > 0) {
levelClearDelay--;
if (levelClearDelay === 0) {
nextLevel();
}
return; // Pause other updates during level transition
}
// Enemy spawn logic
if (enemySpawnTimer > 0) {
enemySpawnTimer--;
} else {
spawnEnemy();
// Adjust spawn rate based on level
enemySpawnTimer = bossActive ? 120 : Math.max(20, 60 - level * 5);
}
// Update lightnings
for (var i = lightnings.length - 1; i >= 0; i--) {
var lightning = lightnings[i];
lightning.update();
// Remove lightning if off screen
if (lightning.y < -100) {
lightning.destroy();
lightnings.splice(i, 1);
continue;
}
// Check for hits with enemies
var hitEnemy = false;
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (lightning.intersects(enemy)) {
hitEnemy = true;
// Enemy takes damage
if (enemy.hit(lightning.power)) {
// Enemy defeated
createExplosion(enemy.x, enemy.y, enemy instanceof BossEnemy ? 2 : 1);
updateScore(enemy.points);
enemiesDefeated++;
// Check if boss was defeated
if (enemy instanceof BossEnemy) {
bossActive = false;
levelClearDelay = 120; // 2 second delay before next level
LK.effects.flashScreen(0xffffff, 300);
}
// Chance to drop power-up
if (Math.random() < 0.2) {
var powerup = new PowerUp();
powerup.init(enemy.x, enemy.y);
powerups.push(powerup);
game.addChild(powerup);
}
enemy.destroy();
enemies.splice(j, 1);
} else {
// Enemy hit but not defeated
LK.getSound('enemyHit').play();
}
// Remove lightning unless it has chain lightning
if (!lightning.chainLightningEnabled) {
lightning.destroy();
lightnings.splice(i, 1);
continue; // Use continue to check other enemies
}
}
}
}
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
var enemy = enemies[i];
var shouldShoot = enemy.update();
// Check if enemy has moved off screen
if (enemy.y > 2732 + 100) {
enemy.destroy();
enemies.splice(i, 1);
continue;
}
// Enemy shoots projectile
if (shouldShoot) {
var projectile = new EnemyProjectile();
projectile.init(enemy.x, enemy.y, wizard.x, wizard.y);
enemyProjectiles.push(projectile);
game.addChild(projectile);
}
}
// Update enemy projectiles
for (var i = enemyProjectiles.length - 1; i >= 0; i--) {
var projectile = enemyProjectiles[i];
projectile.update();
// Check if projectile is off screen
if (projectile.y > 2732 + 20 || projectile.y < -20 || projectile.x > 2048 + 20 || projectile.x < -20) {
projectile.destroy();
enemyProjectiles.splice(i, 1);
continue;
}
// Check for collision with wizard
if (projectile.intersects(wizard)) {
if (wizard.hit()) {
// Player was hit
LK.getSound('playerHit').play();
lives--;
livesText.setText('Lives: ' + lives);
// Create explosion effect
createExplosion(projectile.x, projectile.y, 0.5);
// Screen shake
shakeIntensity = 5;
// Check for game over
if (lives <= 0) {
gameActive = false;
LK.effects.flashScreen(0xff0000, 1000);
LK.setTimeout(function () {
LK.showGameOver();
}, 1500);
}
}
// Remove projectile
projectile.destroy();
enemyProjectiles.splice(i, 1);
}
}
// Update powerups
for (var i = powerups.length - 1; i >= 0; i--) {
var powerup = powerups[i];
powerup.update();
// Check if powerup is off screen
if (powerup.y > 2732 + 30) {
powerup.destroy();
powerups.splice(i, 1);
continue;
}
// Check for collision with wizard
if (powerup.intersects(wizard)) {
// Apply powerup effect
wizard.applyPowerup(powerup.type);
// Play sound
LK.getSound('powerupCollect').play();
// Visual feedback
LK.effects.flashObject(wizard, 0x00ffff, 500);
// Remove powerup
powerup.destroy();
powerups.splice(i, 1);
}
}
// Update explosions
for (var i = explosions.length - 1; i >= 0; i--) {
if (explosions[i].update()) {
explosions[i].destroy();
explosions.splice(i, 1);
}
}
};
2d 16 bit classic image jellyfish. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
2d 16 bit image classic image evil jellyfish. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
epic blue 16 bit bubble pieces explode. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
shining plankton. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
15 bit image red crab. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
32 bit image anime style of beautyfull quite empty under sea water. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
2d 16 bit silver pearl shell top down. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows
shining sea bubble. Single Game Texture. In-Game asset. 2d. Blank background. High contrast. No shadows