User prompt
make the song grasswalk play loop
User prompt
Cherry bomb only does damage to one zombie, now make it do damage in a range of 3x3 squares.
User prompt
Chomper and the zombie jackinthebox are red, make them not red anymore. When chomper is recharging, make it black and after the recharging time, make it normal again. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add more health to the zomboni, and make the game more difficult from wave 3 onwards.
User prompt
Make the skeletons have more life and be faster, make more zombies appear as the waves advance to make the game more difficult. add a new asset for the zomboni, which is a car with double the life of a normal zombie and a little faster crushing any plant killing it instantly, make it appear from wave 5 ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
When it gets dark the background has to stay dark blue during the 5 waves until it turns green again when it gets daylight. Add a new plant, chomper, it kills any zombie that is one square ahead of it, in one bite, but it has to wait 20 seconds to kill another zombie. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Now make after 5 waves the background change to a dark blue color simulating night, and make more zombies appear after that, and after another 5 waves make it daytime again. now add a new asset for the Gargantuar zombie, which has too many health, is a bit slow and destroys any plant with a single bite. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
there is a bug when zombies eat a plant, they can no longer place plants in the square where they ate that plant, fix it.
User prompt
there is a bug with Cherrybomb, when you put it in a box and it explodes you can't place plants there anymore, fix it. increase a little bit the speed of jack in the box zombie, and reduce the reload time to use the plants. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Add a new asset for the Jack in the box zombie, which will appear from wave 4 and acts like a normal zombie but can explode in a random time of 8 to 15 seconds destroying plants in a range of 3x3 squares. make spikeweed completely ignored by the zombies, so that they do not eat it, going completely unnoticed. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
The spikeweed should not kill the zombies immediately, it has to do the same damage as a pea every 0.6 seconds. add the zombie all stars, which appears from the second wave, to be a new type of zombie that moves faster and has much more health points. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
The pruners don't work, fix whatever is going wrong and put them a little further ahead. add a new plant the spikeweed, the zombies don't eat it because it is on the ground while the grass spikeweed can hurt them when they are on top of it. add the zombie all stars, which has much more stamina and more speed than a normal zombei. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
The icons are too small make them much bigger, reduce the speed of the zombies, add a recharge time to use each plant, and add the pruners, which are 1 in each line, they are on the back paste of the map, and when a zombie touches a pruner it activates moving forward killing all the zombies in the line. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
The text to select the repeater is below the text to select the cherrybomb, fix it by changing that text to icons that below them show the price, and at the top add an icon to select the shovel, which is used to remove the plants.
User prompt
make the zombies take 25 seconds to appear initially, and add a new plant, the repeater, it is the same as the lanzaguizantes but shoots 2 peas and is worth 200 soles. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the suns of the sunflower bigger, make the zombies appear after 15 seconds at the start of the game and after that time sound an alert with the message zombies are coming. the space where the game takes place is still small, make it bigger without having more squares on the grid. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Now that the resources are called suns, and that the zombies do not produce them when they die, instead put a sunflower that is worth 50 and generates them in the garden to collect them, each sun is worth 25. the space where the game takes place is very small, make it bigger without having more squares in the grid. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Garden Defense: Plants vs Undead
Initial prompt
Tower defense of plants vs undead on a grid
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ var AllStarZombie = Container.expand(function () { var self = Container.call(this); var zombieGraphics = self.attachAsset('zombie', { anchorX: 0.5, anchorY: 0.5 }); // Tint to differentiate from normal zombie zombieGraphics.tint = 0x888888; self.health = 200; self.maxHealth = 200; self.speed = -1.2; // Faster than normal zombie self.damage = 40; self.attackTimer = 0; self.attackDelay = 45; // Faster attack self.row = 0; self.attacking = false; self.update = function () { if (!self.attacking) { self.x += self.speed; } else { self.attackTimer++; if (self.attackTimer >= self.attackDelay) { self.attack(); self.attackTimer = 0; } } }; self.takeDamage = function (damage) { self.health -= damage; LK.effects.flashObject(self, 0xff0000, 200); LK.getSound('zombie_hit').play(); if (self.health <= 0) { // Remove from enemies array for (var i = 0; i < enemies.length; i++) { if (enemies[i] === self) { enemies.splice(i, 1); break; } } // No resources awarded on death self.destroy(); } }; self.attack = function () { // Find plant to attack for (var i = 0; i < plants.length; i++) { var plant = plants[i]; if (plant.row === self.row && Math.abs(plant.x - self.x) <= 50) { // Skip spikeweed - zombies ignore it completely if (plant instanceof Spikeweed) { continue; } plant.health -= self.damage; LK.effects.flashObject(plant, 0xff0000, 200); if (plant.health <= 0) { plants.splice(i, 1); plant.destroy(); grid[plant.row][plant.col].occupied = false; self.attacking = false; } break; } } }; return self; }); var CherryBomb = Container.expand(function () { var self = Container.call(this); var bombGraphics = self.attachAsset('cherryBomb', { anchorX: 0.5, anchorY: 0.5 }); self.cost = 150; self.health = 50; self.maxHealth = 50; self.fuseTimer = 0; self.fuseDelay = 180; // 3 seconds self.update = function () { self.fuseTimer++; if (self.fuseTimer >= self.fuseDelay) { self.explode(); } }; self.explode = function () { var explosion = game.addChild(LK.getAsset('explosion', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y })); // Damage all enemies in 3x3 area for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; var distance = Math.sqrt(Math.pow(enemy.x - self.x, 2) + Math.pow(enemy.y - self.y, 2)); if (distance <= 150) { enemy.takeDamage(100); } } LK.getSound('explode').play(); // Remove explosion after animation tween(explosion, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 500, onFinish: function onFinish() { explosion.destroy(); } }); // Remove self for (var j = 0; j < plants.length; j++) { if (plants[j] === self) { plants.splice(j, 1); // Clear grid occupied status grid[self.row][self.col].occupied = false; break; } } self.destroy(); }; return self; }); var Chomper = Container.expand(function () { var self = Container.call(this); var chomperGraphics = self.attachAsset('chomper', { anchorX: 0.5, anchorY: 0.5 }); // Tint to differentiate from pea shooter chomperGraphics.tint = 0x8B4513; self.cost = 150; self.health = 200; self.maxHealth = 200; self.row = 0; self.col = 0; self.attackTimer = 0; self.attackDelay = 1200; // 20 seconds at 60fps self.canAttack = true; self.update = function () { if (self.attackTimer > 0) { self.attackTimer--; if (self.attackTimer === 0) { self.canAttack = true; // Change back to normal color when ready tween(chomperGraphics, { tint: 0x8B4513 }, { duration: 200 }); } } if (self.canAttack) { // Check for enemy one square ahead var targetCol = self.col + 1; if (targetCol < GRID_COLS) { for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; var enemyCol = Math.floor((enemy.x - GRID_START_X) / CELL_SIZE); if (enemy.row === self.row && enemyCol === targetCol && Math.abs(enemy.x - (GRID_START_X + targetCol * CELL_SIZE + CELL_SIZE / 2)) <= 80) { self.chomp(enemy); break; } } } } }; self.chomp = function (enemy) { // Instantly kill the enemy enemy.takeDamage(10000); // Start cooldown self.canAttack = false; self.attackTimer = self.attackDelay; // Visual feedback - flash red during cooldown tween(chomperGraphics, { tint: 0xFF0000 }, { duration: 200 }); LK.getSound('zombie_hit').play(); }; return self; }); var Gargantuar = Container.expand(function () { var self = Container.call(this); var gargantuarGraphics = self.attachAsset('gargantuar', { anchorX: 0.5, anchorY: 0.5 }); // Tint to differentiate from other zombies gargantuarGraphics.tint = 0x8B4513; self.health = 500; // Very high health self.maxHealth = 500; self.speed = -0.3; // Slow movement self.damage = 1000; // One-hit kill for plants self.attackTimer = 0; self.attackDelay = 90; // Slower attack self.row = 0; self.attacking = false; self.update = function () { if (!self.attacking) { self.x += self.speed; } else { self.attackTimer++; if (self.attackTimer >= self.attackDelay) { self.attack(); self.attackTimer = 0; } } }; self.takeDamage = function (damage) { self.health -= damage; LK.effects.flashObject(self, 0xff0000, 200); LK.getSound('zombie_hit').play(); if (self.health <= 0) { // Remove from enemies array for (var i = 0; i < enemies.length; i++) { if (enemies[i] === self) { enemies.splice(i, 1); break; } } self.destroy(); } }; self.attack = function () { // Find plant to attack (but ignore spikeweed) for (var i = 0; i < plants.length; i++) { var plant = plants[i]; if (plant.row === self.row && Math.abs(plant.x - self.x) <= 50) { // Skip spikeweed - zombies ignore it completely if (plant instanceof Spikeweed) { continue; } // Gargantuar destroys any plant with one hit plant.health = 0; LK.effects.flashObject(plant, 0xff0000, 200); plants.splice(i, 1); plant.destroy(); grid[plant.row][plant.col].occupied = false; self.attacking = false; break; } } }; return self; }); var JackInTheBoxZombie = Container.expand(function () { var self = Container.call(this); var zombieGraphics = self.attachAsset('jackInTheBox', { anchorX: 0.5, anchorY: 0.5 }); // Tint to differentiate from normal zombie zombieGraphics.tint = 0x9400d3; self.health = 80; self.maxHealth = 80; self.speed = -0.8; self.damage = 25; self.attackTimer = 0; self.attackDelay = 60; self.row = 0; self.attacking = false; // Explosion timer (8-15 seconds randomly) self.explosionTimer = 0; self.explosionDelay = Math.floor(Math.random() * (900 - 480) + 480); // 8-15 seconds at 60fps self.exploded = false; self.update = function () { if (!self.exploded) { self.explosionTimer++; if (self.explosionTimer >= self.explosionDelay) { self.explode(); return; } } if (!self.attacking) { self.x += self.speed; } else { self.attackTimer++; if (self.attackTimer >= self.attackDelay) { self.attack(); self.attackTimer = 0; } } }; self.explode = function () { if (self.exploded) return; self.exploded = true; var explosion = game.addChild(LK.getAsset('explosion', { anchorX: 0.5, anchorY: 0.5, x: self.x, y: self.y })); // Destroy plants in 3x3 area around explosion var explosionRow = self.row; var explosionCol = Math.floor((self.x - GRID_START_X) / CELL_SIZE); for (var row = explosionRow - 1; row <= explosionRow + 1; row++) { for (var col = explosionCol - 1; col <= explosionCol + 1; col++) { if (row >= 0 && row < GRID_ROWS && col >= 0 && col < GRID_COLS) { if (grid[row][col].occupied) { for (var i = plants.length - 1; i >= 0; i--) { var plant = plants[i]; if (plant.row === row && plant.col === col) { plants.splice(i, 1); plant.destroy(); grid[row][col].occupied = false; break; } } } } } } LK.getSound('explode').play(); // Remove explosion after animation tween(explosion, { alpha: 0, scaleX: 2, scaleY: 2 }, { duration: 500, onFinish: function onFinish() { explosion.destroy(); } }); // Remove self from enemies array for (var j = 0; j < enemies.length; j++) { if (enemies[j] === self) { enemies.splice(j, 1); break; } } self.destroy(); }; self.takeDamage = function (damage) { self.health -= damage; LK.effects.flashObject(self, 0xff0000, 200); LK.getSound('zombie_hit').play(); if (self.health <= 0) { // Remove from enemies array for (var i = 0; i < enemies.length; i++) { if (enemies[i] === self) { enemies.splice(i, 1); break; } } self.destroy(); } }; self.attack = function () { // Find plant to attack (but ignore spikeweed) for (var i = 0; i < plants.length; i++) { var plant = plants[i]; if (plant.row === self.row && Math.abs(plant.x - self.x) <= 50) { // Skip spikeweed - zombies ignore it completely if (plant instanceof Spikeweed) { continue; } plant.health -= self.damage; LK.effects.flashObject(plant, 0xff0000, 200); if (plant.health <= 0) { plants.splice(i, 1); plant.destroy(); grid[plant.row][plant.col].occupied = false; self.attacking = false; } break; } } }; 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; }; return self; }); var PeaShooter = Container.expand(function () { var self = Container.call(this); var shooterGraphics = self.attachAsset('peaShooter', { anchorX: 0.5, anchorY: 0.5 }); self.cost = 100; self.health = 100; self.maxHealth = 100; self.shootTimer = 0; self.shootDelay = 90; // 1.5 seconds at 60fps self.row = 0; self.update = function () { self.shootTimer++; if (self.shootTimer >= self.shootDelay) { // Check if there's an enemy in this row var hasEnemyInRow = false; for (var i = 0; i < enemies.length; i++) { if (enemies[i].row === self.row && enemies[i].x > self.x) { hasEnemyInRow = true; break; } } if (hasEnemyInRow) { var pea = new Pea(); pea.x = self.x + 50; pea.y = self.y; pea.row = self.row; projectiles.push(pea); game.addChild(pea); LK.getSound('shoot').play(); self.shootTimer = 0; } } }; return self; }); var Pruner = Container.expand(function () { var self = Container.call(this); var prunerGraphics = self.attachAsset('pruner', { anchorX: 0.5, anchorY: 0.5 }); self.activated = false; self.speed = 0; self.row = 0; self.update = function () { if (self.activated) { self.x += self.speed; // Check collision with enemies while moving for (var i = enemies.length - 1; i >= 0; i--) { var enemy = enemies[i]; if (enemy.row === self.row && Math.abs(enemy.x - self.x) <= 80) { enemy.takeDamage(1000); // Instant kill } } // Remove if off screen if (self.x > 2200) { for (var j = 0; j < pruners.length; j++) { if (pruners[j] === self) { pruners.splice(j, 1); break; } } self.destroy(); } } }; self.activate = function () { if (!self.activated) { self.activated = true; self.speed = 12; tween(self, { tint: 0xff0000 }, { duration: 200 }); } }; return self; }); var Repeater = Container.expand(function () { var self = Container.call(this); var repeaterGraphics = self.attachAsset('repeater', { anchorX: 0.5, anchorY: 0.5 }); self.cost = 200; self.health = 100; self.maxHealth = 100; self.shootTimer = 0; self.shootDelay = 90; // 1.5 seconds at 60fps self.row = 0; self.update = function () { self.shootTimer++; if (self.shootTimer >= self.shootDelay) { // Check if there's an enemy in this row var hasEnemyInRow = false; for (var i = 0; i < enemies.length; i++) { if (enemies[i].row === self.row && enemies[i].x > self.x) { hasEnemyInRow = true; break; } } if (hasEnemyInRow) { // Shoot first pea var pea1 = new Pea(); pea1.x = self.x + 50; pea1.y = self.y; pea1.row = self.row; projectiles.push(pea1); game.addChild(pea1); // Shoot second pea slightly delayed var pea2 = new Pea(); pea2.x = self.x + 30; pea2.y = self.y; pea2.row = self.row; projectiles.push(pea2); game.addChild(pea2); LK.getSound('shoot').play(); self.shootTimer = 0; } } }; return self; }); var Skeleton = Container.expand(function () { var self = Container.call(this); var skeletonGraphics = self.attachAsset('skeleton', { anchorX: 0.5, anchorY: 0.5 }); self.health = 120; self.maxHealth = 120; self.speed = -1.0; self.damage = 20; self.attackTimer = 0; self.attackDelay = 45; // Faster attack self.row = 0; self.attacking = false; self.update = function () { if (!self.attacking) { self.x += self.speed; } else { self.attackTimer++; if (self.attackTimer >= self.attackDelay) { self.attack(); self.attackTimer = 0; } } }; self.takeDamage = function (damage) { self.health -= damage; LK.effects.flashObject(self, 0xff0000, 200); LK.getSound('zombie_hit').play(); if (self.health <= 0) { // Remove from enemies array for (var i = 0; i < enemies.length; i++) { if (enemies[i] === self) { enemies.splice(i, 1); break; } } // No resources awarded on death self.destroy(); } }; self.attack = function () { // Find plant to attack for (var i = 0; i < plants.length; i++) { var plant = plants[i]; if (plant.row === self.row && Math.abs(plant.x - self.x) <= 50) { // Skip spikeweed - zombies ignore it completely if (plant instanceof Spikeweed) { continue; } plant.health -= self.damage; LK.effects.flashObject(plant, 0xff0000, 200); if (plant.health <= 0) { plants.splice(i, 1); plant.destroy(); grid[plant.row][plant.col].occupied = false; self.attacking = false; } break; } } }; return self; }); var Spikeweed = Container.expand(function () { var self = Container.call(this); var spikeweedGraphics = self.attachAsset('spikeweed', { anchorX: 0.5, anchorY: 0.5 }); self.cost = 100; self.health = 300; self.maxHealth = 300; self.damage = 20; self.damageTimer = 0; self.damageDelay = 36; // 0.6 seconds at 60fps self.update = function () { self.damageTimer++; // Check for enemies stepping on spikeweed for (var i = 0; i < enemies.length; i++) { var enemy = enemies[i]; if (enemy.row === self.row && Math.abs(enemy.x - self.x) <= 80 && Math.abs(enemy.y - self.y) <= 80) { if (self.damageTimer >= self.damageDelay) { enemy.takeDamage(self.damage); LK.effects.flashObject(self, 0xff0000, 200); self.damageTimer = 0; } } } }; 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.lifeTimer = 0; self.maxLifeTime = 600; // 10 seconds self.collected = false; self.update = function () { self.lifeTimer++; if (self.lifeTimer >= self.maxLifeTime && !self.collected) { // Remove from suns array for (var i = 0; i < suns.length; i++) { if (suns[i] === self) { suns.splice(i, 1); break; } } self.destroy(); } }; self.down = function (x, y, obj) { if (!self.collected) { self.collected = true; resources += self.value; updateResourcesDisplay(); // Animate collection tween(self, { scaleX: 0.1, scaleY: 0.1, alpha: 0 }, { duration: 300, onFinish: function onFinish() { // Remove from suns array for (var i = 0; i < suns.length; i++) { if (suns[i] === self) { suns.splice(i, 1); break; } } self.destroy(); } }); } }; return self; }); var Sunflower = Container.expand(function () { var self = Container.call(this); var sunflowerGraphics = self.attachAsset('sunflower', { anchorX: 0.5, anchorY: 0.5 }); self.cost = 50; self.health = 100; self.maxHealth = 100; self.sunTimer = 0; self.sunDelay = 480; // 8 seconds self.update = function () { self.sunTimer++; if (self.sunTimer >= self.sunDelay) { self.produceSun(); self.sunTimer = 0; } }; self.produceSun = function () { var sun = new Sun(); sun.x = self.x + (Math.random() - 0.5) * 60; sun.y = self.y + (Math.random() - 0.5) * 60; suns.push(sun); game.addChild(sun); }; return self; }); var WallNut = Container.expand(function () { var self = Container.call(this); var nutGraphics = self.attachAsset('wallNut', { anchorX: 0.5, anchorY: 0.5 }); self.cost = 50; self.health = 200; self.maxHealth = 200; return self; }); var Zombie = Container.expand(function () { var self = Container.call(this); var zombieGraphics = self.attachAsset('zombie', { anchorX: 0.5, anchorY: 0.5 }); self.health = 80; self.maxHealth = 80; self.speed = -0.6; self.damage = 25; self.attackTimer = 0; self.attackDelay = 60; // 1 second self.row = 0; self.attacking = false; self.update = function () { if (!self.attacking) { self.x += self.speed; } else { self.attackTimer++; if (self.attackTimer >= self.attackDelay) { self.attack(); self.attackTimer = 0; } } }; self.takeDamage = function (damage) { self.health -= damage; LK.effects.flashObject(self, 0xff0000, 200); LK.getSound('zombie_hit').play(); if (self.health <= 0) { // Remove from enemies array for (var i = 0; i < enemies.length; i++) { if (enemies[i] === self) { enemies.splice(i, 1); break; } } // No resources awarded on death self.destroy(); } }; self.attack = function () { // Find plant to attack for (var i = 0; i < plants.length; i++) { var plant = plants[i]; if (plant.row === self.row && Math.abs(plant.x - self.x) <= 50) { // Skip spikeweed - zombies ignore it completely if (plant instanceof Spikeweed) { continue; } plant.health -= self.damage; LK.effects.flashObject(plant, 0xff0000, 200); if (plant.health <= 0) { plants.splice(i, 1); plant.destroy(); grid[plant.row][plant.col].occupied = false; self.attacking = false; } break; } } }; return self; }); var Zomboni = Container.expand(function () { var self = Container.call(this); var zomboniGraphics = self.attachAsset('zomboni', { anchorX: 0.5, anchorY: 0.5 }); // Tint to differentiate from other zombies zomboniGraphics.tint = 0x444444; self.health = 300; // Triple normal zombie health self.maxHealth = 300; self.speed = -0.8; // Faster than normal zombie self.damage = 1000; // Crushes plants instantly self.attackTimer = 0; self.attackDelay = 30; // Fast crushing self.row = 0; self.attacking = false; self.update = function () { if (!self.attacking) { self.x += self.speed; } else { self.attackTimer++; if (self.attackTimer >= self.attackDelay) { self.attack(); self.attackTimer = 0; } } }; self.takeDamage = function (damage) { self.health -= damage; LK.effects.flashObject(self, 0xff0000, 200); LK.getSound('zombie_hit').play(); if (self.health <= 0) { // Remove from enemies array for (var i = 0; i < enemies.length; i++) { if (enemies[i] === self) { enemies.splice(i, 1); break; } } self.destroy(); } }; self.attack = function () { // Find plant to attack and crush it instantly for (var i = 0; i < plants.length; i++) { var plant = plants[i]; if (plant.row === self.row && Math.abs(plant.x - self.x) <= 50) { // Skip spikeweed - zombies ignore it completely if (plant instanceof Spikeweed) { continue; } // Zomboni crushes any plant instantly plant.health = 0; LK.effects.flashObject(plant, 0xff0000, 200); plants.splice(i, 1); plant.destroy(); grid[plant.row][plant.col].occupied = false; self.attacking = false; break; } } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x2d5016 }); /**** * Game Code ****/ // Grid setup var GRID_ROWS = 5; var GRID_COLS = 9; var CELL_SIZE = 200; var GRID_START_X = 224; // Center the grid: (2048 - 1800) / 2 var GRID_START_Y = 700; // Game state var resources = 150; var currentWave = 1; var enemiesSpawned = 0; var enemiesPerWave = 5; var waveDelay = 300; // 5 seconds between waves var waveTimer = 0; var gameStartTimer = 0; var firstWaveStarted = false; var alertShown = false; var gameState = 'playing'; // 'playing', 'won', 'lost' var isNight = false; var nightTransitionCompleted = false; var dayTransitionCompleted = false; // Game objects var grid = []; var plants = []; var enemies = []; var projectiles = []; var suns = []; var pruners = []; var selectedPlantType = 'peaShooter'; // Plant recharge system var plantRecharges = { peaShooter: 0, wallNut: 0, sunflower: 0, repeater: 0, cherryBomb: 0, spikeweed: 0, chomper: 0 }; var plantRechargeTimes = { peaShooter: 180, // 3 seconds wallNut: 300, // 5 seconds sunflower: 240, // 4 seconds repeater: 360, // 6 seconds cherryBomb: 600, // 10 seconds spikeweed: 240, // 4 seconds chomper: 420 // 7 seconds }; // UI elements var resourcesText = new Text2('Resources: ' + resources, { size: 60, fill: 0xFFFFFF }); resourcesText.anchor.set(0, 0); resourcesText.x = 120; resourcesText.y = 50; LK.gui.topLeft.addChild(resourcesText); var waveText = new Text2('Wave: ' + currentWave, { size: 60, fill: 0xFFFFFF }); waveText.anchor.set(0.5, 0); waveText.x = 0; waveText.y = 50; LK.gui.top.addChild(waveText); var instructionText = new Text2('Tap grid to place plants', { size: 40, fill: 0xFFFF00 }); instructionText.anchor.set(0.5, 0); instructionText.x = 0; instructionText.y = 120; LK.gui.top.addChild(instructionText); // Shovel button at top var shovelBtn = LK.getAsset('shovel', { anchorX: 0.5, anchorY: 0.5 }); shovelBtn.x = 0; shovelBtn.y = 200; LK.gui.top.addChild(shovelBtn); // Plant selection buttons with icons and prices var peaShooterBtn = LK.getAsset('peaShooter', { anchorX: 0.5, anchorY: 1, scaleX: 0.8, scaleY: 0.8 }); peaShooterBtn.x = 75; peaShooterBtn.y = -160; LK.gui.bottomLeft.addChild(peaShooterBtn); var peaShooterPrice = new Text2('100', { size: 30, fill: 0xFFFFFF }); peaShooterPrice.anchor.set(0.5, 0); peaShooterPrice.x = 75; peaShooterPrice.y = -160; LK.gui.bottomLeft.addChild(peaShooterPrice); var wallNutBtn = LK.getAsset('wallNut', { anchorX: 0.5, anchorY: 1, scaleX: 0.8, scaleY: 0.8 }); wallNutBtn.x = 225; wallNutBtn.y = -160; LK.gui.bottomLeft.addChild(wallNutBtn); var wallNutPrice = new Text2('50', { size: 30, fill: 0xFFFFFF }); wallNutPrice.anchor.set(0.5, 0); wallNutPrice.x = 225; wallNutPrice.y = -160; LK.gui.bottomLeft.addChild(wallNutPrice); var sunflowerBtn = LK.getAsset('sunflower', { anchorX: 0.5, anchorY: 1, scaleX: 0.8, scaleY: 0.8 }); sunflowerBtn.x = 375; sunflowerBtn.y = -160; LK.gui.bottomLeft.addChild(sunflowerBtn); var sunflowerPrice = new Text2('50', { size: 30, fill: 0xFFFFFF }); sunflowerPrice.anchor.set(0.5, 0); sunflowerPrice.x = 375; sunflowerPrice.y = -160; LK.gui.bottomLeft.addChild(sunflowerPrice); var repeaterBtn = LK.getAsset('repeater', { anchorX: 0.5, anchorY: 1, scaleX: 0.8, scaleY: 0.8 }); repeaterBtn.x = 525; repeaterBtn.y = -160; LK.gui.bottomLeft.addChild(repeaterBtn); var repeaterPrice = new Text2('200', { size: 30, fill: 0xFFFFFF }); repeaterPrice.anchor.set(0.5, 0); repeaterPrice.x = 525; repeaterPrice.y = -160; LK.gui.bottomLeft.addChild(repeaterPrice); var cherryBombBtn = LK.getAsset('cherryBomb', { anchorX: 0.5, anchorY: 1, scaleX: 0.8, scaleY: 0.8 }); cherryBombBtn.x = 675; cherryBombBtn.y = -160; LK.gui.bottomLeft.addChild(cherryBombBtn); var cherryBombPrice = new Text2('150', { size: 30, fill: 0xFFFFFF }); cherryBombPrice.anchor.set(0.5, 0); cherryBombPrice.x = 675; cherryBombPrice.y = -160; LK.gui.bottomLeft.addChild(cherryBombPrice); var spikeweedBtn = LK.getAsset('spikeweed', { anchorX: 0.5, anchorY: 1, scaleX: 0.8, scaleY: 0.8 }); spikeweedBtn.x = 825; spikeweedBtn.y = -160; LK.gui.bottomLeft.addChild(spikeweedBtn); var spikeweedPrice = new Text2('100', { size: 30, fill: 0xFFFFFF }); spikeweedPrice.anchor.set(0.5, 0); spikeweedPrice.x = 825; spikeweedPrice.y = -160; LK.gui.bottomLeft.addChild(spikeweedPrice); var chomperBtn = LK.getAsset('chomper', { anchorX: 0.5, anchorY: 1, scaleX: 0.8, scaleY: 0.8 }); chomperBtn.x = 975; chomperBtn.y = -160; LK.gui.bottomLeft.addChild(chomperBtn); var chomperPrice = new Text2('150', { size: 30, fill: 0xFFFFFF }); chomperPrice.anchor.set(0.5, 0); chomperPrice.x = 975; chomperPrice.y = -160; LK.gui.bottomLeft.addChild(chomperPrice); // Create grid for (var row = 0; row < GRID_ROWS; row++) { grid[row] = []; for (var col = 0; col < GRID_COLS; col++) { var cell = game.addChild(LK.getAsset('gridCell', { anchorX: 0.5, anchorY: 0.5, x: GRID_START_X + col * CELL_SIZE + CELL_SIZE / 2, y: GRID_START_Y + row * CELL_SIZE + CELL_SIZE / 2, alpha: 0.3 })); cell.row = row; cell.col = col; cell.occupied = false; grid[row][col] = cell; } } // Create pruners (one per row at the back) for (var row = 0; row < GRID_ROWS; row++) { var pruner = new Pruner(); pruner.x = GRID_START_X - 50; // Further ahead pruner.y = GRID_START_Y + row * CELL_SIZE + CELL_SIZE / 2; pruner.row = row; pruners.push(pruner); game.addChild(pruner); } function updateResourcesDisplay() { resourcesText.setText('Resources: ' + resources); } function updateWaveDisplay() { waveText.setText('Wave: ' + currentWave); } function getPlantCost(plantType) { switch (plantType) { case 'peaShooter': return 100; case 'wallNut': return 50; case 'sunflower': return 50; case 'repeater': return 200; case 'cherryBomb': return 150; case 'spikeweed': return 100; case 'chomper': return 150; default: return 100; } } function canAffordPlant(plantType) { return resources >= getPlantCost(plantType); } function placePlant(row, col, plantType) { if (grid[row][col].occupied || !canAffordPlant(plantType) || plantRecharges[plantType] > 0) { return false; } var plant; var cost = getPlantCost(plantType); switch (plantType) { case 'peaShooter': plant = new PeaShooter(); break; case 'wallNut': plant = new WallNut(); break; case 'sunflower': plant = new Sunflower(); break; case 'repeater': plant = new Repeater(); break; case 'cherryBomb': plant = new CherryBomb(); break; case 'spikeweed': plant = new Spikeweed(); break; case 'chomper': plant = new Chomper(); break; default: return false; } plant.x = GRID_START_X + col * CELL_SIZE + CELL_SIZE / 2; plant.y = GRID_START_Y + row * CELL_SIZE + CELL_SIZE / 2; plant.row = row; plant.col = col; plants.push(plant); game.addChild(plant); grid[row][col].occupied = true; resources -= cost; plantRecharges[plantType] = plantRechargeTimes[plantType]; updateResourcesDisplay(); LK.getSound('plant').play(); return true; } function removePlant(row, col) { if (!grid[row][col].occupied) { return false; } // Find and remove plant from plants array for (var i = 0; i < plants.length; i++) { var plant = plants[i]; if (plant.row === row && plant.col === col) { plants.splice(i, 1); plant.destroy(); grid[row][col].occupied = false; return true; } } return false; } function spawnEnemy(row) { var enemy; var rand = Math.random(); var spawnMultiplier = isNight ? 1.5 : 1; // More enemies at night var waveMultiplier = Math.min(1 + (currentWave - 1) * 0.15, 2.5); // Increase spawn chance more aggressively with waves if (currentWave >= 5 && rand < 0.12 * waveMultiplier) { enemy = new Gargantuar(); } else if (currentWave >= 4 && rand < 0.18 * waveMultiplier) { enemy = new Zomboni(); } else if (currentWave >= 3 && rand < 0.25 * waveMultiplier) { enemy = new JackInTheBoxZombie(); } else if (currentWave >= 2 && rand < 0.35 * waveMultiplier) { enemy = new AllStarZombie(); } else if (currentWave >= 3 && rand < 0.6 * waveMultiplier) { enemy = new Skeleton(); } else { enemy = new Zombie(); } enemy.x = 2000; enemy.y = GRID_START_Y + row * CELL_SIZE + CELL_SIZE / 2; enemy.row = row; enemiesSpawned++; enemies.push(enemy); game.addChild(enemy); // Spawn additional enemies at night and more as waves progress from wave 3 var extraSpawnChance = isNight ? 0.4 : 0.2; if (currentWave >= 3) { extraSpawnChance += (currentWave - 1) * 0.08; // More aggressive increase with waves } if (Math.random() < extraSpawnChance) { var extraEnemy = new Zombie(); extraEnemy.x = 2050; extraEnemy.y = GRID_START_Y + row * CELL_SIZE + CELL_SIZE / 2; extraEnemy.row = row; enemies.push(extraEnemy); game.addChild(extraEnemy); } } function checkWaveComplete() { if (enemiesSpawned >= enemiesPerWave && enemies.length === 0) { currentWave++; updateWaveDisplay(); if (currentWave > 10) { gameState = 'won'; LK.showYouWin(); return; } enemiesSpawned = 0; enemiesPerWave = Math.min(5 + currentWave * 4, 30); waveTimer = 0; } } function checkGameOver() { for (var i = 0; i < enemies.length; i++) { if (enemies[i].x <= GRID_START_X - 50) { gameState = 'lost'; LK.showGameOver(); return; } } } // Button event handlers shovelBtn.down = function (x, y, obj) { selectedPlantType = 'shovel'; instructionText.setText('Selected: Shovel - Click plants to remove'); }; peaShooterBtn.down = function (x, y, obj) { if (plantRecharges.peaShooter === 0) { selectedPlantType = 'peaShooter'; instructionText.setText('Selected: Pea Shooter (100)'); } else { instructionText.setText('Pea Shooter recharging: ' + Math.ceil(plantRecharges.peaShooter / 60) + 's'); } }; wallNutBtn.down = function (x, y, obj) { if (plantRecharges.wallNut === 0) { selectedPlantType = 'wallNut'; instructionText.setText('Selected: Wall Nut (50)'); } else { instructionText.setText('Wall Nut recharging: ' + Math.ceil(plantRecharges.wallNut / 60) + 's'); } }; sunflowerBtn.down = function (x, y, obj) { if (plantRecharges.sunflower === 0) { selectedPlantType = 'sunflower'; instructionText.setText('Selected: Sunflower (50)'); } else { instructionText.setText('Sunflower recharging: ' + Math.ceil(plantRecharges.sunflower / 60) + 's'); } }; repeaterBtn.down = function (x, y, obj) { if (plantRecharges.repeater === 0) { selectedPlantType = 'repeater'; instructionText.setText('Selected: Repeater (200)'); } else { instructionText.setText('Repeater recharging: ' + Math.ceil(plantRecharges.repeater / 60) + 's'); } }; cherryBombBtn.down = function (x, y, obj) { if (plantRecharges.cherryBomb === 0) { selectedPlantType = 'cherryBomb'; instructionText.setText('Selected: Cherry Bomb (150)'); } else { instructionText.setText('Cherry Bomb recharging: ' + Math.ceil(plantRecharges.cherryBomb / 60) + 's'); } }; spikeweedBtn.down = function (x, y, obj) { if (plantRecharges.spikeweed === 0) { selectedPlantType = 'spikeweed'; instructionText.setText('Selected: Spikeweed (100)'); } else { instructionText.setText('Spikeweed recharging: ' + Math.ceil(plantRecharges.spikeweed / 60) + 's'); } }; chomperBtn.down = function (x, y, obj) { if (plantRecharges.chomper === 0) { selectedPlantType = 'chomper'; instructionText.setText('Selected: Chomper (150)'); } else { instructionText.setText('Chomper recharging: ' + Math.ceil(plantRecharges.chomper / 60) + 's'); } }; // Grid click handler game.down = function (x, y, obj) { if (gameState !== 'playing') return; // Check if click is within grid bounds if (x >= GRID_START_X && x <= GRID_START_X + GRID_COLS * CELL_SIZE && y >= GRID_START_Y && y <= GRID_START_Y + GRID_ROWS * CELL_SIZE) { var col = Math.floor((x - GRID_START_X) / CELL_SIZE); var row = Math.floor((y - GRID_START_Y) / CELL_SIZE); if (row >= 0 && row < GRID_ROWS && col >= 0 && col < GRID_COLS) { if (selectedPlantType === 'shovel') { removePlant(row, col); } else { placePlant(row, col, selectedPlantType); } } } }; // Main game loop game.update = function () { if (gameState !== 'playing') return; // Handle day/night cycle if (currentWave === 6 && !nightTransitionCompleted) { // Transition to night after wave 5 isNight = true; nightTransitionCompleted = true; game.setBackgroundColor(0x001122); // Flash screen to indicate night LK.effects.flashScreen(0x000044, 1000); } else if (currentWave === 11 && !dayTransitionCompleted) { // Transition back to day after wave 10 isNight = false; dayTransitionCompleted = true; game.setBackgroundColor(0x2d5016); // Flash screen to indicate day LK.effects.flashScreen(0x88ff44, 1000); } // Keep background color consistent during night/day periods if (isNight && currentWave >= 6 && currentWave < 11) { game.setBackgroundColor(0x001122); } else if (!isNight && (currentWave < 6 || currentWave >= 11)) { game.setBackgroundColor(0x2d5016); } // Handle game start delay if (!firstWaveStarted) { gameStartTimer++; if (gameStartTimer >= 1500 && !alertShown) { // 25 seconds alertShown = true; LK.effects.flashScreen(0xff0000, 2000); // Create alert text var alertText = new Text2('ZOMBIES ARE COMING!', { size: 80, fill: 0xff0000 }); alertText.anchor.set(0.5, 0.5); alertText.x = 0; alertText.y = 0; LK.gui.center.addChild(alertText); // Animate alert text tween(alertText, { scaleX: 1.5, scaleY: 1.5 }, { duration: 500 }); tween(alertText, { alpha: 0 }, { duration: 2000, onFinish: function onFinish() { alertText.destroy(); firstWaveStarted = true; } }); } } // Spawn enemies if (firstWaveStarted) { waveTimer++; if (enemiesSpawned < enemiesPerWave && waveTimer % 120 === 0) { // Every 2 seconds var randomRow = Math.floor(Math.random() * GRID_ROWS); spawnEnemy(randomRow); } } // Update projectiles for (var i = projectiles.length - 1; i >= 0; i--) { var projectile = projectiles[i]; // Check collision with enemies var hit = false; for (var j = 0; j < enemies.length; j++) { var enemy = enemies[j]; if (projectile.row === enemy.row && projectile.x >= enemy.x - 35 && projectile.x <= enemy.x + 35) { enemy.takeDamage(projectile.damage); hit = true; break; } } // Remove projectile if hit or off screen if (hit || projectile.x > 2100) { projectiles.splice(i, 1); projectile.destroy(); } } // Check enemy-plant collisions for (var k = 0; k < enemies.length; k++) { var enemy = enemies[k]; enemy.attacking = false; for (var l = 0; l < plants.length; l++) { var plant = plants[l]; if (enemy.row === plant.row && enemy.x >= plant.x - 50 && enemy.x <= plant.x + 50) { // Skip spikeweed - zombies ignore it completely and don't stop for it if (plant instanceof Spikeweed) { continue; } enemy.attacking = true; break; } } } // Update plant recharges for (var plantType in plantRecharges) { if (plantRecharges[plantType] > 0) { plantRecharges[plantType]--; } } // Check pruner activation for (var m = 0; m < pruners.length; m++) { var pruner = pruners[m]; if (!pruner.activated) { for (var n = 0; n < enemies.length; n++) { var enemy = enemies[n]; if (enemy.row === pruner.row && Math.abs(enemy.x - pruner.x) <= 80) { pruner.activate(); break; } } } } checkWaveComplete(); checkGameOver(); };
===================================================================
--- original.js
+++ change.js
@@ -769,10 +769,10 @@
anchorY: 0.5
});
// Tint to differentiate from other zombies
zomboniGraphics.tint = 0x444444;
- self.health = 160; // Double normal zombie health
- self.maxHealth = 160;
+ self.health = 300; // Triple normal zombie health
+ self.maxHealth = 300;
self.speed = -0.8; // Faster than normal zombie
self.damage = 1000; // Crushes plants instantly
self.attackTimer = 0;
self.attackDelay = 30; // Fast crushing
@@ -1161,18 +1161,18 @@
function spawnEnemy(row) {
var enemy;
var rand = Math.random();
var spawnMultiplier = isNight ? 1.5 : 1; // More enemies at night
- var waveMultiplier = Math.min(1 + (currentWave - 1) * 0.1, 2.0); // Increase spawn chance with waves
- if (currentWave >= 6 && rand < 0.1 * waveMultiplier) {
+ var waveMultiplier = Math.min(1 + (currentWave - 1) * 0.15, 2.5); // Increase spawn chance more aggressively with waves
+ if (currentWave >= 5 && rand < 0.12 * waveMultiplier) {
enemy = new Gargantuar();
- } else if (currentWave >= 5 && rand < 0.15 * waveMultiplier) {
+ } else if (currentWave >= 4 && rand < 0.18 * waveMultiplier) {
enemy = new Zomboni();
- } else if (currentWave >= 4 && rand < 0.2 * waveMultiplier) {
+ } else if (currentWave >= 3 && rand < 0.25 * waveMultiplier) {
enemy = new JackInTheBoxZombie();
- } else if (currentWave >= 2 && rand < 0.3 * waveMultiplier) {
+ } else if (currentWave >= 2 && rand < 0.35 * waveMultiplier) {
enemy = new AllStarZombie();
- } else if (currentWave > 3 && rand < 0.5 * waveMultiplier) {
+ } else if (currentWave >= 3 && rand < 0.6 * waveMultiplier) {
enemy = new Skeleton();
} else {
enemy = new Zombie();
}
@@ -1181,11 +1181,13 @@
enemy.row = row;
enemiesSpawned++;
enemies.push(enemy);
game.addChild(enemy);
- // Spawn additional enemies at night and more as waves progress
- var extraSpawnChance = isNight ? 0.3 : 0.15;
- extraSpawnChance += (currentWave - 1) * 0.05; // Increase with waves
+ // Spawn additional enemies at night and more as waves progress from wave 3
+ var extraSpawnChance = isNight ? 0.4 : 0.2;
+ if (currentWave >= 3) {
+ extraSpawnChance += (currentWave - 1) * 0.08; // More aggressive increase with waves
+ }
if (Math.random() < extraSpawnChance) {
var extraEnemy = new Zombie();
extraEnemy.x = 2050;
extraEnemy.y = GRID_START_Y + row * CELL_SIZE + CELL_SIZE / 2;
@@ -1203,9 +1205,9 @@
LK.showYouWin();
return;
}
enemiesSpawned = 0;
- enemiesPerWave = Math.min(5 + currentWave * 3, 25);
+ enemiesPerWave = Math.min(5 + currentWave * 4, 30);
waveTimer = 0;
}
}
function checkGameOver() {
La Petacereza es un par de cerezas gemelas de un rojo intenso y brillante, unidas por sus delgados tallos que se juntan en una pequeña ramita coronada por tres hojas verdes oscuras. Cada fruto tiene rasgos agresivos: ojos amarillentos con iris rojizos y cejas fruncidas, y bocas torcidas en muecas de enfado que sugieren su inminente explosión. Sus superficies lucen suaves, con leves reflejos que acentúan su redondez perfecta.. In-Game asset. 2d. High contrast. No shadows
una planta de color verde brillante con forma de pistola vegetal: su “cañón” cilíndrico, ligeramente más ancho en la boca, luce un tono verde claro con un suave degradado y un brillo que le da volumen. Sus ojos son dos círculos lisos y oscuros, casi sin pupila, que le aportan un aire simpático y sencillo. El cuerpo descansa sobre un tallo delgado y flexible, sostenido por cuatro hojas arqueadas y onduladas en la base, de un verde más intenso, que sirven de “pies” y refuerzan su aparienciauna planta de color verde brillante con forma de pistola vegetal: su “cañón” cilíndrico, ligeramente más ancho en la boca, luce un tono verde claro con un suave degradado y un brillo que le da volumen. Sus ojos son dos círculos lisos y oscuros, casi sin pupila, que le aportan un aire simpático y sencillo. El cuerpo descansa sobre un tallo delgado y flexible, sostenido por cuatro hojas arqueadas y onduladas en la base, de un verde más intenso, que sirven de “pies” y refuerzan su apariencia. In-Game asset. High contrast. No shadows
Un girasol con una cabeza redonda y marrón con pétalos amarillos brillantes que lo rodean como una corona. Su tallo es verde y tiene dos hojas grandes y anchas que sobresalen a los lados. En su cara, tiene dos ojos pequeños y negros, y una boca curvada en una sonrisa amigable.. In-Game asset. High contrast. No shadows
varias nubes de Humo color rojo un poco oscuro saliendo de una explosión. In-Game asset. High contrast
Una planta de color verde brillante, con un cuerpo principal esférico que se estrecha hacia adelante para formar una boca grande y redonda. De la parte posterior de su cabeza, brotan varias hojas puntiagudas. Tiene dos ojos grandes y redondos, con pupilas negras, y su expresión es decidida. Su tallo es delgado y verde, anclado en un grupo de hojas más grandes en la base.. In-Game asset. High contrast. No shadows
Nuez de color marrón claro, con una textura rugosa que le da un aspecto robusto. Es de forma ovalada, ligeramente más ancha en la base. Tiene dos ojos grandes y blancos con pupilas negras, que miran hacia adelante, y una boca pequeña y sonriente que le da una expresión algo asustadiza o sorprendida.. In-Game asset. High contrast. No shadows
Una casilla de pasto con bordes color verde oscuro que cubra toda la imagen y unas pequeñas flores. In-Game asset. High contrast
Esqueleto zombi en cuerpo completo caminando. In-Game asset. 2d. High contrast. No shadows
Zombie de piel verdosa y pálida, con una cabeza ovalada y dos grandes ojos saltones con pupilas pequeñas y rojizas. Su boca está abierta, mostrando dientes irregulares. Viste un traje de negocios marrón claro, una camisa blanca y una corbata roja a rayas, todo rasgado y sucio. Sus pantalones azules están hechos jirones, dejando ver una pierna esquelética, y calza zapatos marrones desgastados. Sus brazos están extendidos ligeramente hacia adelante. In-Game asset. 2d. High contrast. No shadows
Un guisante. In-Game asset. 2d. High contrast. No shadows
Sol puntiagudo luminoso. In-Game asset. 2d. High contrast. No shadows
Zombi a cuerpo completo de piel verdosa y pálida, con cabello desordenado y ojos saltones, viste una camisa de fuerza con correas de cuero alrededor de sus brazos y torso. sostiene una caja de sorpresas roja y blanca con estrellas, que tiene una manivela en un lado. Su expresión es de una sonrisa macabra. In-Game asset. 2d. High contrast. No shadows
Una podadora de césped compacta y robusta, predominantemente de color rojo vibrante. Tiene un motor gris con una tapa roja en la parte superior. Cuenta con cuatro ruedas pequeñas y oscuras, y un mango largo y negro en forma de "U" invertida que se extiende hacia atrás.. In-Game asset. 2d. High contrast. No shadows
pequeña pala de acero, con mango de madera y un agarre de color rojo. In-Game asset. 2d. High contrast. No shadows
Un zombi gigante y musculoso de piel verdosa. Viste un chaleco marrón roto y pantalones oscuros desgarrados, dejando ver parte de sus piernas. En su mano derecha, blande un poste de luz improvisado con cuatro farolas, usándolo como arma. Sobre su espalda, lleva a un zombi pequeño, sujeto por unas correas. Sus ojos son grandes y saltones, y su boca está abierta mostrando una dentadura irregular, dándole una expresión de furia.. In-Game asset. 2d. High contrast. No shadows
Un zombi con piel verdosa y pálida, cabello rojizo despeinado y un gorro de lana rojo. Viste un chaleco de mezclilla sin mangas sobre una camiseta negra y pantalones de mezclilla. Está sentado en un vehículo de mantenimiento de hielo azul y gris, similar a una Zamboni, con una gran "Z" roja en el frente. El vehículo tiene ruedas pequeñas y negras, y el Zomboni lo conduce con una expresión de asombro y determinación, con la boca abierta.. In-Game asset. 2d. High contrast. No shadows
una planta que emerge del suelo como una masa de tierra marrón, semi-enterrada. De ella sobresalen una serie de púas afiladas de color beige, de diferentes tamaños y ángulos, dispuestas en varias filas. En el centro, asoman dos ojos pequeños y rojos, con una mirada intensa y ligeramente enojada.. In-Game asset. 2d. High contrast. No shadows
Planta Carnívora con una cabeza grande y ovalada de color púrpura oscuro, salpicada con manchas más claras del mismo tono. Su boca es enorme, bordeada por un labio verde lima y llena de dientes blancos y afilados. Dentro de su boca, se ve una lengua rosada y una garganta oscura. Un tallo delgado y púrpura sostiene la cabeza, y en su base, tiene varias hojas verdes que se curvan hacia abajo. Pequeñas hojas puntiagudas también brotan de la parte superior y trasera de su cabeza.. In-Game asset. 2d. High contrast. No shadows