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(); ===================================================================
--- original.js
+++ change.js
@@ -466,17 +466,19 @@
function updateScore() {
scoreTxt.setText(LK.getScore().toString());
multiplierTxt.setText('x' + scoreMultiplier);
// Update health bar
- 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;
+ 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() {