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);
// 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');
// Initialize UI
initUI();
// 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
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
@@ -1,6 +1,738 @@
-/****
+/****
+* 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: 0x000000
-});
\ No newline at end of file
+ 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);
+ // 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');
+ // Initialize UI
+ initUI();
+ // 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
+ 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();
\ No newline at end of file