User prompt
Please fix the bug: 'ReferenceError: _CRYPTO_ is not defined' in or related to this line: 'var dx = _CRYPTO_ - self.x;' Line Number: 80
Code edit (2 edits merged)
Please save this source code
User prompt
Please fix the bug: 'setTimeout is not a function' in or related to this line: 'setTimeout(function () {' Line Number: 497
User prompt
Please fix the bug: 'Graphics is not a constructor' in or related to this line: 'var waveProgressBg = LK.gui.top.addChild(new Graphics());' Line Number: 413
Code edit (1 edits merged)
Please save this source code
User prompt
Grandma Click Fury
Initial prompt
Create a 2D pixel art arcade-style action game titled “Grandma Click Fury”. The main character is Grandma Turbo, a wild old lady riding a rocket-powered shopping cart through chaotic food-themed worlds while battling evil cyber pigeons. Grandma follows the mouse cursor slowly, and all actions are triggered with clicks. Clicking makes her attack, holding click charges a turbo boost, and double-clicking throws a food bomb. The game is fast-paced, full of funny sound effects and over-the-top animations. Grandma has sassy voice lines like “Click me harder, baby!”, “That’s how grandma rolls!”, and “Pigeon trash, back off!”. 🎮 Game Mechanics: Grandma rolls toward the mouse cursor. Click to swing her cane. Hold click to charge a forward turbo boost. Double-click to throw a ketchup bomb. Power-ups appear on the ground and activate with a single click. 🌍 Worlds: Syrup Street – A sticky breakfast world with waffle bridges, toast traps, and syrup waterfalls. Pizza Parade – A lunch-themed level where cheese slows you down, and flying pineapple drones shoot pepperoni lasers. Microwave Mountain – The final world, filled with floating forks, bouncing meatballs, and the evil boss Microwave Overlord. 🦅 Enemies: Cyber pigeons that swoop in quickly. Egg-throwing pigeons that stay at range. Hover drones dropping mustard bombs. Mini-bosses like The Burger Bomber and The Bacon Snake. 💥 Power-Ups: Click-Coffee: Temporarily increases movement speed. Cookie Shield: Blocks the next hit. Bingo Blast: Summons a squad of old ladies who do an area attack with knitting needles. 📦 UI: Health bar: Yarn balls. Energy meter: Fills while holding click. Score: Number of pies collected. Funny text when power-ups activate: “¡Turbo Granny Time!” or “Bingo Blitz Ready!” The art should be vibrant, cartoonish pixel style, with exaggerated squash-and-stretch animations, food explosions, and chaotic action. Add juicy sound effects and a retro-style upbeat soundtrack. The game should be fun, silly, satisfying to click, and visually explosive — designed to be addictive and hilarious.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BossPigeon = Container.expand(function () {
var self = Container.call(this);
var pigeonGraphics = self.attachAsset('cyberPigeon', {
anchorX: 0.5,
anchorY: 0.5
});
// Boss más grande y diferente color
pigeonGraphics.scaleX = 2;
pigeonGraphics.scaleY = 2;
pigeonGraphics.tint = 0x8000ff; // Púrpura
self.health = 100 + wave * 20;
self.maxHealth = self.health;
self.speed = 1;
self.attackCooldown = 0;
self.specialAttackCooldown = 0;
self.isBoss = true;
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xff0000, 200);
// Texto de daño más grande para boss
var damageText = new Text2('-' + damage, {
size: 60,
fill: 0xffff00
});
damageText.x = self.x;
damageText.y = self.y - 50;
game.addChild(damageText);
tween(damageText, {
y: damageText.y - 80,
alpha: 0
}, {
duration: 1000,
onComplete: function onComplete() {
damageText.destroy();
}
});
if (self.health <= 0) {
score += 100;
// Explosión más grande
for (var i = 0; i < 3; i++) {
setTimeout(function () {
var explosion = new Explosion();
explosion.x = self.x + (Math.random() - 0.5) * 100;
explosion.y = self.y + (Math.random() - 0.5) * 100;
game.addChild(explosion);
explosions.push(explosion);
LK.getSound('explosion').play();
}, i * 200);
}
// Drop garantizado de power-ups
for (var i = 0; i < 3; i++) {
spawnPowerUpAt(self.x + (Math.random() - 0.5) * 150, self.y + (Math.random() - 0.5) * 150);
}
return true;
}
return false;
};
self.update = function () {
// Movimiento del boss
var dx = grandma.x - self.x;
var dy = grandma.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 200) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
} else {
// Círculo alrededor de grandma
self.x += Math.cos(LK.ticks * 0.05) * 2;
self.y += Math.sin(LK.ticks * 0.05) * 2;
}
// Ataque especial cada 5 segundos
if (self.specialAttackCooldown <= 0) {
// Spawn mini pigeons
for (var i = 0; i < 3; i++) {
var miniPigeon = new CyberPigeon();
miniPigeon.x = self.x + (Math.random() - 0.5) * 100;
miniPigeon.y = self.y + (Math.random() - 0.5) * 100;
miniPigeon.health = 15;
cyberPigeons.push(miniPigeon);
game.addChild(miniPigeon);
}
self.specialAttackCooldown = 300; // 5 segundos
} else {
self.specialAttackCooldown--;
}
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
pigeonGraphics.rotation = Math.atan2(dy, dx);
};
return self;
});
var CyberPigeon = Container.expand(function () {
var self = Container.call(this);
var pigeonGraphics = self.attachAsset('cyberPigeon', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 30 + wave * 5; // Más salud por wave
self.maxHealth = self.health;
self.speed = 1.5 + wave * 0.3; // Velocidad aumenta con wave
self.attackCooldown = 0;
self.type = Math.random() < 0.8 ? 'normal' : 'fast'; // 20% pigeons rápidos
// Pigeons especiales
if (self.type === 'fast') {
self.speed *= 2;
self.health *= 0.7;
pigeonGraphics.tint = 0xff6666; // Tinte rojo para los rápidos
}
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xff0000, 150);
// Efecto de sangre/daño
var damageText = new Text2('-' + damage, {
size: 40,
fill: 0xff0000
});
damageText.x = self.x;
damageText.y = self.y - 30;
game.addChild(damageText);
// Animar el texto de daño
tween(damageText, {
y: damageText.y - 60,
alpha: 0
}, {
duration: 800,
onComplete: function onComplete() {
damageText.destroy();
}
});
if (self.health <= 0) {
// Puntos variables según tipo
score += self.type === 'fast' ? 15 : 10;
var explosion = new Explosion();
explosion.x = self.x;
explosion.y = self.y;
game.addChild(explosion);
explosions.push(explosion);
LK.getSound('explosion').play();
// Chance de drop power-up al morir
if (Math.random() < 0.15) {
spawnPowerUpAt(self.x, self.y);
}
return true;
}
return false;
};
self.update = function () {
// Movimiento más inteligente
var dx = grandma.x - self.x;
var dy = grandma.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// Movimiento serpenteante para algunos pigeons
var wobble = self.type === 'fast' ? Math.sin(LK.ticks * 0.2) * 20 : 0;
self.x += dx / distance * self.speed + Math.sin(LK.ticks * 0.1) * 0.5;
self.y += dy / distance * self.speed + wobble * 0.1;
}
// Attack cooldown
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
// Rotación hacia grandma
pigeonGraphics.rotation = Math.atan2(dy, dx);
};
return self;
});
var Explosion = Container.expand(function () {
var self = Container.call(this);
var explosionGraphics = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5
});
self.lifeTime = 40;
self.radius = 90;
explosionGraphics.scaleX = 0.1;
explosionGraphics.scaleY = 0.1;
self.update = function () {
self.lifeTime--;
var progress = 1 - self.lifeTime / 40;
explosionGraphics.scaleX = 0.1 + progress * 2.5;
explosionGraphics.scaleY = 0.1 + progress * 2.5;
explosionGraphics.alpha = 1 - progress;
explosionGraphics.rotation += 0.2; // Rotación
return self.lifeTime <= 0;
};
return self;
});
var Grandma = Container.expand(function () {
var self = Container.call(this);
var grandmaGraphics = self.attachAsset('grandma', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.targetX = 1024;
self.targetY = 1366;
self.speed = 4;
self.caneDamage = 30;
self.caneRange = 120;
self.bombDamage = 50;
// Mejoras permanentes
self.speedBoost = 0;
self.damageBoost = 0;
self.rangeBoost = 0;
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xff0000, 300);
// Screen shake al recibir daño
game.x = (Math.random() - 0.5) * 20;
game.y = (Math.random() - 0.5) * 20;
setTimeout(function () {
game.x = 0;
game.y = 0;
}, 100);
if (self.health <= 0) {
LK.showGameOver();
}
};
self.update = function () {
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var currentSpeed = self.speed + self.speedBoost;
if (distance > 5) {
self.x += dx / distance * currentSpeed;
self.y += dy / distance * currentSpeed;
}
// Regeneración lenta de salud
if (self.health < self.maxHealth && LK.ticks % 600 === 0) {
// cada 10 segundos
self.health = Math.min(self.health + 1, self.maxHealth);
}
};
return self;
});
var KetchupBomb = Container.expand(function () {
var self = Container.call(this);
var bombGraphics = self.attachAsset('ketchupBomb', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.lifeTime = 100;
self.damage = grandma.bombDamage + grandma.damageBoost;
// Efecto de trail
self.trail = [];
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.lifeTime--;
// Rotación
bombGraphics.rotation += 0.3;
// Trail effect
self.trail.push({
x: self.x,
y: self.y,
alpha: 1
});
if (self.trail.length > 5) {
self.trail.shift();
}
if (self.lifeTime <= 0) {
var explosion = new Explosion();
explosion.x = self.x;
explosion.y = self.y;
game.addChild(explosion);
explosions.push(explosion);
LK.getSound('explosion').play();
return true;
}
return false;
};
return self;
});
var PowerUp = Container.expand(function () {
var self = Container.call(this);
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
var types = ['speed', 'health', 'damage', 'range', 'multishot'];
self.type = types[Math.floor(Math.random() * types.length)];
self.lifeTime = 900; // 15 segundos
// Color según tipo
switch (self.type) {
case 'speed':
powerUpGraphics.tint = 0x00ff00;
break;
case 'health':
powerUpGraphics.tint = 0xff0000;
break;
case 'damage':
powerUpGraphics.tint = 0xffaa00;
break;
case 'range':
powerUpGraphics.tint = 0x0088ff;
break;
case 'multishot':
powerUpGraphics.tint = 0xff00ff;
break;
}
self.update = function () {
self.lifeTime--;
// Animación flotante más dramática
self.y += Math.sin(LK.ticks * 0.15) * 1;
powerUpGraphics.rotation += 0.05;
powerUpGraphics.scaleX = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
powerUpGraphics.scaleY = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
// Parpadeo cuando está por expirar
if (self.lifeTime < 180) {
powerUpGraphics.alpha = Math.sin(LK.ticks * 0.3) * 0.5 + 0.5;
}
return self.lifeTime <= 0;
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb
});
/****
* Game Code
****/
/****
* Game Variables
****/
var grandma;
var cyberPigeons = [];
var ketchupBombs = [];
var explosions = [];
var powerUps = [];
var score = 0;
var wave = 1;
var enemiesKilled = 0;
var enemiesThisWave = 0;
var totalEnemiesThisWave = 0;
var lastClickTime = 0;
var comboCounter = 0;
var comboTimer = 0;
var difficulty = 1;
var bossWave = false;
/****
* UI Elements
****/
var scoreText = new Text2('Score: 0', {
size: 50,
fill: 0xFFFFFF,
stroke: 0x000000,
strokeThickness: 3
});
scoreText.x = 50;
scoreText.y = 50;
LK.gui.topLeft.addChild(scoreText);
var healthText = new Text2('Health: 100/100', {
size: 50,
fill: 0xFF0000,
stroke: 0x000000,
strokeThickness: 3
});
healthText.anchor.set(1, 0);
LK.gui.topRight.addChild(healthText);
var waveText = new Text2('Wave: 1', {
size: 50,
fill: 0xFFFF00,
stroke: 0x000000,
strokeThickness: 3
});
waveText.anchor.set(0.5, 0);
LK.gui.top.addChild(waveText);
var comboText = new Text2('', {
size: 60,
fill: 0x00FFFF,
stroke: 0x000000,
strokeThickness: 3
});
comboText.anchor.set(0.5, 0);
comboText.x = 1024;
comboText.y = 200;
game.addChild(comboText);
// Barra de progreso de wave
var waveProgressBg = LK.getAsset('chargeBarBg', {
anchorX: 0.5,
anchorY: 0,
scaleX: 1.5,
x: 0,
y: 60
});
LK.gui.top.addChild(waveProgressBg);
var waveProgressBar = LK.getAsset('chargeBar', {
anchorX: 0,
anchorY: 0,
scaleX: 0,
x: -150,
y: 60
});
LK.gui.top.addChild(waveProgressBar);
/****
* Game Functions
****/
function createGrandma() {
grandma = game.addChild(new Grandma());
grandma.x = 1024;
grandma.y = 1366;
}
function caneAttack() {
LK.getSound('attack').play();
LK.effects.flashObject(grandma, 0xffff00, 200);
var enemiesHit = 0;
var range = grandma.caneRange + grandma.rangeBoost;
var damage = grandma.caneDamage + grandma.damageBoost;
for (var i = cyberPigeons.length - 1; i >= 0; i--) {
var pigeon = cyberPigeons[i];
var dx = pigeon.x - grandma.x;
var dy = pigeon.y - grandma.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < range) {
if (pigeon.takeDamage(damage)) {
pigeon.destroy();
cyberPigeons.splice(i, 1);
enemiesKilled++;
enemiesThisWave++;
enemiesHit++;
}
}
}
// Sistema de combo
if (enemiesHit > 0) {
comboCounter += enemiesHit;
comboTimer = 180; // 3 segundos
if (comboCounter >= 3) {
score += comboCounter * 5; // Bonus por combo
}
}
}
function throwKetchupBomb(targetX, targetY) {
var bomb = new KetchupBomb();
bomb.x = grandma.x;
bomb.y = grandma.y;
var dx = targetX - grandma.x;
var dy = targetY - grandma.y;
var distance = Math.sqrt(dx * dx + dy * dy);
var speed = 10;
if (distance > 0) {
bomb.velocityX = dx / distance * speed;
bomb.velocityY = dy / distance * speed;
}
ketchupBombs.push(bomb);
game.addChild(bomb);
}
function spawnEnemies() {
bossWave = wave % 5 === 0; // Boss cada 5 waves
if (bossWave) {
// Spawn boss
var boss = new BossPigeon();
boss.x = 1024;
boss.y = -100;
cyberPigeons.push(boss);
game.addChild(boss);
totalEnemiesThisWave = 1;
} else {
// Enemigos normales
var enemiesToSpawn = Math.min(3 + wave, 12);
totalEnemiesThisWave = enemiesToSpawn;
for (var i = 0; i < enemiesToSpawn; i++) {
setTimeout(function () {
var pigeon = new CyberPigeon();
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
pigeon.x = Math.random() * 2048;
pigeon.y = -50;
break;
case 1:
// Right
pigeon.x = 2098;
pigeon.y = Math.random() * 2732;
break;
case 2:
// Bottom
pigeon.x = Math.random() * 2048;
pigeon.y = 2782;
break;
case 3:
// Left
pigeon.x = -50;
pigeon.y = Math.random() * 2732;
break;
}
cyberPigeons.push(pigeon);
game.addChild(pigeon);
}, i * 500); // Spawn escalonado
}
}
enemiesThisWave = 0;
}
function spawnPowerUpAt(x, y) {
var powerUp = new PowerUp();
powerUp.x = x;
powerUp.y = y;
powerUps.push(powerUp);
game.addChild(powerUp);
}
function collectPowerUp(powerUp) {
LK.getSound('powerup').play();
LK.effects.flashObject(grandma, 0x00ff00, 500);
var bonusText = new Text2('', {
size: 50,
fill: 0x00ff00
});
bonusText.x = grandma.x;
bonusText.y = grandma.y - 60;
game.addChild(bonusText);
switch (powerUp.type) {
case 'speed':
grandma.speedBoost += 1;
bonusText.setText('SPEED UP!');
break;
case 'health':
grandma.health = Math.min(grandma.health + 30, grandma.maxHealth);
bonusText.setText('HEALTH +30!');
break;
case 'damage':
grandma.damageBoost += 10;
bonusText.setText('DAMAGE UP!');
break;
case 'range':
grandma.rangeBoost += 20;
bonusText.setText('RANGE UP!');
break;
case 'multishot':
// Mejora temporal implementada en el ataque
bonusText.setText('MULTISHOT!');
break;
}
tween(bonusText, {
y: bonusText.y - 100,
alpha: 0
}, {
duration: 1500,
onComplete: function onComplete() {
bonusText.destroy();
}
});
}
/****
* Event Handlers
****/
game.move = function (x, y, obj) {
grandma.targetX = x;
grandma.targetY = y;
};
game.down = function (x, y, obj) {
var currentTime = LK.ticks;
var timeSinceLastClick = currentTime - lastClickTime;
if (timeSinceLastClick < 20) {
// Double click más sensible
throwKetchupBomb(x, y);
} else {
caneAttack();
}
lastClickTime = currentTime;
};
/****
* Game Loop
****/
createGrandma();
LK.playMusic('gameMusic');
spawnEnemies();
game.update = function () {
// Update combo timer
if (comboTimer > 0) {
comboTimer--;
if (comboCounter >= 3) {
comboText.setText('COMBO x' + comboCounter + '!');
} else {
comboText.setText('');
}
} else {
comboCounter = 0;
comboText.setText('');
}
// Update pigeons
for (var i = cyberPigeons.length - 1; i >= 0; i--) {
var pigeon = cyberPigeons[i];
pigeon.update();
// Collision with grandma
if (pigeon.intersects(grandma) && pigeon.attackCooldown <= 0) {
var damage = pigeon.isBoss ? 20 : 10;
grandma.takeDamage(damage);
pigeon.attackCooldown = 60;
}
// Remove if off screen
if (pigeon.x < -200 || pigeon.x > 2248 || pigeon.y < -200 || pigeon.y > 2932) {
pigeon.destroy();
cyberPigeons.splice(i, 1);
}
}
// Update ketchup bombs
for (var i = ketchupBombs.length - 1; i >= 0; i--) {
var bomb = ketchupBombs[i];
var shouldRemove = bomb.update();
if (shouldRemove || bomb.x < -100 || bomb.x > 2148 || bomb.y < -100 || bomb.y > 2832) {
bomb.destroy();
ketchupBombs.splice(i, 1);
} else {
// Check collision with enemies
for (var j = cyberPigeons.length - 1; j >= 0; j--) {
var pigeon = cyberPigeons[j];
if (bomb.intersects(pigeon)) {
if (pigeon.takeDamage(bomb.damage)) {
pigeon.destroy();
cyberPigeons.splice(j, 1);
enemiesKilled++;
enemiesThisWave++;
}
bomb.destroy();
ketchupBombs.splice(i, 1);
break;
}
}
}
}
// Update explosions
for (var i = explosions.length - 1; i >= 0; i--) {
var explosion = explosions[i];
var shouldRemove = explosion.update();
if (shouldRemove) {
explosion.destroy();
explosions.splice(i, 1);
} else {
// Explosion damage
for (var j = cyberPigeons.length - 1; j >= 0; j--) {
var pigeon = cyberPigeons[j];
var dx = pigeon.x - explosion.x;
var dy = pigeon.y - explosion.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < explosion.radius) {
var damage = 40 + grandma.damageBoost;
if (pigeon.takeDamage(damage)) {
pigeon.destroy();
cyberPigeons.splice(j, 1);
enemiesKilled++;
enemiesThisWave++;
}
}
}
}
}
// Update power-ups
for (var i = powerUps.length - 1; i >= 0; i--) {
var powerUp = powerUps[i];
var shouldRemove = powerUp.update();
if (shouldRemove) {
powerUp.destroy();
powerUps.splice(i, 1);
} else if (powerUp.intersects(grandma)) {
collectPowerUp(powerUp);
powerUp.destroy();
powerUps.splice(i, 1);
}
}
// Wave management
if (cyberPigeons.length === 0) {
wave++;
spawnEnemies();
// Chance de power-up al completar wave
if (Math.random() < 0.4) {
spawnPowerUpAt(Math.random() * 1600 + 200, Math.random() * 2200 + 200);
}
}
// Update UI
scoreText.setText('Score: ' + score);
healthText.setText('Health: ' + grandma.health + '/' + grandma.maxHealth);
waveText.setText('Wave: ' + wave + (bossWave ? ' (BOSS)' : ''));
// Wave progress bar
var progress = totalEnemiesThisWave > 0 ? enemiesThisWave / totalEnemiesThisWave : 0;
waveProgressBar.scaleX = progress * 1.5;
// Update LK score
LK.setScore(score);
// Victory condition
if (wave > 20) {
LK.showYouWin();
}
}; ===================================================================
--- original.js
+++ change.js
@@ -5,47 +5,172 @@
/****
* Classes
****/
+var BossPigeon = Container.expand(function () {
+ var self = Container.call(this);
+ var pigeonGraphics = self.attachAsset('cyberPigeon', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Boss más grande y diferente color
+ pigeonGraphics.scaleX = 2;
+ pigeonGraphics.scaleY = 2;
+ pigeonGraphics.tint = 0x8000ff; // Púrpura
+ self.health = 100 + wave * 20;
+ self.maxHealth = self.health;
+ self.speed = 1;
+ self.attackCooldown = 0;
+ self.specialAttackCooldown = 0;
+ self.isBoss = true;
+ self.takeDamage = function (damage) {
+ self.health -= damage;
+ LK.effects.flashObject(self, 0xff0000, 200);
+ // Texto de daño más grande para boss
+ var damageText = new Text2('-' + damage, {
+ size: 60,
+ fill: 0xffff00
+ });
+ damageText.x = self.x;
+ damageText.y = self.y - 50;
+ game.addChild(damageText);
+ tween(damageText, {
+ y: damageText.y - 80,
+ alpha: 0
+ }, {
+ duration: 1000,
+ onComplete: function onComplete() {
+ damageText.destroy();
+ }
+ });
+ if (self.health <= 0) {
+ score += 100;
+ // Explosión más grande
+ for (var i = 0; i < 3; i++) {
+ setTimeout(function () {
+ var explosion = new Explosion();
+ explosion.x = self.x + (Math.random() - 0.5) * 100;
+ explosion.y = self.y + (Math.random() - 0.5) * 100;
+ game.addChild(explosion);
+ explosions.push(explosion);
+ LK.getSound('explosion').play();
+ }, i * 200);
+ }
+ // Drop garantizado de power-ups
+ for (var i = 0; i < 3; i++) {
+ spawnPowerUpAt(self.x + (Math.random() - 0.5) * 150, self.y + (Math.random() - 0.5) * 150);
+ }
+ return true;
+ }
+ return false;
+ };
+ self.update = function () {
+ // Movimiento del boss
+ var dx = grandma.x - self.x;
+ var dy = grandma.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance > 200) {
+ self.x += dx / distance * self.speed;
+ self.y += dy / distance * self.speed;
+ } else {
+ // Círculo alrededor de grandma
+ self.x += Math.cos(LK.ticks * 0.05) * 2;
+ self.y += Math.sin(LK.ticks * 0.05) * 2;
+ }
+ // Ataque especial cada 5 segundos
+ if (self.specialAttackCooldown <= 0) {
+ // Spawn mini pigeons
+ for (var i = 0; i < 3; i++) {
+ var miniPigeon = new CyberPigeon();
+ miniPigeon.x = self.x + (Math.random() - 0.5) * 100;
+ miniPigeon.y = self.y + (Math.random() - 0.5) * 100;
+ miniPigeon.health = 15;
+ cyberPigeons.push(miniPigeon);
+ game.addChild(miniPigeon);
+ }
+ self.specialAttackCooldown = 300; // 5 segundos
+ } else {
+ self.specialAttackCooldown--;
+ }
+ if (self.attackCooldown > 0) {
+ self.attackCooldown--;
+ }
+ pigeonGraphics.rotation = Math.atan2(dy, dx);
+ };
+ return self;
+});
var CyberPigeon = Container.expand(function () {
var self = Container.call(this);
var pigeonGraphics = self.attachAsset('cyberPigeon', {
anchorX: 0.5,
anchorY: 0.5
});
- self.health = 20;
- self.speed = 2;
+ self.health = 30 + wave * 5; // Más salud por wave
+ self.maxHealth = self.health;
+ self.speed = 1.5 + wave * 0.3; // Velocidad aumenta con wave
self.attackCooldown = 0;
- self.lastX = self.x;
- self.lastY = self.y;
+ self.type = Math.random() < 0.8 ? 'normal' : 'fast'; // 20% pigeons rápidos
+ // Pigeons especiales
+ if (self.type === 'fast') {
+ self.speed *= 2;
+ self.health *= 0.7;
+ pigeonGraphics.tint = 0xff6666; // Tinte rojo para los rápidos
+ }
self.takeDamage = function (damage) {
self.health -= damage;
- LK.effects.flashObject(self, 0xff0000, 100);
+ LK.effects.flashObject(self, 0xff0000, 150);
+ // Efecto de sangre/daño
+ var damageText = new Text2('-' + damage, {
+ size: 40,
+ fill: 0xff0000
+ });
+ damageText.x = self.x;
+ damageText.y = self.y - 30;
+ game.addChild(damageText);
+ // Animar el texto de daño
+ tween(damageText, {
+ y: damageText.y - 60,
+ alpha: 0
+ }, {
+ duration: 800,
+ onComplete: function onComplete() {
+ damageText.destroy();
+ }
+ });
if (self.health <= 0) {
- score += 10;
+ // Puntos variables según tipo
+ score += self.type === 'fast' ? 15 : 10;
var explosion = new Explosion();
explosion.x = self.x;
explosion.y = self.y;
game.addChild(explosion);
explosions.push(explosion);
LK.getSound('explosion').play();
+ // Chance de drop power-up al morir
+ if (Math.random() < 0.15) {
+ spawnPowerUpAt(self.x, self.y);
+ }
return true;
}
return false;
};
self.update = function () {
- // Move towards grandma
+ // Movimiento más inteligente
var dx = grandma.x - self.x;
var dy = grandma.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;
+ // Movimiento serpenteante para algunos pigeons
+ var wobble = self.type === 'fast' ? Math.sin(LK.ticks * 0.2) * 20 : 0;
+ self.x += dx / distance * self.speed + Math.sin(LK.ticks * 0.1) * 0.5;
+ self.y += dy / distance * self.speed + wobble * 0.1;
}
// Attack cooldown
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
+ // Rotación hacia grandma
+ pigeonGraphics.rotation = Math.atan2(dy, dx);
};
return self;
});
var Explosion = Container.expand(function () {
@@ -53,20 +178,19 @@
var explosionGraphics = self.attachAsset('explosion', {
anchorX: 0.5,
anchorY: 0.5
});
- self.lifeTime = 30; // 0.5 seconds
- self.radius = 80;
- // Start small and grow
+ self.lifeTime = 40;
+ self.radius = 90;
explosionGraphics.scaleX = 0.1;
explosionGraphics.scaleY = 0.1;
self.update = function () {
self.lifeTime--;
- // Grow and fade
- var progress = 1 - self.lifeTime / 30;
- explosionGraphics.scaleX = 0.1 + progress * 2;
- explosionGraphics.scaleY = 0.1 + progress * 2;
+ var progress = 1 - self.lifeTime / 40;
+ explosionGraphics.scaleX = 0.1 + progress * 2.5;
+ explosionGraphics.scaleY = 0.1 + progress * 2.5;
explosionGraphics.alpha = 1 - progress;
+ explosionGraphics.rotation += 0.2; // Rotación
return self.lifeTime <= 0;
};
return self;
});
@@ -76,35 +200,46 @@
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
- self.chargeLevel = 0;
- self.maxCharge = 100;
- self.isCharging = false;
- self.lastClickTime = 0;
+ self.maxHealth = 100;
self.targetX = 1024;
self.targetY = 1366;
- self.speed = 3;
+ self.speed = 4;
+ self.caneDamage = 30;
+ self.caneRange = 120;
+ self.bombDamage = 50;
+ // Mejoras permanentes
+ self.speedBoost = 0;
+ self.damageBoost = 0;
+ self.rangeBoost = 0;
self.takeDamage = function (damage) {
self.health -= damage;
- LK.effects.flashObject(self, 0xff0000, 200);
+ LK.effects.flashObject(self, 0xff0000, 300);
+ // Screen shake al recibir daño
+ game.x = (Math.random() - 0.5) * 20;
+ game.y = (Math.random() - 0.5) * 20;
+ setTimeout(function () {
+ game.x = 0;
+ game.y = 0;
+ }, 100);
if (self.health <= 0) {
LK.showGameOver();
}
};
self.update = function () {
- // Move towards target position smoothly
var dx = self.targetX - self.x;
var dy = self.targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
+ var currentSpeed = self.speed + self.speedBoost;
if (distance > 5) {
- self.x += dx / distance * self.speed;
- self.y += dy / distance * self.speed;
+ self.x += dx / distance * currentSpeed;
+ self.y += dy / distance * currentSpeed;
}
- // Charge meter decay
- if (!self.isCharging && self.chargeLevel > 0) {
- self.chargeLevel -= 2;
- if (self.chargeLevel < 0) self.chargeLevel = 0;
+ // Regeneración lenta de salud
+ if (self.health < self.maxHealth && LK.ticks % 600 === 0) {
+ // cada 10 segundos
+ self.health = Math.min(self.health + 1, self.maxHealth);
}
};
return self;
});
@@ -115,15 +250,28 @@
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
- self.lifeTime = 120; // 2 seconds at 60fps
+ self.lifeTime = 100;
+ self.damage = grandma.bombDamage + grandma.damageBoost;
+ // Efecto de trail
+ self.trail = [];
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
self.lifeTime--;
+ // Rotación
+ bombGraphics.rotation += 0.3;
+ // Trail effect
+ self.trail.push({
+ x: self.x,
+ y: self.y,
+ alpha: 1
+ });
+ if (self.trail.length > 5) {
+ self.trail.shift();
+ }
if (self.lifeTime <= 0) {
- // Explode
var explosion = new Explosion();
explosion.x = self.x;
explosion.y = self.y;
game.addChild(explosion);
@@ -140,14 +288,40 @@
var powerUpGraphics = self.attachAsset('powerUp', {
anchorX: 0.5,
anchorY: 0.5
});
- self.type = 'speed'; // 'speed', 'health', 'damage'
- self.lifeTime = 600; // 10 seconds
+ var types = ['speed', 'health', 'damage', 'range', 'multishot'];
+ self.type = types[Math.floor(Math.random() * types.length)];
+ self.lifeTime = 900; // 15 segundos
+ // Color según tipo
+ switch (self.type) {
+ case 'speed':
+ powerUpGraphics.tint = 0x00ff00;
+ break;
+ case 'health':
+ powerUpGraphics.tint = 0xff0000;
+ break;
+ case 'damage':
+ powerUpGraphics.tint = 0xffaa00;
+ break;
+ case 'range':
+ powerUpGraphics.tint = 0x0088ff;
+ break;
+ case 'multishot':
+ powerUpGraphics.tint = 0xff00ff;
+ break;
+ }
self.update = function () {
self.lifeTime--;
- // Gentle floating animation
- self.y += Math.sin(LK.ticks * 0.1) * 0.5;
+ // Animación flotante más dramática
+ self.y += Math.sin(LK.ticks * 0.15) * 1;
+ powerUpGraphics.rotation += 0.05;
+ powerUpGraphics.scaleX = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
+ powerUpGraphics.scaleY = 1 + Math.sin(LK.ticks * 0.1) * 0.2;
+ // Parpadeo cuando está por expirar
+ if (self.lifeTime < 180) {
+ powerUpGraphics.alpha = Math.sin(LK.ticks * 0.3) * 0.5 + 0.5;
+ }
return self.lifeTime <= 0;
};
return self;
});
@@ -161,217 +335,300 @@
/****
* Game Code
****/
-// Game variables
+/****
+* Game Variables
+****/
var grandma;
var cyberPigeons = [];
var ketchupBombs = [];
var explosions = [];
var powerUps = [];
var score = 0;
var wave = 1;
var enemiesKilled = 0;
+var enemiesThisWave = 0;
+var totalEnemiesThisWave = 0;
var lastClickTime = 0;
-var isMouseDown = false;
-var chargeStartTime = 0;
-// UI Elements
+var comboCounter = 0;
+var comboTimer = 0;
+var difficulty = 1;
+var bossWave = false;
+/****
+* UI Elements
+****/
var scoreText = new Text2('Score: 0', {
- size: 60,
- fill: 0xFFFFFF
+ size: 50,
+ fill: 0xFFFFFF,
+ stroke: 0x000000,
+ strokeThickness: 3
});
-scoreText.anchor.set(0, 0);
-scoreText.x = 150;
+scoreText.x = 50;
scoreText.y = 50;
LK.gui.topLeft.addChild(scoreText);
-var healthText = new Text2('Health: 100', {
- size: 60,
- fill: 0xFF0000
+var healthText = new Text2('Health: 100/100', {
+ size: 50,
+ fill: 0xFF0000,
+ stroke: 0x000000,
+ strokeThickness: 3
});
healthText.anchor.set(1, 0);
LK.gui.topRight.addChild(healthText);
var waveText = new Text2('Wave: 1', {
- size: 60,
- fill: 0xFFFF00
+ size: 50,
+ fill: 0xFFFF00,
+ stroke: 0x000000,
+ strokeThickness: 3
});
waveText.anchor.set(0.5, 0);
LK.gui.top.addChild(waveText);
-// Create grandma
-grandma = game.addChild(new Grandma());
-grandma.x = 1024;
-grandma.y = 1366;
-// Mouse event handlers
-game.move = function (x, y, obj) {
- grandma.targetX = x;
- grandma.targetY = y;
- // Charge turbo if mouse is held down
- if (isMouseDown) {
- var chargeTime = LK.ticks - chargeStartTime;
- grandma.chargeLevel = Math.min(chargeTime * 2, grandma.maxCharge);
- grandma.isCharging = true;
- }
-};
-game.down = function (x, y, obj) {
- var currentTime = LK.ticks;
- var timeSinceLastClick = currentTime - lastClickTime;
- // Double click detection (within 30 frames / 0.5 seconds)
- if (timeSinceLastClick < 30) {
- // Double click - throw ketchup bomb
- throwKetchupBomb(x, y);
- } else {
- // Single click - cane attack
- caneAttack();
- }
- lastClickTime = currentTime;
- isMouseDown = true;
- chargeStartTime = currentTime;
- grandma.isCharging = true;
-};
-game.up = function (x, y, obj) {
- isMouseDown = false;
- grandma.isCharging = false;
- // Use charged turbo boost
- if (grandma.chargeLevel > 30) {
- turboBoost(x, y);
- grandma.chargeLevel = 0;
- }
-};
+var comboText = new Text2('', {
+ size: 60,
+ fill: 0x00FFFF,
+ stroke: 0x000000,
+ strokeThickness: 3
+});
+comboText.anchor.set(0.5, 0);
+comboText.x = 1024;
+comboText.y = 200;
+game.addChild(comboText);
+// Barra de progreso de wave
+var waveProgressBg = LK.getAsset('chargeBarBg', {
+ anchorX: 0.5,
+ anchorY: 0,
+ scaleX: 1.5,
+ x: 0,
+ y: 60
+});
+LK.gui.top.addChild(waveProgressBg);
+var waveProgressBar = LK.getAsset('chargeBar', {
+ anchorX: 0,
+ anchorY: 0,
+ scaleX: 0,
+ x: -150,
+ y: 60
+});
+LK.gui.top.addChild(waveProgressBar);
+/****
+* Game Functions
+****/
+function createGrandma() {
+ grandma = game.addChild(new Grandma());
+ grandma.x = 1024;
+ grandma.y = 1366;
+}
function caneAttack() {
LK.getSound('attack').play();
LK.effects.flashObject(grandma, 0xffff00, 200);
- // Check for enemies in range
+ var enemiesHit = 0;
+ var range = grandma.caneRange + grandma.rangeBoost;
+ var damage = grandma.caneDamage + grandma.damageBoost;
for (var i = cyberPigeons.length - 1; i >= 0; i--) {
var pigeon = cyberPigeons[i];
var dx = pigeon.x - grandma.x;
var dy = pigeon.y - grandma.y;
var distance = Math.sqrt(dx * dx + dy * dy);
- if (distance < 100) {
- if (pigeon.takeDamage(25)) {
+ if (distance < range) {
+ if (pigeon.takeDamage(damage)) {
pigeon.destroy();
cyberPigeons.splice(i, 1);
enemiesKilled++;
+ enemiesThisWave++;
+ enemiesHit++;
}
}
}
+ // Sistema de combo
+ if (enemiesHit > 0) {
+ comboCounter += enemiesHit;
+ comboTimer = 180; // 3 segundos
+ if (comboCounter >= 3) {
+ score += comboCounter * 5; // Bonus por combo
+ }
+ }
}
function throwKetchupBomb(targetX, targetY) {
var bomb = new KetchupBomb();
bomb.x = grandma.x;
bomb.y = grandma.y;
- // Calculate velocity towards target
var dx = targetX - grandma.x;
var dy = targetY - grandma.y;
var distance = Math.sqrt(dx * dx + dy * dy);
- var speed = 8;
+ var speed = 10;
if (distance > 0) {
bomb.velocityX = dx / distance * speed;
bomb.velocityY = dy / distance * speed;
}
ketchupBombs.push(bomb);
game.addChild(bomb);
}
-function turboBoost(targetX, targetY) {
- // Quick dash towards target
- var dx = targetX - grandma.x;
- var dy = targetY - grandma.y;
- var distance = Math.sqrt(dx * dx + dy * dy);
- if (distance > 0) {
- var dashDistance = Math.min(distance, 200);
- var newX = grandma.x + dx / distance * dashDistance;
- var newY = grandma.y + dy / distance * dashDistance;
- // Keep within bounds
- newX = Math.max(60, Math.min(1988, newX));
- newY = Math.max(60, Math.min(2672, newY));
- tween(grandma, {
- x: newX,
- y: newY
- }, {
- duration: 200,
- easing: tween.easeOut
- });
- LK.effects.flashObject(grandma, 0x00ff00, 300);
- }
-}
function spawnEnemies() {
- var enemiesToSpawn = Math.min(wave + 2, 8);
- for (var i = 0; i < enemiesToSpawn; i++) {
- var pigeon = new CyberPigeon();
- // Spawn from edges
- var side = Math.floor(Math.random() * 4);
- switch (side) {
- case 0:
- // Top
- pigeon.x = Math.random() * 2048;
- pigeon.y = -50;
- break;
- case 1:
- // Right
- pigeon.x = 2098;
- pigeon.y = Math.random() * 2732;
- break;
- case 2:
- // Bottom
- pigeon.x = Math.random() * 2048;
- pigeon.y = 2782;
- break;
- case 3:
- // Left
- pigeon.x = -50;
- pigeon.y = Math.random() * 2732;
- break;
+ bossWave = wave % 5 === 0; // Boss cada 5 waves
+ if (bossWave) {
+ // Spawn boss
+ var boss = new BossPigeon();
+ boss.x = 1024;
+ boss.y = -100;
+ cyberPigeons.push(boss);
+ game.addChild(boss);
+ totalEnemiesThisWave = 1;
+ } else {
+ // Enemigos normales
+ var enemiesToSpawn = Math.min(3 + wave, 12);
+ totalEnemiesThisWave = enemiesToSpawn;
+ for (var i = 0; i < enemiesToSpawn; i++) {
+ setTimeout(function () {
+ var pigeon = new CyberPigeon();
+ var side = Math.floor(Math.random() * 4);
+ switch (side) {
+ case 0:
+ // Top
+ pigeon.x = Math.random() * 2048;
+ pigeon.y = -50;
+ break;
+ case 1:
+ // Right
+ pigeon.x = 2098;
+ pigeon.y = Math.random() * 2732;
+ break;
+ case 2:
+ // Bottom
+ pigeon.x = Math.random() * 2048;
+ pigeon.y = 2782;
+ break;
+ case 3:
+ // Left
+ pigeon.x = -50;
+ pigeon.y = Math.random() * 2732;
+ break;
+ }
+ cyberPigeons.push(pigeon);
+ game.addChild(pigeon);
+ }, i * 500); // Spawn escalonado
}
- cyberPigeons.push(pigeon);
- game.addChild(pigeon);
}
+ enemiesThisWave = 0;
}
-function spawnPowerUp() {
- if (Math.random() < 0.3) {
- var powerUp = new PowerUp();
- powerUp.x = Math.random() * (2048 - 120) + 60;
- powerUp.y = Math.random() * (2732 - 120) + 60;
- var types = ['speed', 'health', 'damage'];
- powerUp.type = types[Math.floor(Math.random() * types.length)];
- powerUps.push(powerUp);
- game.addChild(powerUp);
+function spawnPowerUpAt(x, y) {
+ var powerUp = new PowerUp();
+ powerUp.x = x;
+ powerUp.y = y;
+ powerUps.push(powerUp);
+ game.addChild(powerUp);
+}
+function collectPowerUp(powerUp) {
+ LK.getSound('powerup').play();
+ LK.effects.flashObject(grandma, 0x00ff00, 500);
+ var bonusText = new Text2('', {
+ size: 50,
+ fill: 0x00ff00
+ });
+ bonusText.x = grandma.x;
+ bonusText.y = grandma.y - 60;
+ game.addChild(bonusText);
+ switch (powerUp.type) {
+ case 'speed':
+ grandma.speedBoost += 1;
+ bonusText.setText('SPEED UP!');
+ break;
+ case 'health':
+ grandma.health = Math.min(grandma.health + 30, grandma.maxHealth);
+ bonusText.setText('HEALTH +30!');
+ break;
+ case 'damage':
+ grandma.damageBoost += 10;
+ bonusText.setText('DAMAGE UP!');
+ break;
+ case 'range':
+ grandma.rangeBoost += 20;
+ bonusText.setText('RANGE UP!');
+ break;
+ case 'multishot':
+ // Mejora temporal implementada en el ataque
+ bonusText.setText('MULTISHOT!');
+ break;
}
+ tween(bonusText, {
+ y: bonusText.y - 100,
+ alpha: 0
+ }, {
+ duration: 1500,
+ onComplete: function onComplete() {
+ bonusText.destroy();
+ }
+ });
}
-// Start music
+/****
+* Event Handlers
+****/
+game.move = function (x, y, obj) {
+ grandma.targetX = x;
+ grandma.targetY = y;
+};
+game.down = function (x, y, obj) {
+ var currentTime = LK.ticks;
+ var timeSinceLastClick = currentTime - lastClickTime;
+ if (timeSinceLastClick < 20) {
+ // Double click más sensible
+ throwKetchupBomb(x, y);
+ } else {
+ caneAttack();
+ }
+ lastClickTime = currentTime;
+};
+/****
+* Game Loop
+****/
+createGrandma();
LK.playMusic('gameMusic');
-// Spawn initial enemies
spawnEnemies();
game.update = function () {
- // Update all objects
+ // Update combo timer
+ if (comboTimer > 0) {
+ comboTimer--;
+ if (comboCounter >= 3) {
+ comboText.setText('COMBO x' + comboCounter + '!');
+ } else {
+ comboText.setText('');
+ }
+ } else {
+ comboCounter = 0;
+ comboText.setText('');
+ }
+ // Update pigeons
for (var i = cyberPigeons.length - 1; i >= 0; i--) {
var pigeon = cyberPigeons[i];
- pigeon.lastX = pigeon.x;
- pigeon.lastY = pigeon.y;
- // Check collision with grandma
+ pigeon.update();
+ // Collision with grandma
if (pigeon.intersects(grandma) && pigeon.attackCooldown <= 0) {
- grandma.takeDamage(10);
- pigeon.attackCooldown = 60; // 1 second cooldown
+ var damage = pigeon.isBoss ? 20 : 10;
+ grandma.takeDamage(damage);
+ pigeon.attackCooldown = 60;
}
// Remove if off screen
- if (pigeon.x < -100 || pigeon.x > 2148 || pigeon.y < -100 || pigeon.y > 2832) {
+ if (pigeon.x < -200 || pigeon.x > 2248 || pigeon.y < -200 || pigeon.y > 2932) {
pigeon.destroy();
cyberPigeons.splice(i, 1);
}
}
// Update ketchup bombs
for (var i = ketchupBombs.length - 1; i >= 0; i--) {
var bomb = ketchupBombs[i];
var shouldRemove = bomb.update();
- if (shouldRemove || bomb.x < -50 || bomb.x > 2098 || bomb.y < -50 || bomb.y > 2782) {
+ if (shouldRemove || bomb.x < -100 || bomb.x > 2148 || bomb.y < -100 || bomb.y > 2832) {
bomb.destroy();
ketchupBombs.splice(i, 1);
} else {
// Check collision with enemies
for (var j = cyberPigeons.length - 1; j >= 0; j--) {
var pigeon = cyberPigeons[j];
if (bomb.intersects(pigeon)) {
- if (pigeon.takeDamage(40)) {
+ if (pigeon.takeDamage(bomb.damage)) {
pigeon.destroy();
cyberPigeons.splice(j, 1);
enemiesKilled++;
+ enemiesThisWave++;
}
bomb.destroy();
ketchupBombs.splice(i, 1);
break;
@@ -386,19 +643,21 @@
if (shouldRemove) {
explosion.destroy();
explosions.splice(i, 1);
} else {
- // Explosion damage to enemies
+ // Explosion damage
for (var j = cyberPigeons.length - 1; j >= 0; j--) {
var pigeon = cyberPigeons[j];
var dx = pigeon.x - explosion.x;
var dy = pigeon.y - explosion.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < explosion.radius) {
- if (pigeon.takeDamage(30)) {
+ var damage = 40 + grandma.damageBoost;
+ if (pigeon.takeDamage(damage)) {
pigeon.destroy();
cyberPigeons.splice(j, 1);
enemiesKilled++;
+ enemiesThisWave++;
}
}
}
}
@@ -410,39 +669,32 @@
if (shouldRemove) {
powerUp.destroy();
powerUps.splice(i, 1);
} else if (powerUp.intersects(grandma)) {
- // Collect power-up
- LK.getSound('powerup').play();
- LK.effects.flashObject(grandma, 0x00ff00, 500);
- switch (powerUp.type) {
- case 'speed':
- grandma.speed = Math.min(grandma.speed + 1, 8);
- break;
- case 'health':
- grandma.health = Math.min(grandma.health + 25, 100);
- break;
- case 'damage':
- // Temporary damage boost (not implemented in this basic version)
- break;
- }
+ collectPowerUp(powerUp);
powerUp.destroy();
powerUps.splice(i, 1);
}
}
// Wave management
if (cyberPigeons.length === 0) {
wave++;
spawnEnemies();
- spawnPowerUp();
+ // Chance de power-up al completar wave
+ if (Math.random() < 0.4) {
+ spawnPowerUpAt(Math.random() * 1600 + 200, Math.random() * 2200 + 200);
+ }
}
// Update UI
scoreText.setText('Score: ' + score);
- healthText.setText('Health: ' + grandma.health);
- waveText.setText('Wave: ' + wave);
- // Check win condition
- if (wave > 10) {
- LK.showYouWin();
- }
+ healthText.setText('Health: ' + grandma.health + '/' + grandma.maxHealth);
+ waveText.setText('Wave: ' + wave + (bossWave ? ' (BOSS)' : ''));
+ // Wave progress bar
+ var progress = totalEnemiesThisWave > 0 ? enemiesThisWave / totalEnemiesThisWave : 0;
+ waveProgressBar.scaleX = progress * 1.5;
// Update LK score
LK.setScore(score);
+ // Victory condition
+ if (wave > 20) {
+ LK.showYouWin();
+ }
};
\ No newline at end of file
Pixel art sprite of a fierce old lady wearing sunglasses and a scarf, riding a rocket-powered shopping cart. She’s holding a glowing cane like a weapon. Side view, colorful retro 2D style. PNG. In-Game asset. 2d. High contrast. No shadows
Pixel art of an evil pigeon with robotic parts, red glowing eyes, and tiny armor. Flying pose, side view, 2D pixel sprite for an arcade game. In-Game asset. 2d. High contrast. No shadows
Pixel art of a red ketchup bottle turned into a bomb, with a fuse and tomato sauce leaking out. Small item, cartoonish and fun, pixel style. In-Game asset. 2d. High contrast. No shadows
pixel art dog. In-Game asset. 2d. High contrast. No shadows
explosion. In-Game asset. 2d. High contrast. No shadows
background pixel art cielo azul. In-Game asset. 2d. High contrast. No shadows
Pixel art of a smaller robotic pigeon with jet wings and a streamlined shape. Fast enemy type in a 2D arcade game. Side view, green metal feathers. In-Game asset. 2d. High contrast. No shadows
Pixel art of a purple power-up icon with a spiked fist symbol or explosion inside. Represents bonus attack damage in a retro game. In-Game asset. 2d. High contrast. No shadows
Pixel art of a dark purple robotic pigeon spinning in midair, wings blurred in motion. Enemy type in a 2D arcade game, side view. In-Game asset. 2d. High contrast. No shadows
Pixel art of a green power-up icon with a heart or medical cross symbol inside. Represents healing in a 2D pixel arcade game. Glowing green, square icon. In-Game asset. 2d. High contrast. No shadows
Pixel art of a red power-up icon with a bold lightning bolt symbol inside. Represents a temporary speed boost in a retro-style arcade game. Glowing red, square icon. In-Game asset. 2d. High contrast. No shadows
Pixel art of a violet power-up icon with three small arrows or projectiles spreading outward. Represents multishot power in a retro-style game. Glowing, pixelated square icon. In-Game asset. 2d. High contrast. No shadows