User prompt
Has que el strong zombie sea aun mas grande
User prompt
Has que el strong zombie tenga mas vida y aga más daño a las plantas, has que sea más grande
User prompt
Añade el Sprite para ponerle otro sprite al strong zombie
User prompt
Añade un zombie normal extra , con más vida un poco más rápido que no sea especial que aparezca al principio y al final que sea igual que el normal zombie pero con más vida
User prompt
Elimina el super zombie
User prompt
Has que ese zombie aparezca al principio y no de ningún punto
User prompt
Añade un zombie extra que tenga mas vida que el normal
User prompt
Has que el tank zombie tenga 777 de vida
User prompt
Has que los puntos digan girasoles en vez de puntos
User prompt
Has que el burstpeashooter haga 8 de daño por bola
User prompt
Arregla ese error visual del burstpeashooter que está rojo
User prompt
Has que el burstpeashooter no tenga animación
User prompt
Has que el triple lanza guisantes no sea rojo
User prompt
Hasme una fusion con el doble lanza guisante y otro lanza guisantes que dispare una ráfaga de 15 bolas que agan 5 de daño cada una y tengan un coldawn de 3.9 segundos
User prompt
Has que la triple girasol tenga un nuevo Sprite y no desaparezca
User prompt
Has que el girasol y el doble girasol se puedan fusionar y den 35 puntos
User prompt
Has que cuando cambie de idiomas los botones de pongan en ingles ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Has que la musica suene 7.5 segundos después de iniciar el juego osea después de darle a jugar ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
No funcionó
User prompt
Has que cuando se reproduzca el sonido de ingles o español la música se detenga y luego vuelva a sonar despues de 6.6 segundos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Has que en la opción de idiomas este el idioma ingles y español, cuando le des a jugar suene un sonido si le diste a inglés 1 y si le diste a español 2 ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Has un menú principal que diga idiomas, jugar, ajustes
User prompt
Has que los proyectiles explosivos tengan un área de daño ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Has que los proyectiles explosivos hagan 25 de daño
User prompt
Has que cuando fuisiones la papapum y el lanza guisantes tenga un nuevo Sprite , y que no tenga coldawn de explosion el proyectil ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var ExplosiveProjectile = Container.expand(function (startX, startY, target, damage) {
var self = Container.call(this);
self.graphics = self.attachAsset('pea', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF4444,
scaleX: 1.3,
scaleY: 1.3
});
self.x = startX;
self.y = startY;
self.target = target;
self.damage = 25;
self.speed = 8;
self.explosionRadius = 150;
// Shoot straight horizontally to the right
self.dirX = 1;
self.dirY = 0;
self.update = function () {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
// Pulsing red animation while flying
if (LK.ticks % 8 === 0) {
tween(self.graphics, {
tint: 0xFF0000
}, {
duration: 80
});
tween(self.graphics, {
tint: 0xFF4444
}, {
duration: 80
});
}
// Check collision with any zombie
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
if (Math.abs(zombie.x - self.x) < 30 && Math.abs(zombie.y - self.y) < 30) {
// Create explosion visual effect
tween(self.graphics, {
tint: 0xFFFFFF,
scaleX: 4,
scaleY: 4,
alpha: 0.7
}, {
duration: 300
});
// Immediate explosion - damage all zombies in radius
for (var j = zombies.length - 1; j >= 0; j--) {
var targetZombie = zombies[j];
var dx = targetZombie.x - self.x;
var dy = targetZombie.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.explosionRadius) {
targetZombie.takeDamage(self.damage);
}
}
LK.getSound('explosion').play();
self.destroy();
projectiles.splice(projectiles.indexOf(self), 1);
return;
}
}
// Remove if off-screen
if (self.x > 2100 || self.x < -50 || self.y > 2800 || self.y < -50) {
self.destroy();
projectiles.splice(projectiles.indexOf(self), 1);
}
};
self.explode = function () {
// Explosion animation
tween(self.graphics, {
tint: 0xFF0000,
scaleX: 4,
scaleY: 4
}, {
duration: 200,
onFinish: function onFinish() {
// Damage all zombies in explosion radius
for (var i = zombies.length - 1; i >= 0; i--) {
var zombie = zombies[i];
var dx = zombie.x - self.x;
var dy = zombie.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.explosionRadius) {
zombie.takeDamage(self.damage);
}
}
LK.getSound('explosion').play();
self.destroy();
projectiles.splice(projectiles.indexOf(self), 1);
}
});
};
return self;
});
var Plant = Container.expand(function (type) {
var self = Container.call(this);
self.type = type;
self.health = 100;
self.maxHealth = 100;
self.shootTimer = 0;
self.shootCooldown = 60; // 1 second at 60fps
if (type === 'peashooter') {
self.graphics = self.attachAsset('peashooter', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 25;
self.range = 400;
self.shootCooldown = 228; // 3.8 seconds at 60fps (3.8 * 60 = 228)
} else if (type === 'doublepeashooter') {
self.graphics = self.attachAsset('doublepeashooter', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 50;
self.range = 400;
self.shootCooldown = 210; // Total cycle time: 3.5 seconds (3.5 * 60 = 210)
self.firstShotTime = 60; // First shot at 1 second (1 * 60 = 60)
self.secondShotTime = 114; // Second shot at 1.9 seconds (1.9 * 60 = 114)
self.hasFiredFirst = false;
self.hasFiredSecond = false;
} else if (type === 'wallnut') {
self.graphics = self.attachAsset('wallnut', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1500;
self.maxHealth = 1500;
self.damage = 0;
} else if (type === 'cherrybomb') {
self.graphics = self.attachAsset('cherrybomb', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 200;
self.explosionRadius = 540; // 3 slots * 180px per slot
self.fuseTimer = 180; // 3 seconds
} else if (type === 'sunflower') {
self.graphics = self.attachAsset('sunflower', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 0;
self.sunTimer = 0;
self.sunInterval = 1200; // 20 seconds at 60fps
} else if (type === 'pointshooter') {
self.graphics = self.attachAsset('pointShooter', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 65;
self.maxHealth = 65;
self.damage = 0; // Doesn't damage, gives points instead
self.range = 400;
self.shootCooldown = 270; // Shoots every 4.5 seconds (270 frames at 60fps)
} else if (type === 'doublesunflower') {
self.graphics = self.attachAsset('doublesunflower', {
anchorX: 0.5,
anchorY: 0.5
});
self.damage = 0;
self.sunTimer = 0;
self.sunInterval = 330; // 5.5 seconds at 60fps (5.5 * 60 = 330)
} else if (type === 'armoredshooter') {
self.graphics = self.attachAsset('armoredshooter', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 350; // High health like wallnut but less
self.maxHealth = 350;
self.damage = 35; // More damage than regular peashooter
self.range = 400;
self.shootCooldown = 240; // 4 seconds at 60fps (4 * 60 = 240)
} else if (type === 'papapum') {
self.graphics = self.attachAsset('papapum', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 80; // Lower health since it's a mine
self.maxHealth = 80;
self.damage = 250; // High explosive damage
self.explosionRadius = 300; // Explosion range
self.isTriggered = false; // Track if mine has been triggered
self.cooldownTimer = 0; // Add cooldown timer starting at 0
self.cooldownDuration = 540; // 9 seconds at 60fps (9 * 60 = 540)
} else if (type === 'explosivewallnut') {
self.graphics = self.attachAsset('explosivewallnut', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1200; // High health like wallnut but slightly less
self.maxHealth = 1200;
self.damage = 300; // Explosive damage when destroyed
self.explosionRadius = 400; // Large explosion range
} else if (type === 'explosivepeashooter') {
self.graphics = self.attachAsset('explosivepeashooter', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 120; // Slightly more than regular peashooter
self.maxHealth = 120;
self.damage = 40; // Higher damage than regular peashooter
self.range = 400;
self.shootCooldown = 180; // 3 seconds at 60fps (3 * 60 = 180)
} else if (type === 'triplesunflower') {
self.graphics = self.attachAsset('triplesunflower', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFD700
});
self.damage = 0;
self.sunTimer = 0;
self.sunInterval = 180; // 3 seconds at 60fps (3 * 60 = 180)
} else if (type === 'burstpeashooter') {
self.graphics = self.attachAsset('burstpeashooter', {
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFFFFFF
});
self.health = 150;
self.maxHealth = 150;
self.damage = 8; // Each projectile does 8 damage
self.range = 400;
self.shootCooldown = 234; // 3.9 seconds at 60fps (3.9 * 60 = 234)
self.burstCount = 15; // Number of projectiles in burst
self.burstDelay = 6; // Frames between each projectile in burst (0.1 seconds)
self.burstProgress = 0; // Track current burst progress
self.isBursting = false; // Track if currently in burst mode
}
self.update = function () {
if (self.type === 'peashooter' || self.type === 'doublepeashooter' || self.type === 'pointshooter' || self.type === 'armoredshooter' || self.type === 'explosivepeashooter' || self.type === 'burstpeashooter') {
self.shootTimer++;
if (self.type === 'doublepeashooter') {
var target = self.findZombieInLane();
if (target) {
// First shot at 1 second
if (self.shootTimer >= self.firstShotTime && !self.hasFiredFirst) {
self.shoot(target);
self.hasFiredFirst = true;
}
// Second shot at 1.9 seconds
if (self.shootTimer >= self.secondShotTime && !self.hasFiredSecond) {
self.shoot(target);
self.hasFiredSecond = true;
}
}
// Reset cycle after total cooldown (3.5 seconds)
if (self.shootTimer >= self.shootCooldown) {
self.shootTimer = 0;
self.hasFiredFirst = false;
self.hasFiredSecond = false;
}
} else if (self.type === 'burstpeashooter') {
var target = self.findZombieInLane();
if (target && !self.isBursting) {
// Start burst sequence
if (self.shootTimer >= self.shootCooldown) {
self.isBursting = true;
self.burstProgress = 0;
self.shootTimer = 0;
}
}
// Handle burst firing
if (self.isBursting) {
if (self.shootTimer % self.burstDelay === 0 && self.burstProgress < self.burstCount) {
var currentTarget = self.findZombieInLane();
if (currentTarget) {
// Create projectile directly without animation
var projectile = new Projectile(self.x, self.y, currentTarget, self.damage);
projectiles.push(projectile);
game.addChild(projectile);
LK.getSound('shoot').play();
}
self.burstProgress++;
}
// End burst sequence
if (self.burstProgress >= self.burstCount) {
self.isBursting = false;
self.burstProgress = 0;
}
}
} else if (self.shootTimer >= self.shootCooldown) {
var target = self.findZombieInLane();
if (target) {
if (self.type === 'pointshooter') {
self.shootPoints(target);
} else if (self.type === 'explosivepeashooter') {
self.shootExplosive(target);
} else {
self.shoot(target);
}
}
self.shootTimer = 0;
}
} else if (self.type === 'cherrybomb') {
self.fuseTimer--;
if (self.fuseTimer <= 0) {
self.explode();
}
} else if (self.type === 'sunflower') {
self.sunTimer++;
if (self.sunTimer >= self.sunInterval) {
LK.setScore(LK.getScore() + 5);
scoreText.setText('Girasoles: ' + LK.getScore());
self.sunTimer = 0;
}
} else if (self.type === 'doublesunflower') {
self.sunTimer++;
if (self.sunTimer >= self.sunInterval) {
LK.setScore(LK.getScore() + 15);
scoreText.setText('Girasoles: ' + LK.getScore());
self.sunTimer = 0;
}
} else if (self.type === 'triplesunflower') {
self.sunTimer++;
if (self.sunTimer >= self.sunInterval) {
LK.setScore(LK.getScore() + 35);
scoreText.setText('Girasoles: ' + LK.getScore());
self.sunTimer = 0;
// Special golden glow animation every time it generates sun
tween(self.graphics, {
scaleX: 1.3,
scaleY: 1.3,
tint: 0xFFFF00
}, {
duration: 200,
onFinish: function onFinish() {
tween(self.graphics, {
scaleX: 1,
scaleY: 1,
tint: 0xFFD700
}, {
duration: 200
});
}
});
}
} else if (self.type === 'papapum' && !self.isTriggered) {
// Increment cooldown timer
self.cooldownTimer++;
// Ready animation when cooldown just completes
if (self.cooldownTimer === self.cooldownDuration) {
// Papapum ready animation - pulsing green glow
tween(self.graphics, {
tint: 0x00FF00,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 300,
onFinish: function onFinish() {
tween(self.graphics, {
tint: 0xFFFFFF,
scaleX: 1,
scaleY: 1
}, {
duration: 300
});
}
});
}
// Only become active after cooldown period
if (self.cooldownTimer >= self.cooldownDuration) {
// Check if any zombie is stepping on the papapum
for (var z = 0; z < zombies.length; z++) {
var zombie = zombies[z];
if (Math.abs(zombie.x - self.x) < 90 && Math.abs(zombie.y - self.y) < 90) {
self.isTriggered = true;
self.explode();
break;
}
}
}
}
};
self.findZombieInLane = function () {
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
// Check if zombie is in same lane (within 100px vertically) and to the right
if (Math.abs(zombie.y - self.y) < 100 && zombie.x > self.x) {
return zombie;
}
}
return null;
};
self.getDistanceTo = function (target) {
var dx = target.x - self.x;
var dy = target.y - self.y;
return Math.sqrt(dx * dx + dy * dy);
};
self.shoot = function (target) {
// Shooting animation - scale and recoil effect
tween(self.graphics, {
scaleX: 1.3,
scaleY: 1.3
}, {
duration: 100
});
tween(self.graphics, {
scaleX: 1,
scaleY: 1
}, {
duration: 200
});
tween(self.graphics, {
x: -10
}, {
duration: 100
});
tween(self.graphics, {
x: 0
}, {
duration: 200
});
var projectile = new Projectile(self.x, self.y, target, self.damage);
projectiles.push(projectile);
game.addChild(projectile);
LK.getSound('shoot').play();
};
self.shootPoints = function (target) {
// Golden shooting animation
tween(self.graphics, {
scaleX: 1.2,
scaleY: 1.2,
tint: 0xFFD700
}, {
duration: 150
});
tween(self.graphics, {
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 250
});
var pointProjectile = new PointProjectile(self.x, self.y, target);
projectiles.push(pointProjectile);
game.addChild(pointProjectile);
LK.getSound('shoot').play();
};
self.shootExplosive = function (target) {
// Red explosive shooting animation
tween(self.graphics, {
scaleX: 1.4,
scaleY: 1.4,
tint: 0xFF0000
}, {
duration: 120
});
tween(self.graphics, {
scaleX: 1,
scaleY: 1,
tint: 0xFF4444
}, {
duration: 200
});
tween(self.graphics, {
x: -15
}, {
duration: 120
});
tween(self.graphics, {
x: 0
}, {
duration: 200
});
var explosiveProjectile = new ExplosiveProjectile(self.x, self.y, target, self.damage);
projectiles.push(explosiveProjectile);
game.addChild(explosiveProjectile);
LK.getSound('shoot').play();
};
self.explode = function () {
// Explosion animation - flash and scale up
tween(self.graphics, {
tint: 0xFF4444,
scaleX: 3,
scaleY: 3
}, {
duration: 300,
onFinish: function onFinish() {
// Damage all zombies in explosion radius
for (var i = zombies.length - 1; i >= 0; i--) {
var zombie = zombies[i];
if (self.getDistanceTo(zombie) <= self.explosionRadius) {
zombie.takeDamage(self.damage);
}
}
LK.getSound('explosion').play();
self.destroy();
plants.splice(plants.indexOf(self), 1);
}
});
};
self.takeDamage = function (damage) {
self.health -= damage;
// Change wallnut sprite when health drops to 670 or below
if (self.type === 'wallnut' && self.health <= 670 && self.health > 0) {
// Remove current graphics
self.removeChild(self.graphics);
// Add damaged wallnut graphics
self.graphics = self.attachAsset('wallnutDamaged', {
anchorX: 0.5,
anchorY: 0.5
});
}
// Change armoredshooter sprite when health drops to 175 or below (half of 350)
if (self.type === 'armoredshooter' && self.health <= 175 && self.health > 0) {
// Remove current graphics
self.removeChild(self.graphics);
// Add damaged wallnut graphics (reuse damaged wallnut sprite)
self.graphics = self.attachAsset('wallnutDamaged', {
anchorX: 0.5,
anchorY: 0.5
});
}
// Change explosivewallnut sprite when health drops to 600 or below (half of 1200)
if (self.type === 'explosivewallnut' && self.health <= 600 && self.health > 0) {
// Remove current graphics
self.removeChild(self.graphics);
// Add damaged wallnut graphics
self.graphics = self.attachAsset('wallnutDamaged', {
anchorX: 0.5,
anchorY: 0.5
});
}
if (self.health <= 0) {
// If explosivewallnut is destroyed, explode
if (self.type === 'explosivewallnut') {
self.explode();
} else {
self.destroy();
plants.splice(plants.indexOf(self), 1);
}
}
};
return self;
});
var PlantButton = Container.expand(function (plantType, index) {
var self = Container.call(this);
self.plantType = plantType;
self.button = self.attachAsset('plantButton', {
anchorX: 0.5,
anchorY: 0.5
});
var icon;
if (plantType === 'peashooter') {
icon = self.attachAsset('peashooter', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
} else if (plantType === 'wallnut') {
icon = self.attachAsset('wallnut', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
} else if (plantType === 'cherrybomb') {
icon = self.attachAsset('cherrybomb', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
} else if (plantType === 'sunflower') {
icon = self.attachAsset('sunflower', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
} else if (plantType === 'papapum') {
icon = self.attachAsset('papapum', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
} else if (plantType === 'shovel') {
icon = self.attachAsset('shovel', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.6,
scaleY: 0.6
});
}
self.x = 1024 - plantTypes.length * 200 / 2 + index * 200;
self.y = 2600;
self.down = function (x, y, obj) {
selectedPlantType = self.plantType;
// Visual feedback
for (var i = 0; i < plantButtons.length; i++) {
plantButtons[i].button.tint = 0xFFFFFF;
}
self.button.tint = 0x00FF00;
};
return self;
});
var PointProjectile = Container.expand(function (startX, startY, target) {
var self = Container.call(this);
self.graphics = self.attachAsset('pointPea', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = startX;
self.y = startY;
self.target = target;
self.speed = 6;
// Shoot straight horizontally to the right
self.dirX = 1;
self.dirY = 0;
self.update = function () {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
// Golden sparkle animation
if (LK.ticks % 10 === 0) {
tween(self.graphics, {
tint: 0xFFFF00
}, {
duration: 100
});
tween(self.graphics, {
tint: 0xFFD700
}, {
duration: 100
});
}
// Check collision with any zombie
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
if (Math.abs(zombie.x - self.x) < 30 && Math.abs(zombie.y - self.y) < 30) {
// Give 1 point instead of damage
LK.setScore(LK.getScore() + 1);
scoreText.setText('Girasoles: ' + LK.getScore());
// Visual effect on hit
tween(zombie.graphics, {
tint: 0xFFD700
}, {
duration: 200
});
tween(zombie.graphics, {
tint: 0xFFFFFF
}, {
duration: 200
});
self.destroy();
projectiles.splice(projectiles.indexOf(self), 1);
return;
}
}
// Remove if off-screen
if (self.x > 2100 || self.x < -50 || self.y > 2800 || self.y < -50) {
self.destroy();
projectiles.splice(projectiles.indexOf(self), 1);
}
};
return self;
});
var Projectile = Container.expand(function (startX, startY, target, damage) {
var self = Container.call(this);
self.graphics = self.attachAsset('pea', {
anchorX: 0.5,
anchorY: 0.5
});
self.x = startX;
self.y = startY;
self.target = target;
self.damage = damage;
self.speed = 8;
// Shoot straight horizontally to the right
self.dirX = 1;
self.dirY = 0;
self.update = function () {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
// Check collision with target or any zombie
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
if (Math.abs(zombie.x - self.x) < 30 && Math.abs(zombie.y - self.y) < 30) {
zombie.takeDamage(self.damage);
self.destroy();
projectiles.splice(projectiles.indexOf(self), 1);
return;
}
}
// Remove if off-screen
if (self.x > 2100 || self.x < -50 || self.y > 2800 || self.y < -50) {
self.destroy();
projectiles.splice(projectiles.indexOf(self), 1);
}
};
return self;
});
var TankProjectile = Container.expand(function (startX, startY, target) {
var self = Container.call(this);
self.graphics = self.attachAsset('pea', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2,
scaleY: 2,
tint: 0xFF4444
});
self.x = startX;
self.y = startY;
self.target = target;
self.damage = 100;
self.speed = 4;
self.explosionRadius = 200;
// Shoot straight horizontally to the left
self.dirX = -1;
self.dirY = 0;
self.update = function () {
self.x += self.dirX * self.speed;
self.y += self.dirY * self.speed;
// Check collision with any plant
for (var i = 0; i < plants.length; i++) {
var plant = plants[i];
if (Math.abs(plant.x - self.x) < 40 && Math.abs(plant.y - self.y) < 40) {
self.explode();
return;
}
}
// Remove if off-screen
if (self.x < -50 || self.x > 2100 || self.y > 2800 || self.y < -50) {
self.destroy();
projectiles.splice(projectiles.indexOf(self), 1);
}
};
self.explode = function () {
// Explosion animation
tween(self.graphics, {
tint: 0xFF0000,
scaleX: 4,
scaleY: 4
}, {
duration: 300,
onFinish: function onFinish() {
// Damage all plants in explosion radius
for (var i = plants.length - 1; i >= 0; i--) {
var plant = plants[i];
var dx = plant.x - self.x;
var dy = plant.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= self.explosionRadius) {
plant.takeDamage(self.damage);
}
}
LK.getSound('explosion').play();
self.destroy();
projectiles.splice(projectiles.indexOf(self), 1);
}
});
};
return self;
});
var Zombie = Container.expand(function (type, lane) {
var self = Container.call(this);
self.type = type;
self.lane = lane;
self.id = Math.random().toString(36).substr(2, 9); // Generate unique ID
self.speed = 1;
self.health = 100;
self.maxHealth = 100;
self.damage = 25;
self.attackCooldown = 60;
self.attackTimer = 0;
self.isAttacking = false;
if (type === 'basic') {
self.graphics = self.attachAsset('basicZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.5;
self.health = 215;
self.maxHealth = 215;
} else if (type === 'fast') {
self.graphics = self.attachAsset('fastZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1.2;
self.health = 215;
self.maxHealth = 215;
} else if (type === 'strong') {
self.graphics = self.attachAsset('strongZombie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.6,
scaleY: 1.6
});
self.speed = 0.7;
self.health = 500;
self.maxHealth = 500;
self.damage = 45;
} else if (type === 'tank') {
self.graphics = self.attachAsset('tankZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.3;
self.health = 777;
self.maxHealth = 777;
self.damage = 50;
self.shootTimer = 0;
self.shootCooldown = 300; // 5 seconds at 60fps
}
self.x = 2048 + 50; // Start off-screen right
self.y = 300 + lane * 250; // Position in lane
// Play zombie sound when spawned
LK.getSound('zombie').play();
self.update = function () {
if (!self.isAttacking) {
self.x -= self.speed;
// Walking animation - bob up and down
if (self.type === 'basic') {
// Slower walking animation for basic zombie
if (LK.ticks % 40 < 20) {
tween(self.graphics, {
y: 5
}, {
duration: 200
});
} else {
tween(self.graphics, {
y: -5
}, {
duration: 200
});
}
} else if (self.type === 'fast') {
// Faster walking animation for fast zombie
if (LK.ticks % 20 < 10) {
tween(self.graphics, {
y: 8
}, {
duration: 100
});
} else {
tween(self.graphics, {
y: -8
}, {
duration: 100
});
}
} else if (self.type === 'strong') {
// Medium walking animation for strong zombie
if (LK.ticks % 30 < 15) {
tween(self.graphics, {
y: 6
}, {
duration: 150
});
} else {
tween(self.graphics, {
y: -6
}, {
duration: 150
});
}
} else if (self.type === 'tank') {
// Slow heavy walking animation for tank zombie
if (LK.ticks % 60 < 30) {
tween(self.graphics, {
y: 3
}, {
duration: 300
});
} else {
tween(self.graphics, {
y: -3
}, {
duration: 300
});
}
}
// Tank zombie shooting logic
if (self.type === 'tank') {
self.shootTimer++;
if (self.shootTimer >= self.shootCooldown) {
var target = self.findPlantInLane();
if (target) {
var tankProjectile = new TankProjectile(self.x, self.y, target);
projectiles.push(tankProjectile);
game.addChild(tankProjectile);
LK.getSound('shoot').play();
}
self.shootTimer = 0;
}
}
// Check for plant collision
var plantInWay = self.findPlantInWay();
if (plantInWay) {
self.isAttacking = true;
self.attackTimer = 0;
}
} else {
self.attackTimer++;
if (self.attackTimer >= self.attackCooldown) {
var plantInWay = self.findPlantInWay();
if (plantInWay) {
plantInWay.takeDamage(self.damage);
self.attackTimer = 0;
} else {
self.isAttacking = false;
}
}
}
// Check if reached end
if (self.x < -50) {
zombiesReachedEnd++;
self.destroy();
zombies.splice(zombies.indexOf(self), 1);
}
};
self.findPlantInWay = function () {
for (var i = 0; i < plants.length; i++) {
var plant = plants[i];
if (Math.abs(plant.x - self.x) < 80 && Math.abs(plant.y - self.y) < 80) {
return plant;
}
}
return null;
};
self.findPlantInLane = function () {
for (var i = 0; i < plants.length; i++) {
var plant = plants[i];
// Check if plant is in same lane (within 100px vertically) and to the left
if (Math.abs(plant.y - self.y) < 100 && plant.x < self.x) {
return plant;
}
}
return null;
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.getSound('zombieHit').play();
// Visual feedback
tween(self.graphics, {
tint: 0xFF0000
}, {
duration: 200
});
tween(self.graphics, {
tint: 0xFFFFFF
}, {
duration: 200
});
if (self.health <= 0) {
// Give points based on zombie type
if (self.type === 'tank') {
LK.setScore(LK.getScore() + 450);
zombiesKilled++;
} else if (self.type === 'strong') {
// Strong zombie gives no points but still counts as killed
zombiesKilled++;
} else {
zombiesKilled++;
}
scoreText.setText('Girasoles: ' + LK.getScore());
// Clean up shots tracking for all plants
for (var p = 0; p < plants.length; p++) {
if (plants[p].shotsFired && plants[p].shotsFired[self.id]) {
delete plants[p].shotsFired[self.id];
}
}
self.destroy();
zombies.splice(zombies.indexOf(self), 1);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2E7D32
});
/****
* Game Code
****/
// Sounds
// Grid and UI
// Projectiles
// Zombies
// Plants
// Game variables
var plants = [];
var zombies = [];
var projectiles = [];
var plantButtons = [];
var gridCells = [];
var selectedPlantType = null;
var waveNumber = 1;
var zombiesInWave = 5;
var zombieSpawnTimer = 0;
var zombieSpawnInterval = 120; // 2 seconds
var zombiesSpawned = 0;
var zombiesReachedEnd = 0;
var maxZombiesAllowed = 5;
var gameState = 'menu'; // 'menu', 'playing', 'gameOver', 'victory'
var autoPointTimer = 0;
var autoPointInterval = 420; // 7 seconds at 60fps (7 * 60 = 420)
var zombiesKilled = 0;
var selectedLanguage = storage.selectedLanguage || 'spanish'; // Default to Spanish
// Menu elements
var menuContainer = new Container();
game.addChild(menuContainer);
// Menu title
var titleText = new Text2('Plants vs Zombies', {
size: 80,
fill: '#00FF00'
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 1024;
titleText.y = 600;
menuContainer.addChild(titleText);
// Menu buttons
var idiomasButton = LK.getAsset('plantButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.2
});
idiomasButton.x = 1024;
idiomasButton.y = 1000;
menuContainer.addChild(idiomasButton);
var idiomasText = new Text2('IDIOMAS', {
size: 50,
fill: '#FFFFFF'
});
idiomasText.anchor.set(0.5, 0.5);
idiomasText.x = 1024;
idiomasText.y = 1000;
menuContainer.addChild(idiomasText);
var jugarButton = LK.getAsset('plantButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.2
});
jugarButton.x = 1024;
jugarButton.y = 1300;
menuContainer.addChild(jugarButton);
var jugarText = new Text2('JUGAR', {
size: 50,
fill: '#FFFFFF'
});
jugarText.anchor.set(0.5, 0.5);
jugarText.x = 1024;
jugarText.y = 1300;
menuContainer.addChild(jugarText);
var ajustesButton = LK.getAsset('plantButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.2
});
ajustesButton.x = 1024;
ajustesButton.y = 1600;
menuContainer.addChild(ajustesButton);
var ajustesText = new Text2('AJUSTES', {
size: 50,
fill: '#FFFFFF'
});
ajustesText.anchor.set(0.5, 0.5);
ajustesText.x = 1024;
ajustesText.y = 1600;
menuContainer.addChild(ajustesText);
// Language selection menu (initially hidden)
var languageMenuContainer = new Container();
game.addChild(languageMenuContainer);
languageMenuContainer.visible = false;
// Language menu title
var languageTitleText = new Text2('Select Language', {
size: 60,
fill: '#00FF00'
});
languageTitleText.anchor.set(0.5, 0.5);
languageTitleText.x = 1024;
languageTitleText.y = 700;
languageMenuContainer.addChild(languageTitleText);
// English button
var englishButton = LK.getAsset('plantButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.2
});
englishButton.x = 1024;
englishButton.y = 1000;
languageMenuContainer.addChild(englishButton);
var englishText = new Text2('ENGLISH', {
size: 50,
fill: '#FFFFFF'
});
englishText.anchor.set(0.5, 0.5);
englishText.x = 1024;
englishText.y = 1000;
languageMenuContainer.addChild(englishText);
// Spanish button
var spanishButton = LK.getAsset('plantButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.2
});
spanishButton.x = 1024;
spanishButton.y = 1300;
languageMenuContainer.addChild(spanishButton);
var spanishText = new Text2('ESPAÑOL', {
size: 50,
fill: '#FFFFFF'
});
spanishText.anchor.set(0.5, 0.5);
spanishText.x = 1024;
spanishText.y = 1300;
languageMenuContainer.addChild(spanishText);
// Back button
var backButton = LK.getAsset('plantButton', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.0
});
backButton.x = 1024;
backButton.y = 1600;
languageMenuContainer.addChild(backButton);
var backText = new Text2('BACK', {
size: 40,
fill: '#FFFFFF'
});
backText.anchor.set(0.5, 0.5);
backText.x = 1024;
backText.y = 1600;
languageMenuContainer.addChild(backText);
// Function to update menu texts based on selected language
function updateMenuTexts() {
if (selectedLanguage === 'english') {
idiomasText.setText('LANGUAGES');
jugarText.setText('PLAY');
ajustesText.setText('SETTINGS');
backText.setText('BACK');
} else {
idiomasText.setText('IDIOMAS');
jugarText.setText('JUGAR');
ajustesText.setText('AJUSTES');
backText.setText('VOLVER');
}
}
// Initialize menu texts based on selected language
updateMenuTexts();
// UI Elements
// Set initial score to 100
LK.setScore(100);
var scoreText = new Text2('Girasoles: ' + LK.getScore(), {
size: 40,
fill: '#FFFFFF'
});
scoreText.anchor.set(0, 0);
scoreText.x = 150;
scoreText.y = 20;
LK.gui.topLeft.addChild(scoreText);
scoreText.visible = false; // Hide during menu
var waveText = new Text2('Wave: 1', {
size: 40,
fill: '#FFFFFF'
});
waveText.anchor.set(0.5, 0);
waveText.x = 1024;
waveText.y = 20;
LK.gui.top.addChild(waveText);
waveText.visible = false; // Hide during menu
var livesText = new Text2('Lives: 5', {
size: 40,
fill: '#FF0000'
});
livesText.anchor.set(1, 0);
livesText.x = 1900;
livesText.y = 20;
LK.gui.topRight.addChild(livesText);
livesText.visible = false; // Hide during menu
function startGame() {
gameState = 'playing';
menuContainer.visible = false;
scoreText.visible = true;
waveText.visible = true;
livesText.visible = true;
// Show plant buttons
for (var i = 0; i < plantButtons.length; i++) {
plantButtons[i].visible = true;
}
// Show grid cells
for (var row = 0; row < gridRows; row++) {
for (var col = 0; col < gridCols; col++) {
gridCells[row][col].visible = true;
}
}
// Music will start 7.5 seconds after clicking play button
}
// Create plant selection buttons
var plantTypes = ['sunflower', 'peashooter', 'wallnut', 'cherrybomb', 'papapum', 'shovel'];
for (var i = 0; i < plantTypes.length; i++) {
var button = new PlantButton(plantTypes[i], i);
plantButtons.push(button);
game.addChild(button);
button.visible = false; // Hide during menu
}
// Create grid - scale to use full screen
var gridStartX = 150;
var gridStartY = 300;
var gridRows = 5;
var gridCols = 8;
for (var row = 0; row < gridRows; row++) {
gridCells[row] = [];
for (var col = 0; col < gridCols; col++) {
var cell = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.3
});
cell.x = gridStartX + col * 200;
cell.y = gridStartY + row * 250;
cell.row = row;
cell.col = col;
cell.occupied = false;
cell.visible = false; // Hide during menu
gridCells[row][col] = cell;
game.addChild(cell);
}
}
// Game event handlers
game.down = function (x, y, obj) {
// Handle language menu interactions
if (languageMenuContainer.visible) {
// Check if clicking on English button
if (Math.abs(x - englishButton.x) < 135 && Math.abs(y - englishButton.y) < 60) {
selectedLanguage = 'english';
storage.selectedLanguage = 'english';
// Update menu texts to English
updateMenuTexts();
// English button animation
tween(englishButton, {
scaleX: 1.7,
scaleY: 1.4,
tint: 0x00FF00
}, {
duration: 150,
onFinish: function onFinish() {
tween(englishButton, {
scaleX: 1.5,
scaleY: 1.2,
tint: 0xFFFFFF
}, {
duration: 150
});
}
});
// Hide language menu and show main menu
languageMenuContainer.visible = false;
menuContainer.visible = true;
return;
}
// Check if clicking on Spanish button
if (Math.abs(x - spanishButton.x) < 135 && Math.abs(y - spanishButton.y) < 60) {
selectedLanguage = 'spanish';
storage.selectedLanguage = 'spanish';
// Update menu texts to Spanish
updateMenuTexts();
// Spanish button animation
tween(spanishButton, {
scaleX: 1.7,
scaleY: 1.4,
tint: 0x00FF00
}, {
duration: 150,
onFinish: function onFinish() {
tween(spanishButton, {
scaleX: 1.5,
scaleY: 1.2,
tint: 0xFFFFFF
}, {
duration: 150
});
}
});
// Hide language menu and show main menu
languageMenuContainer.visible = false;
menuContainer.visible = true;
return;
}
// Check if clicking on Back button
if (Math.abs(x - backButton.x) < 90 && Math.abs(y - backButton.y) < 50) {
// Back button animation
tween(backButton, {
scaleX: 1.4,
scaleY: 1.2,
tint: 0xFFCC00
}, {
duration: 150,
onFinish: function onFinish() {
tween(backButton, {
scaleX: 1.2,
scaleY: 1.0,
tint: 0xFFFFFF
}, {
duration: 150
});
}
});
// Hide language menu and show main menu
languageMenuContainer.visible = false;
menuContainer.visible = true;
return;
}
return;
}
// Handle menu interactions
if (gameState === 'menu') {
// Check if clicking on Jugar button
if (Math.abs(x - jugarButton.x) < 135 && Math.abs(y - jugarButton.y) < 60) {
// Jugar button animation
tween(jugarButton, {
scaleX: 1.7,
scaleY: 1.4,
tint: 0x00FF00
}, {
duration: 150,
onFinish: function onFinish() {
tween(jugarButton, {
scaleX: 1.5,
scaleY: 1.2,
tint: 0xFFFFFF
}, {
duration: 150
});
}
});
// Stop music and play sound based on selected language
LK.stopMusic();
if (selectedLanguage === 'english') {
LK.getSound('english').play();
} else {
LK.getSound('spanish').play();
}
// Start music 7.5 seconds after clicking play
LK.setTimeout(function () {
if (gameState === 'playing') {
LK.playMusic('Musixa');
}
}, 7500);
startGame();
return;
}
// Check if clicking on Idiomas button
if (Math.abs(x - idiomasButton.x) < 135 && Math.abs(y - idiomasButton.y) < 60) {
// Idiomas button animation
tween(idiomasButton, {
scaleX: 1.7,
scaleY: 1.4,
tint: 0x0088FF
}, {
duration: 150,
onFinish: function onFinish() {
tween(idiomasButton, {
scaleX: 1.5,
scaleY: 1.2,
tint: 0xFFFFFF
}, {
duration: 150
});
}
});
// Show language menu and hide main menu
menuContainer.visible = false;
languageMenuContainer.visible = true;
return;
}
// Check if clicking on Ajustes button
if (Math.abs(x - ajustesButton.x) < 135 && Math.abs(y - ajustesButton.y) < 60) {
// Ajustes button animation
tween(ajustesButton, {
scaleX: 1.7,
scaleY: 1.4,
tint: 0xFF8800
}, {
duration: 150,
onFinish: function onFinish() {
tween(ajustesButton, {
scaleX: 1.5,
scaleY: 1.2,
tint: 0xFFFFFF
}, {
duration: 150
});
}
});
return;
}
return;
}
if (gameState !== 'playing') return;
if (!selectedPlantType) return;
// Check if clicking on grid
for (var row = 0; row < gridRows; row++) {
for (var col = 0; col < gridCols; col++) {
var cell = gridCells[row][col];
if (Math.abs(x - cell.x) < 80 && Math.abs(y - cell.y) < 80) {
// Check for fusion - peashooter + peashooter or sunflower + peashooter or papapum + wallnut
if (cell.occupied && (selectedPlantType === 'peashooter' || selectedPlantType === 'sunflower' || selectedPlantType === 'wallnut' || selectedPlantType === 'papapum')) {
// Find existing plant at this position
var existingPlant = null;
for (var p = 0; p < plants.length; p++) {
if (Math.abs(plants[p].x - cell.x) < 40 && Math.abs(plants[p].y - cell.y) < 40) {
existingPlant = plants[p];
break;
}
}
// Peashooter + Peashooter = Double Peashooter
if (existingPlant && existingPlant.type === 'peashooter' && selectedPlantType === 'peashooter') {
var cost = 10;
if (LK.getScore() < cost) {
return; // Not enough points
}
// Remove existing peashooter
existingPlant.destroy();
plants.splice(plants.indexOf(existingPlant), 1);
// Create double peashooter
var fusedPlant = new Plant('doublepeashooter');
fusedPlant.x = cell.x;
fusedPlant.y = cell.y;
plants.push(fusedPlant);
game.addChild(fusedPlant);
LK.setScore(LK.getScore() - cost);
scoreText.setText('Girasoles: ' + LK.getScore());
LK.getSound('plantPlace').play();
// Fusion animation
tween(fusedPlant.graphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0x00FF00
}, {
duration: 300,
onFinish: function onFinish() {
tween(fusedPlant.graphics, {
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
// Reset selection
selectedPlantType = null;
for (var i = 0; i < plantButtons.length; i++) {
plantButtons[i].button.tint = 0xFFFFFF;
}
return;
}
// Double Peashooter + Peashooter = Burst Peashooter
else if (existingPlant && (existingPlant.type === 'doublepeashooter' && selectedPlantType === 'peashooter' || existingPlant.type === 'peashooter' && selectedPlantType === 'doublepeashooter')) {
var cost = selectedPlantType === 'peashooter' ? 10 : 20;
if (LK.getScore() < cost) {
return; // Not enough points
}
// Remove existing plant
existingPlant.destroy();
plants.splice(plants.indexOf(existingPlant), 1);
// Create burst peashooter
var fusedPlant = new Plant('burstpeashooter');
fusedPlant.x = cell.x;
fusedPlant.y = cell.y;
plants.push(fusedPlant);
game.addChild(fusedPlant);
LK.setScore(LK.getScore() - cost);
scoreText.setText('Girasoles: ' + LK.getScore());
LK.getSound('plantPlace').play();
// Special burst fusion animation with white tint
tween(fusedPlant.graphics, {
scaleX: 1.6,
scaleY: 1.6,
tint: 0xFFFFFF
}, {
duration: 400,
onFinish: function onFinish() {
tween(fusedPlant.graphics, {
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 250
});
}
});
// Reset selection
selectedPlantType = null;
for (var i = 0; i < plantButtons.length; i++) {
plantButtons[i].button.tint = 0xFFFFFF;
}
return;
}
// Sunflower + Sunflower = Double Sunflower
else if (existingPlant && existingPlant.type === 'sunflower' && selectedPlantType === 'sunflower') {
var cost = 15;
if (LK.getScore() < cost) {
return; // Not enough points
}
// Remove existing sunflower
existingPlant.destroy();
plants.splice(plants.indexOf(existingPlant), 1);
// Create double sunflower
var fusedPlant = new Plant('doublesunflower');
fusedPlant.x = cell.x;
fusedPlant.y = cell.y;
plants.push(fusedPlant);
game.addChild(fusedPlant);
LK.setScore(LK.getScore() - cost);
scoreText.setText('Girasoles: ' + LK.getScore());
LK.getSound('plantPlace').play();
// Golden fusion animation for double sun production with sprite transformation
tween(fusedPlant.graphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFFF00
}, {
duration: 300,
onFinish: function onFinish() {
tween(fusedPlant.graphics, {
scaleX: 1,
scaleY: 1,
tint: 0xFFD700
}, {
duration: 200
});
}
});
// Reset selection
selectedPlantType = null;
for (var i = 0; i < plantButtons.length; i++) {
plantButtons[i].button.tint = 0xFFFFFF;
}
return;
}
// Sunflower + Double Sunflower = Triple Sunflower
else if (existingPlant && (existingPlant.type === 'sunflower' && selectedPlantType === 'doublesunflower' || existingPlant.type === 'doublesunflower' && selectedPlantType === 'sunflower')) {
var cost = selectedPlantType === 'sunflower' ? 15 : 35;
if (LK.getScore() < cost) {
return; // Not enough points
}
// Remove existing plant
existingPlant.destroy();
plants.splice(plants.indexOf(existingPlant), 1);
// Create triple sunflower
var fusedPlant = new Plant('triplesunflower');
fusedPlant.x = cell.x;
fusedPlant.y = cell.y;
plants.push(fusedPlant);
game.addChild(fusedPlant);
LK.setScore(LK.getScore() - cost);
scoreText.setText('Girasoles: ' + LK.getScore());
LK.getSound('plantPlace').play();
// Special golden fusion animation for triple sun production
tween(fusedPlant.graphics, {
scaleX: 1.8,
scaleY: 1.8,
tint: 0xFFFF00
}, {
duration: 400,
onFinish: function onFinish() {
tween(fusedPlant.graphics, {
scaleX: 1,
scaleY: 1,
tint: 0xFFD700
}, {
duration: 300
});
}
});
// Reset selection
selectedPlantType = null;
for (var i = 0; i < plantButtons.length; i++) {
plantButtons[i].button.tint = 0xFFFFFF;
}
return;
}
// Sunflower + Peashooter = Point Shooter
else if (existingPlant && (existingPlant.type === 'sunflower' && selectedPlantType === 'peashooter' || existingPlant.type === 'peashooter' && selectedPlantType === 'sunflower')) {
var cost = selectedPlantType === 'peashooter' ? 10 : 15;
if (LK.getScore() < cost) {
return; // Not enough points
}
// Remove existing plant
existingPlant.destroy();
plants.splice(plants.indexOf(existingPlant), 1);
// Create point shooter
var fusedPlant = new Plant('pointshooter');
fusedPlant.x = cell.x;
fusedPlant.y = cell.y;
plants.push(fusedPlant);
game.addChild(fusedPlant);
LK.setScore(LK.getScore() - cost);
scoreText.setText('Girasoles: ' + LK.getScore());
LK.getSound('plantPlace').play();
// Golden fusion animation
tween(fusedPlant.graphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFFD700
}, {
duration: 300,
onFinish: function onFinish() {
tween(fusedPlant.graphics, {
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
// Reset selection
selectedPlantType = null;
for (var i = 0; i < plantButtons.length; i++) {
plantButtons[i].button.tint = 0xFFFFFF;
}
return;
}
// Wallnut + Peashooter = Armored Shooter
else if (existingPlant && (existingPlant.type === 'wallnut' && selectedPlantType === 'peashooter' || existingPlant.type === 'peashooter' && selectedPlantType === 'wallnut')) {
var cost = selectedPlantType === 'peashooter' ? 10 : 20;
if (LK.getScore() < cost) {
return; // Not enough points
}
// Remove existing plant
existingPlant.destroy();
plants.splice(plants.indexOf(existingPlant), 1);
// Create armored shooter
var fusedPlant = new Plant('armoredshooter');
fusedPlant.x = cell.x;
fusedPlant.y = cell.y;
plants.push(fusedPlant);
game.addChild(fusedPlant);
LK.setScore(LK.getScore() - cost);
scoreText.setText('Girasoles: ' + LK.getScore());
LK.getSound('plantPlace').play();
// Defensive fusion animation with green tint
tween(fusedPlant.graphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0x00AA00
}, {
duration: 300,
onFinish: function onFinish() {
tween(fusedPlant.graphics, {
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
// Reset selection
selectedPlantType = null;
for (var i = 0; i < plantButtons.length; i++) {
plantButtons[i].button.tint = 0xFFFFFF;
}
return;
}
// Papapum + Wallnut = Explosive Wallnut
else if (existingPlant && (existingPlant.type === 'papapum' && selectedPlantType === 'wallnut' || existingPlant.type === 'wallnut' && selectedPlantType === 'papapum')) {
var cost = selectedPlantType === 'papapum' ? 25 : 20;
if (LK.getScore() < cost) {
return; // Not enough points
}
// Remove existing plant
existingPlant.destroy();
plants.splice(plants.indexOf(existingPlant), 1);
// Create explosive wallnut
var fusedPlant = new Plant('explosivewallnut');
fusedPlant.x = cell.x;
fusedPlant.y = cell.y;
plants.push(fusedPlant);
game.addChild(fusedPlant);
LK.setScore(LK.getScore() - cost);
scoreText.setText('Girasoles: ' + LK.getScore());
LK.getSound('plantPlace').play();
// Explosive fusion animation with red tint
tween(fusedPlant.graphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFF4444
}, {
duration: 300,
onFinish: function onFinish() {
tween(fusedPlant.graphics, {
scaleX: 1,
scaleY: 1,
tint: 0xFFFFFF
}, {
duration: 200
});
}
});
// Reset selection
selectedPlantType = null;
for (var i = 0; i < plantButtons.length; i++) {
plantButtons[i].button.tint = 0xFFFFFF;
}
return;
}
// Papapum + Peashooter = Explosive Peashooter
else if (existingPlant && (existingPlant.type === 'papapum' && selectedPlantType === 'peashooter' || existingPlant.type === 'peashooter' && selectedPlantType === 'papapum')) {
var cost = selectedPlantType === 'papapum' ? 25 : 10;
if (LK.getScore() < cost) {
return; // Not enough points
}
// Remove existing plant
existingPlant.destroy();
plants.splice(plants.indexOf(existingPlant), 1);
// Create explosive peashooter
var fusedPlant = new Plant('explosivepeashooter');
fusedPlant.x = cell.x;
fusedPlant.y = cell.y;
plants.push(fusedPlant);
game.addChild(fusedPlant);
LK.setScore(LK.getScore() - cost);
scoreText.setText('Girasoles: ' + LK.getScore());
LK.getSound('plantPlace').play();
// Explosive fusion animation with red tint
tween(fusedPlant.graphics, {
scaleX: 1.5,
scaleY: 1.5,
tint: 0xFF4444
}, {
duration: 300,
onFinish: function onFinish() {
tween(fusedPlant.graphics, {
scaleX: 1,
scaleY: 1,
tint: 0xFF4444
}, {
duration: 200
});
}
});
// Reset selection
selectedPlantType = null;
for (var i = 0; i < plantButtons.length; i++) {
plantButtons[i].button.tint = 0xFFFFFF;
}
return;
}
}
// Handle shovel selection - remove existing plant
if (selectedPlantType === 'shovel' && cell.occupied) {
// Find and remove the plant at this position
for (var p = plants.length - 1; p >= 0; p--) {
if (Math.abs(plants[p].x - cell.x) < 40 && Math.abs(plants[p].y - cell.y) < 40) {
plants[p].destroy();
plants.splice(p, 1);
// Make sure to update the grid cell's occupied status
gridCells[row][col].occupied = false;
break;
}
}
// Reset selection
selectedPlantType = null;
for (var i = 0; i < plantButtons.length; i++) {
plantButtons[i].button.tint = 0xFFFFFF;
}
return;
}
if (!cell.occupied && selectedPlantType !== 'shovel') {
var cost = 0;
if (selectedPlantType === 'peashooter') cost = 10;
if (selectedPlantType === 'sunflower') cost = 15;
if (selectedPlantType === 'wallnut') cost = 20;
if (selectedPlantType === 'cherrybomb') cost = 50;
if (selectedPlantType === 'papapum') cost = 25;
if (LK.getScore() < cost) {
return; // Not enough points
}
var plant = new Plant(selectedPlantType);
plant.x = cell.x;
plant.y = cell.y;
plants.push(plant);
game.addChild(plant);
// Update grid cell occupied status using row/col indices
gridCells[row][col].occupied = true;
if (cost > 0) {
LK.setScore(LK.getScore() - cost);
scoreText.setText('Girasoles: ' + LK.getScore());
}
LK.getSound('plantPlace').play();
// Reset selection
selectedPlantType = null;
for (var i = 0; i < plantButtons.length; i++) {
plantButtons[i].button.tint = 0xFFFFFF;
}
return;
}
}
}
}
};
function spawnZombie() {
if (zombiesSpawned >= zombiesInWave) return;
var lane = Math.floor(Math.random() * gridRows);
var zombieTypes = ['basic', 'fast', 'strong'];
var type = zombieTypes[Math.floor(Math.random() * zombieTypes.length)];
// Tank zombies appear after 50 zombies killed
if (zombiesKilled >= 50) {
zombieTypes = ['basic', 'fast', 'strong', 'tank'];
}
// Increase difficulty with wave number
if (waveNumber > 3) {
type = zombieTypes[Math.floor(Math.random() * zombieTypes.length)];
} else if (waveNumber > 1) {
type = Math.random() < 0.7 ? 'basic' : Math.random() < 0.5 ? 'fast' : 'strong';
} else {
type = Math.random() < 0.6 ? 'basic' : 'strong';
}
var zombie = new Zombie(type, lane);
zombies.push(zombie);
game.addChild(zombie);
zombiesSpawned++;
}
function checkWaveComplete() {
if (zombiesSpawned >= zombiesInWave && zombies.length === 0) {
// Wave complete
waveNumber++;
zombiesInWave += 2;
zombiesSpawned = 0;
waveText.setText('Wave: ' + waveNumber);
if (waveNumber > 10) {
gameState = 'victory';
LK.showYouWin();
}
}
}
function checkGameOver() {
if (zombiesReachedEnd >= 1) {
gameState = 'gameOver';
LK.showGameOver();
}
livesText.setText('Lives: ' + (maxZombiesAllowed - zombiesReachedEnd));
}
// Main game loop
game.update = function () {
if (gameState !== 'playing') return;
// Auto point generation - 7 points every 7 seconds
autoPointTimer++;
if (autoPointTimer >= autoPointInterval) {
LK.setScore(LK.getScore() + 7);
scoreText.setText('Girasoles: ' + LK.getScore());
autoPointTimer = 0;
}
// Spawn zombies
zombieSpawnTimer++;
if (zombieSpawnTimer >= zombieSpawnInterval) {
spawnZombie();
zombieSpawnTimer = 0;
}
// Update all objects
for (var i = plants.length - 1; i >= 0; i--) {
if (plants[i].update) {
plants[i].update();
}
}
for (var i = zombies.length - 1; i >= 0; i--) {
if (zombies[i].update) {
zombies[i].update();
}
}
for (var i = projectiles.length - 1; i >= 0; i--) {
if (projectiles[i].update) {
projectiles[i].update();
}
}
checkWaveComplete();
checkGameOver();
}; ===================================================================
--- original.js
+++ change.js
@@ -796,10 +796,10 @@
} else if (type === 'strong') {
self.graphics = self.attachAsset('strongZombie', {
anchorX: 0.5,
anchorY: 0.5,
- scaleX: 1.3,
- scaleY: 1.3
+ scaleX: 1.6,
+ scaleY: 1.6
});
self.speed = 0.7;
self.health = 500;
self.maxHealth = 500;
Zombie básico del videojuego plantas vs zombies. In-Game asset. No shadows
Un lanza guisantes del videojuego plantas vs zombies. In-Game asset. No shadows
Fast zombie del videojuego plantas vs zombies. In-Game asset. No shadows
Cherrybomb del videojuego plantas vs zombies. In-Game asset. No shadows
Girasol de juego plantas vs zombies. In-Game asset
doublepeashooter del juego plantas vs zombies fusion. In-Game asset. No shadows
Un lanza guisantes fusionado cun un girasol de plantas vs zombies fusion. In-Game asset. No shadows
Cuadro rojo con azul para seleccionar algo. In-Game asset. No shadows
Wallnut del videojuego plantas vs zombies. In-Game asset. No shadows
Tank zombie del juego plantas vs zombies. In-Game asset. No shadows
Cuadrado de cesped con flores visto desde arriba. In-Game asset. No shadows
Shovel de plantas vs zombies. In-Game asset. 2d. No shadows
wallnutDamaged del videojuego de plantas vs zombies. In-Game asset. 2d. No shadows
doublesunflower de plantas vs zombies fusion. In-Game asset. 2d. No shadows
Una fusion del wallnut de plantas vs zombies con el lanza guisantes. In-Game asset. No shadows
Papapum de plantas vs zombies que sea tierna. In-Game asset. No shadows
explosivewallnut de plantas vs zombies fusion. In-Game asset. 2d. High contrast
explosivepeashooter de plantas vs zombie fusion. In-Game asset. 2d. High contrast
Triple girasol de plantas vs zombies. In-Game asset. 2d. High contrast
Triple lanza guisantes del videojuego plantas vs zombies fusion con cascos militares y boca de metralletas. In-Game asset. 2d. High contrast
Strong zombie de plantas vs zombies. In-Game asset. 2d. High contrast. No shadows
Crazy Dave del juego plantas vs zombies con cara alegre y con una pelota desinflada en la cabeza. In-Game asset. 2d. High contrast
Planta piraña de plantas vs zombies. In-Game asset. 2d. High contrast. No shadows
Piraña explosiva del plantas vs zombies. In-Game asset. 2d. High contrast
Sprite de explosion estilo plantas vs zombies. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Fondo para menú de un juego que tarda de plantas vs zombies fusion con plantas y zombies con plantas fusionadas como. Lanza guisantes con girasol , etc sin texto. 2048x2732. In-Game asset. 2d. High contrast. No shadows