User prompt
Make the zombies do more damage to the plants
User prompt
Make zombies at the start of a wave take a while to spawn ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
make the shovel appear below the wave letters
User prompt
creates a shovel that allows you to remove a selected plant
User prompt
Please fix the bug: 'TypeError: zombie.takeDamage is not a function' in or related to this line: 'zombie.takeDamage(self.damage);' Line Number: 259
User prompt
Creates a zombie called Jack in Box that explodes when it touches a plant, eliminating nearby plants ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Please fix the bug: 'TypeError: zombie.takeDamage is not a function' in or related to this line: 'zombie.takeDamage(self.damage);' Line Number: 174
User prompt
Make the wave letters black and make the screen flash red every time a wave increases. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Make the suns bigger and make the zombies take a little longer to spawn.
User prompt
move the plant selector to the bottom of the screen
User prompt
Create a cherry popper asset that costs 150 soles and make the asset a red square that explodes when planted, eliminating nearby zombies. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
Code edit (1 edits merged)
Please save this source code
User prompt
Garden Defense: Zombie Invasion
Initial prompt
tower defense plants vs zombies
/****
* 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 = 20;
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 FastZombie = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('fastZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1.2;
self.health = 60;
self.maxHealth = 60;
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.shootTimer = 0;
self.shootDelay = 90; // 1.5 seconds at 60fps
self.gridX = 0;
self.gridY = 0;
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.sunTimer = 0;
self.sunDelay = 600; // 10 seconds at 60fps
self.gridX = 0;
self.gridY = 0;
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 TankZombie = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('tankZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.3;
self.health = 200;
self.maxHealth = 200;
self.damage = 40;
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 = 120; // 2 seconds
var zombiesPerWave = 5;
var zombiesSpawned = 0;
var zombiesKilled = 0;
var totalZombiesToKill = 0;
// 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: 0xFFFFFF
});
waveDisplay.anchor.set(0.5, 0);
LK.gui.top.addChild(waveDisplay);
waveDisplay.y = 20;
// Plant selection buttons
var peashooterBtn = LK.getAsset('peashooter', {
x: 50,
y: 200,
scaleX: 0.8,
scaleY: 0.8,
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(peashooterBtn);
var sunflowerBtn = LK.getAsset('sunflower', {
x: 50,
y: 350,
scaleX: 0.8,
scaleY: 0.8,
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(sunflowerBtn);
var wallnutBtn = LK.getAsset('wallnut', {
x: 50,
y: 500,
scaleX: 0.8,
scaleY: 0.8,
anchorX: 0.5,
anchorY: 0.5
});
game.addChild(wallnutBtn);
// Cost display texts
var peaCostTxt = new Text2('100', {
size: 40,
fill: 0xFFFFFF
});
peaCostTxt.anchor.set(0.5, 0);
game.addChild(peaCostTxt);
peaCostTxt.x = 50;
peaCostTxt.y = 250;
var sunCostTxt = new Text2('50', {
size: 40,
fill: 0xFFFFFF
});
sunCostTxt.anchor.set(0.5, 0);
game.addChild(sunCostTxt);
sunCostTxt.x = 50;
sunCostTxt.y = 400;
var wallCostTxt = new Text2('50', {
size: 40,
fill: 0xFFFFFF
});
wallCostTxt.anchor.set(0.5, 0);
game.addChild(wallCostTxt);
wallCostTxt.x = 50;
wallCostTxt.y = 550;
// 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 > 5 && zombieType < 0.2) {
zombie = new TankZombie();
} else if (currentWave > 3 && zombieType < 0.4) {
zombie = new FastZombie();
} else {
zombie = new BasicZombie();
}
zombie.x = gridStartX + gridCols * gridWidth + 100;
zombie.y = gridStartY + lane * gridHeight + gridHeight / 2;
zombie.gridY = lane;
zombies.push(zombie);
game.addChild(zombie);
zombiesSpawned++;
}
function startNextWave() {
if (currentWave <= maxWaves) {
zombiesPerWave = 5 + Math.floor(currentWave / 2);
zombiesSpawned = 0;
waveDisplay.setText('Wave: ' + currentWave + '/' + maxWaves);
}
}
// 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);
}
};
game.down = function (x, y, obj) {
var gridPos = getGridPosition(x, y);
if (gridPos && selectedPlantType) {
var gridKey = gridPos.col + ',' + gridPos.row;
// 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;
}
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
if (zombiesSpawned < zombiesPerWave) {
zombieSpawnTimer++;
if (zombieSpawnTimer >= zombieSpawnDelay) {
spawnZombie();
zombieSpawnTimer = 0;
}
}
// 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;
};
// Start first wave
startNextWave(); ===================================================================
--- original.js
+++ change.js
@@ -1,6 +1,542 @@
-/****
+/****
+* 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 = 20;
+ 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 FastZombie = Container.expand(function () {
+ var self = Container.call(this);
+ var graphics = self.attachAsset('fastZombie', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 1.2;
+ self.health = 60;
+ self.maxHealth = 60;
+ 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.shootTimer = 0;
+ self.shootDelay = 90; // 1.5 seconds at 60fps
+ self.gridX = 0;
+ self.gridY = 0;
+ 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.sunTimer = 0;
+ self.sunDelay = 600; // 10 seconds at 60fps
+ self.gridX = 0;
+ self.gridY = 0;
+ 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 TankZombie = Container.expand(function () {
+ var self = Container.call(this);
+ var graphics = self.attachAsset('tankZombie', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ self.speed = 0.3;
+ self.health = 200;
+ self.maxHealth = 200;
+ self.damage = 40;
+ 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: 0x000000
-});
\ No newline at end of file
+ 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 = 120; // 2 seconds
+var zombiesPerWave = 5;
+var zombiesSpawned = 0;
+var zombiesKilled = 0;
+var totalZombiesToKill = 0;
+// 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: 0xFFFFFF
+});
+waveDisplay.anchor.set(0.5, 0);
+LK.gui.top.addChild(waveDisplay);
+waveDisplay.y = 20;
+// Plant selection buttons
+var peashooterBtn = LK.getAsset('peashooter', {
+ x: 50,
+ y: 200,
+ scaleX: 0.8,
+ scaleY: 0.8,
+ anchorX: 0.5,
+ anchorY: 0.5
+});
+game.addChild(peashooterBtn);
+var sunflowerBtn = LK.getAsset('sunflower', {
+ x: 50,
+ y: 350,
+ scaleX: 0.8,
+ scaleY: 0.8,
+ anchorX: 0.5,
+ anchorY: 0.5
+});
+game.addChild(sunflowerBtn);
+var wallnutBtn = LK.getAsset('wallnut', {
+ x: 50,
+ y: 500,
+ scaleX: 0.8,
+ scaleY: 0.8,
+ anchorX: 0.5,
+ anchorY: 0.5
+});
+game.addChild(wallnutBtn);
+// Cost display texts
+var peaCostTxt = new Text2('100', {
+ size: 40,
+ fill: 0xFFFFFF
+});
+peaCostTxt.anchor.set(0.5, 0);
+game.addChild(peaCostTxt);
+peaCostTxt.x = 50;
+peaCostTxt.y = 250;
+var sunCostTxt = new Text2('50', {
+ size: 40,
+ fill: 0xFFFFFF
+});
+sunCostTxt.anchor.set(0.5, 0);
+game.addChild(sunCostTxt);
+sunCostTxt.x = 50;
+sunCostTxt.y = 400;
+var wallCostTxt = new Text2('50', {
+ size: 40,
+ fill: 0xFFFFFF
+});
+wallCostTxt.anchor.set(0.5, 0);
+game.addChild(wallCostTxt);
+wallCostTxt.x = 50;
+wallCostTxt.y = 550;
+// 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 > 5 && zombieType < 0.2) {
+ zombie = new TankZombie();
+ } else if (currentWave > 3 && zombieType < 0.4) {
+ zombie = new FastZombie();
+ } else {
+ zombie = new BasicZombie();
+ }
+ zombie.x = gridStartX + gridCols * gridWidth + 100;
+ zombie.y = gridStartY + lane * gridHeight + gridHeight / 2;
+ zombie.gridY = lane;
+ zombies.push(zombie);
+ game.addChild(zombie);
+ zombiesSpawned++;
+}
+function startNextWave() {
+ if (currentWave <= maxWaves) {
+ zombiesPerWave = 5 + Math.floor(currentWave / 2);
+ zombiesSpawned = 0;
+ waveDisplay.setText('Wave: ' + currentWave + '/' + maxWaves);
+ }
+}
+// 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);
+ }
+};
+game.down = function (x, y, obj) {
+ var gridPos = getGridPosition(x, y);
+ if (gridPos && selectedPlantType) {
+ var gridKey = gridPos.col + ',' + gridPos.row;
+ // 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;
+ }
+ 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
+ if (zombiesSpawned < zombiesPerWave) {
+ zombieSpawnTimer++;
+ if (zombieSpawnTimer >= zombieSpawnDelay) {
+ spawnZombie();
+ zombieSpawnTimer = 0;
+ }
+ }
+ // 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;
+};
+// Start first wave
+startNextWave();
\ No newline at end of file