User prompt
Please fix the bug: 'TypeError: Cannot read properties of undefined (reading 'to')' in or related to this line: 'tween(explosion).to({' Line Number: 167 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'ReferenceError: tween is not defined' in or related to this line: 'tween(explosion).to({' Line Number: 162 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make bazooka that can shoot by clicking the bazooka and the bullet go toward the enemy an make range attack
User prompt
make a sound when heal and take ammo
User prompt
in endless nightmare, do not let the boss appear
User prompt
at 06:00 make the boss appear, and after the boss defeated, game over, btw the boss health will be 100000 and show it when boss fight start
User prompt
make a sound when shooting
User prompt
make a music for menu
User prompt
add a music to in game
User prompt
not fast enough
User prompt
make the enemy faster
User prompt
let the bullets go toward the enemy and let enemy down in one hit
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'healthText.style.fill = player.health > 30 ? 0x00ff00 : 0xff0000;' Line Number: 644
User prompt
create a function of each mode by your own
User prompt
make a choosing mode screen after pressing the start button
User prompt
make a menu screen
Code edit (1 edits merged)
Please save this source code
User prompt
remove all codes and assets
User prompt
remove the pickup
User prompt
Please fix the bug: 'TypeError: player.getBounds(...).intersects is not a function' in or related to this line: 'if (player.getBounds().intersects(pickup.getBounds())) {' Line Number: 653
Code edit (1 edits merged)
Please save this source code
User prompt
Night of the Massacre 3: Blood Moon Rising
Initial prompt
the 3rd game of my game series called the night of the massacre
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var AmmoBox = Container.expand(function () {
var self = Container.call(this);
var ammoGraphics = self.attachAsset('ammoBox', {
anchorX: 0.5,
anchorY: 0.5
});
self.ammoAmount = 15;
self.lifetime = 600; // 10 seconds at 60fps
self.update = function () {
self.lifetime--;
// Pulsing effect
ammoGraphics.alpha = 0.7 + Math.sin(self.lifetime * 0.2) * 0.3;
if (self.lifetime <= 0) {
return true; // Should be removed
}
return false;
};
return self;
});
var Bazooka = Container.expand(function () {
var self = Container.call(this);
var bazookaGraphics = self.attachAsset('bazooka', {
anchorX: 0.5,
anchorY: 0.5
});
self.ammo = 5;
self.maxAmmo = 5;
self.cooldown = 0;
self.lastX = 0;
self.lastY = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
if (self.cooldown > 0) {
self.cooldown--;
}
// Pulsing effect when ready to fire
if (self.ammo > 0 && self.cooldown <= 0) {
bazookaGraphics.alpha = 0.8 + Math.sin(LK.ticks * 0.2) * 0.2;
} else {
bazookaGraphics.alpha = 0.5;
}
};
self.down = function (x, y, obj) {
if (self.ammo > 0 && self.cooldown <= 0) {
self.fireBazooka();
}
};
self.fireBazooka = function () {
if (self.ammo <= 0 || self.cooldown > 0) return;
// Find nearest enemy to target
var nearestEnemy = null;
var nearestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestEnemy = enemy;
}
}
// Target boss if no enemies or boss is closer
if (boss) {
var dx = boss.x - self.x;
var dy = boss.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (!nearestEnemy || distance < nearestDistance) {
nearestEnemy = boss;
nearestDistance = distance;
}
}
if (nearestEnemy) {
var bullet = new BazookaBullet();
bullet.x = self.x;
bullet.y = self.y;
var dx = nearestEnemy.x - self.x;
var dy = nearestEnemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
bullet.directionX = dx / distance;
bullet.directionY = dy / distance;
}
bazookaBullets.push(bullet);
game.addChild(bullet);
self.ammo--;
self.cooldown = 120; // 2 seconds at 60fps
// Play bazooka sound
LK.getSound('bazookaShoot').play();
// Flash effect
LK.effects.flashObject(self, 0xff8800, 300);
}
};
self.addAmmo = function (amount) {
self.ammo = Math.min(self.maxAmmo, self.ammo + amount);
};
return self;
});
var BazookaBullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bazookaBullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.damage = 200;
self.explosionRadius = 150;
self.directionX = 0;
self.directionY = 0;
self.lastX = 0;
self.lastY = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
// Remove if out of bounds
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
return true; // Should be removed
}
return false;
};
self.explode = function () {
// Create explosion visual effect
var explosion = LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5
});
explosion.x = self.x;
explosion.y = self.y;
explosion.alpha = 0.8;
game.addChild(explosion);
// Animate explosion
tween(explosion, {
alpha: 0,
scaleX: 2,
scaleY: 2
}, {
duration: 500,
onFinish: function onFinish() {
explosion.destroy();
}
});
// Play explosion sound
LK.getSound('explosion').play();
// Damage all enemies in radius
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - self.x;
var dy = enemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.explosionRadius) {
enemy.takeDamage(self.damage);
}
}
// Damage boss if in radius
if (boss) {
var dx = boss.x - self.x;
var dy = boss.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.explosionRadius) {
boss.takeDamage(self.damage);
}
}
};
return self;
});
var Boss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 3,
scaleY: 3,
tint: 0x800080
});
self.health = 100000;
self.maxHealth = 100000;
self.speed = 4;
self.damage = 50;
self.attackCooldown = 0;
self.lastX = 0;
self.lastY = 0;
self.lastPlayerDistance = 1000;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
// Move towards player
if (player) {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
// Attack if close enough
var currentDistance = distance;
if (currentDistance < 100 && self.attackCooldown <= 0) {
player.takeDamage(self.damage);
self.attackCooldown = 60;
}
self.lastPlayerDistance = currentDistance;
}
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xffffff, 200);
if (self.health <= 0) {
return true; // Boss died
}
return false;
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 12;
self.damage = 100; // Ensure one-hit kills
self.directionX = 0;
self.directionY = 0;
self.lastX = 0;
self.lastY = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
self.x += self.directionX * self.speed;
self.y += self.directionY * self.speed;
// Remove if out of bounds
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
return true; // Should be removed
}
return false;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50; // Will be one-shot by 100 damage bullets
self.speed = 8;
self.damage = 20;
self.attackCooldown = 0;
self.lastX = 0;
self.lastY = 0;
self.lastPlayerDistance = 1000;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
// Move towards player
if (player) {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
// Attack if close enough
var currentDistance = distance;
if (currentDistance < 50 && self.attackCooldown <= 0) {
player.takeDamage(self.damage);
self.attackCooldown = 60;
}
self.lastPlayerDistance = currentDistance;
}
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xffffff, 200);
if (self.health <= 0) {
return true; // Enemy died
}
return false;
};
return self;
});
var HealthPack = Container.expand(function () {
var self = Container.call(this);
var healthGraphics = self.attachAsset('healthPack', {
anchorX: 0.5,
anchorY: 0.5
});
self.healAmount = 30;
self.lifetime = 600; // 10 seconds at 60fps
self.update = function () {
self.lifetime--;
// Pulsing effect
healthGraphics.alpha = 0.7 + Math.sin(self.lifetime * 0.2) * 0.3;
if (self.lifetime <= 0) {
return true; // Should be removed
}
return false;
};
return self;
});
var MenuScreen = Container.expand(function () {
var self = Container.call(this);
// Dark background
var background = self.attachAsset('menuBackground', {
x: 0,
y: 0
});
// Blood moon effect in top right
var moon = self.attachAsset('moonGlow', {
x: 1600,
y: 300,
alpha: 0.7,
anchorX: 0.5,
anchorY: 0.5
});
// Blood splatter decorations
var splatter1 = self.attachAsset('bloodSplatter', {
x: 200,
y: 500,
alpha: 0.6,
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 1.2
});
var splatter2 = self.attachAsset('bloodSplatter', {
x: 1700,
y: 1800,
alpha: 0.4,
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 0.7
});
// Main title
var titleText = new Text2('NIGHT OF THE\nMASSACRE 3', {
size: 120,
fill: 0xFF4444,
align: 'center'
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 800;
self.addChild(titleText);
// Subtitle
var subtitleText = new Text2('BLOOD MOON RISING', {
size: 60,
fill: 0xFFFFFF,
align: 'center'
});
subtitleText.anchor.set(0.5, 0.5);
subtitleText.x = 1024;
subtitleText.y = 1000;
self.addChild(subtitleText);
// Start instruction
var startText = new Text2('TAP ANYWHERE TO BEGIN', {
size: 40,
fill: 0xCCCCCC,
align: 'center'
});
startText.anchor.set(0.5, 0.5);
startText.x = 1024;
startText.y = 1800;
self.addChild(startText);
// Pulsing effect for start text
self.pulseTimer = 0;
self.update = function () {
self.pulseTimer += 0.1;
startText.alpha = 0.5 + Math.sin(self.pulseTimer) * 0.3;
// Subtle moon glow animation
moon.alpha = 0.5 + Math.sin(self.pulseTimer * 0.5) * 0.2;
};
// Handle tap to start
self.down = function (x, y, obj) {
// Transition to game (this will be handled by destroying menu and starting game)
self.destroy();
startGame();
};
return self;
});
var ModeSelectionScreen = Container.expand(function () {
var self = Container.call(this);
// Dark background
var background = self.attachAsset('menuBackground', {
x: 0,
y: 0
});
// Blood moon effect in top right
var moon = self.attachAsset('moonGlow', {
x: 1600,
y: 300,
alpha: 0.7,
anchorX: 0.5,
anchorY: 0.5
});
// Main title
var titleText = new Text2('CHOOSE YOUR NIGHTMARE', {
size: 80,
fill: 0xFF4444,
align: 'center'
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 600;
self.addChild(titleText);
// Mode 1 - Classic Survival
var mode1Text = new Text2('CLASSIC SURVIVAL', {
size: 60,
fill: 0xFFFFFF,
align: 'center'
});
mode1Text.anchor.set(0.5, 0.5);
mode1Text.x = 1024;
mode1Text.y = 1000;
self.addChild(mode1Text);
var mode1Desc = new Text2('Survive until dawn with limited resources', {
size: 30,
fill: 0xCCCCCC,
align: 'center'
});
mode1Desc.anchor.set(0.5, 0.5);
mode1Desc.x = 1024;
mode1Desc.y = 1080;
self.addChild(mode1Desc);
// Mode 2 - Endless Nightmare
var mode2Text = new Text2('ENDLESS NIGHTMARE', {
size: 60,
fill: 0xFFFFFF,
align: 'center'
});
mode2Text.anchor.set(0.5, 0.5);
mode2Text.x = 1024;
mode2Text.y = 1300;
self.addChild(mode2Text);
var mode2Desc = new Text2('Face endless waves of increasing horror', {
size: 30,
fill: 0xCCCCCC,
align: 'center'
});
mode2Desc.anchor.set(0.5, 0.5);
mode2Desc.x = 1024;
mode2Desc.y = 1380;
self.addChild(mode2Desc);
// Mode 3 - Blood Eclipse
var mode3Text = new Text2('BLOOD ECLIPSE', {
size: 60,
fill: 0xFFFFFF,
align: 'center'
});
mode3Text.anchor.set(0.5, 0.5);
mode3Text.x = 1024;
mode3Text.y = 1600;
self.addChild(mode3Text);
var mode3Desc = new Text2('Ultimate challenge with eclipse phases', {
size: 30,
fill: 0xCCCCCC,
align: 'center'
});
mode3Desc.anchor.set(0.5, 0.5);
mode3Desc.x = 1024;
mode3Desc.y = 1680;
self.addChild(mode3Desc);
// Back instruction
var backText = new Text2('TAP TO SELECT MODE', {
size: 40,
fill: 0xFF6666,
align: 'center'
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 2000;
self.addChild(backText);
// Pulsing effect
self.pulseTimer = 0;
self.update = function () {
self.pulseTimer += 0.1;
backText.alpha = 0.5 + Math.sin(self.pulseTimer) * 0.3;
moon.alpha = 0.5 + Math.sin(self.pulseTimer * 0.5) * 0.2;
};
// Handle mode selection
self.down = function (x, y, obj) {
var selectedMode = 1;
if (y > 1200 && y < 1400) {
selectedMode = 2; // Endless Nightmare
} else if (y > 1500 && y < 1700) {
selectedMode = 3; // Blood Eclipse
}
self.destroy();
startGameWithMode(selectedMode);
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.ammo = 30;
self.maxAmmo = 30;
self.speed = 8;
self.shootCooldown = 0;
self.lastX = 0;
self.lastY = 0;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
// Keep player in bounds
if (self.x < 40) self.x = 40;
if (self.x > 2008) self.x = 2008;
if (self.y < 40) self.y = 40;
if (self.y > 2692) self.y = 2692;
};
self.takeDamage = function (amount) {
self.health -= amount;
if (self.health <= 0) {
self.health = 0;
LK.showGameOver();
}
LK.effects.flashObject(self, 0xff0000, 500);
};
self.heal = function (amount) {
self.health = Math.min(self.maxHealth, self.health + amount);
};
self.addAmmo = function (amount) {
self.ammo = Math.min(self.maxAmmo, self.ammo + amount);
};
self.canShoot = function () {
return self.ammo > 0 && self.shootCooldown <= 0;
};
self.shoot = function () {
if (self.canShoot()) {
self.ammo--;
self.shootCooldown = 15;
return true;
}
return false;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x0400ff
});
/****
* Game Code
****/
var menuScreen = null;
var modeSelectionScreen = null;
var gameStarted = false;
var selectedGameMode = 1;
// Game variables
var player = null;
var enemies = [];
var bullets = [];
var bazookaBullets = [];
var bazooka = null;
var healthPacks = [];
var ammoBoxes = [];
var boss = null;
var bossSpawned = false;
var gameTimer = 0;
var enemySpawnTimer = 0;
var waveNumber = 1;
var enemiesKilled = 0;
var survivalTime = 0;
var eclipsePhase = 0; // 0=normal, 1=blood moon, 2=eclipse
var eclipseTimer = 0;
// UI elements
var healthText = null;
var ammoText = null;
var waveText = null;
var timeText = null;
var eclipseText = null;
var bossHealthText = null;
function startGame() {
// Show mode selection screen instead of starting game directly
showModeSelection();
}
function showMenu() {
if (!menuScreen) {
menuScreen = new MenuScreen();
game.addChild(menuScreen);
LK.playMusic('menumusic');
}
}
function showModeSelection() {
if (!modeSelectionScreen) {
modeSelectionScreen = new ModeSelectionScreen();
game.addChild(modeSelectionScreen);
LK.playMusic('menumusic');
}
}
function startGameWithMode(mode) {
selectedGameMode = mode;
gameStarted = true;
initializeGame();
}
function initializeGame() {
// Clear game state
enemies = [];
bullets = [];
bazookaBullets = [];
healthPacks = [];
ammoBoxes = [];
boss = null;
bossSpawned = false;
gameTimer = 0;
enemySpawnTimer = 0;
waveNumber = 1;
enemiesKilled = 0;
survivalTime = 0;
eclipsePhase = 0;
eclipseTimer = 0;
// Create player
player = new Player();
player.x = 1024;
player.y = 1366;
game.addChild(player);
// Create bazooka
bazooka = new Bazooka();
bazooka.x = 1024;
bazooka.y = 2000;
game.addChild(bazooka);
// Create UI
healthText = new Text2('Health: 100', {
size: 40,
fill: 0x00ff00
});
healthText.x = 150;
healthText.y = 150;
LK.gui.topLeft.addChild(healthText);
ammoText = new Text2('Ammo: 30', {
size: 40,
fill: 0xffff00
});
ammoText.x = 150;
ammoText.y = 200;
LK.gui.topLeft.addChild(ammoText);
waveText = new Text2('Wave: 1', {
size: 40,
fill: 0xffffff
});
waveText.anchor.set(0.5, 0);
LK.gui.top.addChild(waveText);
timeText = new Text2('Time: 0:00', {
size: 40,
fill: 0xffffff
});
timeText.anchor.set(1, 0);
timeText.x = -50;
timeText.y = 150;
LK.gui.topRight.addChild(timeText);
if (selectedGameMode === 3) {
eclipseText = new Text2('Phase: Normal', {
size: 40,
fill: 0xff6666
});
eclipseText.anchor.set(1, 0);
eclipseText.x = -50;
eclipseText.y = 200;
LK.gui.topRight.addChild(eclipseText);
}
// Start background music
LK.playMusic('bgmusic');
}
function spawnEnemy() {
var enemy = new Enemy();
// Spawn from random edge
var edge = Math.floor(Math.random() * 4);
switch (edge) {
case 0:
// Top
enemy.x = Math.random() * 2048;
enemy.y = -30;
break;
case 1:
// Right
enemy.x = 2078;
enemy.y = Math.random() * 2732;
break;
case 2:
// Bottom
enemy.x = Math.random() * 2048;
enemy.y = 2762;
break;
case 3:
// Left
enemy.x = -30;
enemy.y = Math.random() * 2732;
break;
}
// Adjust enemy stats based on mode and wave
if (selectedGameMode === 2) {
// Endless Nightmare
enemy.health += waveNumber * 10;
enemy.speed += waveNumber * 0.3;
enemy.damage += waveNumber * 5;
} else if (selectedGameMode === 3) {
// Blood Eclipse
enemy.health += waveNumber * 15;
enemy.speed += waveNumber * 0.5;
enemy.damage += waveNumber * 8;
if (eclipsePhase === 1) {
// Blood moon
enemy.health *= 1.5;
enemy.speed *= 1.3;
} else if (eclipsePhase === 2) {
// Eclipse
enemy.health *= 2;
enemy.speed *= 1.5;
enemy.damage *= 1.5;
}
}
enemies.push(enemy);
game.addChild(enemy);
}
function spawnHealthPack() {
var healthPack = new HealthPack();
healthPack.x = 100 + Math.random() * 1848;
healthPack.y = 100 + Math.random() * 2532;
healthPacks.push(healthPack);
game.addChild(healthPack);
}
function spawnAmmoBox() {
var ammoBox = new AmmoBox();
ammoBox.x = 100 + Math.random() * 1848;
ammoBox.y = 100 + Math.random() * 2532;
ammoBoxes.push(ammoBox);
game.addChild(ammoBox);
}
function spawnBoss() {
boss = new Boss();
boss.x = 1024;
boss.y = 100;
bossSpawned = true;
game.addChild(boss);
// Create boss health UI
bossHealthText = new Text2('BOSS: 100000 / 100000', {
size: 50,
fill: 0xff0000
});
bossHealthText.anchor.set(0.5, 0);
LK.gui.top.addChild(bossHealthText);
}
function fireBullet(targetX, targetY) {
if (player && player.shoot()) {
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y;
// Find nearest enemy to target
var nearestEnemy = null;
var nearestDistance = Infinity;
for (var i = 0; i < enemies.length; i++) {
var enemy = enemies[i];
var dx = enemy.x - player.x;
var dy = enemy.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < nearestDistance) {
nearestDistance = distance;
nearestEnemy = enemy;
}
}
// If we found an enemy, target it; otherwise use tap location
var dx, dy, distance;
if (nearestEnemy) {
dx = nearestEnemy.x - player.x;
dy = nearestEnemy.y - player.y;
} else {
dx = targetX - player.x;
dy = targetY - player.y;
}
distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
bullet.directionX = dx / distance;
bullet.directionY = dy / distance;
}
bullets.push(bullet);
game.addChild(bullet);
// Play shooting sound
LK.getSound('shoot').play();
}
}
function updateGameMode() {
gameTimer++;
survivalTime = Math.floor(gameTimer / 60);
// Spawn boss at 06:00 (360 seconds) - but not in endless nightmare mode
if (survivalTime >= 360 && !bossSpawned && selectedGameMode !== 2) {
spawnBoss();
}
// Mode specific logic
if (selectedGameMode === 1) {
// Classic Survival
// Win condition: survive 5 minutes
if (survivalTime >= 300) {
LK.showYouWin();
return;
}
// Spawn enemies based on time
if (gameTimer % Math.max(30, 120 - survivalTime) === 0) {
spawnEnemy();
}
// Spawn resources occasionally
if (gameTimer % 600 === 0) spawnHealthPack();
if (gameTimer % 900 === 0) spawnAmmoBox();
} else if (selectedGameMode === 2) {
// Endless Nightmare
// New wave every 30 seconds
var newWave = Math.floor(survivalTime / 30) + 1;
if (newWave > waveNumber) {
waveNumber = newWave;
}
// Spawn enemies more frequently as waves progress
var spawnRate = Math.max(10, 60 - waveNumber * 3);
if (gameTimer % spawnRate === 0) {
spawnEnemy();
}
// Spawn resources based on wave
if (gameTimer % (600 - waveNumber * 20) === 0) spawnHealthPack();
if (gameTimer % (900 - waveNumber * 30) === 0) spawnAmmoBox();
} else if (selectedGameMode === 3) {
// Blood Eclipse
eclipseTimer++;
// Eclipse phases: 90s normal, 60s blood moon, 30s eclipse, repeat
var cycleTime = eclipseTimer % (180 * 60); // 3 minutes cycle
if (cycleTime < 90 * 60) {
eclipsePhase = 0; // Normal
} else if (cycleTime < 150 * 60) {
eclipsePhase = 1; // Blood moon
} else {
eclipsePhase = 2; // Eclipse
}
// Spawn rate increases with phase
var spawnRate = [60, 30, 15][eclipsePhase];
if (gameTimer % spawnRate === 0) {
spawnEnemy();
}
// Resources spawn less during eclipse phases
var resourceRate = [600, 800, 1200][eclipsePhase];
if (gameTimer % resourceRate === 0) spawnHealthPack();
if (gameTimer % (resourceRate * 1.5) === 0) spawnAmmoBox();
}
}
function updateUI() {
if (healthText) {
healthText.setText('Health: ' + player.health);
healthText.fill = player.health > 30 ? 0x00ff00 : 0xff0000;
}
if (ammoText) {
ammoText.setText('Ammo: ' + player.ammo);
ammoText.fill = player.ammo > 5 ? 0xffff00 : 0xff0000;
}
if (waveText) {
waveText.setText('Wave: ' + waveNumber);
}
if (timeText) {
var minutes = Math.floor(survivalTime / 60);
var seconds = survivalTime % 60;
timeText.setText('Time: ' + minutes + ':' + (seconds < 10 ? '0' : '') + seconds);
}
if (eclipseText && selectedGameMode === 3) {
var phases = ['Normal', 'Blood Moon', 'Eclipse'];
eclipseText.setText('Phase: ' + phases[eclipsePhase]);
eclipseText.fill = [0xffffff, 0xff6666, 0x660000][eclipsePhase];
}
if (bossHealthText && boss) {
bossHealthText.setText('BOSS: ' + boss.health + ' / ' + boss.maxHealth);
}
}
// Show menu on game start
showMenu();
game.down = function (x, y, obj) {
if (gameStarted && player) {
fireBullet(x, y);
}
};
game.move = function (x, y, obj) {
if (gameStarted && player) {
player.x = x;
player.y = y;
}
};
game.update = function () {
if (!gameStarted) {
return;
}
if (!player) return;
// Update game mode logic
updateGameMode();
// Update enemies
for (var i = enemies.length - 1; i >= 0; i--) {
enemies[i].update();
// Check if enemy should be removed
if (enemies[i].health <= 0) {
enemies[i].destroy();
enemies.splice(i, 1);
enemiesKilled++;
}
}
// Update boss
if (boss) {
boss.update();
// Check if boss died
if (boss.health <= 0) {
boss.destroy();
boss = null;
bossSpawned = false;
if (bossHealthText) {
bossHealthText.destroy();
bossHealthText = null;
}
LK.showGameOver();
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
var shouldRemove = bullet.update();
if (shouldRemove) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check bullet-enemy collisions
for (var j = enemies.length - 1; j >= 0; j--) {
if (bullet.intersects(enemies[j])) {
var enemyDied = enemies[j].takeDamage(bullet.damage);
bullet.destroy();
bullets.splice(i, 1);
if (enemyDied) {
enemies[j].destroy();
enemies.splice(j, 1);
enemiesKilled++;
}
break;
}
}
// Check bullet-boss collision
if (boss && bullet.intersects(boss)) {
var bossDied = boss.takeDamage(bullet.damage);
bullet.destroy();
bullets.splice(i, 1);
if (bossDied) {
boss.destroy();
boss = null;
bossSpawned = false;
if (bossHealthText) {
bossHealthText.destroy();
bossHealthText = null;
}
LK.showGameOver();
}
break;
}
}
// Update bazooka bullets
for (var i = bazookaBullets.length - 1; i >= 0; i--) {
var bullet = bazookaBullets[i];
var shouldRemove = bullet.update();
if (shouldRemove) {
bullet.explode();
bullet.destroy();
bazookaBullets.splice(i, 1);
continue;
}
// Check bazooka bullet-enemy collisions
for (var j = enemies.length - 1; j >= 0; j--) {
if (bullet.intersects(enemies[j])) {
bullet.explode();
bullet.destroy();
bazookaBullets.splice(i, 1);
break;
}
}
// Check bazooka bullet-boss collision
if (boss && bullet.intersects(boss)) {
bullet.explode();
bullet.destroy();
bazookaBullets.splice(i, 1);
break;
}
}
// Update bazooka
if (bazooka) {
bazooka.update();
}
// Update health packs
for (var i = healthPacks.length - 1; i >= 0; i--) {
var pack = healthPacks[i];
var shouldRemove = pack.update();
if (shouldRemove) {
pack.destroy();
healthPacks.splice(i, 1);
continue;
}
// Check player collision
if (player.intersects(pack)) {
player.heal(pack.healAmount);
LK.getSound('heal').play();
pack.destroy();
healthPacks.splice(i, 1);
}
}
// Update ammo boxes
for (var i = ammoBoxes.length - 1; i >= 0; i--) {
var box = ammoBoxes[i];
var shouldRemove = box.update();
if (shouldRemove) {
box.destroy();
ammoBoxes.splice(i, 1);
continue;
}
// Check player collision
if (player.intersects(box)) {
player.addAmmo(box.ammoAmount);
LK.getSound('ammo').play();
box.destroy();
ammoBoxes.splice(i, 1);
}
}
// Update UI
updateUI();
}; ===================================================================
--- original.js
+++ change.js
@@ -139,14 +139,17 @@
explosion.y = self.y;
explosion.alpha = 0.8;
game.addChild(explosion);
// Animate explosion
- tween(explosion).to({
+ tween(explosion, {
alpha: 0,
scaleX: 2,
scaleY: 2
- }, 500).onComplete(function () {
- explosion.destroy();
+ }, {
+ duration: 500,
+ onFinish: function onFinish() {
+ explosion.destroy();
+ }
});
// Play explosion sound
LK.getSound('explosion').play();
// Damage all enemies in radius