User prompt
delete the button and the double speed function
User prompt
Please fix the bug: 'Uncaught TypeError: LK.setTimeScale is not a function' in or related to this line: 'LK.setTimeScale(2.0);' Line Number: 1397
User prompt
Create a button that when pressed makes the game twice as fast, but if pressed again it will return to its normal speed and is next to the wave letters.
User prompt
Creates a zombie called minerzombie that appears as a normal zombie but after 3 seconds it will teleport to the first square attacking the plants from behind the garden. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the newspaperzombie unable to be slowed down
User prompt
make the damage of the peas less
User prompt
Make the spawn chance of Zomboni, Jesterzombie, and Gargantuar higher from wave 15 onwards.
User prompt
creates a zombie called jesterzombie that will not take damage from peas and will return them by hitting the plants
User prompt
creates a zombie called jesterzombie that will not take damage from peas and will return them by hitting the plants
User prompt
make the zombies bigger
User prompt
make the peas bigger
User prompt
returns all plants and zombies to their original size
User prompt
adjust the size of zombies and plants ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the grass a little smaller by adjusting it next to the plants and zombie spawn.
User prompt
make the grass bigger
User prompt
creates a zombie called gargantuar that is slow and eliminates the plant it touches and is also resistant and when it has half its life it will make a fastzombie appear and also the cherrypopper explosion leaves it at half its life but with a second cherrypopper explosion it eliminates it ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the suns bigger
User prompt
make the zomboni unable to be slowed down
User prompt
Make it 20 waves and from wave 11 the background changes color to dark blue and from wave 11 the zombies appear faster ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the basic zombie, fast zombie, jackinboxzombie, newspaperzombie, zomboni bigger ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Creates a plant called Snowshooter that shoots frozen peas that slow down the zombie the pea hit and creates another separate asset for the pea. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
creates a zombie called zomboni that eliminates the plant it touches and is fast ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the zombies appear faster from wave 5 onwards ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
creates a zombie called newspaperzombie that when it has half health its speed and damage increase ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make Peashooter and Sunflower able to take damage
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
var BasicZombie = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('basicZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.5;
self.health = 100;
self.maxHealth = 100;
self.damage = 40;
self.gridY = 0;
self.attackTimer = 0;
self.attackDelay = 60;
self.update = function () {
// Check if there's a plant to attack
var plantToAttack = null;
for (var i = 0; i < plants.length; i++) {
var plant = plants[i];
if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 80) {
plantToAttack = plant;
break;
}
}
if (plantToAttack) {
self.attackTimer++;
if (self.attackTimer >= self.attackDelay) {
if (plantToAttack.takeDamage) {
plantToAttack.takeDamage(self.damage);
}
self.attackTimer = 0;
}
} else {
self.x -= self.speed;
self.attackTimer = 0;
}
// Check if reached house
if (self.x < 150) {
LK.showGameOver();
}
};
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xff0000, 200);
LK.getSound('zombie_hit').play();
if (self.health <= 0) {
self.destroy();
for (var i = 0; i < zombies.length; i++) {
if (zombies[i] === self) {
zombies.splice(i, 1);
break;
}
}
zombiesKilled++;
}
};
return self;
});
var Zomboni = BasicZombie.expand(function () {
var self = BasicZombie.call(this);
// Replace the graphics with zomboni asset
self.removeChild(self.children[0]);
var graphics = self.attachAsset('zomboni', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1.5; // Fast movement
self.health = 150;
self.maxHealth = 150;
self.damage = 100;
self.gridY = 0;
self.attackTimer = 0;
self.attackDelay = 30; // Faster elimination
self.update = function () {
// Move forward continuously
self.x -= self.speed;
// Check for plants to eliminate (in a wider area due to size)
for (var i = plants.length - 1; i >= 0; i--) {
var plant = plants[i];
if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 100) {
// Instantly eliminate the plant
LK.effects.flashObject(plant, 0xff0000, 200);
// Remove from plant grid
var gridKey = plant.gridX + ',' + plant.gridY;
delete plantGrid[gridKey];
plant.destroy();
plants.splice(i, 1);
}
}
// Check if reached house
if (self.x < 150) {
LK.showGameOver();
}
};
return self;
});
var TankZombie = BasicZombie.expand(function () {
var self = BasicZombie.call(this);
// Replace the graphics with tank zombie asset
self.removeChild(self.children[0]);
var graphics = self.attachAsset('tankZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.3;
self.health = 200;
self.maxHealth = 200;
self.damage = 80;
self.gridY = 0;
self.attackTimer = 0;
self.attackDelay = 60;
return self;
});
var NewspaperZombie = BasicZombie.expand(function () {
var self = BasicZombie.call(this);
// Replace the graphics with newspaper zombie asset
self.removeChild(self.children[0]);
var graphics = self.attachAsset('newspaperZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.5;
self.health = 100;
self.maxHealth = 100;
self.damage = 40;
self.gridY = 0;
self.attackTimer = 0;
self.attackDelay = 60;
self.hasRaged = false;
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xff0000, 200);
LK.getSound('zombie_hit').play();
// Check if health dropped to half or below and hasn't raged yet
if (self.health <= self.maxHealth / 2 && !self.hasRaged) {
self.hasRaged = true;
// Increase speed and damage
self.speed = 1.5;
self.damage = 80;
// Visual effect for rage mode - flash red and change tint
LK.effects.flashObject(self, 0xff0000, 500);
tween(graphics, {
tint: 0xff4444
}, {
duration: 300,
easing: tween.easeOut
});
}
if (self.health <= 0) {
self.destroy();
for (var i = 0; i < zombies.length; i++) {
if (zombies[i] === self) {
zombies.splice(i, 1);
break;
}
}
zombiesKilled++;
}
};
return self;
});
var JackInBoxZombie = BasicZombie.expand(function () {
var self = BasicZombie.call(this);
// Replace the graphics with jack in box zombie asset
self.removeChild(self.children[0]);
var graphics = self.attachAsset('jackInBoxZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.7;
self.health = 80;
self.maxHealth = 80;
self.damage = 60;
self.hasExploded = false;
self.explode = function () {
if (self.hasExploded) return;
self.hasExploded = true;
// Flash the jack in box zombie white before exploding
LK.effects.flashObject(self, 0xffffff, 200);
// Scale up effect for explosion
tween(graphics, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Remove from zombies array
for (var i = 0; i < zombies.length; i++) {
if (zombies[i] === self) {
zombies.splice(i, 1);
break;
}
}
// Destroy the jack in box zombie
self.destroy();
}
});
// Eliminate plants in a 250 pixel radius
var explosionRadius = 250;
for (var i = plants.length - 1; i >= 0; i--) {
var plant = plants[i];
var distance = Math.sqrt(Math.pow(plant.x - self.x, 2) + Math.pow(plant.y - self.y, 2));
if (distance <= explosionRadius) {
// Flash plant red before destroying
LK.effects.flashObject(plant, 0xff0000, 200);
// Remove from plant grid
var gridKey = plant.gridX + ',' + plant.gridY;
delete plantGrid[gridKey];
plant.destroy();
plants.splice(i, 1);
}
}
};
self.update = function () {
// Check if there's a plant to explode on
var plantToExplode = null;
for (var i = 0; i < plants.length; i++) {
var plant = plants[i];
if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 80) {
plantToExplode = plant;
break;
}
}
if (plantToExplode && !self.hasExploded) {
self.explode();
} else {
self.x -= self.speed;
}
// Check if reached house
if (self.x < 150) {
LK.showGameOver();
}
};
return self;
});
var FastZombie = BasicZombie.expand(function () {
var self = BasicZombie.call(this);
// Replace the graphics with fast zombie asset
self.removeChild(self.children[0]);
var graphics = self.attachAsset('fastZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1.2;
self.health = 60;
self.maxHealth = 60;
self.damage = 40;
self.gridY = 0;
self.attackTimer = 0;
self.attackDelay = 60;
return self;
});
var CherryPopper = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('cherrypopper', {
anchorX: 0.5,
anchorY: 0.5
});
self.cost = 150;
self.gridX = 0;
self.gridY = 0;
self.hasExploded = false;
self.explode = function () {
if (self.hasExploded) return;
self.hasExploded = true;
// Flash the cherry popper white before exploding
LK.effects.flashObject(self, 0xffffff, 200);
// Scale up effect for explosion
tween(graphics, {
scaleX: 3,
scaleY: 3,
alpha: 0
}, {
duration: 500,
easing: tween.easeOut,
onFinish: function onFinish() {
// Remove from plants array
for (var i = 0; i < plants.length; i++) {
if (plants[i] === self) {
plants.splice(i, 1);
break;
}
}
// Remove from plant grid
var gridKey = self.gridX + ',' + self.gridY;
delete plantGrid[gridKey];
// Destroy the cherry popper
self.destroy();
}
});
// Eliminate zombies in a 300 pixel radius
var explosionRadius = 300;
for (var i = zombies.length - 1; i >= 0; i--) {
var zombie = zombies[i];
var distance = Math.sqrt(Math.pow(zombie.x - self.x, 2) + Math.pow(zombie.y - self.y, 2));
if (distance <= explosionRadius) {
// Flash zombie red before destroying
LK.effects.flashObject(zombie, 0xff0000, 200);
zombie.destroy();
zombies.splice(i, 1);
zombiesKilled++;
}
}
};
// Auto-explode when planted (immediately after placement)
self.update = function () {
if (!self.hasExploded) {
self.explode();
}
};
return self;
});
var Pea = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('pea', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.damage = 20;
self.gridY = 0;
self.update = function () {
self.x += self.speed;
// Check collision with zombies
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
if (zombie.gridY === self.gridY && self.intersects(zombie)) {
zombie.takeDamage(self.damage);
self.destroy();
for (var j = 0; j < peas.length; j++) {
if (peas[j] === self) {
peas.splice(j, 1);
break;
}
}
return;
}
}
// Remove if off screen
if (self.x > 2200) {
self.destroy();
for (var k = 0; k < peas.length; k++) {
if (peas[k] === self) {
peas.splice(k, 1);
break;
}
}
}
};
return self;
});
var Peashooter = Container.expand(function () {
var self = Container.call(this);
var graphics = 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.gridX = 0;
self.gridY = 0;
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xff0000, 200);
if (self.health <= 0) {
self.destroy();
for (var i = 0; i < plants.length; i++) {
if (plants[i] === self) {
plants.splice(i, 1);
break;
}
}
var gridKey = self.gridX + ',' + self.gridY;
delete plantGrid[gridKey];
} else {
// Visual damage feedback
var damageRatio = self.health / self.maxHealth;
graphics.alpha = 0.3 + damageRatio * 0.7;
}
};
self.update = function () {
self.shootTimer++;
if (self.shootTimer >= self.shootDelay) {
// Check if there's a zombie in this lane
var hasZombieInLane = false;
for (var i = 0; i < zombies.length; i++) {
if (zombies[i].gridY === self.gridY && zombies[i].x > self.x) {
hasZombieInLane = true;
break;
}
}
if (hasZombieInLane) {
self.shoot();
self.shootTimer = 0;
}
}
};
self.shoot = function () {
var pea = new Pea();
pea.x = self.x + 60;
pea.y = self.y;
pea.gridY = self.gridY;
peas.push(pea);
game.addChild(pea);
LK.getSound('shoot').play();
};
return self;
});
var Sun = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('sun', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 25;
self.lifeTimer = 0;
self.maxLife = 600; // 10 seconds
self.update = function () {
self.lifeTimer++;
if (self.lifeTimer > self.maxLife) {
self.destroy();
for (var i = 0; i < suns.length; i++) {
if (suns[i] === self) {
suns.splice(i, 1);
break;
}
}
}
};
self.down = function (x, y, obj) {
sunPoints += self.value;
updateSunDisplay();
self.destroy();
for (var i = 0; i < suns.length; i++) {
if (suns[i] === self) {
suns.splice(i, 1);
break;
}
}
LK.getSound('collect').play();
};
return self;
});
var Sunflower = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('sunflower', {
anchorX: 0.5,
anchorY: 0.5
});
self.cost = 50;
self.health = 100;
self.maxHealth = 100;
self.sunTimer = 0;
self.sunDelay = 600; // 10 seconds at 60fps
self.gridX = 0;
self.gridY = 0;
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xff0000, 200);
if (self.health <= 0) {
self.destroy();
for (var i = 0; i < plants.length; i++) {
if (plants[i] === self) {
plants.splice(i, 1);
break;
}
}
var gridKey = self.gridX + ',' + self.gridY;
delete plantGrid[gridKey];
} else {
// Visual damage feedback
var damageRatio = self.health / self.maxHealth;
graphics.alpha = 0.3 + damageRatio * 0.7;
}
};
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) * 50;
sun.y = self.y + (Math.random() - 0.5) * 50;
suns.push(sun);
game.addChild(sun);
};
return self;
});
var WallNut = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('wallnut', {
anchorX: 0.5,
anchorY: 0.5
});
self.cost = 50;
self.health = 300;
self.maxHealth = 300;
self.gridX = 0;
self.gridY = 0;
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.destroy();
for (var i = 0; i < plants.length; i++) {
if (plants[i] === self) {
plants.splice(i, 1);
break;
}
}
var gridKey = self.gridX + ',' + self.gridY;
delete plantGrid[gridKey];
} else {
// Visual damage feedback
var damageRatio = self.health / self.maxHealth;
graphics.alpha = 0.3 + damageRatio * 0.7;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x8BC34A
});
/****
* Game Code
****/
// Sounds
// Zombies
// Projectiles and collectibles
// Plants
// Game grid and UI elements
// Game variables
var sunPoints = 150;
var currentWave = 1;
var maxWaves = 10;
var waveTimer = 0;
var waveDelay = 1800; // 30 seconds
var zombieSpawnTimer = 0;
var zombieSpawnDelay = 240; // 4 seconds
var zombiesPerWave = 5;
var zombiesSpawned = 0;
var zombiesKilled = 0;
var totalZombiesToKill = 0;
var waveStarted = false;
var zombieSpawnQueue = [];
// Game arrays
var plants = [];
var zombies = [];
var peas = [];
var suns = [];
var plantGrid = {}; // Track occupied grid positions
// Grid settings
var gridStartX = 400;
var gridStartY = 400;
var gridWidth = 256;
var gridHeight = 182;
var gridCols = 5;
var gridRows = 5;
// Selected plant type
var selectedPlantType = null;
// Create lawn grid
for (var row = 0; row < gridRows; row++) {
for (var col = 0; col < gridCols; col++) {
var tile = game.addChild(LK.getAsset('grass', {
x: gridStartX + col * gridWidth,
y: gridStartY + row * gridHeight,
anchorX: 0,
anchorY: 0
}));
}
}
// Create paths (zombie lanes)
for (var lane = 0; lane < gridRows; lane++) {
var pathTile = game.addChild(LK.getAsset('path', {
x: gridStartX + gridCols * gridWidth,
y: gridStartY + lane * gridHeight,
anchorX: 0,
anchorY: 0
}));
}
// Create house
var house = game.addChild(LK.getAsset('house', {
x: 50,
y: gridStartY + gridRows * gridHeight / 2 - 200,
anchorX: 0,
anchorY: 0
}));
// UI Setup
var sunDisplay = new Text2(sunPoints.toString(), {
size: 80,
fill: 0xFFD700
});
sunDisplay.anchor.set(0, 0);
LK.gui.topLeft.addChild(sunDisplay);
sunDisplay.x = 120;
sunDisplay.y = 20;
var waveDisplay = new Text2('Wave: ' + currentWave + '/' + maxWaves, {
size: 60,
fill: 0x000000
});
waveDisplay.anchor.set(0.5, 0);
LK.gui.top.addChild(waveDisplay);
waveDisplay.y = 20;
// Plant selection buttons
var peashooterBtn = LK.getAsset('peashooter', {
x: 400,
y: 2500,
scaleX: 0.8,
scaleY: 0.8,
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(peashooterBtn);
var sunflowerBtn = LK.getAsset('sunflower', {
x: 650,
y: 2500,
scaleX: 0.8,
scaleY: 0.8,
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(sunflowerBtn);
var wallnutBtn = LK.getAsset('wallnut', {
x: 900,
y: 2500,
scaleX: 0.8,
scaleY: 0.8,
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(wallnutBtn);
var cherrypopperBtn = LK.getAsset('cherrypopper', {
x: 1150,
y: 2500,
scaleX: 0.8,
scaleY: 0.8,
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(cherrypopperBtn);
var shovelBtn = LK.getAsset('shovel', {
x: 1024,
y: 150,
scaleX: 0.8,
scaleY: 0.8,
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(shovelBtn);
// Cost display texts
var peaCostTxt = new Text2('100', {
size: 40,
fill: 0xFFFFFF
});
peaCostTxt.anchor.set(0.5, 0);
game.addChild(peaCostTxt);
peaCostTxt.x = 400;
peaCostTxt.y = 2580;
var sunCostTxt = new Text2('50', {
size: 40,
fill: 0xFFFFFF
});
sunCostTxt.anchor.set(0.5, 0);
game.addChild(sunCostTxt);
sunCostTxt.x = 650;
sunCostTxt.y = 2580;
var wallCostTxt = new Text2('50', {
size: 40,
fill: 0xFFFFFF
});
wallCostTxt.anchor.set(0.5, 0);
game.addChild(wallCostTxt);
wallCostTxt.x = 900;
wallCostTxt.y = 2580;
var cherryCostTxt = new Text2('150', {
size: 40,
fill: 0xFFFFFF
});
cherryCostTxt.anchor.set(0.5, 0);
game.addChild(cherryCostTxt);
cherryCostTxt.x = 1150;
cherryCostTxt.y = 2580;
var shovelCostTxt = new Text2('Free', {
size: 40,
fill: 0xFFFFFF
});
shovelCostTxt.anchor.set(0.5, 0);
game.addChild(shovelCostTxt);
shovelCostTxt.x = 1024;
shovelCostTxt.y = 230;
// Calculate total zombies for victory condition
for (var w = 1; w <= maxWaves; w++) {
totalZombiesToKill += zombiesPerWave + Math.floor(w / 2);
}
function updateSunDisplay() {
sunDisplay.setText(sunPoints.toString());
}
function getGridPosition(x, y) {
var col = Math.floor((x - gridStartX) / gridWidth);
var row = Math.floor((y - gridStartY) / gridHeight);
if (col >= 0 && col < gridCols && row >= 0 && row < gridRows) {
return {
col: col,
row: row,
x: gridStartX + col * gridWidth + gridWidth / 2,
y: gridStartY + row * gridHeight + gridHeight / 2
};
}
return null;
}
function spawnZombie() {
var lane = Math.floor(Math.random() * gridRows);
var zombieType = Math.random();
var zombie;
if (currentWave > 6 && zombieType < 0.1) {
zombie = new Zomboni();
} else if (currentWave > 5 && zombieType < 0.2) {
zombie = new TankZombie();
} else if (currentWave > 2 && zombieType < 0.4) {
zombie = new JackInBoxZombie();
} else if (currentWave > 3 && zombieType < 0.6) {
zombie = new FastZombie();
} else if (currentWave > 1 && zombieType < 0.8) {
zombie = new NewspaperZombie();
} else {
zombie = new BasicZombie();
}
zombie.x = gridStartX + gridCols * gridWidth + 100;
zombie.y = gridStartY + lane * gridHeight + gridHeight / 2;
zombie.gridY = lane;
// Add spawn delay animation - zombie starts invisible and fades in
zombie.alpha = 0;
zombie.scaleX = 0.5;
zombie.scaleY = 0.5;
// Animate zombie spawning in
tween(zombie, {
alpha: 1,
scaleX: 1,
scaleY: 1
}, {
duration: 800,
easing: tween.easeOut
});
zombies.push(zombie);
game.addChild(zombie);
zombiesSpawned++;
}
function startNextWave() {
if (currentWave <= maxWaves) {
zombiesPerWave = 5 + Math.floor(currentWave / 2);
zombiesSpawned = 0;
waveStarted = false;
zombieSpawnQueue = [];
waveDisplay.setText('Wave: ' + currentWave + '/' + maxWaves);
// Flash screen red when wave increases
LK.effects.flashScreen(0xff0000, 1000);
// Add delay before wave actually starts spawning zombies
LK.setTimeout(function () {
waveStarted = true;
// Pre-queue zombie spawn times with delays
// Use faster spawn delay from wave 5 onwards
var currentSpawnDelay = currentWave >= 5 ? 120 : zombieSpawnDelay; // 2 seconds vs 4 seconds
for (var i = 0; i < zombiesPerWave; i++) {
zombieSpawnQueue.push({
spawnTime: LK.ticks + i * currentSpawnDelay + Math.random() * 60,
// Add some randomness (reduced for faster waves)
spawned: false
});
}
}, 2000); // 2 second delay before wave starts
}
}
// Generate sun periodically
var sunGenerationTimer = 0;
var sunGenerationDelay = 480; // 8 seconds
// Event handlers
peashooterBtn.down = function () {
if (sunPoints >= 100) {
selectedPlantType = 'peashooter';
LK.effects.flashObject(peashooterBtn, 0x00ff00, 300);
}
};
sunflowerBtn.down = function () {
if (sunPoints >= 50) {
selectedPlantType = 'sunflower';
LK.effects.flashObject(sunflowerBtn, 0x00ff00, 300);
}
};
wallnutBtn.down = function () {
if (sunPoints >= 50) {
selectedPlantType = 'wallnut';
LK.effects.flashObject(wallnutBtn, 0x00ff00, 300);
}
};
cherrypopperBtn.down = function () {
if (sunPoints >= 150) {
selectedPlantType = 'cherrypopper';
LK.effects.flashObject(cherrypopperBtn, 0x00ff00, 300);
}
};
shovelBtn.down = function () {
selectedPlantType = 'shovel';
LK.effects.flashObject(shovelBtn, 0x00ff00, 300);
};
game.down = function (x, y, obj) {
var gridPos = getGridPosition(x, y);
if (gridPos && selectedPlantType) {
var gridKey = gridPos.col + ',' + gridPos.row;
// Handle shovel - remove existing plant
if (selectedPlantType === 'shovel') {
if (plantGrid[gridKey]) {
var plantToRemove = plantGrid[gridKey];
// Remove from plants array
for (var i = 0; i < plants.length; i++) {
if (plants[i] === plantToRemove) {
plants.splice(i, 1);
break;
}
}
// Remove from grid
delete plantGrid[gridKey];
// Destroy the plant
plantToRemove.destroy();
selectedPlantType = null;
}
return;
}
// Check if position is already occupied
if (plantGrid[gridKey]) {
return;
}
var plant = null;
var cost = 0;
if (selectedPlantType === 'peashooter' && sunPoints >= 100) {
plant = new Peashooter();
cost = 100;
} else if (selectedPlantType === 'sunflower' && sunPoints >= 50) {
plant = new Sunflower();
cost = 50;
} else if (selectedPlantType === 'wallnut' && sunPoints >= 50) {
plant = new WallNut();
cost = 50;
} else if (selectedPlantType === 'cherrypopper' && sunPoints >= 150) {
plant = new CherryPopper();
cost = 150;
}
if (plant) {
plant.x = gridPos.x;
plant.y = gridPos.y;
plant.gridX = gridPos.col;
plant.gridY = gridPos.row;
plants.push(plant);
game.addChild(plant);
plantGrid[gridKey] = plant;
sunPoints -= cost;
updateSunDisplay();
selectedPlantType = null;
LK.getSound('plant').play();
}
}
};
game.update = function () {
// Generate sun periodically
sunGenerationTimer++;
if (sunGenerationTimer >= sunGenerationDelay) {
var sun = new Sun();
sun.x = 200 + Math.random() * 1600;
sun.y = 200 + Math.random() * 1000;
suns.push(sun);
game.addChild(sun);
sunGenerationTimer = 0;
}
// Wave management
if (currentWave <= maxWaves) {
waveTimer++;
// Spawn zombies for current wave using queue system
if (waveStarted && zombiesSpawned < zombiesPerWave) {
for (var i = 0; i < zombieSpawnQueue.length; i++) {
var queueItem = zombieSpawnQueue[i];
if (!queueItem.spawned && LK.ticks >= queueItem.spawnTime) {
spawnZombie();
queueItem.spawned = true;
break; // Only spawn one zombie per frame
}
}
}
// Start next wave
if (zombiesSpawned >= zombiesPerWave && zombies.length === 0) {
currentWave++;
if (currentWave <= maxWaves) {
startNextWave();
waveTimer = 0;
}
}
}
// Check victory condition
if (currentWave > maxWaves && zombies.length === 0) {
LK.showYouWin();
}
// Update button availability
peashooterBtn.alpha = sunPoints >= 100 ? 1.0 : 0.5;
sunflowerBtn.alpha = sunPoints >= 50 ? 1.0 : 0.5;
wallnutBtn.alpha = sunPoints >= 50 ? 1.0 : 0.5;
cherrypopperBtn.alpha = sunPoints >= 150 ? 1.0 : 0.5;
shovelBtn.alpha = 1.0; // Shovel is always available
};
// Start first wave
startNextWave(); ===================================================================
--- original.js
+++ change.js
@@ -62,8 +62,46 @@
}
};
return self;
});
+var Zomboni = BasicZombie.expand(function () {
+ var self = BasicZombie.call(this);
+ // Replace the graphics with zomboni asset
+ self.removeChild(self.children[0]);
+ var graphics = self.attachAsset('zomboni', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 1.5; // Fast movement
+ self.health = 150;
+ self.maxHealth = 150;
+ self.damage = 100;
+ self.gridY = 0;
+ self.attackTimer = 0;
+ self.attackDelay = 30; // Faster elimination
+ self.update = function () {
+ // Move forward continuously
+ self.x -= self.speed;
+ // Check for plants to eliminate (in a wider area due to size)
+ for (var i = plants.length - 1; i >= 0; i--) {
+ var plant = plants[i];
+ if (plant.gridY === self.gridY && Math.abs(plant.x - self.x) < 100) {
+ // Instantly eliminate the plant
+ LK.effects.flashObject(plant, 0xff0000, 200);
+ // Remove from plant grid
+ var gridKey = plant.gridX + ',' + plant.gridY;
+ delete plantGrid[gridKey];
+ plant.destroy();
+ plants.splice(i, 1);
+ }
+ }
+ // Check if reached house
+ if (self.x < 150) {
+ LK.showGameOver();
+ }
+ };
+ return self;
+});
var TankZombie = BasicZombie.expand(function () {
var self = BasicZombie.call(this);
// Replace the graphics with tank zombie asset
self.removeChild(self.children[0]);
@@ -692,15 +730,17 @@
function spawnZombie() {
var lane = Math.floor(Math.random() * gridRows);
var zombieType = Math.random();
var zombie;
- if (currentWave > 5 && zombieType < 0.15) {
+ if (currentWave > 6 && zombieType < 0.1) {
+ zombie = new Zomboni();
+ } else if (currentWave > 5 && zombieType < 0.2) {
zombie = new TankZombie();
- } else if (currentWave > 2 && zombieType < 0.35) {
+ } else if (currentWave > 2 && zombieType < 0.4) {
zombie = new JackInBoxZombie();
- } else if (currentWave > 3 && zombieType < 0.55) {
+ } else if (currentWave > 3 && zombieType < 0.6) {
zombie = new FastZombie();
- } else if (currentWave > 1 && zombieType < 0.75) {
+ } else if (currentWave > 1 && zombieType < 0.8) {
zombie = new NewspaperZombie();
} else {
zombie = new BasicZombie();
}