/****
* 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(0, 0);
waveText.x = 20;
waveText.y = 120;
LK.gui.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
@@ -1,6 +1,399 @@
-/****
+/****
+* 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: 0x000000
-});
\ No newline at end of file
+ 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(0, 0);
+waveText.x = 20;
+waveText.y = 120;
+LK.gui.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();
+};
\ No newline at end of file