User prompt
que la cantidad de zombies sean mil y que no alla tiempo limite
User prompt
no se supone que esta la sinta transportadora que siempre te dara nueces y con las nueces se las tiraras alos zombies ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
as que en el nivel 5 alla un minijuego estilo bolera con las nueses ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
añade minijuegos
User prompt
porque cuando te vas de los niveles de noche las plantas de la noche siguen hay?
User prompt
solucionalo
User prompt
as que el zombie lector pueda comer al estar enojado y que la probavilidad de que el lanzamais lanse mantequilla sea del 25 porciento
User prompt
no pero as un nuevo asset para el maiz y la mantequilla
User prompt
as que el lanza maiz dispare maiz que aleatoriamente lanse mantequilla que realentisa al enemigo por 10 segundos ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
as que siempre te de 1 maseta en la sinta transportadora y 2 plantas random
User prompt
as que siempre te de 1 maseta en la sinta transportadora y que las semillas no aparescan
User prompt
as que la transportadora pueda darte 3 plantas
User prompt
as un asset diferente para el zombiestain
User prompt
pero que la bola de fuego salga de la boca del jefe y que luego valla a donde se apunto ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
as que la bola de fuego aparesca de la boca de fuego y que no aparescan lapidas en la boss fight ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
as que solo dispare una bola de fuego
User prompt
as que el boss dispare en un lugar random y que las plantas lo puedan atacar ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
as la vida del jefe en la parde de abajo izquierda y que aparesca un circulo rojo en el lugar donde iba a caer la bola de fuego ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
as que la cinta transportadora me de todo menos productores de sol
User prompt
no estas haciendo nada no puedo poner la planta que me da pa cinta transportadora!
User prompt
as que me deje poner la planta de la sinta transportadora ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
as que se muestre en la sinta la planta
User prompt
puedes arreglarlo?
User prompt
no me deja poner plantas
User prompt
pues arreglalo ↪💡 Consider importing and using the following plugins: @upit/tween.v1
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var ConveyorBelt = Container.expand(function () {
var self = Container.call(this);
var beltGraphics = self.attachAsset('conveyorBelt', {
anchorX: 0.5,
anchorY: 0.5
});
self.seedTimer = 0;
self.seedGenerateRate = 600; // 10 seconds at 60fps
// Available seeds for boss level - excluding sun producers (sunflower, sunshroom)
self.availableSeeds = ['wallnut', 'carnivorousplant', 'doomshroom', 'melonpulta', 'coltapulta', 'lanzamaiz'];
// Create text display for seed feedback
var seedText = new Text2('', {
size: 40,
fill: 0xFFFFFF
});
seedText.anchor.set(0.5, 0.5);
seedText.x = 0;
seedText.y = -60; // Above the conveyor belt
seedText.alpha = 0; // Start invisible
self.addChild(seedText);
// Create plant display on conveyor belt
var plantDisplay = null; // Will hold the current plant image
self.update = function () {
self.seedTimer++;
if (self.seedTimer >= self.seedGenerateRate) {
self.seedTimer = 0;
// Generate random seed
var randomSeed = self.availableSeeds[Math.floor(Math.random() * self.availableSeeds.length)];
// Reset cooldown for this seed type - properly reset it
seedCooldowns[randomSeed] = 0;
// Automatically select this plant type for placement
selectedPlantType = randomSeed;
shovelSelected = false;
// Remove previous plant display if it exists
if (plantDisplay) {
plantDisplay.destroy();
plantDisplay = null;
}
// Create new plant display on conveyor belt
plantDisplay = LK.getAsset(randomSeed, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8,
alpha: 0
});
plantDisplay.x = 0;
plantDisplay.y = 0; // Center on conveyor belt
self.addChild(plantDisplay);
// Show clear text feedback of which seed was given
var seedDisplayName = randomSeed.toUpperCase();
if (randomSeed === 'carnivorousplant') seedDisplayName = 'CARNIVOROUS PLANT';
if (randomSeed === 'doomshroom') seedDisplayName = 'DOOM SHROOM';
if (randomSeed === 'melonpulta') seedDisplayName = 'MELON PULTA';
if (randomSeed === 'coltapulta') seedDisplayName = 'COL TAPULTA';
if (randomSeed === 'lanzamaiz') seedDisplayName = 'LANZA MAIZ';
seedText.setText(seedDisplayName + ' SEED!');
// Show plant image with fade in animation
tween(plantDisplay, {
alpha: 1,
scaleX: 1.0,
scaleY: 1.0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
// Keep plant visible for 3 seconds, then fade out
tween(plantDisplay, {
alpha: 0,
scaleX: 0.6,
scaleY: 0.6
}, {
duration: 1500,
easing: tween.easeIn,
onFinish: function onFinish() {
if (plantDisplay) {
plantDisplay.destroy();
plantDisplay = null;
}
}
});
}
});
// Show text with fade in animation
tween(seedText, {
alpha: 1,
scaleX: 1.2,
scaleY: 1.2
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
// Keep text visible for 2 seconds, then fade out
tween(seedText, {
alpha: 0,
scaleX: 1,
scaleY: 1
}, {
duration: 1000,
easing: tween.easeIn
});
}
});
// Visual flash effect to show seed was given
tween(self, {
scaleX: 1.2,
scaleY: 1.2,
tint: 0x00ff00
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1,
tint: 0xffffff
}, {
duration: 300,
easing: tween.easeIn
});
}
});
}
};
return self;
});
var Fireball = Container.expand(function () {
var self = Container.call(this);
var fireballGraphics = self.attachAsset('fireball', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -6;
self.damage = 50;
self.update = function () {
self.x += self.speed;
self.rotation += 0.2; // Spinning effect
// Fireball trail effect
if (LK.ticks % 5 === 0) {
tween(self, {
tint: 0xff8c00
}, {
duration: 100,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
tint: 0xff4500
}, {
duration: 100,
easing: tween.easeIn
});
}
});
}
if (self.x < -100) {
self.destroy();
}
};
return self;
});
var Lawnmower = Container.expand(function () {
var self = Container.call(this);
var lawnmowerGraphics = self.attachAsset('lawnmower', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0; // Starts stationary
self.activated = false;
self.update = function () {
if (self.activated) {
self.x += 12; // Move fast when activated
if (self.x > 2200) {
self.destroy();
}
}
};
return self;
});
var LevelButton = Container.expand(function (levelNumber) {
var self = Container.call(this);
// Level button background
var buttonBg = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
self.addChild(buttonBg);
// Level number text
var levelText = new Text2(levelNumber.toString(), {
size: 60,
fill: 0x000000
});
levelText.anchor.set(0.5, 0.5);
self.addChild(levelText);
self.levelNumber = levelNumber;
self.down = function (x, y, obj) {
// Start the selected level
startLevel(self.levelNumber);
};
return self;
});
var LoadingScreen = Container.expand(function () {
var self = Container.call(this);
// Loading logo image
var loadingLogo = self.attachAsset('loadingLogo', {
anchorX: 0.5,
anchorY: 0.5
});
loadingLogo.x = 1024;
loadingLogo.y = 800;
// Loading bar background
var loadingBarBg = self.attachAsset('loadingBarBg', {
anchorX: 0.5,
anchorY: 0.5
});
loadingBarBg.x = 1024;
loadingBarBg.y = 1400;
// Loading bar fill
var loadingBar = self.attachAsset('loadingBar', {
anchorX: 0,
anchorY: 0.5
});
loadingBar.x = 724; // Start at left edge of background
loadingBar.y = 1400;
loadingBar.width = 0; // Start with no fill
// Loading text
var loadingText = new Text2('CARGANDO...', {
size: 80,
fill: 0xFFFFFF
});
loadingText.anchor.set(0.5, 0.5);
loadingText.x = 1024;
loadingText.y = 1200;
self.addChild(loadingText);
// Progress text
var progressText = new Text2('0%', {
size: 60,
fill: 0xFFFFFF
});
progressText.anchor.set(0.5, 0.5);
progressText.x = 1024;
progressText.y = 1500;
self.addChild(progressText);
self.progress = 0;
self.maxProgress = 300; // 5 seconds at 60fps
self.currentProgress = 0;
self.update = function () {
if (self.currentProgress < self.maxProgress) {
self.currentProgress++;
self.progress = self.currentProgress / self.maxProgress;
// Update loading bar width
loadingBar.width = 600 * self.progress;
// Update progress text
var percentage = Math.floor(self.progress * 100);
progressText.setText(percentage + '%');
// Loading complete
if (self.currentProgress >= self.maxProgress) {
// Transition to level selection
showLevelSelection();
}
}
};
return self;
});
var Pea = Container.expand(function () {
var self = Container.call(this);
var peaGraphics = self.attachAsset('pea', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.damage = 20;
self.update = function () {
self.x += self.speed;
if (self.x > 2200) {
self.destroy();
}
};
return self;
});
var Plant = Container.expand(function (type) {
var self = Container.call(this);
self.type = type;
self.health = 100;
self.maxHealth = 100;
self.shootCooldown = 0;
self.sunTimer = 0;
var plantGraphics;
if (type === 'sunflower') {
plantGraphics = self.attachAsset('sunflower', {
anchorX: 0.5,
anchorY: 0.5
});
self.sunGenerateRate = 300; // ticks between sun generation
} else if (type === 'peashooter') {
plantGraphics = self.attachAsset('peashooter', {
anchorX: 0.5,
anchorY: 0.5
});
self.shootRate = 90; // ticks between shots
} else if (type === 'wallnut') {
plantGraphics = self.attachAsset('wallnut', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 300;
self.maxHealth = 300;
} else if (type === 'potatomine') {
plantGraphics = self.attachAsset('potatomine', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.maxHealth = 50;
self.exploded = false;
} else if (type === 'carnivorousplant') {
plantGraphics = self.attachAsset('carnivorousplant', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 200;
self.maxHealth = 200;
self.attackCooldown = 0;
self.attackRange = 100;
} else if (type === 'doomshroom') {
plantGraphics = self.attachAsset('doomshroom', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.exploded = false;
self.armingTime = 900; // 15 seconds to arm
self.currentArmingTime = 0;
} else if (type === 'repeater') {
plantGraphics = self.attachAsset('repeater', {
anchorX: 0.5,
anchorY: 0.5
});
self.shootRate = 90; // Same as peashooter
} else if (type === 'threepeater') {
plantGraphics = self.attachAsset('threepeater', {
anchorX: 0.5,
anchorY: 0.5
});
self.shootRate = 120; // Slightly slower due to triple shot
} else if (type === 'spikeweed') {
plantGraphics = self.attachAsset('spikeweed', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 300;
self.maxHealth = 300;
} else if (type === 'splitpeater') {
plantGraphics = self.attachAsset('splitpeater', {
anchorX: 0.5,
anchorY: 0.5
});
self.shootRate = 120; // Similar to threepeater
} else if (type === 'lilypad') {
plantGraphics = self.attachAsset('lilypad', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.maxHealth = 50;
} else if (type === 'puffshroom') {
plantGraphics = self.attachAsset('puffshroom', {
anchorX: 0.5,
anchorY: 0.5
});
self.shootRate = 60; // Faster than peashooter but shorter range
self.range = 300; // Limited range
} else if (type === 'sunshroom') {
plantGraphics = self.attachAsset('sunshroom', {
anchorX: 0.5,
anchorY: 0.5
});
self.sunGenerateRate = 150; // Faster than sunflower but produces less
self.sunValue = 15; // Produces less sun than sunflower
} else if (type === 'fumeshroom') {
plantGraphics = self.attachAsset('fumeshroom', {
anchorX: 0.5,
anchorY: 0.5
});
self.shootRate = 120; // Slower but affects multiple zombies
} else if (type === 'gravebuster') {
plantGraphics = self.attachAsset('gravebuster', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1; // Dies after one use
self.maxHealth = 1;
} else if (type === 'hypnoshroom') {
plantGraphics = self.attachAsset('hypnoshroom', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.maxHealth = 50;
} else if (type === 'scaredyshroom') {
plantGraphics = self.attachAsset('scaredyshroom', {
anchorX: 0.5,
anchorY: 0.5
});
self.shootRate = 60;
} else if (type === 'iceshroom') {
plantGraphics = self.attachAsset('iceshroom', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1;
self.maxHealth = 1;
} else if (type === 'melonpulta') {
plantGraphics = self.attachAsset('melonpulta', {
anchorX: 0.5,
anchorY: 0.5
});
self.shootRate = 180; // Slower but more powerful
self.projectileDamage = 80; // High damage
} else if (type === 'coltapulta') {
plantGraphics = self.attachAsset('coltapulta', {
anchorX: 0.5,
anchorY: 0.5
});
self.shootRate = 240; // Slower rate
self.projectileDamage = 60; // Medium damage
} else if (type === 'lanzamaiz') {
plantGraphics = self.attachAsset('lanzamaiz', {
anchorX: 0.5,
anchorY: 0.5
});
self.shootRate = 150; // Fast rate
self.projectileDamage = 40; // Lower damage but faster
} else if (type === 'pot') {
plantGraphics = self.attachAsset('pot', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.maxHealth = 50;
}
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.destroy();
return true;
}
return false;
};
self.update = function () {
if (self.type === 'sunflower') {
self.sunTimer++;
if (self.sunTimer >= self.sunGenerateRate) {
self.sunTimer = 0;
var newSun = new Sun();
newSun.x = self.x + Math.random() * 40 - 20;
newSun.y = self.y + Math.random() * 40 - 20;
game.addChild(newSun);
suns.push(newSun);
}
} else if (self.type === 'peashooter') {
self.shootCooldown++;
if (self.shootCooldown >= self.shootRate) {
// Check if there's a zombie in this row
var myRow = Math.floor((self.y - 500) / 140);
var hasZombieInRow = false;
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var zombieRow = Math.floor((zombie.y - 500) / 140);
if (zombieRow === myRow && zombie.x > self.x) {
hasZombieInRow = true;
break;
}
}
if (hasZombieInRow) {
self.shootCooldown = 0;
// Fisheye shooting effect
tween(self, {
scaleX: 1.3,
scaleY: 0.7
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.easeIn
});
}
});
var pea = new Pea();
pea.x = self.x + 60;
pea.y = self.y;
game.addChild(pea);
peas.push(pea);
LK.getSound('shoot').play();
}
}
} else if (self.type === 'repeater') {
self.shootCooldown++;
if (self.shootCooldown >= self.shootRate) {
// Check if there's a zombie in this row
var myRow = Math.floor((self.y - 500) / 140);
var hasZombieInRow = false;
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var zombieRow = Math.floor((zombie.y - 500) / 140);
if (zombieRow === myRow && zombie.x > self.x) {
hasZombieInRow = true;
break;
}
}
if (hasZombieInRow) {
self.shootCooldown = 0;
// Fisheye shooting effect
tween(self, {
scaleX: 1.3,
scaleY: 0.7
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.easeIn
});
}
});
// Shoot two peas with slight delay
var pea1 = new Pea();
pea1.x = self.x + 60;
pea1.y = self.y;
game.addChild(pea1);
peas.push(pea1);
// Second pea with slight delay
LK.setTimeout(function () {
var pea2 = new Pea();
pea2.x = self.x + 60;
pea2.y = self.y;
game.addChild(pea2);
peas.push(pea2);
}, 150);
LK.getSound('shoot').play();
}
}
} else if (self.type === 'threepeater') {
self.shootCooldown++;
if (self.shootCooldown >= self.shootRate) {
// Check if there's a zombie in any of the three rows (current, above, below)
var myRow = Math.floor((self.y - 500) / 140);
var hasZombieInAnyRow = false;
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var zombieRow = Math.floor((zombie.y - 500) / 140);
if ((zombieRow === myRow || zombieRow === myRow - 1 || zombieRow === myRow + 1) && zombie.x > self.x) {
hasZombieInAnyRow = true;
break;
}
}
if (hasZombieInAnyRow) {
self.shootCooldown = 0;
// Fisheye shooting effect
tween(self, {
scaleX: 1.3,
scaleY: 0.7
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.easeIn
});
}
});
// Shoot three peas - center, above, below
var centerPea = new Pea();
centerPea.x = self.x + 60;
centerPea.y = self.y;
game.addChild(centerPea);
peas.push(centerPea);
// Above pea (if row exists)
if (myRow > 0) {
var abovePea = new Pea();
abovePea.x = self.x + 60;
abovePea.y = self.y - 140;
game.addChild(abovePea);
peas.push(abovePea);
}
// Below pea (if row exists)
if (myRow < gridRows - 1) {
var belowPea = new Pea();
belowPea.x = self.x + 60;
belowPea.y = self.y + 140;
game.addChild(belowPea);
peas.push(belowPea);
}
LK.getSound('shoot').play();
}
}
} else if (self.type === 'potatomine' && !self.exploded) {
// Check for zombies stepping on the mine
var myRow = Math.floor((self.y - 500) / 140);
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var zombieRow = Math.floor((zombie.y - 500) / 140);
if (zombieRow === myRow && Math.abs(self.x - zombie.x) < 80) {
// Explode!
self.exploded = true;
LK.getSound('explode').play();
// Create explosion visual effect
tween(self, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
for (var k = plants.length - 1; k >= 0; k--) {
if (plants[k] === self) {
plants.splice(k, 1);
self.destroy();
break;
}
}
}
});
LK.effects.flashObject(self, 0xFF4500, 500);
// Damage all zombies in the area
for (var j = zombies.length - 1; j >= 0; j--) {
var targetZombie = zombies[j];
var distance = Math.sqrt(Math.pow(self.x - targetZombie.x, 2) + Math.pow(self.y - targetZombie.y, 2));
if (distance < 120) {
if (targetZombie.takeDamage(200)) {
targetZombie.destroy();
zombies.splice(j, 1);
}
}
}
break;
}
}
} else if (self.type === 'carnivorousplant') {
self.attackCooldown++;
if (self.attackCooldown >= 180) {
// Attack every 3 seconds
var myRow = Math.floor((self.y - 500) / 140);
var closestZombie = null;
var closestDistance = Infinity;
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var zombieRow = Math.floor((zombie.y - 500) / 140);
if (zombieRow === myRow) {
var distance = Math.abs(self.x - zombie.x);
if (distance < self.attackRange && distance < closestDistance) {
closestDistance = distance;
closestZombie = zombie;
}
}
}
if (closestZombie) {
self.attackCooldown = 0;
// Attack animation
tween(self, {
scaleX: 1.5,
scaleY: 1.5
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 200,
easing: tween.easeIn
});
}
});
if (closestZombie.takeDamage(100)) {
for (var j = zombies.length - 1; j >= 0; j--) {
if (zombies[j] === closestZombie) {
closestZombie.destroy();
zombies.splice(j, 1);
break;
}
}
}
}
}
} else if (self.type === 'doomshroom' && !self.exploded) {
self.currentArmingTime++;
if (self.currentArmingTime >= self.armingTime) {
// Doom shroom is now armed and explodes
self.exploded = true;
LK.getSound('explode').play();
// Create massive explosion visual effect
tween(self, {
scaleX: 8,
scaleY: 8,
alpha: 0
}, {
duration: 1000,
easing: tween.easeOut,
onFinish: function onFinish() {
for (var k = plants.length - 1; k >= 0; k--) {
if (plants[k] === self) {
plants.splice(k, 1);
self.destroy();
break;
}
}
}
});
LK.effects.flashScreen(0x4B0082, 1000);
// Damage all zombies on screen
for (var j = zombies.length - 1; j >= 0; j--) {
var targetZombie = zombies[j];
if (targetZombie.takeDamage(300)) {
targetZombie.destroy();
zombies.splice(j, 1);
}
}
}
} else if (self.type === 'spikeweed') {
// Damage zombies walking over spikeweed - but don't stop them
var myRow = Math.floor((self.y - 500) / 140);
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var zombieRow = Math.floor((zombie.y - 500) / 140);
if (zombieRow === myRow && Math.abs(self.x - zombie.x) < 70) {
// Only damage zombie if it hasn't been damaged by this spikeweed recently
if (!zombie.lastSpikeweeedDamageTime || LK.ticks - zombie.lastSpikeweeedDamageTime > 30) {
zombie.lastSpikeweeedDamageTime = LK.ticks;
if (zombie.takeDamage(20)) {
for (var j = zombies.length - 1; j >= 0; j--) {
if (zombies[j] === zombie) {
zombie.destroy();
zombies.splice(j, 1);
break;
}
}
}
// Damage spikeweed when used
if (self.takeDamage(1)) {
for (var k = plants.length - 1; k >= 0; k--) {
if (plants[k] === self) {
plants.splice(k, 1);
self.destroy();
break;
}
}
}
}
}
}
} else if (self.type === 'splitpeater') {
self.shootCooldown++;
if (self.shootCooldown >= self.shootRate) {
// Check if there's a zombie in front or behind
var myRow = Math.floor((self.y - 500) / 140);
var hasZombieInFront = false;
var hasZombieBehind = false;
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var zombieRow = Math.floor((zombie.y - 500) / 140);
if (zombieRow === myRow) {
if (zombie.x > self.x) {
hasZombieInFront = true;
} else if (zombie.x < self.x) {
hasZombieBehind = true;
}
}
}
if (hasZombieInFront || hasZombieBehind) {
self.shootCooldown = 0;
// Fisheye shooting effect
tween(self, {
scaleX: 1.3,
scaleY: 0.7
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.easeIn
});
}
});
// Shoot forward if zombie in front
if (hasZombieInFront) {
var forwardPea = new Pea();
forwardPea.x = self.x + 60;
forwardPea.y = self.y;
game.addChild(forwardPea);
peas.push(forwardPea);
}
// Shoot backward if zombie behind
if (hasZombieBehind) {
var backwardPea = new Pea();
backwardPea.x = self.x - 60;
backwardPea.y = self.y;
backwardPea.speed = -8; // Negative speed for backward movement
game.addChild(backwardPea);
peas.push(backwardPea);
}
LK.getSound('shoot').play();
}
}
} else if (self.type === 'puffshroom') {
self.shootCooldown++;
if (self.shootCooldown >= self.shootRate) {
var myRow = Math.floor((self.y - 500) / 140);
var hasZombieInRange = false;
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var zombieRow = Math.floor((zombie.y - 500) / 140);
if (zombieRow === myRow && zombie.x > self.x && zombie.x - self.x < self.range) {
hasZombieInRange = true;
break;
}
}
if (hasZombieInRange) {
self.shootCooldown = 0;
var pea = new Pea();
pea.x = self.x + 60;
pea.y = self.y;
game.addChild(pea);
peas.push(pea);
LK.getSound('shoot').play();
}
}
} else if (self.type === 'sunshroom') {
self.sunTimer++;
if (self.sunTimer >= self.sunGenerateRate) {
self.sunTimer = 0;
var newSun = new Sun();
newSun.value = self.sunValue;
newSun.x = self.x + Math.random() * 40 - 20;
newSun.y = self.y + Math.random() * 40 - 20;
game.addChild(newSun);
suns.push(newSun);
}
} else if (self.type === 'gravebuster') {
// Check for tombstones to destroy
var myRow = Math.floor((self.y - gridStartY + cellSize / 2) / cellSize);
var myCol = Math.floor((self.x - gridStartX + cellSize / 2) / cellSize);
for (var i = tombstones.length - 1; i >= 0; i--) {
var tombstone = tombstones[i];
var tombstoneRow = Math.floor((tombstone.y - gridStartY + cellSize / 2) / cellSize);
var tombstoneCol = Math.floor((tombstone.x - gridStartX + cellSize / 2) / cellSize);
if (tombstoneRow === myRow && tombstoneCol === myCol) {
// Destroy tombstone
tombstone.destroy();
tombstones.splice(i, 1);
// Destroy gravebuster after use
for (var j = plants.length - 1; j >= 0; j--) {
if (plants[j] === self) {
plants.splice(j, 1);
self.destroy();
break;
}
}
break;
}
}
} else if (self.type === 'scaredyshroom') {
self.shootCooldown++;
if (self.shootCooldown >= self.shootRate) {
var myRow = Math.floor((self.y - 500) / 140);
var hasZombieInRow = false;
var zombieTooClose = false;
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var zombieRow = Math.floor((zombie.y - 500) / 140);
if (zombieRow === myRow && zombie.x > self.x) {
hasZombieInRow = true;
if (zombie.x - self.x < 200) {
zombieTooClose = true;
}
break;
}
}
if (hasZombieInRow && !zombieTooClose) {
self.shootCooldown = 0;
var pea = new Pea();
pea.x = self.x + 60;
pea.y = self.y;
game.addChild(pea);
peas.push(pea);
LK.getSound('shoot').play();
}
}
} else if (self.type === 'melonpulta' || self.type === 'coltapulta' || self.type === 'lanzamaiz') {
self.shootCooldown++;
if (self.shootCooldown >= self.shootRate) {
// Check if there's a zombie in this row
var myRow = Math.floor((self.y - 500) / 140);
var hasZombieInRow = false;
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var zombieRow = Math.floor((zombie.y - 500) / 140);
if (zombieRow === myRow && zombie.x > self.x) {
hasZombieInRow = true;
break;
}
}
if (hasZombieInRow) {
self.shootCooldown = 0;
// Catapult shooting animation
tween(self, {
scaleX: 1.3,
scaleY: 0.7
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.easeIn
});
}
});
var pea = new Pea();
pea.damage = self.projectileDamage; // Use custom damage
pea.x = self.x + 60;
pea.y = self.y;
game.addChild(pea);
peas.push(pea);
LK.getSound('shoot').play();
}
}
}
};
return self;
});
var RobotBoss = Container.expand(function () {
var self = Container.call(this);
var bossGraphics = self.attachAsset('robotBoss', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 1000;
self.maxHealth = 1000;
self.attackTimer = 0;
self.attackRate = 240; // 4 seconds between attacks
self.mouthOpen = false;
self.takeDamage = function (damage) {
self.health -= damage;
// Flash red when taking damage
tween(self, {
tint: 0xff0000
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
tint: 0xffffff
}, {
duration: 200,
easing: tween.easeIn
});
}
});
if (self.health <= 0) {
// Boss death animation
tween(self, {
scaleX: 2,
scaleY: 2,
alpha: 0,
rotation: Math.PI
}, {
duration: 2000,
easing: tween.easeOut,
onFinish: function onFinish() {
self.destroy();
// Trigger win condition
if (gameState === 'playing') {
gameState = 'won';
LK.showYouWin();
}
}
});
return true;
}
return false;
};
self.update = function () {
self.attackTimer++;
if (self.attackTimer >= self.attackRate) {
self.attackTimer = 0;
// Randomly choose between fireball attack or zombie spawn
if (Math.random() < 0.6) {
// Show red circle where fireball will land at random position
var landingIndicators = [];
var fireballTargets = []; // Store target position for fireball
// Generate random target position within grid area
var targetX = gridStartX + Math.random() * (gridCols * cellSize);
var targetY = gridStartY + Math.random() * (gridRows * cellSize);
fireballTargets.push({
x: targetX,
y: targetY
});
var indicator = LK.getAsset('fireball', {
anchorX: 0.5,
anchorY: 0.5,
x: targetX,
y: targetY,
scaleX: 2,
scaleY: 2,
tint: 0xff0000,
alpha: 0.7
});
game.addChild(indicator);
landingIndicators.push(indicator);
// Open mouth animation for fireball attack
self.mouthOpen = true;
tween(self, {
scaleY: 1.3,
tint: 0xff4500
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Remove landing indicator
for (var k = 0; k < landingIndicators.length; k++) {
landingIndicators[k].destroy();
}
// Spit single fireball toward random target position from boss mouth
var fireball = new Fireball();
fireball.x = self.x - 80; // Spawn from mouth area (further left from center)
fireball.y = self.y - 50; // Spawn from mouth height (upper part of boss)
game.addChild(fireball);
fireballs.push(fireball);
// Close mouth
tween(self, {
scaleY: 1,
tint: 0xffffff
}, {
duration: 300,
easing: tween.easeIn,
onFinish: function onFinish() {
self.mouthOpen = false;
}
});
}
});
} else {
// Spawn zombies including Zombistein
var zombieTypes = ['normal', 'fast', 'snailBucket', 'zombistein'];
var randomType = zombieTypes[Math.floor(Math.random() * zombieTypes.length)];
var newZombie = new Zombie(randomType);
newZombie.x = 2100;
newZombie.y = gridStartY + Math.floor(Math.random() * gridRows) * cellSize;
game.addChild(newZombie);
zombies.push(newZombie);
// Boss spawn effect
tween(self, {
tint: 0x8000ff
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
tint: 0xffffff
}, {
duration: 200,
easing: tween.easeIn
});
}
});
}
}
// Update boss health display
if (bossHealthDisplay) {
bossHealthDisplay.setText('Boss Health: ' + self.health + '/' + self.maxHealth);
}
};
return self;
});
var Sun = Container.expand(function () {
var self = Container.call(this);
var sunGraphics = self.attachAsset('sun', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 25;
self.collected = false;
self.lifeTimer = 0;
self.maxLifeTime = 300; // 5 seconds at 60 FPS
self.update = function () {
if (!self.collected) {
self.lifeTimer++;
if (self.lifeTimer >= self.maxLifeTime) {
self.collected = true;
self.destroy();
}
}
};
self.down = function (x, y, obj) {
if (!self.collected) {
self.collected = true;
sunPoints += self.value;
updateSunDisplay();
LK.getSound('collect').play();
self.destroy();
}
};
return self;
});
var Tombstone = Container.expand(function () {
var self = Container.call(this);
var tombstoneGraphics = self.attachAsset('tombstone', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.destroy();
return true;
}
return false;
};
return self;
});
var Zombie = Container.expand(function (type) {
var self = Container.call(this);
self.type = type || 'normal';
self.health = 100;
self.maxHealth = 100;
self.speed = -1;
self.attackDamage = 25;
self.attackCooldown = 0;
self.isAttacking = false;
var zombieGraphics;
if (self.type === 'fast') {
zombieGraphics = self.attachAsset('fastZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -2;
self.health = 60;
self.maxHealth = 60;
} else if (self.type === 'snailBucket') {
zombieGraphics = self.attachAsset('snailBucket', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -0.5;
self.health = 250;
self.maxHealth = 250;
} else if (self.type === 'miner') {
zombieGraphics = self.attachAsset('minerZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -1.2;
self.health = 120;
self.maxHealth = 120;
self.underground = false;
self.surfaceTimer = 0;
self.canAttack = true; // Can attack and be attacked when above ground
} else if (self.type === 'cart') {
zombieGraphics = self.attachAsset('cartZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -0.7;
self.health = 300;
self.maxHealth = 300;
self.cartHealth = 200; // Cart has its own health
self.cartDestroyed = false;
} else if (self.type === 'newspaper') {
zombieGraphics = self.attachAsset('newspaperZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = -0.8;
self.health = 150;
self.maxHealth = 150;
self.newspaperHealth = 75; // Newspaper has its own health
self.newspaperDestroyed = false;
self.enraged = false;
} else if (self.type === 'zombistein') {
zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.5,
scaleY: 1.5,
tint: 0x00ff00
});
self.speed = -0.5;
self.health = 500;
self.maxHealth = 500;
self.electricAttack = true;
self.lastElectricAttack = 0;
} else {
zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
}
self.takeDamage = function (damage) {
// Cart zombie takes damage to cart first
if (self.type === 'cart' && !self.cartDestroyed) {
self.cartHealth -= damage;
if (self.cartHealth <= 0) {
self.cartDestroyed = true;
self.speed = -1.5; // Move faster without cart
zombieGraphics.tint = 0x888888;
}
return false; // Cart zombie doesn't die until cart is destroyed
} else if (self.type === 'newspaper' && !self.newspaperDestroyed) {
self.newspaperHealth -= damage;
if (self.newspaperHealth <= 0) {
self.newspaperDestroyed = true;
self.enraged = true;
self.speed = -2.5; // Move much faster when enraged
zombieGraphics.tint = 0xff4444; // Red tint when angry
}
return false; // Newspaper zombie doesn't die until newspaper is destroyed
} else {
// Miner zombie cannot be damaged when underground
if (self.type === 'miner' && self.underground) {
return false; // Cannot be damaged underground
}
self.health -= damage;
if (self.health <= 0) {
// Death animation - fall to ground
tween(self, {
rotation: Math.PI / 2,
y: self.y + 50,
alpha: 0.7
}, {
duration: 800,
easing: tween.easeOut
});
return true;
}
}
return false;
};
self.update = function () {
// Miner zombie behavior
if (self.type === 'miner') {
var lastColumnX = gridStartX; // X position of the last (leftmost) grid column
// Check if miner has reached or passed the last column
var hasReachedLastColumn = self.x <= lastColumnX;
if (!self.underground && self.x < 1500 && !hasReachedLastColumn) {
// Go underground when reaching middle of screen, but only if hasn't reached last column yet
self.underground = true;
self.canAttack = false; // Cannot attack when underground
self.alpha = 0.3; // Make more transparent when underground
self.speed = -2; // Move faster underground
}
if (self.underground) {
// When underground, cannot attack plants - just move through them
// Check if reached the last column (leftmost grid column) to surface and turn around
if (hasReachedLastColumn) {
// Surface at last column and turn around
self.underground = false;
self.canAttack = true; // Can attack again when surfaced
self.alpha = 1;
self.speed = 1.2; // Move right (positive speed) to attack from behind
self.surfaceTimer = 0;
}
}
// Once surfaced at last column, continue moving right and cannot go underground again
if (hasReachedLastColumn && !self.underground && self.speed > 0) {
// Ensure miner continues moving right and cannot go underground
self.canAttack = true;
self.alpha = 1;
}
}
// Zombistein electric attack behavior
if (self.type === 'zombistein' && LK.ticks - self.lastElectricAttack > 300) {
// Electric attack every 5 seconds
self.lastElectricAttack = LK.ticks;
// Damage all plants in a 200px radius
for (var plantIdx = 0; plantIdx < plants.length; plantIdx++) {
var plant = plants[plantIdx];
var distance = Math.sqrt(Math.pow(self.x - plant.x, 2) + Math.pow(self.y - plant.y, 2));
if (distance < 200) {
// Electric visual effect
tween(plant, {
tint: 0x00ffff
}, {
duration: 200,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(plant, {
tint: 0xffffff
}, {
duration: 200,
easing: tween.easeIn
});
}
});
if (plant.takeDamage(30)) {
for (var k = plants.length - 1; k >= 0; k--) {
if (plants[k] === plant) {
plants.splice(k, 1);
plant.destroy();
break;
}
}
}
}
}
}
// Cart zombie behavior
if (self.type === 'cart' && !self.cartDestroyed) {
// Check if cart should be destroyed (takes damage first before zombie)
if (self.cartHealth <= 0) {
self.cartDestroyed = true;
self.speed = -1.5; // Move faster without cart
// Change appearance to show cart is destroyed
zombieGraphics.tint = 0x888888;
}
}
if (!self.isAttacking) {
self.x += self.speed;
// Check if zombie reached the left side
if (self.x < 100) {
gameOver();
return;
}
// Check for plants to attack (ignore spikeweed)
var myRow = Math.floor((self.y - 500) / 140);
for (var i = 0; i < plants.length; i++) {
var plant = plants[i];
var plantRow = Math.floor((plant.y - 500) / 140);
// Ignore spikeweed plants - zombies walk over them
// Miner zombie cannot attack when underground
if (plantRow === myRow && Math.abs(self.x - plant.x) < 80 && plant.type !== 'spikeweed' && self.canAttack) {
// Cart zombie instantly destroys plants except spikeweed
if (self.type === 'cart') {
plant.takeDamage(9999); // Instant destruction
for (var plantIdx = plants.length - 1; plantIdx >= 0; plantIdx--) {
if (plants[plantIdx] === plant) {
plants.splice(plantIdx, 1);
break;
}
}
} else {
self.isAttacking = true;
}
break;
}
}
} else {
// Attack mode
self.attackCooldown++;
if (self.attackCooldown >= 60) {
// Attack every second
self.attackCooldown = 0;
// Find plant to attack (ignore spikeweed)
var myRow = Math.floor((self.y - 500) / 140);
var targetPlant = null;
for (var i = 0; i < plants.length; i++) {
var plant = plants[i];
var plantRow = Math.floor((plant.y - 500) / 140);
// Ignore spikeweed plants - zombies walk over them
// Miner zombie cannot attack when underground
if (plantRow === myRow && Math.abs(self.x - plant.x) < 80 && plant.type !== 'spikeweed' && self.canAttack) {
// Cart zombie instantly destroys plants except spikeweed
if (self.type === 'cart') {
plant.takeDamage(9999); // Instant destruction
for (var plantIdx = plants.length - 1; plantIdx >= 0; plantIdx--) {
if (plants[plantIdx] === plant) {
plants.splice(plantIdx, 1);
break;
}
}
self.isAttacking = false; // Continue moving after instant destruction
targetPlant = null;
} else {
targetPlant = plant;
}
break;
}
}
if (targetPlant) {
// Fisheye eating effect
tween(self, {
scaleX: 1.3,
scaleY: 0.7
}, {
duration: 150,
easing: tween.easeOut,
onFinish: function onFinish() {
tween(self, {
scaleX: 1,
scaleY: 1
}, {
duration: 150,
easing: tween.easeIn
});
}
});
if (targetPlant.takeDamage(self.attackDamage)) {
// Plant destroyed, remove from array
for (var j = plants.length - 1; j >= 0; j--) {
if (plants[j] === targetPlant) {
plants.splice(j, 1);
break;
}
}
self.isAttacking = false;
}
} else {
self.isAttacking = false;
}
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x228B22
});
/****
* Game Code
****/
// Night plants (mushrooms)
// Game variables
var sunPoints = 150;
var currentWave = 1;
var maxWaves = 5;
var waveSpawnTimer = 0;
var zombiesInWave = 0;
var maxZombiesInWave = 30;
var selectedPlantType = null;
var shovelSelected = false;
var gameState = 'loading'; // 'loading', 'levelSelect', 'playing', 'won', 'lost'
var currentLevel = 1;
var loadingScreen = null;
var levelButtons = [];
// Seed recharge system - 3 seconds = 180 ticks at 60 FPS
var seedRechargeTime = 180;
var seedCooldowns = {
sunflower: 0,
peashooter: 0,
wallnut: 0,
potatomine: 0,
carnivorousplant: 0,
doomshroom: 0,
repeater: 0,
threepeater: 0,
spikeweed: 0,
splitpeater: 0,
lilypad: 0,
puffshroom: 0,
sunshroom: 0,
fumeshroom: 0,
gravebuster: 0,
hypnoshroom: 0,
scaredyshroom: 0,
iceshroom: 0,
melonpulta: 0,
coltapulta: 0,
lanzamaiz: 0,
pot: 0
};
// Game arrays
var plants = [];
var zombies = [];
var peas = [];
var suns = [];
var lawnmowers = [];
var waterTiles = [];
var tombstones = [];
var conveyorBelt = null;
var robotBoss = null;
var fireballs = [];
// Grid setup
var gridStartX = 300;
var gridStartY = 350;
var gridCols = 12;
var gridRows = 12;
var cellSize = 140;
// Plant costs
var plantCosts = {
sunflower: 50,
peashooter: 100,
wallnut: 50,
potatomine: 25,
carnivorousplant: 150,
doomshroom: 125,
repeater: 200,
threepeater: 325,
spikeweed: 100,
splitpeater: 175,
lilypad: 25,
puffshroom: 0,
sunshroom: 25,
fumeshroom: 75,
gravebuster: 75,
hypnoshroom: 75,
scaredyshroom: 25,
iceshroom: 75,
melonpulta: 300,
coltapulta: 100,
lanzamaiz: 100,
pot: 25
};
// UI Elements
var sunDisplay = new Text2('Sun: ' + sunPoints, {
size: 60,
fill: 0xFFFF00
});
sunDisplay.anchor.set(0, 0);
LK.gui.topLeft.addChild(sunDisplay);
sunDisplay.x = 120;
sunDisplay.y = 20;
var waveDisplay = new Text2('Wave: ' + currentWave + '/' + maxWaves, {
size: 50,
fill: 0xFFFFFF
});
waveDisplay.anchor.set(0.5, 0);
LK.gui.top.addChild(waveDisplay);
waveDisplay.y = 20;
// Plant selection buttons arranged vertically at bottom of screen
var sunflowerButton = LK.getAsset('sunflower', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: 2100,
scaleX: 0.6,
scaleY: 0.6
});
game.addChild(sunflowerButton);
var peashooterButton = LK.getAsset('peashooter', {
anchorX: 0.5,
anchorY: 0.5,
x: 300,
y: 2100,
scaleX: 0.6,
scaleY: 0.6
});
game.addChild(peashooterButton);
var wallnutButton = LK.getAsset('wallnut', {
anchorX: 0.5,
anchorY: 0.5,
x: 400,
y: 2100,
scaleX: 0.6,
scaleY: 0.6
});
game.addChild(wallnutButton);
var potatomineButton = LK.getAsset('potatomine', {
anchorX: 0.5,
anchorY: 0.5,
x: 500,
y: 2100,
scaleX: 0.6,
scaleY: 0.6
});
game.addChild(potatomineButton);
var carnivorousplantButton = LK.getAsset('carnivorousplant', {
anchorX: 0.5,
anchorY: 0.5,
x: 600,
y: 2100,
scaleX: 0.6,
scaleY: 0.6
});
game.addChild(carnivorousplantButton);
var doomshroomButton = LK.getAsset('doomshroom', {
anchorX: 0.5,
anchorY: 0.5,
x: 700,
y: 2100,
scaleX: 0.6,
scaleY: 0.6
});
game.addChild(doomshroomButton);
var repeaterButton = LK.getAsset('repeater', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: 2100,
scaleX: 0.6,
scaleY: 0.6
});
game.addChild(repeaterButton);
var threepeaterButton = LK.getAsset('threepeater', {
anchorX: 0.5,
anchorY: 0.5,
x: 900,
y: 2100,
scaleX: 0.6,
scaleY: 0.6
});
game.addChild(threepeaterButton);
var spikeButton = LK.getAsset('spikeweed', {
anchorX: 0.5,
anchorY: 0.5,
x: 1000,
y: 2100,
scaleX: 0.6,
scaleY: 0.6
});
game.addChild(spikeButton);
var splitpeaterButton = LK.getAsset('splitpeater', {
anchorX: 0.5,
anchorY: 0.5,
x: 1100,
y: 2100,
scaleX: 0.6,
scaleY: 0.6
});
game.addChild(splitpeaterButton);
var lilypadButton = LK.getAsset('lilypad', {
anchorX: 0.5,
anchorY: 0.5,
x: 1200,
y: 2100,
scaleX: 0.6,
scaleY: 0.6
});
game.addChild(lilypadButton);
// Restart button and shovel moved to right side of screen
var restartButton = LK.getAsset('restartButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1800,
y: 120,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(restartButton);
var shovelButton = LK.getAsset('shovel', {
anchorX: 0.5,
anchorY: 0.5,
x: 1920,
y: 120,
scaleX: 0.6,
scaleY: 0.6
});
game.addChild(shovelButton);
// Plant cost labels - arranged horizontally at bottom next to buttons
var sunflowerCost = new Text2('50', {
size: 20,
fill: 0xFFFFFF
});
sunflowerCost.anchor.set(0.5, 0);
sunflowerCost.x = 200;
sunflowerCost.y = 2140;
game.addChild(sunflowerCost);
var peashooterCost = new Text2('100', {
size: 20,
fill: 0xFFFFFF
});
peashooterCost.anchor.set(0.5, 0);
peashooterCost.x = 300;
peashooterCost.y = 2140;
game.addChild(peashooterCost);
var wallnutCost = new Text2('50', {
size: 20,
fill: 0xFFFFFF
});
wallnutCost.anchor.set(0.5, 0);
wallnutCost.x = 400;
wallnutCost.y = 2140;
game.addChild(wallnutCost);
var potatomineeCost = new Text2('25', {
size: 20,
fill: 0xFFFFFF
});
potatomineeCost.anchor.set(0.5, 0);
potatomineeCost.x = 500;
potatomineeCost.y = 2140;
game.addChild(potatomineeCost);
var carnivorousplantCost = new Text2('150', {
size: 20,
fill: 0xFFFFFF
});
carnivorousplantCost.anchor.set(0.5, 0);
carnivorousplantCost.x = 600;
carnivorousplantCost.y = 2140;
game.addChild(carnivorousplantCost);
var doomshroomCost = new Text2('125', {
size: 20,
fill: 0xFFFFFF
});
doomshroomCost.anchor.set(0.5, 0);
doomshroomCost.x = 700;
doomshroomCost.y = 2140;
game.addChild(doomshroomCost);
var repeaterCost = new Text2('200', {
size: 20,
fill: 0xFFFFFF
});
repeaterCost.anchor.set(0.5, 0);
repeaterCost.x = 800;
repeaterCost.y = 2140;
game.addChild(repeaterCost);
var threepeaterCost = new Text2('325', {
size: 20,
fill: 0xFFFFFF
});
threepeaterCost.anchor.set(0.5, 0);
threepeaterCost.x = 900;
threepeaterCost.y = 2140;
game.addChild(threepeaterCost);
var spikeCost = new Text2('100', {
size: 20,
fill: 0xFFFFFF
});
spikeCost.anchor.set(0.5, 0);
spikeCost.x = 1000;
spikeCost.y = 2140;
game.addChild(spikeCost);
var splitpeaterCost = new Text2('175', {
size: 20,
fill: 0xFFFFFF
});
splitpeaterCost.anchor.set(0.5, 0);
splitpeaterCost.x = 1100;
splitpeaterCost.y = 2140;
game.addChild(splitpeaterCost);
var lilypadCost = new Text2('25', {
size: 20,
fill: 0xFFFFFF
});
lilypadCost.anchor.set(0.5, 0);
lilypadCost.x = 1200;
lilypadCost.y = 2140;
game.addChild(lilypadCost);
// Create separate catapult plant buttons for roof levels
var melonpultaButton = LK.getAsset('melonpulta', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: 2100,
scaleX: 0.6,
scaleY: 0.6
});
game.addChild(melonpultaButton);
melonpultaButton.visible = false; // Hidden by default
var coltapultaButton = LK.getAsset('coltapulta', {
anchorX: 0.5,
anchorY: 0.5,
x: 900,
y: 2100,
scaleX: 0.6,
scaleY: 0.6
});
game.addChild(coltapultaButton);
coltapultaButton.visible = false; // Hidden by default
var lanzamaizButton = LK.getAsset('lanzamaiz', {
anchorX: 0.5,
anchorY: 0.5,
x: 1100,
y: 2100,
scaleX: 0.6,
scaleY: 0.6
});
game.addChild(lanzamaizButton);
lanzamaizButton.visible = false; // Hidden by default
// Create cost labels for catapult plants
var melonpultaCost = new Text2('300', {
size: 20,
fill: 0xFFFFFF
});
melonpultaCost.anchor.set(0.5, 0);
melonpultaCost.x = 800;
melonpultaCost.y = 2140;
game.addChild(melonpultaCost);
melonpultaCost.visible = false; // Hidden by default
var coltapultaCost = new Text2('100', {
size: 20,
fill: 0xFFFFFF
});
coltapultaCost.anchor.set(0.5, 0);
coltapultaCost.x = 900;
coltapultaCost.y = 2140;
game.addChild(coltapultaCost);
coltapultaCost.visible = false; // Hidden by default
var lanzamaizCost = new Text2('100', {
size: 20,
fill: 0xFFFFFF
});
lanzamaizCost.anchor.set(0.5, 0);
lanzamaizCost.x = 1100;
lanzamaizCost.y = 2140;
game.addChild(lanzamaizCost);
lanzamaizCost.visible = false; // Hidden by default
// Create pot plant button for roof levels
var potButton = LK.getAsset('pot', {
anchorX: 0.5,
anchorY: 0.5,
x: 300,
y: 2100,
scaleX: 0.6,
scaleY: 0.6
});
game.addChild(potButton);
potButton.visible = false; // Hidden by default
// Create cost label for pot plant
var potCost = new Text2('25', {
size: 20,
fill: 0xFFFFFF
});
potCost.anchor.set(0.5, 0);
potCost.x = 300;
potCost.y = 2140;
game.addChild(potCost);
potCost.visible = false; // Hidden by default
// Boss health display
var bossHealthDisplay = new Text2('Boss Health: 1000/1000', {
size: 40,
fill: 0xFF0000
});
bossHealthDisplay.anchor.set(0, 1); // Bottom left anchor
bossHealthDisplay.x = 120;
bossHealthDisplay.y = 2600;
game.addChild(bossHealthDisplay);
bossHealthDisplay.visible = false; // Hidden by default
var restartText = new Text2('RESTART', {
size: 16,
fill: 0xFFFFFF
});
restartText.anchor.set(0.5, 0);
restartText.x = 1800;
restartText.y = 90;
game.addChild(restartText);
// Exit level button - positioned next to restart button
var exitLevelButton = LK.getAsset('restartButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 1650,
y: 120,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(exitLevelButton);
var exitText = new Text2('EXIT', {
size: 16,
fill: 0xFFFFFF
});
exitText.anchor.set(0.5, 0);
exitText.x = 1650;
exitText.y = 90;
game.addChild(exitText);
// Draw grid
var gridTiles = [];
for (var row = 0; row < gridRows; row++) {
for (var col = 0; col < gridCols; col++) {
var gridCell = LK.getAsset('gridCell', {
anchorX: 0.5,
anchorY: 0.5,
x: gridStartX + col * cellSize,
y: gridStartY + row * cellSize,
alpha: 0.3
});
game.addChild(gridCell);
gridTiles.push(gridCell);
}
}
// Add decorative bushes on the right to cover zombie spawn area - more bushes arranged at different depths
var bushes = LK.getAsset('bushes', {
anchorX: 0.5,
anchorY: 0.5,
x: 2000,
y: 600,
scaleX: 1.8,
scaleY: 1.8
});
game.addChild(bushes);
var bushes2 = LK.getAsset('bushes', {
anchorX: 0.5,
anchorY: 0.5,
x: 2000,
y: 900,
scaleX: 1.6,
scaleY: 1.6
});
game.addChild(bushes2);
var bushes3 = LK.getAsset('bushes', {
anchorX: 0.5,
anchorY: 0.5,
x: 2000,
y: 1200,
scaleX: 1.7,
scaleY: 1.7
});
game.addChild(bushes3);
var bushes4 = LK.getAsset('bushes', {
anchorX: 0.5,
anchorY: 0.5,
x: 2000,
y: 1500,
scaleX: 1.5,
scaleY: 1.5
});
game.addChild(bushes4);
var bushes5 = LK.getAsset('bushes', {
anchorX: 0.5,
anchorY: 0.5,
x: 2000,
y: 1800,
scaleX: 1.4,
scaleY: 1.4
});
game.addChild(bushes5);
var bushes6 = LK.getAsset('bushes', {
anchorX: 0.5,
anchorY: 0.5,
x: 1900,
y: 750,
scaleX: 1.3,
scaleY: 1.3
});
game.addChild(bushes6);
var bushes7 = LK.getAsset('bushes', {
anchorX: 0.5,
anchorY: 0.5,
x: 1900,
y: 1350,
scaleX: 1.2,
scaleY: 1.2
});
game.addChild(bushes7);
var bushes8 = LK.getAsset('bushes', {
anchorX: 0.5,
anchorY: 0.5,
x: 1950,
y: 450,
scaleX: 1.6,
scaleY: 1.6
});
game.addChild(bushes8);
var bushes9 = LK.getAsset('bushes', {
anchorX: 0.5,
anchorY: 0.5,
x: 1950,
y: 1050,
scaleX: 1.4,
scaleY: 1.4
});
game.addChild(bushes9);
var bushes10 = LK.getAsset('bushes', {
anchorX: 0.5,
anchorY: 0.5,
x: 1950,
y: 1650,
scaleX: 1.5,
scaleY: 1.5
});
game.addChild(bushes10);
var bushes11 = LK.getAsset('bushes', {
anchorX: 0.5,
anchorY: 0.5,
x: 1850,
y: 600,
scaleX: 1.1,
scaleY: 1.1
});
game.addChild(bushes11);
var bushes12 = LK.getAsset('bushes', {
anchorX: 0.5,
anchorY: 0.5,
x: 1850,
y: 1200,
scaleX: 1.0,
scaleY: 1.0
});
game.addChild(bushes12);
var bushes13 = LK.getAsset('bushes', {
anchorX: 0.5,
anchorY: 0.5,
x: 1850,
y: 1800,
scaleX: 1.3,
scaleY: 1.3
});
game.addChild(bushes13);
// Initialize lawnmowers
for (var row = 0; row < gridRows; row++) {
var lawnmower = new Lawnmower();
lawnmower.x = 220;
lawnmower.y = gridStartY + row * cellSize;
game.addChild(lawnmower);
lawnmowers.push(lawnmower);
}
// Move all bushes to front to render above zombies
bushes.parent.removeChild(bushes);
game.addChild(bushes);
bushes2.parent.removeChild(bushes2);
game.addChild(bushes2);
bushes3.parent.removeChild(bushes3);
game.addChild(bushes3);
bushes4.parent.removeChild(bushes4);
game.addChild(bushes4);
bushes5.parent.removeChild(bushes5);
game.addChild(bushes5);
bushes6.parent.removeChild(bushes6);
game.addChild(bushes6);
bushes7.parent.removeChild(bushes7);
game.addChild(bushes7);
bushes8.parent.removeChild(bushes8);
game.addChild(bushes8);
bushes9.parent.removeChild(bushes9);
game.addChild(bushes9);
bushes10.parent.removeChild(bushes10);
game.addChild(bushes10);
bushes11.parent.removeChild(bushes11);
game.addChild(bushes11);
bushes12.parent.removeChild(bushes12);
game.addChild(bushes12);
bushes13.parent.removeChild(bushes13);
game.addChild(bushes13);
// Initialize loading screen
if (gameState === 'loading') {
loadingScreen = new LoadingScreen();
game.addChild(loadingScreen);
// Hide all game elements initially
hideGameElements();
}
function updateGridTiles(levelNumber) {
// Destroy existing grid tiles
for (var i = gridTiles.length - 1; i >= 0; i--) {
gridTiles[i].destroy();
}
gridTiles = [];
// Determine tile type based on level
var tileAsset = 'gridCell';
if (levelNumber > 15) {
// Roof levels
if (levelNumber === 19) {
tileAsset = 'roofTileNight'; // Night roof
} else {
tileAsset = 'roofTileDay'; // Day roof
}
}
// Create new grid with appropriate tiles
for (var row = 0; row < gridRows; row++) {
for (var col = 0; col < gridCols; col++) {
var gridCell = LK.getAsset(tileAsset, {
anchorX: 0.5,
anchorY: 0.5,
x: gridStartX + col * cellSize,
y: gridStartY + row * cellSize,
alpha: 0.3
});
game.addChild(gridCell);
gridTiles.push(gridCell);
}
}
}
function updateSunDisplay() {
sunDisplay.setText('Sun: ' + sunPoints);
}
function canAffordPlant(plantType) {
return sunPoints >= plantCosts[plantType];
}
function isSeedReady(plantType) {
return seedCooldowns[plantType] <= 0;
}
function canPlant(plantType) {
return canAffordPlant(plantType) && isSeedReady(plantType);
}
function getGridPosition(x, y) {
var col = Math.floor((x - gridStartX + cellSize / 2) / cellSize);
var row = Math.floor((y - gridStartY + cellSize / 2) / cellSize);
if (col >= 0 && col < gridCols && row >= 0 && row < gridRows) {
return {
row: row,
col: col,
x: gridStartX + col * cellSize,
y: gridStartY + row * cellSize
};
}
return null;
}
function isGridOccupied(row, col) {
for (var i = 0; i < plants.length; i++) {
var plant = plants[i];
var plantRow = Math.floor((plant.y - gridStartY + cellSize / 2) / cellSize);
var plantCol = Math.floor((plant.x - gridStartX + cellSize / 2) / cellSize);
if (plantRow === row && plantCol === col) {
return true;
}
}
return false;
}
function isPositionOnWater(row, col) {
// Check if position is on water (pool levels 11-15, rows 4-8)
var isPoolLevel = currentLevel > 10;
if (isPoolLevel && row >= 4 && row <= 8) {
return true;
}
return false;
}
function canPlantOnPosition(plantType, row, col) {
// Check what's already at this position
var hasLilypad = false;
var hasPot = false;
var isOccupied = false;
for (var i = 0; i < plants.length; i++) {
var plant = plants[i];
var plantRow = Math.floor((plant.y - gridStartY + cellSize / 2) / cellSize);
var plantCol = Math.floor((plant.x - gridStartX + cellSize / 2) / cellSize);
if (plantRow === row && plantCol === col) {
if (plant.type === 'lilypad') {
hasLilypad = true;
} else if (plant.type === 'pot') {
hasPot = true;
} else {
isOccupied = true; // Other plant types occupy space completely
}
}
}
// Check if this is a roof level
var isRoofLevel = currentLevel > 15;
// Check if this is a water position
var isWaterPos = isPositionOnWater(row, col);
// Handle roof level rules
if (isRoofLevel) {
if (plantType === 'pot') {
return !isOccupied && !hasPot; // Pot needs empty space
} else {
return hasPot && !isOccupied; // Other plants need pot and no other plants
}
}
// Handle water level rules
if (isWaterPos) {
if (plantType === 'lilypad') {
return !isOccupied && !hasLilypad; // Lilypad needs empty water
} else {
return hasLilypad && !isOccupied; // Other plants need lilypad and no other plants
}
}
// Handle regular ground rules
if (plantType === 'lilypad') {
return false; // Lilypad can only be on water
}
return !isOccupied && !hasLilypad && !hasPot; // Regular plants need completely empty space
}
function spawnTombstones() {
// Spawn 3-5 tombstones randomly on the grid for night levels
var tombstoneCount = 3 + Math.floor(Math.random() * 3);
// Define vertical middle line at column 6 (middle of 12 columns)
var middleColumn = Math.floor(gridCols / 2);
for (var i = 0; i < tombstoneCount; i++) {
var attempts = 0;
var placed = false;
while (!placed && attempts < 20) {
var randomRow = Math.floor(Math.random() * gridRows);
// Only spawn tombstones to the right of the middle line (behind middle)
var randomCol = middleColumn + Math.floor(Math.random() * (gridCols - middleColumn - 1));
// Check if position is already occupied
var occupied = false;
for (var j = 0; j < tombstones.length; j++) {
var tombstoneRow = Math.floor((tombstones[j].y - gridStartY + cellSize / 2) / cellSize);
var tombstoneCol = Math.floor((tombstones[j].x - gridStartX + cellSize / 2) / cellSize);
if (tombstoneRow === randomRow && tombstoneCol === randomCol) {
occupied = true;
break;
}
}
if (!occupied) {
var tombstone = new Tombstone();
tombstone.x = gridStartX + randomCol * cellSize;
tombstone.y = gridStartY + randomRow * cellSize;
game.addChild(tombstone);
tombstones.push(tombstone);
placed = true;
}
attempts++;
}
}
}
function spawnZombie() {
var rand = Math.random();
var zombieType = 'normal';
if (rand < 0.15) {
zombieType = 'fast';
} else if (rand < 0.25) {
zombieType = 'snailBucket';
} else if (rand < 0.35) {
zombieType = 'miner';
} else if (rand < 0.45) {
zombieType = 'cart';
} else if (rand < 0.55) {
zombieType = 'newspaper';
}
var zombie = new Zombie(zombieType);
zombie.x = 2100;
zombie.y = gridStartY + Math.floor(Math.random() * gridRows) * cellSize;
game.addChild(zombie);
zombies.push(zombie);
}
function gameOver() {
if (gameState === 'playing') {
gameState = 'lost';
LK.showGameOver();
}
}
function checkWinCondition() {
if (currentWave > maxWaves && zombies.length === 0) {
if (gameState === 'playing') {
gameState = 'won';
LK.showYouWin();
}
}
}
function showLevelSelection() {
gameState = 'levelSelect';
// Clear loading screen
if (loadingScreen) {
loadingScreen.destroy();
loadingScreen = null;
}
// Hide all game elements
hideGameElements();
// Create day level buttons (1-5)
var dayButtonSpacing = 150;
var dayStartX = 1024 - 2 * dayButtonSpacing;
for (var i = 1; i <= 5; i++) {
var levelButton = new LevelButton(i);
levelButton.x = dayStartX + (i - 1) * dayButtonSpacing;
levelButton.y = 600;
game.addChild(levelButton);
levelButtons.push(levelButton);
}
// Create night level buttons (6-10)
var nightButtonSpacing = 150;
var nightStartX = 1024 - 2 * nightButtonSpacing;
for (var j = 6; j <= 10; j++) {
var nightLevelButton = new LevelButton(j);
nightLevelButton.x = nightStartX + (j - 6) * nightButtonSpacing;
nightLevelButton.y = 900;
// Tint night buttons with dark blue
nightLevelButton.tint = 0x000080;
game.addChild(nightLevelButton);
levelButtons.push(nightLevelButton);
}
// Create pool level buttons (11-15)
var poolButtonSpacing = 150;
var poolStartX = 1024 - 2 * poolButtonSpacing;
for (var k = 11; k <= 15; k++) {
var poolLevelButton = new LevelButton(k);
poolLevelButton.x = poolStartX + (k - 11) * poolButtonSpacing;
poolLevelButton.y = 1200;
// Tint pool buttons with cyan/blue for water theme
poolLevelButton.tint = 0x00FFFF;
game.addChild(poolLevelButton);
levelButtons.push(poolLevelButton);
}
// Create roof level buttons (16-18) - day roof levels
var roofButtonSpacing = 150;
var roofStartX = 1024 - 1 * roofButtonSpacing;
for (var r = 16; r <= 18; r++) {
var roofLevelButton = new LevelButton(r);
roofLevelButton.x = roofStartX + (r - 16) * roofButtonSpacing;
roofLevelButton.y = 1500;
// Tint roof buttons with brown/gray for roof theme
roofLevelButton.tint = 0x8B4513;
game.addChild(roofLevelButton);
levelButtons.push(roofLevelButton);
}
// Create night roof boss fight button (19)
var bossLevelButton = new LevelButton(19);
bossLevelButton.x = 1024;
bossLevelButton.y = 1800;
// Tint boss button with dark red for boss theme
bossLevelButton.tint = 0x8B0000;
// Make boss button bigger to indicate it's special
bossLevelButton.scaleX = 1.5;
bossLevelButton.scaleY = 1.5;
game.addChild(bossLevelButton);
levelButtons.push(bossLevelButton);
}
function hideDayPlants() {
sunflowerButton.visible = false;
peashooterButton.visible = false;
wallnutButton.visible = false;
potatomineButton.visible = false;
carnivorousplantButton.visible = false;
doomshroomButton.visible = false;
repeaterButton.visible = false;
threepeaterButton.visible = false;
spikeButton.visible = false;
splitpeaterButton.visible = false;
lilypadButton.visible = false;
melonpultaButton.visible = false;
coltapultaButton.visible = false;
lanzamaizButton.visible = false;
sunflowerCost.visible = false;
peashooterCost.visible = false;
wallnutCost.visible = false;
potatomineeCost.visible = false;
carnivorousplantCost.visible = false;
doomshroomCost.visible = false;
repeaterCost.visible = false;
threepeaterCost.visible = false;
spikeCost.visible = false;
splitpeaterCost.visible = false;
lilypadCost.visible = false;
melonpultaCost.visible = false;
coltapultaCost.visible = false;
lanzamaizCost.visible = false;
potButton.visible = false;
potCost.visible = false;
}
function showDayPlants() {
sunflowerButton.visible = true;
peashooterButton.visible = true;
wallnutButton.visible = true;
potatomineButton.visible = true;
carnivorousplantButton.visible = true;
doomshroomButton.visible = true;
repeaterButton.visible = true;
threepeaterButton.visible = true;
spikeButton.visible = true;
splitpeaterButton.visible = true;
lilypadButton.visible = true;
sunflowerCost.visible = true;
peashooterCost.visible = true;
wallnutCost.visible = true;
potatomineeCost.visible = true;
carnivorousplantCost.visible = true;
doomshroomCost.visible = true;
repeaterCost.visible = true;
threepeaterCost.visible = true;
spikeCost.visible = true;
splitpeaterCost.visible = true;
lilypadCost.visible = true;
}
function createNightPlantButtons() {
// Create night plant buttons
var puffshroomButton = LK.getAsset('puffshroom', {
anchorX: 0.5,
anchorY: 0.5,
x: 200,
y: 2100,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(puffshroomButton);
var sunshroomButton = LK.getAsset('sunshroom', {
anchorX: 0.5,
anchorY: 0.5,
x: 300,
y: 2100,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(sunshroomButton);
var fumeshroomButton = LK.getAsset('fumeshroom', {
anchorX: 0.5,
anchorY: 0.5,
x: 400,
y: 2100,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(fumeshroomButton);
var gravebusterButton = LK.getAsset('gravebuster', {
anchorX: 0.5,
anchorY: 0.5,
x: 500,
y: 2100,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(gravebusterButton);
var hypnoshroomButton = LK.getAsset('hypnoshroom', {
anchorX: 0.5,
anchorY: 0.5,
x: 600,
y: 2100,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(hypnoshroomButton);
var scaredyshroomButton = LK.getAsset('scaredyshroom', {
anchorX: 0.5,
anchorY: 0.5,
x: 700,
y: 2100,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(scaredyshroomButton);
var iceshroomButton = LK.getAsset('iceshroom', {
anchorX: 0.5,
anchorY: 0.5,
x: 800,
y: 2100,
scaleX: 0.8,
scaleY: 0.8
});
game.addChild(iceshroomButton);
// Create night plant cost labels
var puffshroomCost = new Text2('0', {
size: 20,
fill: 0xFFFFFF
});
puffshroomCost.anchor.set(0.5, 0);
puffshroomCost.x = 200;
puffshroomCost.y = 2140;
game.addChild(puffshroomCost);
var sunshroomCost = new Text2('25', {
size: 20,
fill: 0xFFFFFF
});
sunshroomCost.anchor.set(0.5, 0);
sunshroomCost.x = 300;
sunshroomCost.y = 2140;
game.addChild(sunshroomCost);
var fumeshroomCost = new Text2('75', {
size: 20,
fill: 0xFFFFFF
});
fumeshroomCost.anchor.set(0.5, 0);
fumeshroomCost.x = 400;
fumeshroomCost.y = 2140;
game.addChild(fumeshroomCost);
var gravebusterCost = new Text2('75', {
size: 20,
fill: 0xFFFFFF
});
gravebusterCost.anchor.set(0.5, 0);
gravebusterCost.x = 500;
gravebusterCost.y = 2140;
game.addChild(gravebusterCost);
var hypnoshroomCost = new Text2('75', {
size: 20,
fill: 0xFFFFFF
});
hypnoshroomCost.anchor.set(0.5, 0);
hypnoshroomCost.x = 600;
hypnoshroomCost.y = 2140;
game.addChild(hypnoshroomCost);
var scaredyshroomCost = new Text2('25', {
size: 20,
fill: 0xFFFFFF
});
scaredyshroomCost.anchor.set(0.5, 0);
scaredyshroomCost.x = 700;
scaredyshroomCost.y = 2140;
game.addChild(scaredyshroomCost);
var iceshroomCost = new Text2('75', {
size: 20,
fill: 0xFFFFFF
});
iceshroomCost.anchor.set(0.5, 0);
iceshroomCost.x = 800;
iceshroomCost.y = 2140;
game.addChild(iceshroomCost);
// Add event handlers for night plant buttons
puffshroomButton.down = function (x, y, obj) {
if (canPlant('puffshroom')) {
selectedPlantType = 'puffshroom';
shovelSelected = false;
}
};
sunshroomButton.down = function (x, y, obj) {
if (canPlant('sunshroom')) {
selectedPlantType = 'sunshroom';
shovelSelected = false;
}
};
fumeshroomButton.down = function (x, y, obj) {
if (canPlant('fumeshroom')) {
selectedPlantType = 'fumeshroom';
shovelSelected = false;
}
};
gravebusterButton.down = function (x, y, obj) {
if (canPlant('gravebuster')) {
selectedPlantType = 'gravebuster';
shovelSelected = false;
}
};
hypnoshroomButton.down = function (x, y, obj) {
if (canPlant('hypnoshroom')) {
selectedPlantType = 'hypnoshroom';
shovelSelected = false;
}
};
scaredyshroomButton.down = function (x, y, obj) {
if (canPlant('scaredyshroom')) {
selectedPlantType = 'scaredyshroom';
shovelSelected = false;
}
};
iceshroomButton.down = function (x, y, obj) {
if (canPlant('iceshroom')) {
selectedPlantType = 'iceshroom';
shovelSelected = false;
}
};
}
function hideGameElements() {
// Hide all UI elements
sunDisplay.alpha = 0;
waveDisplay.alpha = 0;
// Hide all plant buttons
sunflowerButton.alpha = 0;
peashooterButton.alpha = 0;
wallnutButton.alpha = 0;
potatomineButton.alpha = 0;
carnivorousplantButton.alpha = 0;
doomshroomButton.alpha = 0;
repeaterButton.alpha = 0;
threepeaterButton.alpha = 0;
spikeButton.alpha = 0;
splitpeaterButton.alpha = 0;
restartButton.alpha = 0;
shovelButton.alpha = 0;
// Hide cost labels
sunflowerCost.alpha = 0;
peashooterCost.alpha = 0;
wallnutCost.alpha = 0;
potatomineeCost.alpha = 0;
carnivorousplantCost.alpha = 0;
doomshroomCost.alpha = 0;
repeaterCost.alpha = 0;
threepeaterCost.alpha = 0;
spikeCost.alpha = 0;
splitpeaterCost.alpha = 0;
lilypadCost.alpha = 0;
restartText.alpha = 0;
// Hide lilypad button
lilypadButton.alpha = 0;
// Hide exit button
exitLevelButton.alpha = 0;
exitText.alpha = 0;
// Hide boss health display
bossHealthDisplay.visible = false;
}
function showGameElements() {
// Show all UI elements
sunDisplay.alpha = 1;
waveDisplay.alpha = 1;
// Show all plant buttons
sunflowerButton.alpha = 1;
peashooterButton.alpha = 1;
wallnutButton.alpha = 1;
potatomineButton.alpha = 1;
carnivorousplantButton.alpha = 1;
doomshroomButton.alpha = 1;
repeaterButton.alpha = 1;
threepeaterButton.alpha = 1;
spikeButton.alpha = 1;
splitpeaterButton.alpha = 1;
restartButton.alpha = 1;
shovelButton.alpha = 1;
// Show cost labels
sunflowerCost.alpha = 1;
peashooterCost.alpha = 1;
wallnutCost.alpha = 1;
potatomineeCost.alpha = 1;
carnivorousplantCost.alpha = 1;
doomshroomCost.alpha = 1;
repeaterCost.alpha = 1;
threepeaterCost.alpha = 1;
spikeCost.alpha = 1;
splitpeaterCost.alpha = 1;
lilypadCost.alpha = 1;
restartText.alpha = 1;
// Show lilypad button
lilypadButton.alpha = 1;
// Show exit button
exitLevelButton.alpha = 1;
exitText.alpha = 1;
}
function startLevel(levelNumber) {
currentLevel = levelNumber;
gameState = 'playing';
// Clear level selection elements
for (var i = levelButtons.length - 1; i >= 0; i--) {
levelButtons[i].destroy();
}
levelButtons = [];
// Show game elements
showGameElements();
// Reset game based on level
resetGameForLevel(levelNumber);
}
function resetGameForLevel(levelNumber) {
// Reset all game variables
sunPoints = 150;
currentWave = 1;
maxZombiesInWave = 20 + (levelNumber - 1) * 10; // Increase difficulty per level
maxWaves = 3 + levelNumber; // More waves for higher levels
waveSpawnTimer = 0;
zombiesInWave = 0;
selectedPlantType = null;
shovelSelected = false;
// Set mode based on level number
var isNightMode = levelNumber > 5 && levelNumber <= 10 || levelNumber === 19;
var isPoolMode = levelNumber > 10 && levelNumber <= 15;
var isRoofMode = levelNumber > 15;
if (isRoofMode && levelNumber === 19) {
// Night roof boss fight - only allow sunflower, doomshroom, wallnut, carnivorousplant, melonpulta, coltapulta, lanzamaiz
game.setBackgroundColor(0x0F0F23); // Very dark night background
sunPoints = 50; // Very little sun for boss fight
hideDayPlants();
// Show only specific plants for roof levels
sunflowerButton.visible = true;
wallnutButton.visible = true;
carnivorousplantButton.visible = true;
doomshroomButton.visible = true;
sunflowerCost.visible = true;
wallnutCost.visible = true;
carnivorousplantCost.visible = true;
doomshroomCost.visible = true;
// Show catapult plants for night roof boss level
melonpultaButton.visible = true;
coltapultaButton.visible = true;
lanzamaizButton.visible = true;
melonpultaCost.visible = true;
coltapultaCost.visible = true;
lanzamaizCost.visible = true;
// Show pot plant for roof levels
potButton.visible = true;
potCost.visible = true;
// Show boss health display
bossHealthDisplay.visible = true;
maxZombiesInWave = 50 + (levelNumber - 1) * 15; // Much harder boss fight
maxWaves = 5 + levelNumber; // Many waves for boss
} else if (isRoofMode) {
// Day roof levels - only allow sunflower, doomshroom, wallnut, carnivorousplant, melonpulta, coltapulta, lanzamaiz
game.setBackgroundColor(0x696969); // Gray roof background
sunPoints = 125; // Medium-low sun for roof levels
hideDayPlants();
// Show only specific plants for roof levels
sunflowerButton.visible = true;
wallnutButton.visible = true;
carnivorousplantButton.visible = true;
doomshroomButton.visible = true;
sunflowerCost.visible = true;
wallnutCost.visible = true;
carnivorousplantCost.visible = true;
doomshroomCost.visible = true;
// Show catapult plants for day roof levels
melonpultaButton.visible = true;
coltapultaButton.visible = true;
lanzamaizButton.visible = true;
melonpultaCost.visible = true;
coltapultaCost.visible = true;
lanzamaizCost.visible = true;
// Show pot plant for roof levels
potButton.visible = true;
potCost.visible = true;
} else if (isPoolMode) {
game.setBackgroundColor(0x006994); // Blue pool background
sunPoints = 100; // Medium sun for pool levels
showDayPlants(); // Pool levels use day plants
} else if (isNightMode) {
game.setBackgroundColor(0x1a1a2e); // Dark blue night background
sunPoints = 75; // Start with less sun at night
hideDayPlants(); // Hide day plants
createNightPlantButtons(); // Show night plants
} else {
game.setBackgroundColor(0x228B22); // Green day background
showDayPlants(); // Show day plants
// Hide boss health display for non-boss levels
bossHealthDisplay.visible = false;
}
// Clear all arrays and destroy objects
for (var i = plants.length - 1; i >= 0; i--) {
plants[i].destroy();
}
plants = [];
for (var j = zombies.length - 1; j >= 0; j--) {
zombies[j].destroy();
}
zombies = [];
for (var k = peas.length - 1; k >= 0; k--) {
peas[k].destroy();
}
peas = [];
for (var l = suns.length - 1; l >= 0; l--) {
suns[l].destroy();
}
suns = [];
for (var m = lawnmowers.length - 1; m >= 0; m--) {
lawnmowers[m].destroy();
}
lawnmowers = [];
for (var t = tombstones.length - 1; t >= 0; t--) {
tombstones[t].destroy();
}
tombstones = [];
// Clear boss-specific objects
if (conveyorBelt) {
conveyorBelt.destroy();
conveyorBelt = null;
}
if (robotBoss) {
robotBoss.destroy();
robotBoss = null;
}
for (var f = fireballs.length - 1; f >= 0; f--) {
fireballs[f].destroy();
}
fireballs = [];
// Create boss-specific objects for level 19
if (isRoofMode && levelNumber === 19) {
// Create conveyor belt for boss level
conveyorBelt = new ConveyorBelt();
conveyorBelt.x = 1024; // Center of screen
conveyorBelt.y = 200; // Top area
game.addChild(conveyorBelt);
// Create robot boss
robotBoss = new RobotBoss();
robotBoss.x = 1800; // Right side of screen
robotBoss.y = 1000; // Middle vertically
game.addChild(robotBoss);
}
// Spawn tombstones for night levels after clearing existing ones (but not for boss fight)
if (isNightMode && levelNumber !== 19) {
spawnTombstones();
}
// Reset seed cooldowns
for (var seedType in seedCooldowns) {
seedCooldowns[seedType] = 0;
}
// Reinitialize lawnmowers
for (var row = 0; row < gridRows; row++) {
var lawnmower = new Lawnmower();
lawnmower.x = 220;
lawnmower.y = gridStartY + row * cellSize;
game.addChild(lawnmower);
lawnmowers.push(lawnmower);
}
// Add water tiles for pool levels (11-15)
if (isPoolMode) {
// Add water in the middle rows (approximately rows 4-8) for all columns
for (var waterRow = 4; waterRow <= 8; waterRow++) {
for (var waterCol = 0; waterCol < gridCols; waterCol++) {
var waterTile = LK.getAsset('water', {
anchorX: 0.5,
anchorY: 0.5,
x: gridStartX + waterCol * cellSize,
y: gridStartY + waterRow * cellSize,
alpha: 0.7
});
game.addChild(waterTile);
waterTiles.push(waterTile);
}
}
}
// Update grid tiles for roof levels
if (isRoofMode) {
updateGridTiles(levelNumber);
// Hide bushes for roof levels
bushes.visible = false;
bushes2.visible = false;
bushes3.visible = false;
bushes4.visible = false;
bushes5.visible = false;
bushes6.visible = false;
bushes7.visible = false;
bushes8.visible = false;
bushes9.visible = false;
bushes10.visible = false;
bushes11.visible = false;
bushes12.visible = false;
bushes13.visible = false;
} else {
// Show bushes for non-roof levels
bushes.visible = true;
bushes2.visible = true;
bushes3.visible = true;
bushes4.visible = true;
bushes5.visible = true;
bushes6.visible = true;
bushes7.visible = true;
bushes8.visible = true;
bushes9.visible = true;
bushes10.visible = true;
bushes11.visible = true;
bushes12.visible = true;
bushes13.visible = true;
}
// Add 3 vertical lines of pots for roof levels
if (isRoofMode) {
// Create 3 vertical lines of pots at the first 3 columns from the left (0, 1, 2)
var potColumns = [0, 1, 2];
for (var potColIndex = 0; potColIndex < potColumns.length; potColIndex++) {
var potCol = potColumns[potColIndex];
for (var potRow = 0; potRow < gridRows; potRow++) {
var potPlant = new Plant('pot');
potPlant.x = gridStartX + potCol * cellSize;
potPlant.y = gridStartY + potRow * cellSize;
game.addChild(potPlant);
plants.push(potPlant);
}
}
}
// Update displays
updateSunDisplay();
waveDisplay.setText('Wave: ' + currentWave + '/' + maxWaves);
}
// Button event handlers
sunflowerButton.down = function (x, y, obj) {
if (canPlant('sunflower')) {
selectedPlantType = 'sunflower';
shovelSelected = false;
sunflowerButton.alpha = 1;
sunflowerButton.tint = 0x808080;
peashooterButton.alpha = isSeedReady('peashooter') ? 1 : 0.5;
peashooterButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
potatomineButton.alpha = isSeedReady('potatomine') ? 1 : 0.5;
potatomineButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
repeaterButton.alpha = isSeedReady('repeater') ? 1 : 0.5;
repeaterButton.tint = 0xffffff;
threepeaterButton.alpha = isSeedReady('threepeater') ? 1 : 0.5;
threepeaterButton.tint = 0xffffff;
spikeButton.alpha = isSeedReady('spikeweed') ? 1 : 0.5;
spikeButton.tint = 0xffffff;
splitpeaterButton.alpha = isSeedReady('splitpeater') ? 1 : 0.5;
splitpeaterButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
}
};
peashooterButton.down = function (x, y, obj) {
if (canPlant('peashooter')) {
selectedPlantType = 'peashooter';
shovelSelected = false;
peashooterButton.alpha = 1;
peashooterButton.tint = 0x808080;
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
potatomineButton.alpha = isSeedReady('potatomine') ? 1 : 0.5;
potatomineButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
repeaterButton.alpha = isSeedReady('repeater') ? 1 : 0.5;
repeaterButton.tint = 0xffffff;
threepeaterButton.alpha = isSeedReady('threepeater') ? 1 : 0.5;
threepeaterButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
}
};
wallnutButton.down = function (x, y, obj) {
if (canPlant('wallnut')) {
selectedPlantType = 'wallnut';
shovelSelected = false;
wallnutButton.alpha = 1;
wallnutButton.tint = 0x808080;
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
peashooterButton.alpha = isSeedReady('peashooter') ? 1 : 0.5;
peashooterButton.tint = 0xffffff;
potatomineButton.alpha = isSeedReady('potatomine') ? 1 : 0.5;
potatomineButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
repeaterButton.alpha = isSeedReady('repeater') ? 1 : 0.5;
repeaterButton.tint = 0xffffff;
threepeaterButton.alpha = isSeedReady('threepeater') ? 1 : 0.5;
threepeaterButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
}
};
potatomineButton.down = function (x, y, obj) {
if (canPlant('potatomine')) {
selectedPlantType = 'potatomine';
shovelSelected = false;
potatomineButton.alpha = 1;
potatomineButton.tint = 0x808080;
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
peashooterButton.alpha = isSeedReady('peashooter') ? 1 : 0.5;
peashooterButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
repeaterButton.alpha = isSeedReady('repeater') ? 1 : 0.5;
repeaterButton.tint = 0xffffff;
threepeaterButton.alpha = isSeedReady('threepeater') ? 1 : 0.5;
threepeaterButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
}
};
carnivorousplantButton.down = function (x, y, obj) {
if (canPlant('carnivorousplant')) {
selectedPlantType = 'carnivorousplant';
shovelSelected = false;
carnivorousplantButton.alpha = 1;
carnivorousplantButton.tint = 0x808080;
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
peashooterButton.alpha = isSeedReady('peashooter') ? 1 : 0.5;
peashooterButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
potatomineButton.alpha = isSeedReady('potatomine') ? 1 : 0.5;
potatomineButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
repeaterButton.alpha = isSeedReady('repeater') ? 1 : 0.5;
repeaterButton.tint = 0xffffff;
threepeaterButton.alpha = isSeedReady('threepeater') ? 1 : 0.5;
threepeaterButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
}
};
doomshroomButton.down = function (x, y, obj) {
if (canPlant('doomshroom')) {
selectedPlantType = 'doomshroom';
shovelSelected = false;
doomshroomButton.alpha = 1;
doomshroomButton.tint = 0x808080;
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
peashooterButton.alpha = isSeedReady('peashooter') ? 1 : 0.5;
peashooterButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
potatomineButton.alpha = isSeedReady('potatomine') ? 1 : 0.5;
potatomineButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
repeaterButton.alpha = isSeedReady('repeater') ? 1 : 0.5;
repeaterButton.tint = 0xffffff;
threepeaterButton.alpha = isSeedReady('threepeater') ? 1 : 0.5;
threepeaterButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
}
};
repeaterButton.down = function (x, y, obj) {
if (canPlant('repeater')) {
selectedPlantType = 'repeater';
shovelSelected = false;
repeaterButton.alpha = 1;
repeaterButton.tint = 0x808080;
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
peashooterButton.alpha = isSeedReady('peashooter') ? 1 : 0.5;
peashooterButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
potatomineButton.alpha = isSeedReady('potatomine') ? 1 : 0.5;
potatomineButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
threepeaterButton.alpha = isSeedReady('threepeater') ? 1 : 0.5;
threepeaterButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
}
};
threepeaterButton.down = function (x, y, obj) {
if (canPlant('threepeater')) {
selectedPlantType = 'threepeater';
shovelSelected = false;
threepeaterButton.alpha = 1;
threepeaterButton.tint = 0x808080;
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
peashooterButton.alpha = isSeedReady('peashooter') ? 1 : 0.5;
peashooterButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
potatomineButton.alpha = isSeedReady('potatomine') ? 1 : 0.5;
potatomineButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
repeaterButton.alpha = isSeedReady('repeater') ? 1 : 0.5;
repeaterButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
}
};
spikeButton.down = function (x, y, obj) {
if (canPlant('spikeweed')) {
selectedPlantType = 'spikeweed';
shovelSelected = false;
spikeButton.alpha = 1;
spikeButton.tint = 0x808080;
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
peashooterButton.alpha = isSeedReady('peashooter') ? 1 : 0.5;
peashooterButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
potatomineButton.alpha = isSeedReady('potatomine') ? 1 : 0.5;
potatomineButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
repeaterButton.alpha = isSeedReady('repeater') ? 1 : 0.5;
repeaterButton.tint = 0xffffff;
threepeaterButton.alpha = isSeedReady('threepeater') ? 1 : 0.5;
threepeaterButton.tint = 0xffffff;
splitpeaterButton.alpha = isSeedReady('splitpeater') ? 1 : 0.5;
splitpeaterButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
}
};
splitpeaterButton.down = function (x, y, obj) {
if (canPlant('splitpeater')) {
selectedPlantType = 'splitpeater';
shovelSelected = false;
splitpeaterButton.alpha = 1;
splitpeaterButton.tint = 0x808080;
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
peashooterButton.alpha = isSeedReady('peashooter') ? 1 : 0.5;
peashooterButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
potatomineButton.alpha = isSeedReady('potatomine') ? 1 : 0.5;
potatomineButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
repeaterButton.alpha = isSeedReady('repeater') ? 1 : 0.5;
repeaterButton.tint = 0xffffff;
threepeaterButton.alpha = isSeedReady('threepeater') ? 1 : 0.5;
threepeaterButton.tint = 0xffffff;
spikeButton.alpha = isSeedReady('spikeweed') ? 1 : 0.5;
spikeButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
}
};
restartButton.down = function (x, y, obj) {
// Reset all game variables
sunPoints = 150;
currentWave = 1;
maxZombiesInWave = 30;
waveSpawnTimer = 0;
zombiesInWave = 0;
selectedPlantType = null;
shovelSelected = false;
gameState = 'playing';
// Clear all arrays and destroy objects
for (var i = plants.length - 1; i >= 0; i--) {
plants[i].destroy();
}
plants = [];
for (var j = zombies.length - 1; j >= 0; j--) {
zombies[j].destroy();
}
zombies = [];
for (var k = peas.length - 1; k >= 0; k--) {
peas[k].destroy();
}
peas = [];
for (var l = suns.length - 1; l >= 0; l--) {
suns[l].destroy();
}
suns = [];
for (var m = lawnmowers.length - 1; m >= 0; m--) {
lawnmowers[m].destroy();
}
lawnmowers = [];
for (var n = waterTiles.length - 1; n >= 0; n--) {
waterTiles[n].destroy();
}
waterTiles = [];
for (var t = tombstones.length - 1; t >= 0; t--) {
tombstones[t].destroy();
}
tombstones = [];
// Reset seed cooldowns
for (var seedType in seedCooldowns) {
seedCooldowns[seedType] = 0;
}
// Reinitialize lawnmowers
for (var row = 0; row < gridRows; row++) {
var lawnmower = new Lawnmower();
lawnmower.x = 220;
lawnmower.y = gridStartY + row * cellSize;
game.addChild(lawnmower);
lawnmowers.push(lawnmower);
}
// Update displays
updateSunDisplay();
waveDisplay.setText('Wave: ' + currentWave + '/' + maxWaves);
// Reset button states
sunflowerButton.alpha = 1;
sunflowerButton.tint = 0xffffff;
peashooterButton.alpha = 1;
peashooterButton.tint = 0xffffff;
wallnutButton.alpha = 1;
wallnutButton.tint = 0xffffff;
potatomineButton.alpha = 1;
potatomineButton.tint = 0xffffff;
carnivorousplantButton.alpha = 1;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = 1;
doomshroomButton.tint = 0xffffff;
repeaterButton.alpha = 1;
repeaterButton.tint = 0xffffff;
threepeaterButton.alpha = 1;
threepeaterButton.tint = 0xffffff;
spikeButton.alpha = 1;
spikeButton.tint = 0xffffff;
splitpeaterButton.alpha = 1;
splitpeaterButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
};
lilypadButton.down = function (x, y, obj) {
if (canPlant('lilypad')) {
selectedPlantType = 'lilypad';
shovelSelected = false;
lilypadButton.alpha = 1;
lilypadButton.tint = 0x808080;
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
peashooterButton.alpha = isSeedReady('peashooter') ? 1 : 0.5;
peashooterButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
potatomineButton.alpha = isSeedReady('potatomine') ? 1 : 0.5;
potatomineButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
repeaterButton.alpha = isSeedReady('repeater') ? 1 : 0.5;
repeaterButton.tint = 0xffffff;
threepeaterButton.alpha = isSeedReady('threepeater') ? 1 : 0.5;
threepeaterButton.tint = 0xffffff;
spikeButton.alpha = isSeedReady('spikeweed') ? 1 : 0.5;
spikeButton.tint = 0xffffff;
splitpeaterButton.alpha = isSeedReady('splitpeater') ? 1 : 0.5;
splitpeaterButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
}
};
shovelButton.down = function (x, y, obj) {
shovelSelected = true;
selectedPlantType = null;
shovelButton.alpha = 1;
shovelButton.tint = 0x808080;
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
peashooterButton.alpha = isSeedReady('peashooter') ? 1 : 0.5;
peashooterButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
potatomineButton.alpha = isSeedReady('potatomine') ? 1 : 0.5;
potatomineButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
repeaterButton.alpha = isSeedReady('repeater') ? 1 : 0.5;
repeaterButton.tint = 0xffffff;
threepeaterButton.alpha = isSeedReady('threepeater') ? 1 : 0.5;
threepeaterButton.tint = 0xffffff;
spikeButton.alpha = 1;
spikeButton.tint = 0xffffff;
lilypadButton.alpha = 1;
lilypadButton.tint = 0xffffff;
};
// Add event handlers for catapult plant buttons
melonpultaButton.down = function (x, y, obj) {
if (canPlant('melonpulta')) {
selectedPlantType = 'melonpulta';
shovelSelected = false;
melonpultaButton.alpha = 1;
melonpultaButton.tint = 0x808080;
// Reset other buttons
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
coltapultaButton.alpha = isSeedReady('coltapulta') ? 1 : 0.5;
coltapultaButton.tint = 0xffffff;
lanzamaizButton.alpha = isSeedReady('lanzamaiz') ? 1 : 0.5;
lanzamaizButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
}
};
coltapultaButton.down = function (x, y, obj) {
if (canPlant('coltapulta')) {
selectedPlantType = 'coltapulta';
shovelSelected = false;
coltapultaButton.alpha = 1;
coltapultaButton.tint = 0x808080;
// Reset other buttons
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
melonpultaButton.alpha = isSeedReady('melonpulta') ? 1 : 0.5;
melonpultaButton.tint = 0xffffff;
lanzamaizButton.alpha = isSeedReady('lanzamaiz') ? 1 : 0.5;
lanzamaizButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
}
};
lanzamaizButton.down = function (x, y, obj) {
if (canPlant('lanzamaiz')) {
selectedPlantType = 'lanzamaiz';
shovelSelected = false;
lanzamaizButton.alpha = 1;
lanzamaizButton.tint = 0x808080;
// Reset other buttons
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
melonpultaButton.alpha = isSeedReady('melonpulta') ? 1 : 0.5;
melonpultaButton.tint = 0xffffff;
coltapultaButton.alpha = isSeedReady('coltapulta') ? 1 : 0.5;
coltapultaButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
}
};
// Add event handler for pot plant button
potButton.down = function (x, y, obj) {
if (canPlant('pot')) {
selectedPlantType = 'pot';
shovelSelected = false;
potButton.alpha = 1;
potButton.tint = 0x808080;
// Reset other buttons
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
melonpultaButton.alpha = isSeedReady('melonpulta') ? 1 : 0.5;
melonpultaButton.tint = 0xffffff;
coltapultaButton.alpha = isSeedReady('coltapulta') ? 1 : 0.5;
coltapultaButton.tint = 0xffffff;
lanzamaizButton.alpha = isSeedReady('lanzamaiz') ? 1 : 0.5;
lanzamaizButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
}
};
exitLevelButton.down = function (x, y, obj) {
// Clear all game objects and return to level selection
// Clear plants first to ensure they visually disappear
for (var i = plants.length - 1; i >= 0; i--) {
plants[i].destroy();
}
plants = [];
for (var j = zombies.length - 1; j >= 0; j--) {
zombies[j].destroy();
}
zombies = [];
for (var k = peas.length - 1; k >= 0; k--) {
peas[k].destroy();
}
peas = [];
for (var l = suns.length - 1; l >= 0; l--) {
suns[l].destroy();
}
suns = [];
for (var m = lawnmowers.length - 1; m >= 0; m--) {
lawnmowers[m].destroy();
}
lawnmowers = [];
for (var n = waterTiles.length - 1; n >= 0; n--) {
waterTiles[n].destroy();
}
waterTiles = [];
for (var t = tombstones.length - 1; t >= 0; t--) {
tombstones[t].destroy();
}
tombstones = [];
// Clear seed cooldowns for night mode
for (var seedType in seedCooldowns) {
seedCooldowns[seedType] = 0;
}
// Return to level selection
showLevelSelection();
};
// Game event handlers
game.down = function (x, y, obj) {
if (shovelSelected) {
// Remove plant functionality
var gridPos = getGridPosition(x, y);
if (gridPos) {
for (var i = plants.length - 1; i >= 0; i--) {
var plant = plants[i];
var plantRow = Math.floor((plant.y - gridStartY + cellSize / 2) / cellSize);
var plantCol = Math.floor((plant.x - gridStartX + cellSize / 2) / cellSize);
if (plantRow === gridPos.row && plantCol === gridPos.col) {
plant.destroy();
plants.splice(i, 1);
shovelSelected = false;
// Reset button alphas and tints
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
peashooterButton.alpha = isSeedReady('peashooter') ? 1 : 0.5;
peashooterButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
potatomineButton.alpha = isSeedReady('potatomine') ? 1 : 0.5;
potatomineButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
repeaterButton.alpha = isSeedReady('repeater') ? 1 : 0.5;
repeaterButton.tint = 0xffffff;
threepeaterButton.alpha = isSeedReady('threepeater') ? 1 : 0.5;
threepeaterButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
break;
}
}
}
} else if (selectedPlantType) {
var gridPos = getGridPosition(x, y);
if (gridPos && canPlantOnPosition(selectedPlantType, gridPos.row, gridPos.col)) {
// For conveyor belt seeds (boss level), don't check sun cost or cooldown
var isBossLevel = currentLevel === 19;
var canPlaceFromBelt = isBossLevel && seedCooldowns[selectedPlantType] === 0;
var canPlaceNormal = !isBossLevel && canPlant(selectedPlantType);
if (canPlaceFromBelt || canPlaceNormal) {
// Only deduct sun points for non-boss levels
if (!isBossLevel) {
sunPoints -= plantCosts[selectedPlantType];
updateSunDisplay();
// Start seed recharge for normal levels
seedCooldowns[selectedPlantType] = seedRechargeTime;
}
var newPlant = new Plant(selectedPlantType);
newPlant.x = gridPos.x;
newPlant.y = gridPos.y;
game.addChild(newPlant);
plants.push(newPlant);
LK.getSound('plant').play();
selectedPlantType = null;
// Reset button alphas and tints based on cooldown status
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
sunflowerButton.tint = 0xffffff;
peashooterButton.alpha = isSeedReady('peashooter') ? 1 : 0.5;
peashooterButton.tint = 0xffffff;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
wallnutButton.tint = 0xffffff;
potatomineButton.alpha = isSeedReady('potatomine') ? 1 : 0.5;
potatomineButton.tint = 0xffffff;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
carnivorousplantButton.tint = 0xffffff;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
doomshroomButton.tint = 0xffffff;
repeaterButton.alpha = isSeedReady('repeater') ? 1 : 0.5;
repeaterButton.tint = 0xffffff;
threepeaterButton.alpha = isSeedReady('threepeater') ? 1 : 0.5;
threepeaterButton.tint = 0xffffff;
shovelButton.alpha = 1;
shovelButton.tint = 0xffffff;
}
}
}
};
// Main game update loop
game.update = function () {
if (gameState === 'loading') {
// Loading screen handles its own updates
return;
} else if (gameState === 'levelSelect') {
// Level selection screen - no game updates needed
return;
} else if (gameState !== 'playing') {
return;
}
// Wave management
waveSpawnTimer++;
if (currentWave <= maxWaves) {
// Only spawn zombies if not boss level (level 19) - boss will spawn them
if (currentLevel !== 19 && waveSpawnTimer >= 1500 && zombiesInWave < maxZombiesInWave) {
// Spawn 1 zombie every 25 seconds (1500 ticks)
spawnZombie();
zombiesInWave++;
waveSpawnTimer = 0;
} else if (zombiesInWave >= maxZombiesInWave && zombies.length === 0) {
// Wave completed
currentWave++;
zombiesInWave = 0;
maxZombiesInWave += 5; // Increase difficulty more
waveDisplay.setText('Wave: ' + currentWave + '/' + maxWaves);
}
}
// Pea vs Zombie collision
for (var i = peas.length - 1; i >= 0; i--) {
var pea = peas[i];
var peaHit = false;
for (var j = zombies.length - 1; j >= 0; j--) {
var zombie = zombies[j];
if (Math.abs(pea.x - zombie.x) < 50 && Math.abs(pea.y - zombie.y) < 50) {
if (zombie.takeDamage(pea.damage)) {
zombie.destroy();
zombies.splice(j, 1);
}
pea.destroy();
peas.splice(i, 1);
peaHit = true;
break;
}
}
if (!peaHit && pea.x > 2200) {
pea.destroy();
peas.splice(i, 1);
}
}
// Remove destroyed suns
for (var k = suns.length - 1; k >= 0; k--) {
if (suns[k].collected) {
suns.splice(k, 1);
}
}
// Update seed cooldowns
for (var seedType in seedCooldowns) {
if (seedCooldowns[seedType] > 0) {
seedCooldowns[seedType]--;
}
}
// Lawnmower activation - check if zombies reach the left side
for (var m = zombies.length - 1; m >= 0; m--) {
var zombie = zombies[m];
if (zombie.x < 250) {
var zombieRow = Math.floor((zombie.y - gridStartY + cellSize / 2) / cellSize);
if (zombieRow >= 0 && zombieRow < lawnmowers.length && !lawnmowers[zombieRow].activated) {
lawnmowers[zombieRow].activated = true;
// Remove zombie that triggered the lawnmower
zombie.destroy();
zombies.splice(m, 1);
}
}
}
// Remove lawnmowers that are off screen
for (var n = lawnmowers.length - 1; n >= 0; n--) {
if (lawnmowers[n].x > 2200) {
lawnmowers.splice(n, 1);
}
}
// Lawnmower vs zombie collision
for (var p = 0; p < lawnmowers.length; p++) {
var lawnmower = lawnmowers[p];
if (lawnmower.activated) {
for (var q = zombies.length - 1; q >= 0; q--) {
var zombie = zombies[q];
if (Math.abs(lawnmower.x - zombie.x) < 60 && Math.abs(lawnmower.y - zombie.y) < 60) {
zombie.destroy();
zombies.splice(q, 1);
}
}
}
}
// Update button visual states based on cooldowns
sunflowerButton.alpha = isSeedReady('sunflower') ? 1 : 0.5;
peashooterButton.alpha = isSeedReady('peashooter') ? 1 : 0.5;
wallnutButton.alpha = isSeedReady('wallnut') ? 1 : 0.5;
potatomineButton.alpha = isSeedReady('potatomine') ? 1 : 0.5;
carnivorousplantButton.alpha = isSeedReady('carnivorousplant') ? 1 : 0.5;
doomshroomButton.alpha = isSeedReady('doomshroom') ? 1 : 0.5;
repeaterButton.alpha = isSeedReady('repeater') ? 1 : 0.5;
threepeaterButton.alpha = isSeedReady('threepeater') ? 1 : 0.5;
spikeButton.alpha = isSeedReady('spikeweed') ? 1 : 0.5;
// Fireball vs Plant collision (boss level only)
if (currentLevel === 19 && fireballs && fireballs.length > 0) {
for (var fb = fireballs.length - 1; fb >= 0; fb--) {
var fireball = fireballs[fb];
if (fireball && fireball.x !== undefined) {
var fireballHit = false;
for (var pl = plants.length - 1; pl >= 0; pl--) {
var plant = plants[pl];
if (Math.abs(fireball.x - plant.x) < 60 && Math.abs(fireball.y - plant.y) < 60) {
if (plant.takeDamage(fireball.damage)) {
plant.destroy();
plants.splice(pl, 1);
}
fireball.destroy();
fireballs.splice(fb, 1);
fireballHit = true;
break;
}
}
if (!fireballHit && fireball.x < -100) {
fireball.destroy();
fireballs.splice(fb, 1);
}
}
}
// Pea vs Robot Boss collision
for (var peaIdx = peas.length - 1; peaIdx >= 0; peaIdx--) {
var pea = peas[peaIdx];
if (robotBoss && Math.abs(pea.x - robotBoss.x) < 100 && Math.abs(pea.y - robotBoss.y) < 150) {
if (robotBoss.takeDamage(pea.damage)) {
// Boss defeated, handled in RobotBoss class
}
pea.destroy();
peas.splice(peaIdx, 1);
}
}
}
// Check win condition
checkWinCondition();
}; ===================================================================
--- original.js
+++ change.js
@@ -1052,12 +1052,12 @@
// Remove landing indicator
for (var k = 0; k < landingIndicators.length; k++) {
landingIndicators[k].destroy();
}
- // Spit single fireball toward random target position
+ // Spit single fireball toward random target position from boss mouth
var fireball = new Fireball();
- fireball.x = self.x - 50;
- fireball.y = fireballTargets[0].y; // Use random target Y position
+ fireball.x = self.x - 80; // Spawn from mouth area (further left from center)
+ fireball.y = self.y - 50; // Spawn from mouth height (upper part of boss)
game.addChild(fireball);
fireballs.push(fireball);
// Close mouth
tween(self, {
@@ -2749,10 +2749,10 @@
robotBoss.x = 1800; // Right side of screen
robotBoss.y = 1000; // Middle vertically
game.addChild(robotBoss);
}
- // Spawn tombstones for night levels after clearing existing ones
- if (isNightMode) {
+ // Spawn tombstones for night levels after clearing existing ones (but not for boss fight)
+ if (isNightMode && levelNumber !== 19) {
spawnTombstones();
}
// Reset seed cooldowns
for (var seedType in seedCooldowns) {
Fullscreen modern App Store landscape banner, 16:9, high definition, for a game titled "Plant Defense: Zombie Wave" and with the description "Strategic tower defense game where players place plants to stop zombie waves from crossing their garden lawn.". No text on banner!
un lanzaguisantes. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
un girasol. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
un sol. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
guisante. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
La imagen muestra a una planta del videojuego "Plants vs. Zombies". Es una "Potato Mine" (Papa Mina), un tipo de planta explosiva. Características de la imagen: Forma: Tiene una forma redondeada y abultada, como la de una patata, que sobresale del suelo. Color: Es de color beige o marrón claro. Textura: Parece tener una superficie algo irregular, sugiriendo la textura de una patata o tierra. Cara: Posee dos ojos grandes y negros, de forma ovalada, y una pequeña boca sonriente con dos dientes frontales visibles. Esto le da una expresión amigable. Elemento superior: De la parte superior de la "patata" emerge un tallo gris delgado que sostiene una esfera roja brillante con un pequeño punto blanco en el centro. Esta esfera se asemeja al detonador de una mina o a una palanca de encendido. Base: Está rodeada por terrones de tierra o rocas pequeñas de color marrón oscuro, dando la impresión de que acaba de brotar del suelo o está parcialmente enterrada.. In-Game asset. 2d. High contrast. No shadows
Forma general: La planta tiene un cuerpo principal redondeado, similar a una cabeza, de donde emerge un tallo. Color: El cuerpo principal es de un vibrante color púrpura, salpicado con algunas manchas más oscuras del mismo tono. Boca: Posee una boca enorme y abierta que domina gran parte de su "cabeza". El borde de la boca es de un color verde lima brillante. Dientes: En el interior de la boca, se pueden ver numerosos dientes grandes, afilados y puntiagudos, de color blanco o crema, que sugieren su naturaleza carnívora. La encía visible dentro de la boca es de un tono rosa rojizo. Cuernos/Espinas: En la parte superior de su cabeza, tiene tres o cuatro protuberancias cónicas y afiladas, de color verde claro o blanquecino, que parecen espinas o cuernos. Tallo y hojas: Un tallo largo y curvado de color púrpura oscuro se extiende desde la parte inferior de la cabeza. Varias hojas verdes, con una forma ondulada o dentada, brotan del tallo, tanto cerca de la cabeza como en la base.. In-Game asset. 2d. High contrast. No shadows
Forma: Es una nuez grande y ovalada, con las dos mitades características de una nuez bien definidas y una hendidura central que las separa. Color: Predomina un color marrón dorado, típico de una nuez madura, con algunos matices más oscuros que sugieren textura y profundidad. Textura: La superficie parece rugosa y con imperfecciones, imitando la cáscara dura de una nuez real. Cara: A pesar de ser una nuez, tiene rasgos faciales humanoides en su parte frontal: Ojos: Dos ojos grandes, redondos y saltones con pupilas pequeñas y negras centradas. Los ojos tienen un borde blanco alrededor. Boca: Una pequeña línea horizontal que representa una boca sencilla y recta, dándole una expresión neutral o ligeramente sonriente, pero con una connotación de firmeza o determinación. Expresión: La combinación de los ojos grandes y la boca simple le otorgan una expresión de sorpresa o de estar alerta, lo que encaja con su función de muro defensivo. Fondo: El fondo es cuadriculado, lo que indica que. In-Game asset. 2d. High contrast. No shadows
un zombie de pvz. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
un zombie de pvz. In-Game asset. 2d. High contrast. No shadows
repetidora de pvz. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
una tripitidora de pvz 2 mirando a la derecha. In-Game asset. 2d. High contrast. No shadows
pala. In-Game asset. 2d. High contrast. No shadows
pincho roca pvz. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
Forma general: Es una planta con un tallo central del que brotan hojas y, en la parte superior, tiene dos "cabezas" o vainas de guisante. Color: Predomina un color verde claro brillante en todo el cuerpo de la planta, con algunas sombras que le dan volumen y realismo. Las hojas y el tallo son de un verde ligeramente más oscuro. Cabezas/Vainas: Tiene dos vainas de guisante esféricas unidas, dispuestas una al lado de la otra. Cada una de ellas actúa como un cañón: Orificios de disparo: Ambas vainas tienen una abertura frontal redonda y oscura, que es por donde disparan los guisantes. Ojos: Cada vaina tiene dos pequeños ojos oscuros, similares a cuentas, que le dan una expresión curiosa o atenta. Hojas: En la base de las vainas y a lo largo del tallo, hay varias hojas grandes y ovaladas de color verde oscuro, con nervaduras visibles. Estilo artístico: La imagen tiene un estilo más renderizado y detallado que las ilustraciones típicas del juego, con un sombreado suave que le da una a. In-Game asset. 2d. High contrast. No shadows
lapida estilo PVZ. In-Game asset. 2d. High contrast. No shadows
podadora pvz. In-Game asset. 2d. High contrast. No shadows
El Zomboni es un zombi de tamaño considerable, vestido con un uniforme de trabajador y conduciendo un vehículo grande y robusto. La máquina suele ser de color azul o similar, con un rodillo en la parte trasera que es lo que esparce el hielo. Su aspecto es bastante imponente, señalando que no es un zombi común.. In-Game asset. 2d. High contrast. No shadows
petaseta de pvz en negro y gris con ojos rojos
arbustos grandes. In-Game asset. 2d. High contrast. No shadows
casilla de cesped en imagen completa con flores. In-Game asset. 2d. High contrast. No shadows
valla. In-Game asset. 2d. High contrast. No shadows
zombie minero pvz. In-Game asset. 2d. High contrast. No shadows
zombie leyendo un periodico con traje en cuerpo completo de pvz. In-Game asset. 2d. High contrast. No shadows
Uniforme Completo: Viste un uniforme de fútbol americano bastante completo, lo que le da una apariencia robusta y protegida. Casco de Fútbol: Lleva un casco de fútbol americano de color rojo brillante, adornado con dibujos de calaveras blancas y huesos cruzados, que son un distintivo de los zombis. Este casco no es solo estético, sino que le proporciona una defensa significativa en su cabeza. Hombreras y Camiseta: Tiene unas grandes hombreras blancas y una camiseta roja con el mismo patrón de calaveras y huesos en el pecho. Pantalones y Guantes: Sus pantalones son de color claro (crema o blanco roto) y lleva guantes rojos. Botas de Fútbol: Calza grandes botas de fútbol americano de color gris oscuro o negro. Boca Abierta y Cerebro: Típicamente, como muchos zombis, tiene la boca abierta, mostrando su deseo de cerebros. En tu imagen, parece tener algo verde (quizás una hoja o parte de una planta) sobresaliendo de su boca, lo que podría indicar que ya ha estado masticando algo.. In-Game asset. 2d. High contrast. No shadows
nenufar pvz. In-Game asset. 2d. High contrast. No shadows
Sombrero Púrpura: Tiene un sombrero grande y redondo de color púrpura oscuro o violeta, con manchas o puntos de un púrpura ligeramente más claro. Tallo Verde Claro: Su tallo es corto y robusto, de un color verde claro o menta. Ojos Grandes y Boquilla: Posee dos ojos grandes y redondos, y una "boca" o boquilla prominente en el frente, de color verde oscuro, desde donde expulsa sus proyectiles.. In-Game asset. 2d. High contrast. No shadows
Sombrero Anaranjado/Amarillo: Tiene un sombrero grande y redondo de color anaranjado o amarillo brillante, con manchas de un tono más oscuro o marrón-anaranjado. Los puntos grandes y luminosos en su sombrero le dan un aspecto amigable y sugieren su función solar. Tallo Beige/Crema: Su tallo es corto y regordete, de un color beige o crema claro. Cara Amigable: Posee dos ojos pequeños y redondos, y una pequeña sonrisa, dándole una expresión dulce y pasiva.. In-Game asset. 2d. High contrast. No shadows
Sombrero Iridiscente/Colorido: Su sombrero es la característica más llamativa, mostrando una gama de colores suaves y pastel que se mezclan como un arcoíris o un efecto iridiscente (rosas, azules, verdes claros, morados). Esto sugiere su naturaleza "hipnótica" o alucinógena. Tallo Púrpura Claro/Blanco: Su tallo es de un color púrpura muy claro o casi blanco. Ojos en Espiral/Hipnóticos: Sus "ojos" son dos grandes espirales rojas o rosadas, lo que claramente representa su capacidad de hipnotizar. Boca Triste/Somnolienta: Tiene una pequeña boca que parece un poco triste o somnolienta, lo que contrasta con la intensidad de sus ojos espirales.. In-Game asset. 2d. High contrast. No shadows
Cabeza (sombrero del hongo): Es grande, redonda y de color morado con manchas más oscuras. En el frente tiene una estructura que parece una boquilla o cañón, lo que da la impresión de que puede disparar algo. Cuerpo: Pequeño y de color verde claro, con una expresión facial seria o enojada. Tiene ojos grandes y cejas inclinadas hacia abajo, lo que resalta su actitud agresiva o decidida. Estilo: Es un diseño al estilo de caricatura o videojuego, similar a los personajes de Plants vs. Zombies.. In-Game asset. 2d. High contrast. No shadows
Cuerpo principal: Tiene forma de tronco cortado, de color gris oscuro con textura agrietada, lo que le da un aspecto envejecido o pétreo. La parte inferior tiene bordes irregulares que simulan raíces o madera desgastada. Ojos: Tiene dos ojos brillantes de color amarillo verdoso, con una expresión amenazante o intimidante. No tiene boca visible. Parte superior: Le crecen enredaderas verdes con hojas que sobresalen por arriba, dándole un toque vegetal y natural, como si la criatura estuviera conectada a la naturaleza o corrompida por ella. Estilo general: El diseño es oscuro y misterioso, probablemente representa a un enemigo o criatura poderosa en un juego tipo Plants vs. Zombies.. In-Game asset. 2d. High contrast. No shadows
Cristales de Hielo en la Parte Superior: Su característica más distintiva es la corona de cristales de hielo afilados y translúcidos de color azul brillante que cubren la parte superior de su cuerpo. Estos cristales le dan una apariencia gélida y punzante. Cuerpo Translúcido Azul/Turquesa: Su cuerpo principal es una masa translúcida de color azul claro o turquesa, que se asemeja al hielo o a un cuerpo gelatinoso congelado. Ojos Fruncidos y Fríos: Tiene dos ojos pequeños, oscuros y con las cejas fruncidas, lo que le da una expresión seria y gélida, a juego con su habilidad. Base Escarchada: La base de su cuerpo a menudo tiene un contorno escarchado o irregular, reforzando su temática de hielo.. In-Game asset. 2d. High contrast. No shadows
una lechuga. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
maseta mirando hacia arriba. In-Game asset. 2d. High contrast. No shadows
Cuerpo Robusto y Verde: El Zombot es una mole robótica de gran tamaño, con un cuerpo predominantemente de color verde oscuro, que le da un aspecto industrial y amenazante. Sus "hombros" y parte del torso están cubiertos por una armadura de color óxido o marrón rojizo, con remaches visibles. Cabeza de Zombi Grande: La cabeza del robot es grande y cuadrada, también de color verde, con mandíbulas inferiores prominentes que se abren para revelar dientes afilados. Tiene dos grandes ojos amarillos brillantes que emiten una luz siniestra, lo que lo hace parecer una versión robótica y gigantesca de un zombi común. Múltiples Mangueras y Cables: Varias mangueras o tuberías metálicas segmentadas sobresalen de sus hombros y otras partes del cuerpo, conectándose a sus brazos y cabeza, lo que sugiere un complejo sistema mecánico y de fluido. Brazos y Piernas Robóticas Grandes: Sus brazos son enormes y fornidos, con grandes manos que terminan en "dedos" gruesos y redondeados, capaces de infligir u. In-Game asset. 2d. High contrast. No shadows
Melón como Cuerpo: La planta en sí parece ser un melón grande y redondo, con las características rayas verdes oscuras y claras de una sandía. Cara y Hojas: Tiene dos ojos pequeños y una expresión que denota seriedad o concentración, propia de una planta de ataque. En su base, tiene hojas verdes que la asientan en el suelo. Brazos de Enredadera con Melón: De la parte superior de su cuerpo, salen dos enredaderas o tallos verdes y enrollados que sostienen un melón más pequeño. Este melón es el "proyectil" que lanza. El mecanismo sugiere que es una especie de honda o catapulta natural.. In-Game asset. 2d. High contrast. No shadows
casilla negra. In-Game asset. 2d. High contrast. No shadows
bola de cañon con fuego. In-Game asset. 2d. High contrast. No shadows
mantequilla. In-Game asset. 2d. High contrast. No shadows
grano de mais. In-Game asset. 2d. High contrast. No shadows
Un zombie grande ey fuerte eue sostiene un palo de electricidad. In-Game asset. 2d. High contrast. No shadows
Un botón de continuar al estilo lápida. In-Game asset. 2d. High contrast. No shadows
Tronco enojado con llamas arriba. In-Game asset. 2d. High contrast. No shadows