User prompt
Please fix the bug: 'TypeError: Cannot read properties of null (reading 'health')' in or related to this line: 'var healthPercent = player.health / 100;' Line Number: 487
User prompt
Please fix the bug: 'Cannot read properties of undefined (reading 'setText')' in or related to this line: 'waveTxt.setText('WAVE ' + wave);' Line Number: 386
Code edit (1 edits merged)
Please save this source code
User prompt
MG BlitzZone
Initial prompt
MG BlitzZone
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Bullet = Container.expand(function () { var self = Container.call(this); var bulletGraphic = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 15; self.damage = 10; self.isPlayerBullet = true; self.update = function () { self.y -= self.speed; // Check if bullet is off screen if (self.y < -50 || self.y > 2732 + 50 || self.x < -50 || self.x > 2048 + 50) { return true; // Signal for removal } return false; }; return self; }); var EnemyBullet = Bullet.expand(function () { var self = Bullet.call(this); // Replace the bullet graphic with enemy bullet self.removeChildren(); var bulletGraphic = self.attachAsset('enemyBullet', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 8; self.damage = 15; self.isPlayerBullet = false; self.update = function () { self.y += self.speed; // Check if bullet is off screen if (self.y < -50 || self.y > 2732 + 50 || self.x < -50 || self.x > 2048 + 50) { return true; // Signal for removal } return false; }; return self; }); var Enemy = Container.expand(function () { var self = Container.call(this); var enemyGraphic = self.attachAsset('enemy', { anchorX: 0.5, anchorY: 0.5 }); self.health = 30; self.points = 200; self.speed = 3; self.direction = 1; self.shootDelay = 60; self.lastShot = 0; self.update = function () { self.x += self.speed * self.direction; // Boundary check and reverse direction if (self.x > 2048 - 100 || self.x < 100) { self.direction *= -1; } // Shooting logic self.lastShot++; if (self.lastShot >= self.shootDelay) { self.lastShot = 0; return true; // Signal to shoot } return false; // No shooting this update }; self.hit = function (damage) { self.health -= damage; LK.effects.flashObject(enemyGraphic, 0xff0000, 200); LK.getSound('hit').play(); if (self.health <= 0) { LK.getSound('explosion').play(); return true; // Enemy destroyed } return false; // Enemy still alive }; return self; }); var Explosion = Container.expand(function () { var self = Container.call(this); var explosionGraphic = self.attachAsset('explosion', { anchorX: 0.5, anchorY: 0.5, alpha: 0.8 }); self.lifetime = 0; self.duration = 30; // Frames self.update = function () { self.lifetime++; // Scale explosion up then down if (self.lifetime < self.duration / 2) { explosionGraphic.scale.set(1 + self.lifetime / (self.duration / 2)); } else { explosionGraphic.scale.set(2 - (self.lifetime - self.duration / 2) / (self.duration / 2)); } // Fade out explosionGraphic.alpha = 0.8 * (1 - self.lifetime / self.duration); if (self.lifetime >= self.duration) { return true; // Signal for removal } return false; }; return self; }); var Obstacle = Container.expand(function () { var self = Container.call(this); var obstacleGraphic = self.attachAsset('obstacle', { anchorX: 0.5, anchorY: 0.5 }); self.health = 100; self.hit = function (damage) { self.health -= damage; LK.effects.flashObject(obstacleGraphic, 0x666666, 200); if (self.health <= 0) { return true; // Obstacle destroyed } return false; // Obstacle still intact }; return self; }); var Player = Container.expand(function () { var self = Container.call(this); var playerGraphic = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 10; self.health = 100; self.powerLevel = 1; self.invincible = false; self.lastShot = 0; self.shootDelay = 15; self.flash = function () { if (self.invincible) { return; } self.invincible = true; LK.effects.flashObject(playerGraphic, 0xffffff, 500); LK.setTimeout(function () { self.invincible = false; }, 1500); }; self.takeDamage = function (amount) { if (self.invincible) { return false; } self.health -= amount; self.flash(); if (self.health <= 0) { return true; // Player died } return false; // Player still alive }; self.increasePower = function () { if (self.powerLevel < 3) { self.powerLevel++; self.shootDelay = Math.max(5, self.shootDelay - 3); return true; } return false; }; return self; }); var PowerUp = Container.expand(function () { var self = Container.call(this); var powerupGraphic = self.attachAsset('powerup', { anchorX: 0.5, anchorY: 0.5 }); self.type = "weapon"; // Default powerup type self.speed = 2; self.update = function () { self.y += self.speed; // Check if powerup is off screen if (self.y > 2732 + 50) { return true; // Signal for removal } return false; }; // Make the powerup pulse function pulse() { tween(powerupGraphic, { alpha: 0.6 }, { duration: 500, easing: tween.easeInOut, onFinish: function onFinish() { tween(powerupGraphic, { alpha: 1 }, { duration: 500, easing: tween.easeInOut, onFinish: pulse }); } }); } pulse(); return self; }); var Target = Container.expand(function () { var self = Container.call(this); var targetGraphic = self.attachAsset('target', { anchorX: 0.5, anchorY: 0.5 }); self.health = 20; self.points = 100; self.speed = 0; self.direction = 1; // 1 for right, -1 for left self.update = function () { if (self.speed > 0) { self.x += self.speed * self.direction; // Boundary check and reverse direction if (self.x > 2048 - 100 || self.x < 100) { self.direction *= -1; } } return false; // Not to be removed yet }; self.hit = function (damage) { self.health -= damage; LK.effects.flashObject(targetGraphic, 0xff0000, 200); LK.getSound('hit').play(); if (self.health <= 0) { LK.getSound('explosion').play(); return true; // Target destroyed } return false; // Target still alive }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x000033 }); /**** * Game Code ****/ // Game state var gameActive = true; var waveNumber = 1; var timeLeft = 60; var scoreMultiplier = 1; var combo = 0; var comboTimer = 0; var lastFrameTime = Date.now(); // Game elements var player; var bullets = []; var enemyBullets = []; var targets = []; var enemies = []; var obstacles = []; var powerups = []; var explosions = []; // UI elements var scoreTxt; var multiplierTxt; var waveTxt; var timeTxt; var healthBar; var healthBarBg; // Game controls var touchX = null; var touchY = null; var isTouching = false; // Initialize UI function initUI() { // Score display scoreTxt = new Text2('0', { size: 70, fill: 0xFFFFFF }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // Wave display waveTxt = new Text2('WAVE 1', { size: 50, fill: 0xFFCC00 }); waveTxt.anchor.set(0, 0); waveTxt.x = 150; waveTxt.y = 20; LK.gui.topLeft.addChild(waveTxt); // Time display timeTxt = new Text2('60s', { size: 50, fill: 0xFFFFFF }); timeTxt.anchor.set(1, 0); timeTxt.x = -20; timeTxt.y = 20; LK.gui.topRight.addChild(timeTxt); // Multiplier display multiplierTxt = new Text2('x1', { size: 50, fill: 0x00FFFF }); multiplierTxt.anchor.set(0.5, 0); multiplierTxt.y = 80; LK.gui.top.addChild(multiplierTxt); // Health bar background healthBarBg = LK.getAsset('obstacle', { width: 300, height: 30, anchorX: 0, anchorY: 0, x: 20, y: 80, tint: 0x333333 }); LK.gui.topLeft.addChild(healthBarBg); // Health bar healthBar = LK.getAsset('player', { width: 300, height: 30, anchorX: 0, anchorY: 0, x: 20, y: 80, tint: 0x00ff00 }); LK.gui.topLeft.addChild(healthBar); } // Start the game function startGame() { // Initialize player player = new Player(); player.x = 2048 / 2; player.y = 2732 - 200; game.addChild(player); // Initialize UI initUI(); // Setup first wave setupWave(waveNumber); // Start timer gameTimer = LK.setInterval(function () { timeLeft--; timeTxt.setText(timeLeft + 's'); if (timeLeft <= 0) { endWave(); } }, 1000); // Play background music LK.playMusic('gameplay'); // Update score display updateScore(); } // Set up a new wave function setupWave(wave) { // Clear any existing entities clearEntities(); // Set wave text waveTxt.setText('WAVE ' + wave); // Create targets based on wave number var numTargets = 5 + wave * 2; for (var i = 0; i < numTargets; i++) { var target = new Target(); target.x = 200 + i * 200 % (2048 - 400); target.y = 200 + Math.floor(i / 9) * 150; target.speed = 1 + wave * 0.5; target.health = 20 + wave * 10; target.points = 100 + wave * 20; if (i % 3 === 0) { target.direction = -1; } targets.push(target); game.addChild(target); } // Add enemies for higher waves if (wave > 1) { var numEnemies = Math.min(wave, 5); for (var j = 0; j < numEnemies; j++) { var enemy = new Enemy(); enemy.x = 300 + j * 350; enemy.y = 400; enemy.speed = 2 + wave * 0.3; enemy.health = 30 + wave * 15; enemy.shootDelay = Math.max(30, 60 - wave * 5); enemies.push(enemy); game.addChild(enemy); } } // Add obstacles var numObstacles = Math.min(3, Math.floor(wave / 2)); for (var k = 0; k < numObstacles; k++) { var obstacle = new Obstacle(); obstacle.x = 400 + k * 600; obstacle.y = 700; obstacles.push(obstacle); game.addChild(obstacle); } // Reset timer timeLeft = 60; timeTxt.setText(timeLeft + 's'); } // End the current wave function endWave() { waveNumber++; // If player completed all waves, show win if (waveNumber > 5) { LK.showYouWin(); return; } // Award bonus points for completing wave var timeBonus = timeLeft * 10; LK.setScore(LK.getScore() + timeBonus); updateScore(); // Set up new wave setupWave(waveNumber); } // Clear all entities except player function clearEntities() { // Clear bullets for (var i = bullets.length - 1; i >= 0; i--) { bullets[i].destroy(); } bullets = []; // Clear enemy bullets for (var j = enemyBullets.length - 1; j >= 0; j--) { enemyBullets[j].destroy(); } enemyBullets = []; // Clear targets for (var k = targets.length - 1; k >= 0; k--) { targets[k].destroy(); } targets = []; // Clear enemies for (var l = enemies.length - 1; l >= 0; l--) { enemies[l].destroy(); } enemies = []; // Clear obstacles for (var m = obstacles.length - 1; m >= 0; m--) { obstacles[m].destroy(); } obstacles = []; // Clear powerups for (var n = powerups.length - 1; n >= 0; n--) { powerups[n].destroy(); } powerups = []; // Clear explosions for (var o = explosions.length - 1; o >= 0; o--) { explosions[o].destroy(); } explosions = []; } // Update score display function updateScore() { scoreTxt.setText(LK.getScore().toString()); multiplierTxt.setText('x' + scoreMultiplier); // Update health bar if (player) { var healthPercent = player.health / 100; healthBar.width = 300 * healthPercent; // Change health bar color based on health if (healthPercent > 0.6) { healthBar.tint = 0x00ff00; } else if (healthPercent > 0.3) { healthBar.tint = 0xffff00; } else { healthBar.tint = 0xff0000; } } } // Create a player bullet function firePlayerBullet() { var bullet = new Bullet(); bullet.x = player.x; bullet.y = player.y - 40; bullet.damage = 10 + (player.powerLevel - 1) * 5; bullets.push(bullet); game.addChild(bullet); // If power level > 1, fire additional bullets if (player.powerLevel >= 2) { var bulletLeft = new Bullet(); bulletLeft.x = player.x - 20; bulletLeft.y = player.y - 30; bullets.push(bulletLeft); game.addChild(bulletLeft); if (player.powerLevel >= 3) { var bulletRight = new Bullet(); bulletRight.x = player.x + 20; bulletRight.y = player.y - 30; bullets.push(bulletRight); game.addChild(bulletRight); } } LK.getSound('shoot').play(); } // Create an enemy bullet function fireEnemyBullet(enemy) { var bullet = new EnemyBullet(); bullet.x = enemy.x; bullet.y = enemy.y + 40; enemyBullets.push(bullet); game.addChild(bullet); } // Create an explosion function createExplosion(x, y, scale) { var explosion = new Explosion(); explosion.x = x; explosion.y = y; if (scale) { explosion.scale.set(scale); } explosions.push(explosion); game.addChild(explosion); } // Create a power-up function spawnPowerUp(x, y) { // Only spawn with 30% chance if (Math.random() > 0.3) { return; } var powerup = new PowerUp(); powerup.x = x; powerup.y = y; powerups.push(powerup); game.addChild(powerup); } // Handle touch/mouse movement function handleMove(x, y) { if (isTouching && player) { player.x = x; player.y = y; // Clamp player position to screen bounds player.x = Math.max(50, Math.min(2048 - 50, player.x)); player.y = Math.max(400, Math.min(2732 - 50, player.y)); } } // Game touch/mouse handlers game.down = function (x, y, obj) { touchX = x; touchY = y; isTouching = true; handleMove(x, y); }; game.move = function (x, y, obj) { touchX = x; touchY = y; handleMove(x, y); }; game.up = function (x, y, obj) { isTouching = false; }; // Update game each frame game.update = function () { if (!gameActive) { return; } // Calculate delta time for smoother animations var currentTime = Date.now(); var deltaTime = (currentTime - lastFrameTime) / 16.67; // Normalize to 60fps lastFrameTime = currentTime; // Handle combo system if (combo > 0) { comboTimer++; if (comboTimer > 60) { // 1 second to maintain combo combo = 0; comboTimer = 0; scoreMultiplier = 1; updateScore(); } } // Player shooting if (player) { player.lastShot++; if (player.lastShot >= player.shootDelay) { player.lastShot = 0; firePlayerBullet(); } } // Update bullets for (var i = bullets.length - 1; i >= 0; i--) { if (bullets[i].update()) { bullets[i].destroy(); bullets.splice(i, 1); continue; } // Check bullet collisions with targets for (var t = targets.length - 1; t >= 0; t--) { if (bullets[i] && bullets[i].intersects(targets[t])) { if (targets[t].hit(bullets[i].damage)) { // Target destroyed combo++; comboTimer = 0; scoreMultiplier = Math.min(5, 1 + Math.floor(combo / 3)); LK.setScore(LK.getScore() + targets[t].points * scoreMultiplier); updateScore(); createExplosion(targets[t].x, targets[t].y, 1); spawnPowerUp(targets[t].x, targets[t].y); targets[t].destroy(); targets.splice(t, 1); } bullets[i].destroy(); bullets.splice(i, 1); break; } } // Check bullet collisions with enemies if (bullets[i]) { for (var e = enemies.length - 1; e >= 0; e--) { if (bullets[i] && bullets[i].intersects(enemies[e])) { if (enemies[e].hit(bullets[i].damage)) { // Enemy destroyed combo++; comboTimer = 0; scoreMultiplier = Math.min(5, 1 + Math.floor(combo / 3)); LK.setScore(LK.getScore() + enemies[e].points * scoreMultiplier); updateScore(); createExplosion(enemies[e].x, enemies[e].y, 1.5); spawnPowerUp(enemies[e].x, enemies[e].y); enemies[e].destroy(); enemies.splice(e, 1); } bullets[i].destroy(); bullets.splice(i, 1); break; } } } // Check bullet collisions with obstacles if (bullets[i]) { for (var o = obstacles.length - 1; o >= 0; o--) { if (bullets[i] && bullets[i].intersects(obstacles[o])) { if (obstacles[o].hit(bullets[i].damage)) { // Obstacle destroyed createExplosion(obstacles[o].x, obstacles[o].y, 2); obstacles[o].destroy(); obstacles.splice(o, 1); } bullets[i].destroy(); bullets.splice(i, 1); break; } } } } // Update enemy bullets for (var j = enemyBullets.length - 1; j >= 0; j--) { if (enemyBullets[j].update()) { enemyBullets[j].destroy(); enemyBullets.splice(j, 1); continue; } // Check enemy bullet collisions with player if (player && enemyBullets[j].intersects(player)) { if (player.takeDamage(enemyBullets[j].damage)) { // Player destroyed createExplosion(player.x, player.y, 2); player.destroy(); player = null; LK.showGameOver(); gameActive = false; } updateScore(); enemyBullets[j].destroy(); enemyBullets.splice(j, 1); } // Check enemy bullet collisions with obstacles if (enemyBullets[j]) { for (var p = obstacles.length - 1; p >= 0; p--) { if (enemyBullets[j] && enemyBullets[j].intersects(obstacles[p])) { if (obstacles[p].hit(enemyBullets[j].damage)) { // Obstacle destroyed createExplosion(obstacles[p].x, obstacles[p].y, 2); obstacles[p].destroy(); obstacles.splice(p, 1); } enemyBullets[j].destroy(); enemyBullets.splice(j, 1); break; } } } } // Update targets for (var k = targets.length - 1; k >= 0; k--) { targets[k].update(); } // Update enemies for (var l = enemies.length - 1; l >= 0; l--) { if (enemies[l].update()) { fireEnemyBullet(enemies[l]); } } // Update powerups for (var m = powerups.length - 1; m >= 0; m--) { if (powerups[m].update()) { powerups[m].destroy(); powerups.splice(m, 1); continue; } // Check powerup collision with player if (player && powerups[m].intersects(player)) { if (player.increasePower()) { LK.getSound('powerup').play(); LK.effects.flashObject(player, 0x00ff00, 500); } else { // Already max power, give points instead LK.setScore(LK.getScore() + 500); updateScore(); } powerups[m].destroy(); powerups.splice(m, 1); } } // Update explosions for (var n = explosions.length - 1; n >= 0; n--) { if (explosions[n].update()) { explosions[n].destroy(); explosions.splice(n, 1); } } // Check if all targets destroyed if (targets.length === 0 && enemies.length === 0) { endWave(); } }; // Start the game startGame();
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphic = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 15;
self.damage = 10;
self.isPlayerBullet = true;
self.update = function () {
self.y -= self.speed;
// Check if bullet is off screen
if (self.y < -50 || self.y > 2732 + 50 || self.x < -50 || self.x > 2048 + 50) {
return true; // Signal for removal
}
return false;
};
return self;
});
var EnemyBullet = Bullet.expand(function () {
var self = Bullet.call(this);
// Replace the bullet graphic with enemy bullet
self.removeChildren();
var bulletGraphic = self.attachAsset('enemyBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.damage = 15;
self.isPlayerBullet = false;
self.update = function () {
self.y += self.speed;
// Check if bullet is off screen
if (self.y < -50 || self.y > 2732 + 50 || self.x < -50 || self.x > 2048 + 50) {
return true; // Signal for removal
}
return false;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphic = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 30;
self.points = 200;
self.speed = 3;
self.direction = 1;
self.shootDelay = 60;
self.lastShot = 0;
self.update = function () {
self.x += self.speed * self.direction;
// Boundary check and reverse direction
if (self.x > 2048 - 100 || self.x < 100) {
self.direction *= -1;
}
// Shooting logic
self.lastShot++;
if (self.lastShot >= self.shootDelay) {
self.lastShot = 0;
return true; // Signal to shoot
}
return false; // No shooting this update
};
self.hit = function (damage) {
self.health -= damage;
LK.effects.flashObject(enemyGraphic, 0xff0000, 200);
LK.getSound('hit').play();
if (self.health <= 0) {
LK.getSound('explosion').play();
return true; // Enemy destroyed
}
return false; // Enemy still alive
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var explosionGraphic = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.8
});
self.lifetime = 0;
self.duration = 30; // Frames
self.update = function () {
self.lifetime++;
// Scale explosion up then down
if (self.lifetime < self.duration / 2) {
explosionGraphic.scale.set(1 + self.lifetime / (self.duration / 2));
} else {
explosionGraphic.scale.set(2 - (self.lifetime - self.duration / 2) / (self.duration / 2));
}
// Fade out
explosionGraphic.alpha = 0.8 * (1 - self.lifetime / self.duration);
if (self.lifetime >= self.duration) {
return true; // Signal for removal
}
return false;
};
return self;
});
var Obstacle = Container.expand(function () {
var self = Container.call(this);
var obstacleGraphic = self.attachAsset('obstacle', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.hit = function (damage) {
self.health -= damage;
LK.effects.flashObject(obstacleGraphic, 0x666666, 200);
if (self.health <= 0) {
return true; // Obstacle destroyed
}
return false; // Obstacle still intact
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphic = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 10;
self.health = 100;
self.powerLevel = 1;
self.invincible = false;
self.lastShot = 0;
self.shootDelay = 15;
self.flash = function () {
if (self.invincible) {
return;
}
self.invincible = true;
LK.effects.flashObject(playerGraphic, 0xffffff, 500);
LK.setTimeout(function () {
self.invincible = false;
}, 1500);
};
self.takeDamage = function (amount) {
if (self.invincible) {
return false;
}
self.health -= amount;
self.flash();
if (self.health <= 0) {
return true; // Player died
}
return false; // Player still alive
};
self.increasePower = function () {
if (self.powerLevel < 3) {
self.powerLevel++;
self.shootDelay = Math.max(5, self.shootDelay - 3);
return true;
}
return false;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerupGraphic = self.attachAsset('powerup', {
anchorX: 0.5,
anchorY: 0.5
});
self.type = "weapon"; // Default powerup type
self.speed = 2;
self.update = function () {
self.y += self.speed;
// Check if powerup is off screen
if (self.y > 2732 + 50) {
return true; // Signal for removal
}
return false;
};
// Make the powerup pulse
function pulse() {
tween(powerupGraphic, {
alpha: 0.6
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: function onFinish() {
tween(powerupGraphic, {
alpha: 1
}, {
duration: 500,
easing: tween.easeInOut,
onFinish: pulse
});
}
});
}
pulse();
return self;
});
var Target = Container.expand(function () {
var self = Container.call(this);
var targetGraphic = self.attachAsset('target', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 20;
self.points = 100;
self.speed = 0;
self.direction = 1; // 1 for right, -1 for left
self.update = function () {
if (self.speed > 0) {
self.x += self.speed * self.direction;
// Boundary check and reverse direction
if (self.x > 2048 - 100 || self.x < 100) {
self.direction *= -1;
}
}
return false; // Not to be removed yet
};
self.hit = function (damage) {
self.health -= damage;
LK.effects.flashObject(targetGraphic, 0xff0000, 200);
LK.getSound('hit').play();
if (self.health <= 0) {
LK.getSound('explosion').play();
return true; // Target destroyed
}
return false; // Target still alive
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x000033
});
/****
* Game Code
****/
// Game state
var gameActive = true;
var waveNumber = 1;
var timeLeft = 60;
var scoreMultiplier = 1;
var combo = 0;
var comboTimer = 0;
var lastFrameTime = Date.now();
// Game elements
var player;
var bullets = [];
var enemyBullets = [];
var targets = [];
var enemies = [];
var obstacles = [];
var powerups = [];
var explosions = [];
// UI elements
var scoreTxt;
var multiplierTxt;
var waveTxt;
var timeTxt;
var healthBar;
var healthBarBg;
// Game controls
var touchX = null;
var touchY = null;
var isTouching = false;
// Initialize UI
function initUI() {
// Score display
scoreTxt = new Text2('0', {
size: 70,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// Wave display
waveTxt = new Text2('WAVE 1', {
size: 50,
fill: 0xFFCC00
});
waveTxt.anchor.set(0, 0);
waveTxt.x = 150;
waveTxt.y = 20;
LK.gui.topLeft.addChild(waveTxt);
// Time display
timeTxt = new Text2('60s', {
size: 50,
fill: 0xFFFFFF
});
timeTxt.anchor.set(1, 0);
timeTxt.x = -20;
timeTxt.y = 20;
LK.gui.topRight.addChild(timeTxt);
// Multiplier display
multiplierTxt = new Text2('x1', {
size: 50,
fill: 0x00FFFF
});
multiplierTxt.anchor.set(0.5, 0);
multiplierTxt.y = 80;
LK.gui.top.addChild(multiplierTxt);
// Health bar background
healthBarBg = LK.getAsset('obstacle', {
width: 300,
height: 30,
anchorX: 0,
anchorY: 0,
x: 20,
y: 80,
tint: 0x333333
});
LK.gui.topLeft.addChild(healthBarBg);
// Health bar
healthBar = LK.getAsset('player', {
width: 300,
height: 30,
anchorX: 0,
anchorY: 0,
x: 20,
y: 80,
tint: 0x00ff00
});
LK.gui.topLeft.addChild(healthBar);
}
// Start the game
function startGame() {
// Initialize player
player = new Player();
player.x = 2048 / 2;
player.y = 2732 - 200;
game.addChild(player);
// Initialize UI
initUI();
// Setup first wave
setupWave(waveNumber);
// Start timer
gameTimer = LK.setInterval(function () {
timeLeft--;
timeTxt.setText(timeLeft + 's');
if (timeLeft <= 0) {
endWave();
}
}, 1000);
// Play background music
LK.playMusic('gameplay');
// Update score display
updateScore();
}
// Set up a new wave
function setupWave(wave) {
// Clear any existing entities
clearEntities();
// Set wave text
waveTxt.setText('WAVE ' + wave);
// Create targets based on wave number
var numTargets = 5 + wave * 2;
for (var i = 0; i < numTargets; i++) {
var target = new Target();
target.x = 200 + i * 200 % (2048 - 400);
target.y = 200 + Math.floor(i / 9) * 150;
target.speed = 1 + wave * 0.5;
target.health = 20 + wave * 10;
target.points = 100 + wave * 20;
if (i % 3 === 0) {
target.direction = -1;
}
targets.push(target);
game.addChild(target);
}
// Add enemies for higher waves
if (wave > 1) {
var numEnemies = Math.min(wave, 5);
for (var j = 0; j < numEnemies; j++) {
var enemy = new Enemy();
enemy.x = 300 + j * 350;
enemy.y = 400;
enemy.speed = 2 + wave * 0.3;
enemy.health = 30 + wave * 15;
enemy.shootDelay = Math.max(30, 60 - wave * 5);
enemies.push(enemy);
game.addChild(enemy);
}
}
// Add obstacles
var numObstacles = Math.min(3, Math.floor(wave / 2));
for (var k = 0; k < numObstacles; k++) {
var obstacle = new Obstacle();
obstacle.x = 400 + k * 600;
obstacle.y = 700;
obstacles.push(obstacle);
game.addChild(obstacle);
}
// Reset timer
timeLeft = 60;
timeTxt.setText(timeLeft + 's');
}
// End the current wave
function endWave() {
waveNumber++;
// If player completed all waves, show win
if (waveNumber > 5) {
LK.showYouWin();
return;
}
// Award bonus points for completing wave
var timeBonus = timeLeft * 10;
LK.setScore(LK.getScore() + timeBonus);
updateScore();
// Set up new wave
setupWave(waveNumber);
}
// Clear all entities except player
function clearEntities() {
// Clear bullets
for (var i = bullets.length - 1; i >= 0; i--) {
bullets[i].destroy();
}
bullets = [];
// Clear enemy bullets
for (var j = enemyBullets.length - 1; j >= 0; j--) {
enemyBullets[j].destroy();
}
enemyBullets = [];
// Clear targets
for (var k = targets.length - 1; k >= 0; k--) {
targets[k].destroy();
}
targets = [];
// Clear enemies
for (var l = enemies.length - 1; l >= 0; l--) {
enemies[l].destroy();
}
enemies = [];
// Clear obstacles
for (var m = obstacles.length - 1; m >= 0; m--) {
obstacles[m].destroy();
}
obstacles = [];
// Clear powerups
for (var n = powerups.length - 1; n >= 0; n--) {
powerups[n].destroy();
}
powerups = [];
// Clear explosions
for (var o = explosions.length - 1; o >= 0; o--) {
explosions[o].destroy();
}
explosions = [];
}
// Update score display
function updateScore() {
scoreTxt.setText(LK.getScore().toString());
multiplierTxt.setText('x' + scoreMultiplier);
// Update health bar
if (player) {
var healthPercent = player.health / 100;
healthBar.width = 300 * healthPercent;
// Change health bar color based on health
if (healthPercent > 0.6) {
healthBar.tint = 0x00ff00;
} else if (healthPercent > 0.3) {
healthBar.tint = 0xffff00;
} else {
healthBar.tint = 0xff0000;
}
}
}
// Create a player bullet
function firePlayerBullet() {
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y - 40;
bullet.damage = 10 + (player.powerLevel - 1) * 5;
bullets.push(bullet);
game.addChild(bullet);
// If power level > 1, fire additional bullets
if (player.powerLevel >= 2) {
var bulletLeft = new Bullet();
bulletLeft.x = player.x - 20;
bulletLeft.y = player.y - 30;
bullets.push(bulletLeft);
game.addChild(bulletLeft);
if (player.powerLevel >= 3) {
var bulletRight = new Bullet();
bulletRight.x = player.x + 20;
bulletRight.y = player.y - 30;
bullets.push(bulletRight);
game.addChild(bulletRight);
}
}
LK.getSound('shoot').play();
}
// Create an enemy bullet
function fireEnemyBullet(enemy) {
var bullet = new EnemyBullet();
bullet.x = enemy.x;
bullet.y = enemy.y + 40;
enemyBullets.push(bullet);
game.addChild(bullet);
}
// Create an explosion
function createExplosion(x, y, scale) {
var explosion = new Explosion();
explosion.x = x;
explosion.y = y;
if (scale) {
explosion.scale.set(scale);
}
explosions.push(explosion);
game.addChild(explosion);
}
// Create a power-up
function spawnPowerUp(x, y) {
// Only spawn with 30% chance
if (Math.random() > 0.3) {
return;
}
var powerup = new PowerUp();
powerup.x = x;
powerup.y = y;
powerups.push(powerup);
game.addChild(powerup);
}
// Handle touch/mouse movement
function handleMove(x, y) {
if (isTouching && player) {
player.x = x;
player.y = y;
// Clamp player position to screen bounds
player.x = Math.max(50, Math.min(2048 - 50, player.x));
player.y = Math.max(400, Math.min(2732 - 50, player.y));
}
}
// Game touch/mouse handlers
game.down = function (x, y, obj) {
touchX = x;
touchY = y;
isTouching = true;
handleMove(x, y);
};
game.move = function (x, y, obj) {
touchX = x;
touchY = y;
handleMove(x, y);
};
game.up = function (x, y, obj) {
isTouching = false;
};
// Update game each frame
game.update = function () {
if (!gameActive) {
return;
}
// Calculate delta time for smoother animations
var currentTime = Date.now();
var deltaTime = (currentTime - lastFrameTime) / 16.67; // Normalize to 60fps
lastFrameTime = currentTime;
// Handle combo system
if (combo > 0) {
comboTimer++;
if (comboTimer > 60) {
// 1 second to maintain combo
combo = 0;
comboTimer = 0;
scoreMultiplier = 1;
updateScore();
}
}
// Player shooting
if (player) {
player.lastShot++;
if (player.lastShot >= player.shootDelay) {
player.lastShot = 0;
firePlayerBullet();
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
if (bullets[i].update()) {
bullets[i].destroy();
bullets.splice(i, 1);
continue;
}
// Check bullet collisions with targets
for (var t = targets.length - 1; t >= 0; t--) {
if (bullets[i] && bullets[i].intersects(targets[t])) {
if (targets[t].hit(bullets[i].damage)) {
// Target destroyed
combo++;
comboTimer = 0;
scoreMultiplier = Math.min(5, 1 + Math.floor(combo / 3));
LK.setScore(LK.getScore() + targets[t].points * scoreMultiplier);
updateScore();
createExplosion(targets[t].x, targets[t].y, 1);
spawnPowerUp(targets[t].x, targets[t].y);
targets[t].destroy();
targets.splice(t, 1);
}
bullets[i].destroy();
bullets.splice(i, 1);
break;
}
}
// Check bullet collisions with enemies
if (bullets[i]) {
for (var e = enemies.length - 1; e >= 0; e--) {
if (bullets[i] && bullets[i].intersects(enemies[e])) {
if (enemies[e].hit(bullets[i].damage)) {
// Enemy destroyed
combo++;
comboTimer = 0;
scoreMultiplier = Math.min(5, 1 + Math.floor(combo / 3));
LK.setScore(LK.getScore() + enemies[e].points * scoreMultiplier);
updateScore();
createExplosion(enemies[e].x, enemies[e].y, 1.5);
spawnPowerUp(enemies[e].x, enemies[e].y);
enemies[e].destroy();
enemies.splice(e, 1);
}
bullets[i].destroy();
bullets.splice(i, 1);
break;
}
}
}
// Check bullet collisions with obstacles
if (bullets[i]) {
for (var o = obstacles.length - 1; o >= 0; o--) {
if (bullets[i] && bullets[i].intersects(obstacles[o])) {
if (obstacles[o].hit(bullets[i].damage)) {
// Obstacle destroyed
createExplosion(obstacles[o].x, obstacles[o].y, 2);
obstacles[o].destroy();
obstacles.splice(o, 1);
}
bullets[i].destroy();
bullets.splice(i, 1);
break;
}
}
}
}
// Update enemy bullets
for (var j = enemyBullets.length - 1; j >= 0; j--) {
if (enemyBullets[j].update()) {
enemyBullets[j].destroy();
enemyBullets.splice(j, 1);
continue;
}
// Check enemy bullet collisions with player
if (player && enemyBullets[j].intersects(player)) {
if (player.takeDamage(enemyBullets[j].damage)) {
// Player destroyed
createExplosion(player.x, player.y, 2);
player.destroy();
player = null;
LK.showGameOver();
gameActive = false;
}
updateScore();
enemyBullets[j].destroy();
enemyBullets.splice(j, 1);
}
// Check enemy bullet collisions with obstacles
if (enemyBullets[j]) {
for (var p = obstacles.length - 1; p >= 0; p--) {
if (enemyBullets[j] && enemyBullets[j].intersects(obstacles[p])) {
if (obstacles[p].hit(enemyBullets[j].damage)) {
// Obstacle destroyed
createExplosion(obstacles[p].x, obstacles[p].y, 2);
obstacles[p].destroy();
obstacles.splice(p, 1);
}
enemyBullets[j].destroy();
enemyBullets.splice(j, 1);
break;
}
}
}
}
// Update targets
for (var k = targets.length - 1; k >= 0; k--) {
targets[k].update();
}
// Update enemies
for (var l = enemies.length - 1; l >= 0; l--) {
if (enemies[l].update()) {
fireEnemyBullet(enemies[l]);
}
}
// Update powerups
for (var m = powerups.length - 1; m >= 0; m--) {
if (powerups[m].update()) {
powerups[m].destroy();
powerups.splice(m, 1);
continue;
}
// Check powerup collision with player
if (player && powerups[m].intersects(player)) {
if (player.increasePower()) {
LK.getSound('powerup').play();
LK.effects.flashObject(player, 0x00ff00, 500);
} else {
// Already max power, give points instead
LK.setScore(LK.getScore() + 500);
updateScore();
}
powerups[m].destroy();
powerups.splice(m, 1);
}
}
// Update explosions
for (var n = explosions.length - 1; n >= 0; n--) {
if (explosions[n].update()) {
explosions[n].destroy();
explosions.splice(n, 1);
}
}
// Check if all targets destroyed
if (targets.length === 0 && enemies.length === 0) {
endWave();
}
};
// Start the game
startGame();