/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
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 = 1;
self.lane = 0;
self.update = function () {
self.x += self.speed;
};
return self;
});
var Plant = Container.expand(function (plantType) {
var self = Container.call(this);
self.plantType = plantType || 'peashooter';
self.health = 100;
self.maxHealth = 100;
self.shootTimer = 0;
self.sunTimer = 0;
self.lane = 0;
self.gridX = 0;
self.gridY = 0;
var plantGraphics = self.attachAsset(self.plantType, {
anchorX: 0.5,
anchorY: 0.5
});
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
self.shouldRemove = true;
}
};
self.update = function () {
if (self.plantType === 'peashooter') {
self.shootTimer++;
if (self.shootTimer >= 60) {
// Shoot every second
// Check for zombies in same lane
var hasTarget = false;
for (var i = 0; i < zombies.length; i++) {
if (zombies[i].lane === self.lane && zombies[i].x > self.x) {
hasTarget = true;
break;
}
}
if (hasTarget) {
var pea = new Pea();
pea.x = self.x + 60;
pea.y = self.y;
pea.lane = self.lane;
peas.push(pea);
game.addChild(pea);
LK.getSound('shoot').play();
}
self.shootTimer = 0;
}
} else if (self.plantType === 'sunflower') {
self.sunTimer++;
if (self.sunTimer >= 480) {
// Generate sun every 8 seconds
var sun = new Sun();
sun.x = self.x + (Math.random() - 0.5) * 100;
sun.y = self.y + (Math.random() - 0.5) * 100;
suns.push(sun);
game.addChild(sun);
self.sunTimer = 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.lifeTime = 0;
self.maxLife = 600; // 10 seconds at 60fps
self.update = function () {
self.lifeTime++;
if (self.lifeTime > self.maxLife) {
self.shouldRemove = true;
}
// Gentle pulsing animation
var scale = 1 + Math.sin(self.lifeTime * 0.1) * 0.1;
sunGraphics.scaleX = scale;
sunGraphics.scaleY = scale;
};
self.down = function (x, y, obj) {
sunPoints += self.value;
sunText.setText(sunPoints);
LK.getSound('sunCollect').play();
self.shouldRemove = true;
};
return self;
});
var Zombie = Container.expand(function (zombieType) {
var self = Container.call(this);
self.zombieType = zombieType || 'basicZombie';
self.health = zombieType === 'coneZombie' ? 30 : 15;
self.maxHealth = self.health;
self.speed = zombieType === 'coneZombie' ? -1.5 : -2;
self.lane = 0;
self.eatTimer = 0;
self.targetPlant = null;
var zombieGraphics = self.attachAsset(self.zombieType, {
anchorX: 0.5,
anchorY: 0.5
});
self.takeDamage = function (damage) {
self.health -= damage;
LK.effects.flashObject(self, 0xff0000, 200);
LK.getSound('zombieHit').play();
if (self.health <= 0) {
self.shouldRemove = true;
}
};
self.update = function () {
// Check for plants to eat
var foundPlant = null;
for (var i = 0; i < plants.length; i++) {
var plant = plants[i];
if (plant.lane === self.lane && Math.abs(plant.x - self.x) < 80 && plant.x < self.x) {
foundPlant = plant;
break;
}
}
if (foundPlant) {
self.targetPlant = foundPlant;
self.eatTimer++;
if (self.eatTimer >= 60) {
// Eat every second
foundPlant.takeDamage(10);
self.eatTimer = 0;
}
} else {
self.targetPlant = null;
self.x += self.speed;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x228B22
});
/****
* Game Code
****/
// Sound effects
// Zombie assets
// Projectile and pickup assets
// Plant assets
// Grid and UI assets
// Game constants
var GRID_COLS = 9;
var GRID_ROWS = 5;
var GRID_SIZE = 160;
var GRID_SPACING = 164;
var GRID_START_X = 300;
var GRID_START_Y = 400;
// Game state
var sunPoints = 150;
var selectedPlant = null;
var waveTimer = 0;
var currentWave = 1;
var zombiesThisWave = 0;
var maxZombiesPerWave = 5;
var sunGenerationTimer = 0;
// Game arrays
var plants = [];
var zombies = [];
var peas = [];
var suns = [];
var gridCells = [];
// Create grid
for (var row = 0; row < GRID_ROWS; row++) {
gridCells[row] = [];
for (var col = 0; col < GRID_COLS; col++) {
var gridBorder = game.addChild(LK.getAsset('gridBorder', {
x: GRID_START_X + col * GRID_SPACING,
y: GRID_START_Y + row * GRID_SPACING,
anchorX: 0.5,
anchorY: 0.5
}));
var gridCell = game.addChild(LK.getAsset('gridCell', {
x: GRID_START_X + col * GRID_SPACING,
y: GRID_START_Y + row * GRID_SPACING,
anchorX: 0.5,
anchorY: 0.5
}));
gridCell.gridX = col;
gridCell.gridY = row;
gridCell.isEmpty = true;
gridCells[row][col] = gridCell;
gridCell.down = function (x, y, obj) {
if (selectedPlant && obj.isEmpty) {
var plantCost = getPlantCost(selectedPlant);
if (sunPoints >= plantCost) {
var newPlant = new Plant(selectedPlant);
newPlant.x = obj.x;
newPlant.y = obj.y;
newPlant.lane = obj.gridY;
newPlant.gridX = obj.gridX;
newPlant.gridY = obj.gridY;
plants.push(newPlant);
game.addChild(newPlant);
obj.isEmpty = false;
sunPoints -= plantCost;
sunText.setText(sunPoints);
selectedPlant = null;
updatePlantButtons();
LK.getSound('plantPlaced').play();
}
}
};
}
}
// Create house wall
var houseWall = game.addChild(LK.getAsset('houseWall', {
x: 200,
y: 1366,
anchorX: 0.5,
anchorY: 0.5
}));
// Create UI
var sunText = new Text2(sunPoints.toString(), {
size: 80,
fill: 0xFFFF00
});
sunText.anchor.set(0.5, 0);
LK.gui.top.addChild(sunText);
var waveText = new Text2('Wave: 1', {
size: 60,
fill: 0xFFFFFF
});
waveText.anchor.set(1, 1);
LK.gui.bottomRight.addChild(waveText);
// Plant selection buttons
var plantButtons = [];
var plantTypes = ['peashooter', 'sunflower', 'wallnut'];
var plantCosts = [100, 50, 50];
for (var i = 0; i < plantTypes.length; i++) {
var button = game.addChild(LK.getAsset(plantTypes[i], {
x: 100,
y: 200 + i * 180,
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.8,
scaleY: 0.8
}));
button.plantType = plantTypes[i];
button.cost = plantCosts[i];
button.originalAlpha = 1;
var costText = new Text2(button.cost.toString(), {
size: 40,
fill: 0xFFFF00
});
costText.anchor.set(0.5, 0);
costText.x = button.x;
costText.y = button.y + 80;
game.addChild(costText);
button.costText = costText;
button.down = function (x, y, obj) {
if (sunPoints >= obj.cost) {
selectedPlant = obj.plantType;
updatePlantButtons();
}
};
plantButtons.push(button);
}
function getPlantCost(plantType) {
switch (plantType) {
case 'peashooter':
return 100;
case 'sunflower':
return 50;
case 'wallnut':
return 50;
default:
return 100;
}
}
function updatePlantButtons() {
for (var i = 0; i < plantButtons.length; i++) {
var button = plantButtons[i];
if (sunPoints >= button.cost) {
button.alpha = button.plantType === selectedPlant ? 0.7 : 1;
} else {
button.alpha = 0.3;
}
}
}
function spawnZombie() {
var zombieType = Math.random() < 0.3 ? 'coneZombie' : 'basicZombie';
var zombie = new Zombie(zombieType);
zombie.x = 2100;
zombie.y = GRID_START_Y + Math.floor(Math.random() * GRID_ROWS) * GRID_SPACING;
zombie.lane = Math.floor((zombie.y - GRID_START_Y + GRID_SPACING / 2) / GRID_SPACING);
zombies.push(zombie);
game.addChild(zombie);
}
game.update = function () {
// Generate sun over time
sunGenerationTimer++;
if (sunGenerationTimer >= 600) {
// Every 10 seconds
var sun = new Sun();
sun.x = 400 + Math.random() * 1200;
sun.y = 300 + Math.random() * 400;
suns.push(sun);
game.addChild(sun);
sunGenerationTimer = 0;
}
// Spawn zombies
waveTimer++;
if (waveTimer >= 300 && zombiesThisWave < maxZombiesPerWave) {
// Every 5 seconds
spawnZombie();
zombiesThisWave++;
waveTimer = 0;
}
if (zombiesThisWave >= maxZombiesPerWave && zombies.length === 0) {
// Start next wave
currentWave++;
maxZombiesPerWave = Math.min(15, 5 + currentWave * 2);
zombiesThisWave = 0;
waveTimer = 0;
waveText.setText('Wave: ' + currentWave);
}
// Update and remove peas
for (var i = peas.length - 1; i >= 0; i--) {
var pea = peas[i];
if (pea.x > 2200) {
pea.destroy();
peas.splice(i, 1);
continue;
}
// Check pea-zombie collision
for (var j = 0; j < zombies.length; j++) {
var zombie = zombies[j];
if (pea.lane === zombie.lane && pea.x >= zombie.x - 50 && pea.x <= zombie.x + 50 && Math.abs(pea.y - zombie.y) < 70) {
zombie.takeDamage(pea.damage);
pea.destroy();
peas.splice(i, 1);
break;
}
}
}
// Update and remove zombies
for (var i = zombies.length - 1; i >= 0; i--) {
var zombie = zombies[i];
if (zombie.shouldRemove) {
zombie.destroy();
zombies.splice(i, 1);
continue;
}
if (zombie.x < 250) {
LK.showGameOver();
return;
}
}
// Update and remove plants
for (var i = plants.length - 1; i >= 0; i--) {
var plant = plants[i];
if (plant.shouldRemove) {
gridCells[plant.gridY][plant.gridX].isEmpty = true;
plant.destroy();
plants.splice(i, 1);
}
}
// Update and remove suns
for (var i = suns.length - 1; i >= 0; i--) {
var sun = suns[i];
if (sun.shouldRemove) {
sun.destroy();
suns.splice(i, 1);
}
}
updatePlantButtons();
}; ===================================================================
--- original.js
+++ change.js
@@ -249,12 +249,10 @@
var waveText = new Text2('Wave: 1', {
size: 60,
fill: 0xFFFFFF
});
-waveText.anchor.set(0, 0);
-waveText.x = 20;
-waveText.y = 120;
-LK.gui.addChild(waveText);
+waveText.anchor.set(1, 1);
+LK.gui.bottomRight.addChild(waveText);
// Plant selection buttons
var plantButtons = [];
var plantTypes = ['peashooter', 'sunflower', 'wallnut'];
var plantCosts = [100, 50, 50];