User prompt
As oscuro a la caja trampa y que recobre color cuando la barra de ritmo este en el punto perfecto ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Ponle una textura al contador de balas restantes
User prompt
Agrega una textura al contador de balas
User prompt
Agrega una textura al texto de estado
User prompt
Que los enemigos estén oscurecidos y que cuando la barra de ritmo este en el punto perfecto recobren color ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
As que las mesas sean oscuras y cuando la barra de ritmo este en el punto perfecto las mesas tomen color ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
As que las mesas de la derecha miren a la izquierda
User prompt
Sube las mesas un poco para que las mesas de la fila 2 estén en el centro
User prompt
Centra las mesas
User prompt
Cambia a qué tengan 400 de distancia
User prompt
As que cada mesa tenga 100 de distancia entre cada una
User prompt
As mucho más grandes las mesas y que cubran al menos la mitad del mapa
User prompt
Agrega mesas en filas de 2 x 3 hacia abajo en el centro del mapa y que sean destruidas al entrar en contacto con el enemigo
User prompt
Que las cajas trampa solo puedan hacer aparecer 1 enemigo a la vez
User prompt
Que las cajas de munición desaparezcan a los 5 segundos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Que se detenga más arriba la caja trampa
User prompt
Que la caja trampa se detenga más arriba
User prompt
Agrega un límite de aparición de enemigos de 10
User prompt
Reduzca un poco la velocidad de los enemigos de piedra
User prompt
Agrega un nuevo enemigo que sea de piedra, agrégale una nueva textura y que tenga 7 de vida
User prompt
Que la barra de ritmo este por encima de los enemigos
User prompt
Agrega texturas a la partícula de sangre , y que desaparezca al pasar 1 segundo ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Al conectar una bala agrega partículas de sangre ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Que la caja trampa tarde en salir 25 segundos
User prompt
Que la cajatrampa se detenga de baja por en cima del medio ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var Boss = Container.expand(function (generation) {
var self = Container.call(this);
var bossGraphics = self.attachAsset('boss', {
anchorX: 0.5,
anchorY: 0.5
});
// Assign random color to boss but make it initially dark
var randomColors = [0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0x96CEB4, 0xFECE7C, 0xF38BA8, 0xA8E6CF, 0xC7CEEA, 0xFFB3BA, 0xBAE1FF];
var randomColor = randomColors[Math.floor(Math.random() * randomColors.length)];
// Store the original color for later use
self.originalColor = randomColor;
// Make boss initially dark
bossGraphics.tint = 0x404040;
self.speed = 1;
self.generation = generation || 1;
self.health = (2 + self.generation) * 3; // First boss has 9 health, second has 12, etc.
self.maxHealth = (2 + self.generation) * 3;
self.isDying = false;
self.direction = {
x: 0,
y: 0
};
// Each generation doubles in base size: 1.5 * (2^(generation-1))
self.baseScale = 1.5 * Math.pow(2, self.generation - 1);
self.maxScale = self.baseScale * 2.67; // Keep same ratio as original (4/1.5)
self.lastDistanceFromPlayer = 0;
// Health bar setup
var healthBarBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.y = -80; // Position above boss
var healthBarFill = self.attachAsset('healthBarFill', {
anchorX: 0,
anchorY: 0.5
});
healthBarFill.x = healthBarBg.x - healthBarBg.width / 2;
healthBarFill.y = healthBarBg.y;
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
healthBarFill.width = 120 * healthPercent;
// Change color based on health
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00ff00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xffff00; // Yellow
} else {
healthBarFill.tint = 0xff0000; // Red
}
};
// Initialize health bar
self.updateHealthBar();
self.startDeathSequence = function () {
if (self.isDying) return;
self.isDying = true;
self.speed = 0; // Stop movement
// Change color to red
tween(bossGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
// Wait one second then destroy
tween(self, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
self.destroy();
}
});
}
});
};
self.update = function () {
if (self.isDying) return; // Don't move if dying
// Calculate direction toward player every frame
var dx = player.x - self.x;
var dy = player.y - self.y;
var length = Math.sqrt(dx * dx + dy * dy);
// Track distance for scaling
self.lastDistanceFromPlayer = length;
if (length > 0) {
self.direction.x = dx / length;
self.direction.y = dy / length;
}
// Keep boss at constant base scale
bossGraphics.scaleX = self.baseScale;
bossGraphics.scaleY = self.baseScale;
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
// Update health bar
self.updateHealthBar();
};
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 = 80;
self.direction = {
x: 0,
y: 0
};
self.isGuided = false;
self.setDirection = function (dirX, dirY) {
self.direction.x = dirX;
self.direction.y = dirY;
// Calculate rotation angle based on direction and rotate the bullet graphics
var angle = Math.atan2(dirY, dirX);
bulletGraphics.rotation = angle;
};
self.update = function () {
if (self.isGuided) {
// Find closest enemy
var closestEnemy = null;
var closestDistance = Infinity;
// Check regular enemies
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 < closestDistance) {
closestDistance = distance;
closestEnemy = enemy;
}
}
// Check golden enemies
for (var i = 0; i < goldenEnemies.length; i++) {
var goldenEnemy = goldenEnemies[i];
var dx = goldenEnemy.x - self.x;
var dy = goldenEnemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < closestDistance) {
closestDistance = distance;
closestEnemy = goldenEnemy;
}
}
// Check explosive enemies
for (var i = 0; i < explosiveEnemies.length; i++) {
var explosiveEnemy = explosiveEnemies[i];
var dx = explosiveEnemy.x - self.x;
var dy = explosiveEnemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < closestDistance) {
closestDistance = distance;
closestEnemy = explosiveEnemy;
}
}
// Check stone enemies
for (var i = 0; i < stoneEnemies.length; i++) {
var stoneEnemy = stoneEnemies[i];
var dx = stoneEnemy.x - self.x;
var dy = stoneEnemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < closestDistance) {
closestDistance = distance;
closestEnemy = stoneEnemy;
}
}
// Check bosses
for (var i = 0; i < bosses.length; i++) {
var boss = bosses[i];
var dx = boss.x - self.x;
var dy = boss.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < closestDistance) {
closestDistance = distance;
closestEnemy = boss;
}
}
// Update direction towards closest enemy
if (closestEnemy && closestDistance > 0) {
var dx = closestEnemy.x - self.x;
var dy = closestEnemy.y - self.y;
var length = Math.sqrt(dx * dx + dy * dy);
self.direction.x = dx / length;
self.direction.y = dy / length;
// Update bullet rotation
var angle = Math.atan2(dy, dx);
bulletGraphics.rotation = angle;
}
}
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
};
return self;
});
var Enemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('enemy', {
anchorX: 0.5,
anchorY: 0.5
});
// Make enemy initially dark
enemyGraphics.tint = 0x404040;
self.speed = 2;
self.health = 1;
self.isDying = false;
self.direction = {
x: 0,
y: 0
};
self.startDeathSequence = function () {
if (self.isDying) return;
self.isDying = true;
self.speed = 0; // Stop movement
// Change color to red
tween(enemyGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
// Wait one second then destroy
tween(self, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
self.destroy();
}
});
}
});
};
self.update = function () {
if (self.isDying) return; // Don't move if dying
// Calculate direction toward player every frame
var dx = player.x - self.x;
var dy = player.y - self.y;
var length = Math.sqrt(dx * dx + dy * dy);
if (length > 0) {
self.direction.x = dx / length;
self.direction.y = dy / length;
}
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
};
return self;
});
var ExplosiveEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('explosiveEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
// Assign random color to explosive enemy but make it initially dark
var randomColors = [0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0x96CEB4, 0xFECE7C, 0xF38BA8, 0xA8E6CF, 0xC7CEEA, 0xFFB3BA, 0xBAE1FF];
var randomColor = randomColors[Math.floor(Math.random() * randomColors.length)];
// Store the original color for later use
self.originalColor = randomColor;
// Make enemy initially dark
enemyGraphics.tint = 0x404040;
self.speed = 1.8;
self.health = 5;
self.maxHealth = 5;
self.isDying = false;
self.direction = {
x: 0,
y: 0
};
self.hasExploded = false;
self.startDeathSequence = function () {
if (self.isDying || self.hasExploded) return;
self.isDying = true;
self.speed = 0; // Stop movement
// Change color to red
tween(enemyGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
// Wait one second then destroy
tween(self, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
self.destroy();
}
});
}
});
};
// Create explosion damage zone
self.explode = function () {
if (self.hasExploded) return;
self.hasExploded = true;
// Create explosion visual effect
LK.effects.flashObject(self, 0xFF0000, 500);
LK.effects.flashScreen(0xFF4444, 300);
// Check for damage to nearby enemies and player
var explosionRadius = 500;
// Damage player if in range
var playerDx = player.x - self.x;
var playerDy = player.y - self.y;
var playerDistance = Math.sqrt(playerDx * playerDx + playerDy * playerDy);
if (playerDistance <= explosionRadius) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
return;
}
// Damage nearby enemies
for (var i = enemies.length - 1; i >= 0; 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 <= explosionRadius && enemy !== self) {
enemy.destroy();
enemies.splice(i, 1);
LK.setScore(LK.getScore() + 5);
playRandomEnemyKillSound();
}
}
// Damage nearby golden enemies
for (var i = goldenEnemies.length - 1; i >= 0; i--) {
var goldenEnemy = goldenEnemies[i];
var dx = goldenEnemy.x - self.x;
var dy = goldenEnemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= explosionRadius) {
goldenEnemy.destroy();
goldenEnemies.splice(i, 1);
LK.setScore(LK.getScore() + 25);
playRandomEnemyKillSound();
}
}
// Damage nearby explosive enemies (including self)
for (var i = explosiveEnemies.length - 1; i >= 0; i--) {
var explosiveEnemy = explosiveEnemies[i];
var dx = explosiveEnemy.x - self.x;
var dy = explosiveEnemy.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= explosionRadius) {
explosiveEnemy.destroy();
explosiveEnemies.splice(i, 1);
LK.setScore(LK.getScore() + 15);
playRandomEnemyKillSound();
}
}
// Damage nearby bosses
for (var i = 0; i < bosses.length; i++) {
var boss = bosses[i];
var dx = boss.x - self.x;
var dy = boss.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= explosionRadius) {
boss.health -= 2;
boss.updateHealthBar();
LK.effects.flashObject(boss, 0xFF0000, 300);
LK.setScore(LK.getScore() + 10);
}
}
// Create visual explosion zone
var explosionZone = LK.getAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5
});
explosionZone.x = self.x;
explosionZone.y = self.y;
explosionZone.scaleX = explosionRadius / 200;
explosionZone.scaleY = explosionRadius / 200;
explosionZone.alpha = 0.8;
game.addChild(explosionZone);
// Animate explosion zone
tween(explosionZone, {
scaleX: explosionZone.scaleX * 1.5,
scaleY: explosionZone.scaleY * 1.5,
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
explosionZone.destroy();
}
});
};
self.update = function () {
if (self.isDying) return; // Don't move if dying
// Calculate direction toward player every frame
var dx = player.x - self.x;
var dy = player.y - self.y;
var length = Math.sqrt(dx * dx + dy * dy);
if (length > 0) {
self.direction.x = dx / length;
self.direction.y = dy / length;
}
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
// Check if health reached 1 and explode
if (self.health <= 1 && !self.hasExploded) {
self.explode();
self.startDeathSequence(); // Start death sequence after exploding
}
};
return self;
});
var GoldenEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('goldenEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
// Make golden enemy initially dark
enemyGraphics.tint = 0x404040;
self.speed = 1.5;
self.health = 2;
self.isDying = false;
self.direction = {
x: 0,
y: 0
};
self.startDeathSequence = function () {
if (self.isDying) return;
self.isDying = true;
self.speed = 0; // Stop movement
// Change color to red
tween(enemyGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
// Wait one second then destroy
tween(self, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
self.destroy();
}
});
}
});
};
self.update = function () {
if (self.isDying) return; // Don't move if dying
// Calculate direction toward player every frame
var dx = player.x - self.x;
var dy = player.y - self.y;
var length = Math.sqrt(dx * dx + dy * dy);
if (length > 0) {
self.direction.x = dx / length;
self.direction.y = dy / length;
}
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.canShoot = false;
return self;
});
var PowerupCrate = Container.expand(function () {
var self = Container.call(this);
var crateGraphics = self.attachAsset('powerupCrate', {
anchorX: 0.5,
anchorY: 0.5
});
self.bobDirection = 1;
self.bobSpeed = 0.5;
self.baseY = 0;
self.isDestroying = false;
// Start 5 second countdown to destruction
tween(self, {}, {
duration: 5000,
onFinish: function onFinish() {
if (!self.isDestroying) {
self.isDestroying = true;
// Fade out animation before destruction
tween(self, {
alpha: 0
}, {
duration: 500,
onFinish: function onFinish() {
self.destroy();
}
});
}
}
});
self.update = function () {
if (self.isDestroying) return;
// Simple bobbing animation
self.y += self.bobDirection * self.bobSpeed;
var distanceFromBase = Math.abs(self.y - self.baseY);
if (distanceFromBase > 10) {
self.bobDirection *= -1;
}
};
return self;
});
var RhythmIndicator = Container.expand(function () {
var self = Container.call(this);
var rhythmBar = self.attachAsset('rhythmBar', {
anchorX: 0.5,
anchorY: 0.5
});
var perfectZone = self.attachAsset('perfectZone', {
anchorX: 0.5,
anchorY: 0.5
});
perfectZone.alpha = 0.7;
var indicator = self.attachAsset('rhythmIndicator', {
anchorX: 0.5,
anchorY: 0.5
});
indicator.x = -200;
self.beatDuration = 1000;
self.startTime = 0;
self.update = function () {
var elapsed = LK.ticks * (1000 / 60) - self.startTime;
var progress = elapsed % self.beatDuration / self.beatDuration;
indicator.x = -200 + progress * 400;
var perfectZoneStart = 150;
var perfectZoneEnd = 250;
var indicatorPos = 200 + indicator.x;
if (indicatorPos >= perfectZoneStart && indicatorPos <= perfectZoneEnd) {
player.canShoot = true;
perfectZone.tint = 0x27AE60;
// Make ground fully visible when in perfect zone
tween(ground, {
alpha: 1
}, {
duration: 100
});
// Light up all tables when in perfect zone
for (var t = 0; t < tables.length; t++) {
var table = tables[t];
if (!table.isDestroyed) {
tween(table, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
}
// Light up all enemies when in perfect zone
for (var e = 0; e < enemies.length; e++) {
var enemy = enemies[e];
if (!enemy.isDying) {
tween(enemy, {
tint: 0xFFFFFF
}, {
duration: 100
});
}
}
for (var ge = 0; ge < goldenEnemies.length; ge++) {
var goldenEnemy = goldenEnemies[ge];
if (!goldenEnemy.isDying) {
tween(goldenEnemy, {
tint: 0xFFD700
}, {
duration: 100
});
}
}
for (var ee = 0; ee < explosiveEnemies.length; ee++) {
var explosiveEnemy = explosiveEnemies[ee];
if (!explosiveEnemy.isDying) {
tween(explosiveEnemy, {
tint: explosiveEnemy.originalColor
}, {
duration: 100
});
}
}
for (var se = 0; se < stoneEnemies.length; se++) {
var stoneEnemy = stoneEnemies[se];
if (!stoneEnemy.isDying) {
tween(stoneEnemy, {
tint: stoneEnemy.originalColor
}, {
duration: 100
});
}
}
for (var b = 0; b < bosses.length; b++) {
var boss = bosses[b];
if (!boss.isDying) {
tween(boss, {
tint: boss.originalColor
}, {
duration: 100
});
}
}
} else {
player.canShoot = false;
perfectZone.tint = 0xE67E22;
// Make ground semi-transparent when not in perfect zone
tween(ground, {
alpha: 0.3
}, {
duration: 100
});
// Make tables dark when not in perfect zone
for (var t = 0; t < tables.length; t++) {
var table = tables[t];
if (!table.isDestroyed) {
tween(table, {
tint: 0x404040
}, {
duration: 100
});
}
}
// Make enemies dark when not in perfect zone
for (var e = 0; e < enemies.length; e++) {
var enemy = enemies[e];
if (!enemy.isDying) {
tween(enemy, {
tint: 0x404040
}, {
duration: 100
});
}
}
for (var ge = 0; ge < goldenEnemies.length; ge++) {
var goldenEnemy = goldenEnemies[ge];
if (!goldenEnemy.isDying) {
tween(goldenEnemy, {
tint: 0x404040
}, {
duration: 100
});
}
}
for (var ee = 0; ee < explosiveEnemies.length; ee++) {
var explosiveEnemy = explosiveEnemies[ee];
if (!explosiveEnemy.isDying) {
tween(explosiveEnemy, {
tint: 0x404040
}, {
duration: 100
});
}
}
for (var se = 0; se < stoneEnemies.length; se++) {
var stoneEnemy = stoneEnemies[se];
if (!stoneEnemy.isDying) {
tween(stoneEnemy, {
tint: 0x404040
}, {
duration: 100
});
}
}
for (var b = 0; b < bosses.length; b++) {
var boss = bosses[b];
if (!boss.isDying) {
tween(boss, {
tint: 0x404040
}, {
duration: 100
});
}
}
}
};
return self;
});
var StoneEnemy = Container.expand(function () {
var self = Container.call(this);
var enemyGraphics = self.attachAsset('stoneEnemy', {
anchorX: 0.5,
anchorY: 0.5
});
// Give stone enemy a gray stone-like tint but make it initially dark
self.originalColor = 0x808080;
// Make enemy initially dark
enemyGraphics.tint = 0x404040;
self.speed = 0.8;
self.health = 7;
self.maxHealth = 7;
self.isDying = false;
self.direction = {
x: 0,
y: 0
};
// Health bar setup
var healthBarBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.y = -80; // Position above stone enemy
var healthBarFill = self.attachAsset('healthBarFill', {
anchorX: 0,
anchorY: 0.5
});
healthBarFill.x = healthBarBg.x - healthBarBg.width / 2;
healthBarFill.y = healthBarBg.y;
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
healthBarFill.width = 120 * healthPercent;
// Change color based on health
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00ff00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xffff00; // Yellow
} else {
healthBarFill.tint = 0xff0000; // Red
}
};
// Initialize health bar
self.updateHealthBar();
self.startDeathSequence = function () {
if (self.isDying) return;
self.isDying = true;
self.speed = 0; // Stop movement
// Change color to red
tween(enemyGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
// Wait one second then destroy
tween(self, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
self.destroy();
}
});
}
});
};
self.update = function () {
if (self.isDying) return; // Don't move if dying
// Calculate direction toward player every frame
var dx = player.x - self.x;
var dy = player.y - self.y;
var length = Math.sqrt(dx * dx + dy * dy);
if (length > 0) {
self.direction.x = dx / length;
self.direction.y = dy / length;
}
self.x += self.direction.x * self.speed;
self.y += self.direction.y * self.speed;
// Update health bar
self.updateHealthBar();
};
return self;
});
var Table = Container.expand(function () {
var self = Container.call(this);
var tableGraphics = self.attachAsset('table', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1;
self.isDestroyed = false;
self.destroy = function () {
if (self.isDestroyed) return;
self.isDestroyed = true;
// Visual feedback for table destruction
LK.effects.flashObject(self, 0xFF0000, 300);
tween(self, {
alpha: 0
}, {
duration: 300,
onFinish: function onFinish() {
Container.prototype.destroy.call(self);
}
});
};
return self;
});
var TrapBox = Container.expand(function () {
var self = Container.call(this);
var trapBoxGraphics = self.attachAsset('trapBox', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 10;
self.maxHealth = 10;
self.isDying = false;
self.spawnTimer = 0;
self.spawnedEnemy = null; // Track the currently spawned enemy
// Health bar setup
var healthBarBg = self.attachAsset('healthBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
healthBarBg.y = -80; // Position above trap box
var healthBarFill = self.attachAsset('healthBarFill', {
anchorX: 0,
anchorY: 0.5
});
healthBarFill.x = healthBarBg.x - healthBarBg.width / 2;
healthBarFill.y = healthBarBg.y;
self.updateHealthBar = function () {
var healthPercent = self.health / self.maxHealth;
healthBarFill.width = 120 * healthPercent;
// Change color based on health
if (healthPercent > 0.6) {
healthBarFill.tint = 0x00ff00; // Green
} else if (healthPercent > 0.3) {
healthBarFill.tint = 0xffff00; // Yellow
} else {
healthBarFill.tint = 0xff0000; // Red
}
};
// Initialize health bar
self.updateHealthBar();
self.startDeathSequence = function () {
if (self.isDying) return;
self.isDying = true;
self.speed = 0; // Stop movement
// Change color to red
tween(trapBoxGraphics, {
tint: 0xFF0000
}, {
duration: 100,
onFinish: function onFinish() {
// Wait one second then destroy
tween(self, {
alpha: 0
}, {
duration: 1000,
onFinish: function onFinish() {
self.destroy();
}
});
}
});
};
self.spawnRandomEnemy = function () {
// Only spawn if no enemy is currently spawned or if the spawned enemy is destroyed
if (self.spawnedEnemy && self.spawnedEnemy.parent) {
return; // Don't spawn if there's already an active enemy
}
var enemyTypes = ['normal', 'golden', 'explosive'];
var randomType = enemyTypes[Math.floor(Math.random() * enemyTypes.length)];
var newEnemy;
if (randomType === 'normal') {
newEnemy = new Enemy();
enemies.push(newEnemy);
} else if (randomType === 'golden') {
newEnemy = new GoldenEnemy();
goldenEnemies.push(newEnemy);
} else if (randomType === 'explosive') {
newEnemy = new ExplosiveEnemy();
explosiveEnemies.push(newEnemy);
}
// Position enemy at trap box location
newEnemy.x = self.x;
newEnemy.y = self.y;
self.spawnedEnemy = newEnemy; // Track this enemy
game.addChild(newEnemy);
};
self.update = function () {
if (self.isDying) return; // Don't move or spawn if dying
// Zigzag movement pattern
if (!self.zigzagDirection) self.zigzagDirection = 1; // Initialize zigzag direction
if (!self.zigzagSpeed) self.zigzagSpeed = 2; // Zigzag horizontal speed
if (!self.zigzagTimer) self.zigzagTimer = 0; // Timer for zigzag changes
// Change zigzag direction every 60 ticks (1 second)
self.zigzagTimer++;
if (self.zigzagTimer >= 60) {
self.zigzagDirection *= -1;
self.zigzagTimer = 0;
}
// Apply zigzag movement
self.x += self.zigzagDirection * self.zigzagSpeed;
// Fall down slowly only if above middle of screen
if (self.y < 1000) {
// Stop falling when reaching above middle (2732/2)
self.y += 1; // Much slower speed (was 3, now 1)
}
// Clean up reference to destroyed enemy
if (self.spawnedEnemy && !self.spawnedEnemy.parent) {
self.spawnedEnemy = null;
}
// Spawn enemy every 3 seconds (180 ticks at 60 FPS)
self.spawnTimer++;
if (self.spawnTimer >= 180) {
self.spawnRandomEnemy();
self.spawnTimer = 0;
}
// Update health bar
self.updateHealthBar();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x1A1A2E
});
/****
* Game Code
****/
// Create ground texture first to render below enemies
var ground = LK.getAsset('ground', {
anchorX: 0.5,
anchorY: 1
});
ground.x = 1024; // Center horizontally
ground.y = 2732; // Position at bottom of screen
// Scale ground to ensure it covers the full screen width
ground.scaleX = 2048 / ground.width; // Scale to cover full width
ground.scaleY = Math.max(1, 2732 / ground.height); // Scale to cover full height if needed
// Make ground semi-transparent initially
ground.alpha = 0.3;
game.addChild(ground);
var player = game.addChild(new Player());
player.x = 1024;
player.y = 2400;
var rhythmIndicator = new RhythmIndicator();
rhythmIndicator.x = 1024;
rhythmIndicator.y = 200;
rhythmIndicator.beatDuration = 600; // 100 BPM = 60000ms / 100 beats = 600ms per beat (synchronized with bgmusic)
rhythmIndicator.startTime = LK.ticks * (1000 / 60);
var enemies = [];
var goldenEnemies = [];
var explosiveEnemies = [];
var bullets = [];
var powerupCrates = [];
var spawnTimer = 0;
var goldenSpawnTimer = 0;
var explosiveSpawnTimer = 0;
var stoneEnemies = [];
var stoneSpawnTimer = 0;
var gameSpeed = 1;
var bulletCount = 10;
var maxBullets = 10;
var isReloading = false;
var reloadTimer = 0;
var shotgunMode = false;
var shotgunBulletCount = 1;
var bosses = [];
var trapBoxes = [];
var trapBoxSpawnTimer = 0;
var comboCount = 0;
var lastShotWasPerfect = false;
var tables = [];
// Create tables in 2x3 grid formation in center of map
var tableStartX = 1024 - 400; // Center horizontally accounting for table width and spacing
var tableStartY = 766; // Position so second row is centered vertically
var tableSpacingX = 800; // 400 pixels distance between tables (400 table width + 400 spacing)
var tableSpacingY = 600; // 400 pixels distance between tables (200 table height + 400 spacing)
for (var row = 0; row < 3; row++) {
for (var col = 0; col < 2; col++) {
var table = new Table();
table.x = tableStartX + col * tableSpacingX;
table.y = tableStartY + row * tableSpacingY;
// Flip right column tables (col === 1) to face left
if (col === 1) {
table.scaleX = -1;
}
// Make tables initially dark
table.tint = 0x404040;
tables.push(table);
game.addChild(table);
}
}
var scoreTxt = new Text2('Score: 0', {
size: 60,
fill: 0xFFFFFF
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
var rhythmTxt = new Text2('Hit the beat!', {
size: 40,
fill: 0x27AE60,
stroke: 0x000000,
strokeThickness: 4,
font: "'Arial Black', Impact, Arial, sans-serif"
});
rhythmTxt.anchor.set(0.5, 0);
rhythmTxt.y = 80;
LK.gui.top.addChild(rhythmTxt);
var ammoTxt = new Text2('Ammo: 10', {
size: 80,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 4,
font: "'Arial Black', Impact, Arial, sans-serif"
});
ammoTxt.anchor.set(0, 1);
LK.gui.bottomLeft.addChild(ammoTxt);
var comboTxt = new Text2('Combo: 0', {
size: 60,
fill: 0xFFD700
});
comboTxt.anchor.set(1, 1);
LK.gui.bottomRight.addChild(comboTxt);
function playRandomEnemyKillSound() {
var killSounds = ['enemyKill', 'enemyKill2', 'enemyKill3', 'enemyKill4'];
var randomSound = killSounds[Math.floor(Math.random() * killSounds.length)];
LK.getSound(randomSound).play();
}
function spawnEnemy() {
// Check if we've reached the enemy limit
if (enemies.length >= 10) {
return; // Don't spawn if we have 10 or more enemies
}
var enemy = new Enemy();
// Only spawn from top
enemy.x = Math.random() * 2048;
enemy.y = -50;
// Direction will be calculated in enemy.update() to continuously track player
enemies.push(enemy);
game.addChild(enemy);
}
function spawnGoldenEnemy() {
var goldenEnemy = new GoldenEnemy();
// Only spawn from top
goldenEnemy.x = Math.random() * 2048;
goldenEnemy.y = -50;
// Direction will be calculated in goldenEnemy.update() to continuously track player
goldenEnemies.push(goldenEnemy);
game.addChild(goldenEnemy);
}
function spawnExplosiveEnemy() {
var explosiveEnemy = new ExplosiveEnemy();
// Only spawn from top
explosiveEnemy.x = Math.random() * 2048;
explosiveEnemy.y = -50;
explosiveEnemies.push(explosiveEnemy);
game.addChild(explosiveEnemy);
}
function spawnStoneEnemy() {
var stoneEnemy = new StoneEnemy();
// Only spawn from top
stoneEnemy.x = Math.random() * 2048;
stoneEnemy.y = -50;
stoneEnemies.push(stoneEnemy);
game.addChild(stoneEnemy);
}
function spawnBoss() {
// Starting from generation 5, spawn double bosses
var bossesToSpawn = bossGeneration >= 5 ? 2 : 1;
for (var b = 0; b < bossesToSpawn; b++) {
var boss = new Boss(bossGeneration);
// Spawn from top with some horizontal spacing for double bosses
if (bossesToSpawn === 2) {
boss.x = Math.random() * 1024 + b * 1024; // Split screen into two halves
} else {
boss.x = Math.random() * 2048;
}
boss.y = -500;
bosses.push(boss);
game.addChild(boss);
}
// Visual feedback for boss spawn
LK.effects.flashScreen(0x8B0000, 1000);
if (bossesToSpawn === 2) {
rhythmTxt.setText('DOUBLE BOSS LV' + bossGeneration + ' INCOMING!');
} else {
rhythmTxt.setText('BOSS LV' + bossGeneration + ' INCOMING!');
}
rhythmTxt.tint = 0x8B0000;
// Increase enemy spawn rate when boss appears
gameSpeed += 0.5;
// Increment boss generation for next spawn
bossGeneration++;
}
function shootBullet(targetX, targetY) {
if (bulletCount <= 0 || isReloading) {
rhythmTxt.setText('Reloading...');
rhythmTxt.tint = 0xFFFF00;
return;
}
if (!player.canShoot) {
rhythmTxt.setText('Wrong timing!');
rhythmTxt.tint = 0xE74C3C;
// Reset combo on wrong timing
comboCount = 0;
comboTxt.setText('Combo: ' + comboCount);
lastShotWasPerfect = false;
// Consume bullet even on wrong timing
bulletCount--;
ammoTxt.setText('Ammo: ' + bulletCount);
// Add failure effect
LK.effects.flashScreen(0xFF4444, 300);
// Play miss sound
LK.getSound('miss').play();
// Check if need to reload
if (bulletCount <= 0) {
isReloading = true;
reloadTimer = 120; // 2 seconds at 60 FPS
ammoTxt.setText('Reloading...');
ammoTxt.tint = 0xFFFF00;
}
return;
}
rhythmTxt.setText('Perfect!');
rhythmTxt.tint = 0x27AE60;
// Increment combo count on perfect shot
comboCount++;
comboTxt.setText('Combo: ' + comboCount);
lastShotWasPerfect = true;
bulletCount--;
ammoTxt.setText('Ammo: ' + bulletCount);
if (bulletCount <= 0) {
isReloading = true;
reloadTimer = 120; // 2 seconds at 60 FPS
ammoTxt.setText('Reloading...');
ammoTxt.tint = 0xFFFF00;
}
// Calculate base direction
var dx = targetX - player.x;
var dy = targetY - player.y;
var length = Math.sqrt(dx * dx + dy * dy);
var baseAngle = Math.atan2(dy, dx);
// Check if we should create a guided bullet (every 5 combos) or redirect all bullets (every 10 combos)
var shouldCreateGuided = comboCount > 0 && comboCount % 5 === 0 && lastShotWasPerfect;
var shouldRedirectAll = comboCount > 0 && comboCount % 10 === 0 && lastShotWasPerfect;
if (shotgunMode) {
// Fire bullets based on accumulated shotgun count
var totalBullets = shotgunBulletCount;
var spreadRange = 0.8; // Total spread range in radians
var angleStep = totalBullets > 1 ? spreadRange / (totalBullets - 1) : 0;
var startAngle = baseAngle - spreadRange / 2;
for (var s = 0; s < totalBullets; s++) {
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y;
var angle = totalBullets > 1 ? startAngle + s * angleStep : baseAngle;
bullet.setDirection(Math.cos(angle), Math.sin(angle));
// Assign random color to bullet
var randomColors = [0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0x96CEB4, 0xFECE7C, 0xF38BA8, 0xA8E6CF, 0xC7CEEA, 0xFFB3BA, 0xBAE1FF];
var randomColor = randomColors[Math.floor(Math.random() * randomColors.length)];
bullet.tint = randomColor;
// Make first bullet guided if combo condition is met, or all bullets if combo 10
if (s === 0 && shouldCreateGuided || shouldRedirectAll) {
bullet.isGuided = true;
// Visual feedback for guided bullet
var bulletColor = shouldRedirectAll ? 0xFFD700 : 0x00FFFF; // Gold for combo 10, cyan for combo 5
tween(bullet, {
tint: bulletColor
}, {
duration: 200
});
}
bullets.push(bullet);
game.addChild(bullet);
}
} else {
// Fire single bullet
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y;
bullet.setDirection(dx / length, dy / length);
// Assign random color to bullet
var randomColors = [0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0x96CEB4, 0xFECE7C, 0xF38BA8, 0xA8E6CF, 0xC7CEEA, 0xFFB3BA, 0xBAE1FF];
var randomColor = randomColors[Math.floor(Math.random() * randomColors.length)];
bullet.tint = randomColor;
// Make bullet guided if combo condition is met
if (shouldCreateGuided || shouldRedirectAll) {
bullet.isGuided = true;
// Visual feedback for guided bullet
var bulletColor = shouldRedirectAll ? 0xFFD700 : 0x00FFFF; // Gold for combo 10, cyan for combo 5
tween(bullet, {
tint: bulletColor
}, {
duration: 200
});
}
bullets.push(bullet);
game.addChild(bullet);
}
// Show special feedback for combo milestones
if (shouldRedirectAll) {
rhythmTxt.setText('ALL SHOTS GUIDED! Combo x' + comboCount);
rhythmTxt.tint = 0xFFD700;
LK.effects.flashScreen(0xFFD700, 500);
} else if (shouldCreateGuided) {
rhythmTxt.setText('GUIDED SHOT! Combo x' + comboCount);
rhythmTxt.tint = 0x00FFFF;
LK.effects.flashScreen(0x00FFFF, 300);
}
LK.getSound('shoot').play();
// Add camera shake when shooting
var shakeIntensity = shotgunMode ? shotgunBulletCount * 8 : 20;
tween(game, {
x: game.x + shakeIntensity
}, {
duration: 50,
onFinish: function onFinish() {
tween(game, {
x: game.x - shakeIntensity * 2
}, {
duration: 50,
onFinish: function onFinish() {
tween(game, {
x: 0
}, {
duration: 50
});
}
});
}
});
}
game.down = function (x, y, obj) {
shootBullet(x, y);
};
game.update = function () {
spawnTimer++;
goldenSpawnTimer++;
explosiveSpawnTimer++;
if (spawnTimer >= 120 / gameSpeed) {
spawnEnemy();
spawnTimer = 0;
}
// Spawn golden enemy every 10 seconds (600 ticks at 60 FPS)
if (goldenSpawnTimer >= 600) {
spawnGoldenEnemy();
goldenSpawnTimer = 0;
}
// Spawn explosive enemy every 8 seconds (480 ticks at 60 FPS)
if (explosiveSpawnTimer >= 480) {
spawnExplosiveEnemy();
explosiveSpawnTimer = 0;
}
// Spawn stone enemy every 12 seconds (720 ticks at 60 FPS)
stoneSpawnTimer++;
if (stoneSpawnTimer >= 720) {
spawnStoneEnemy();
stoneSpawnTimer = 0;
}
// Spawn trap box every 25 seconds (1500 ticks at 60 FPS)
trapBoxSpawnTimer++;
if (trapBoxSpawnTimer >= 1500) {
var trapBox = new TrapBox();
trapBox.x = Math.random() * 2048;
trapBox.y = -50;
trapBoxes.push(trapBox);
game.addChild(trapBox);
trapBoxSpawnTimer = 0;
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
if (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782) {
bullet.destroy();
bullets.splice(i, 1);
continue;
}
// Check bullet-enemy collisions
for (var j = enemies.length - 1; j >= 0; j--) {
var enemy = enemies[j];
if (bullet.intersects(enemy) && !enemy.isDying) {
enemy.health--;
if (enemy.health <= 0) {
LK.setScore(LK.getScore() + 10);
scoreTxt.setText('Score: ' + LK.getScore());
// Add combo point for hitting enemy
comboCount++;
comboTxt.setText('Combo: ' + comboCount);
LK.getSound('hit').play();
playRandomEnemyKillSound();
LK.effects.flashObject(enemy, 0xFFFFFF, 200);
// Start death sequence
enemy.startDeathSequence();
// Remove from array after starting death sequence
enemies.splice(j, 1);
// Add camera shake when hitting enemy
tween(game, {
x: game.x + 12
}, {
duration: 30,
onFinish: function onFinish() {
tween(game, {
x: game.x - 24
}, {
duration: 30,
onFinish: function onFinish() {
tween(game, {
x: 0
}, {
duration: 30
});
}
});
}
});
}
bullet.destroy();
bullets.splice(i, 1);
break;
}
}
// Check bullet-golden enemy collisions
for (var j = goldenEnemies.length - 1; j >= 0; j--) {
var goldenEnemy = goldenEnemies[j];
if (bullet.intersects(goldenEnemy)) {
goldenEnemy.health--;
// Add combo point for hitting golden enemy
comboCount++;
comboTxt.setText('Combo: ' + comboCount);
LK.getSound('hit').play();
LK.effects.flashObject(goldenEnemy, 0xFFFFFF, 200);
// Add camera shake when hitting golden enemy
tween(game, {
x: game.x + 16
}, {
duration: 35,
onFinish: function onFinish() {
tween(game, {
x: game.x - 32
}, {
duration: 35,
onFinish: function onFinish() {
tween(game, {
x: 0
}, {
duration: 35
});
}
});
}
});
bullet.destroy();
bullets.splice(i, 1);
if (goldenEnemy.health <= 0) {
LK.setScore(LK.getScore() + 50);
scoreTxt.setText('Score: ' + LK.getScore());
playRandomEnemyKillSound();
// Drop powerup crate at golden enemy position
var crate = new PowerupCrate();
crate.x = goldenEnemy.x;
crate.y = goldenEnemy.y;
crate.baseY = goldenEnemy.y;
powerupCrates.push(crate);
game.addChild(crate);
// Start death sequence
goldenEnemy.startDeathSequence();
goldenEnemies.splice(j, 1);
} else {
LK.setScore(LK.getScore() + 10);
scoreTxt.setText('Score: ' + LK.getScore());
}
break;
}
}
// Check bullet-explosive enemy collisions
for (var j = explosiveEnemies.length - 1; j >= 0; j--) {
var explosiveEnemy = explosiveEnemies[j];
if (bullet.intersects(explosiveEnemy)) {
explosiveEnemy.health--;
// Add combo point for hitting explosive enemy
comboCount++;
comboTxt.setText('Combo: ' + comboCount);
LK.getSound('hit').play();
LK.effects.flashObject(explosiveEnemy, 0xFFFFFF, 200);
// Add camera shake when hitting explosive enemy
tween(game, {
x: game.x + 18
}, {
duration: 35,
onFinish: function onFinish() {
tween(game, {
x: game.x - 36
}, {
duration: 35,
onFinish: function onFinish() {
tween(game, {
x: 0
}, {
duration: 35
});
}
});
}
});
bullet.destroy();
bullets.splice(i, 1);
if (explosiveEnemy.health <= 0) {
LK.setScore(LK.getScore() + 30);
scoreTxt.setText('Score: ' + LK.getScore());
playRandomEnemyKillSound();
// Start death sequence
explosiveEnemy.startDeathSequence();
explosiveEnemies.splice(j, 1);
} else {
LK.setScore(LK.getScore() + 15);
scoreTxt.setText('Score: ' + LK.getScore());
}
break;
}
}
// Check bullet-boss collisions
for (var j = bosses.length - 1; j >= 0; j--) {
var boss = bosses[j];
if (bullet.intersects(boss)) {
boss.health--;
boss.updateHealthBar(); // Update health bar immediately
// Add combo point for hitting boss
comboCount++;
comboTxt.setText('Combo: ' + comboCount);
LK.getSound('hit').play();
LK.effects.flashObject(boss, 0xFFFFFF, 200);
// Add camera shake when hitting boss
tween(game, {
x: game.x + 24
}, {
duration: 40,
onFinish: function onFinish() {
tween(game, {
x: game.x - 48
}, {
duration: 40,
onFinish: function onFinish() {
tween(game, {
x: 0
}, {
duration: 40
});
}
});
}
});
bullet.destroy();
bullets.splice(i, 1);
if (boss.health <= 0) {
LK.setScore(LK.getScore() + 100);
scoreTxt.setText('Score: ' + LK.getScore());
playRandomEnemyKillSound();
// Visual feedback for boss defeat
LK.effects.flashScreen(0x00FF00, 800);
rhythmTxt.setText('BOSS DEFEATED!');
rhythmTxt.tint = 0x00FF00;
// Start death sequence
boss.startDeathSequence();
bosses.splice(j, 1);
} else {
LK.setScore(LK.getScore() + 20);
scoreTxt.setText('Score: ' + LK.getScore());
}
break;
}
}
// Check bullet-powerup crate collisions
for (var j = powerupCrates.length - 1; j >= 0; j--) {
var crate = powerupCrates[j];
if (bullet.intersects(crate) && !crate.isDestroying) {
// Check if we haven't reached the maximum of 2 crates
var maxShotgunBullets = 9; // 3^2 = 9 (maximum 2 crates accumulated)
if (shotgunBulletCount < maxShotgunBullets) {
// Enable shotgun mode and triple bullet count
shotgunMode = true;
shotgunBulletCount *= 3;
// Visual feedback
LK.effects.flashScreen(0x8e44ad, 500);
rhythmTxt.setText('Shotgun x' + shotgunBulletCount + '!');
rhythmTxt.tint = 0x8e44ad;
} else {
// Maximum reached, show different feedback
LK.effects.flashScreen(0xFFD700, 300);
rhythmTxt.setText('Max Shotgun!');
rhythmTxt.tint = 0xFFD700;
}
// Remove crate and bullet
bullet.destroy();
bullets.splice(i, 1);
crate.destroy();
powerupCrates.splice(j, 1);
break;
}
}
// Check bullet-stone enemy collisions
for (var j = stoneEnemies.length - 1; j >= 0; j--) {
var stoneEnemy = stoneEnemies[j];
if (bullet.intersects(stoneEnemy) && !stoneEnemy.isDying) {
stoneEnemy.health--;
// Add combo point for hitting stone enemy
comboCount++;
comboTxt.setText('Combo: ' + comboCount);
LK.getSound('hit').play();
LK.effects.flashObject(stoneEnemy, 0xFFFFFF, 200);
// Add camera shake when hitting stone enemy
tween(game, {
x: game.x + 14
}, {
duration: 35,
onFinish: function onFinish() {
tween(game, {
x: game.x - 28
}, {
duration: 35,
onFinish: function onFinish() {
tween(game, {
x: 0
}, {
duration: 35
});
}
});
}
});
bullet.destroy();
bullets.splice(i, 1);
if (stoneEnemy.health <= 0) {
LK.setScore(LK.getScore() + 35);
scoreTxt.setText('Score: ' + LK.getScore());
playRandomEnemyKillSound();
// Start death sequence
stoneEnemy.startDeathSequence();
stoneEnemies.splice(j, 1);
} else {
LK.setScore(LK.getScore() + 5);
scoreTxt.setText('Score: ' + LK.getScore());
}
break;
}
}
// Check bullet-trap box collisions
for (var j = trapBoxes.length - 1; j >= 0; j--) {
var trapBox = trapBoxes[j];
if (bullet.intersects(trapBox) && !trapBox.isDying) {
trapBox.health--;
// Add combo point for hitting trap box
comboCount++;
comboTxt.setText('Combo: ' + comboCount);
LK.getSound('hit').play();
LK.effects.flashObject(trapBox, 0xFFFFFF, 200);
bullet.destroy();
bullets.splice(i, 1);
if (trapBox.health <= 0) {
LK.setScore(LK.getScore() + 20);
scoreTxt.setText('Score: ' + LK.getScore());
playRandomEnemyKillSound();
// Start death sequence
trapBox.startDeathSequence();
trapBoxes.splice(j, 1);
} else {
LK.setScore(LK.getScore() + 5);
scoreTxt.setText('Score: ' + LK.getScore());
}
break;
}
}
}
// Update enemies
for (var k = enemies.length - 1; k >= 0; k--) {
var enemy = enemies[k];
if (enemy.intersects(player)) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
return;
}
// Check enemy-table collisions
for (var t = tables.length - 1; t >= 0; t--) {
var table = tables[t];
if (!table.isDestroyed && enemy.intersects(table)) {
table.destroy();
tables.splice(t, 1);
break;
}
}
if (enemy.x < -100 || enemy.x > 2148 || enemy.y < -100 || enemy.y > 2832) {
enemy.destroy();
enemies.splice(k, 1);
}
}
// Update golden enemies
for (var k = goldenEnemies.length - 1; k >= 0; k--) {
var goldenEnemy = goldenEnemies[k];
if (goldenEnemy.intersects(player)) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
return;
}
// Check golden enemy-table collisions
for (var t = tables.length - 1; t >= 0; t--) {
var table = tables[t];
if (!table.isDestroyed && goldenEnemy.intersects(table)) {
table.destroy();
tables.splice(t, 1);
break;
}
}
if (goldenEnemy.x < -100 || goldenEnemy.x > 2148 || goldenEnemy.y < -100 || goldenEnemy.y > 2832) {
goldenEnemy.destroy();
goldenEnemies.splice(k, 1);
}
}
// Update bosses
for (var k = bosses.length - 1; k >= 0; k--) {
var boss = bosses[k];
if (boss.intersects(player)) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
return;
}
// Check boss-table collisions
for (var t = tables.length - 1; t >= 0; t--) {
var table = tables[t];
if (!table.isDestroyed && boss.intersects(table)) {
table.destroy();
tables.splice(t, 1);
break;
}
}
if (boss.x < -200 || boss.x > 2248 || boss.y < -200 || boss.y > 2932) {
boss.destroy();
bosses.splice(k, 1);
}
}
// Update explosive enemies
for (var k = explosiveEnemies.length - 1; k >= 0; k--) {
var explosiveEnemy = explosiveEnemies[k];
if (explosiveEnemy.intersects(player)) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
return;
}
// Check explosive enemy-table collisions
for (var t = tables.length - 1; t >= 0; t--) {
var table = tables[t];
if (!table.isDestroyed && explosiveEnemy.intersects(table)) {
table.destroy();
tables.splice(t, 1);
break;
}
}
if (explosiveEnemy.x < -100 || explosiveEnemy.x > 2148 || explosiveEnemy.y < -100 || explosiveEnemy.y > 2832) {
explosiveEnemy.destroy();
explosiveEnemies.splice(k, 1);
}
}
// Update and cleanup powerup crates
for (var k = powerupCrates.length - 1; k >= 0; k--) {
var crate = powerupCrates[k];
// Check if crate was destroyed (by timer or going off screen)
if (!crate.parent) {
powerupCrates.splice(k, 1);
continue;
}
if (crate.x < -100 || crate.x > 2148 || crate.y < -100 || crate.y > 2832) {
crate.destroy();
powerupCrates.splice(k, 1);
}
}
// Update stone enemies
for (var k = stoneEnemies.length - 1; k >= 0; k--) {
var stoneEnemy = stoneEnemies[k];
if (stoneEnemy.intersects(player)) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
return;
}
// Check stone enemy-table collisions
for (var t = tables.length - 1; t >= 0; t--) {
var table = tables[t];
if (!table.isDestroyed && stoneEnemy.intersects(table)) {
table.destroy();
tables.splice(t, 1);
break;
}
}
if (stoneEnemy.x < -150 || stoneEnemy.x > 2198 || stoneEnemy.y < -150 || stoneEnemy.y > 2882) {
stoneEnemy.destroy();
stoneEnemies.splice(k, 1);
}
}
// Update trap boxes
for (var k = trapBoxes.length - 1; k >= 0; k--) {
var trapBox = trapBoxes[k];
if (trapBox.intersects(player)) {
LK.effects.flashScreen(0xFF0000, 1000);
LK.showGameOver();
return;
}
// Check trap box-table collisions
for (var t = tables.length - 1; t >= 0; t--) {
var table = tables[t];
if (!table.isDestroyed && trapBox.intersects(table)) {
table.destroy();
tables.splice(t, 1);
break;
}
}
if (trapBox.x < -200 || trapBox.x > 2248 || trapBox.y < -200 || trapBox.y > 2932) {
trapBox.destroy();
trapBoxes.splice(k, 1);
}
}
// Handle reloading
if (isReloading) {
reloadTimer--;
if (reloadTimer <= 0) {
bulletCount = maxBullets;
isReloading = false;
ammoTxt.setText('Ammo: ' + bulletCount);
ammoTxt.tint = 0xFFFFFF;
}
}
// Ensure rhythm indicator stays on top by moving it to the end of children array
if (rhythmIndicator.parent) {
game.setChildIndex(rhythmIndicator, game.children.length - 1);
}
// Increase difficulty over time
if (LK.getScore() > 0 && LK.getScore() % 100 === 0 && LK.ticks % 60 === 0) {
gameSpeed += 0.1;
rhythmIndicator.beatDuration = Math.max(600, rhythmIndicator.beatDuration - 50);
}
};
// Add rhythm indicator last to ensure it renders above all other elements
game.addChild(rhythmIndicator);
// Ensure rhythm indicator stays on top of all enemies and ground
game.setChildIndex(rhythmIndicator, game.children.length - 1);
LK.playMusic('bgmusic');
; ===================================================================
--- original.js
+++ change.js
@@ -994,9 +994,12 @@
rhythmTxt.y = 80;
LK.gui.top.addChild(rhythmTxt);
var ammoTxt = new Text2('Ammo: 10', {
size: 80,
- fill: 0xFFFFFF
+ fill: 0xFFFFFF,
+ stroke: 0x000000,
+ strokeThickness: 4,
+ font: "'Arial Black', Impact, Arial, sans-serif"
});
ammoTxt.anchor.set(0, 1);
LK.gui.bottomLeft.addChild(ammoTxt);
var comboTxt = new Text2('Combo: 0', {
Modern App Store icon, high definition, square with rounded corners, for a game titled "Rhythm Shooter" and with the description "Time your shots to the beat! A rhythm-based shooter where you can only fire when hitting the perfect musical timing.". No text on icon!
Zombie desde arriba estilo rpg, pixelart. In-Game asset. 2d. High contrast. No shadows
Zombie de oro , pixelart
Cámbialo a color neon blanco retro
Borra todo lo del sentro y crea un marco multicolor retro
Caja de munición de colores retro pixelart. In-Game asset. 2d. High contrast. No shadows
Vuelvelo neon brillante por bordes
Agrégale una bata negra y un bastón, pixelart
Agrega un círculo en el medio estilo retro con un arma, pixelart
Cambiarles los colores a azul y rojo escuro , pixelart
Una barra neon de forma cuadrada. In-Game asset. 2d. High contrast. No shadows