User prompt
KAFASINDA TENEKE OLAN ZOMBİNİN CANINI ARTIR
User prompt
KAFASIN DA TENEKE OLAN ZOMBİ EKLE
User prompt
ZOMBİ LER HASAR ALINCA YAVAŞ LAMASIN
User prompt
BU OYUNU YAYINLA
User prompt
Please fix the bug: 'TypeError: self.targetPlant.takeDamage is not a function' in or related to this line: 'self.targetPlant.takeDamage(1);' Line Number: 124
User prompt
FARKLI ZOMBİLER EKLE
User prompt
ZOMBİLERİN HIZLARI FARKLI OLSUN
User prompt
SÜRE İLER LEDİKÇE DAHA FAZLAZOMBİ GELSİN
User prompt
3 ZOMBİ GİRİNCE BİTSİN
User prompt
ZOMBİ ÇOK HIZLI
User prompt
ZOMBİ Yİ YAVAŞLAT
User prompt
güneşin hızını azLT
Code edit (1 edits merged)
Please save this source code
User prompt
Plants vs. Zombies: Mini Defense
Initial prompt
plant vs zombie
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // BucketheadZombie: stronger zombie with a tin bucket on its head var BucketheadZombie = Container.expand(function () { var self = Container.call(this); // Use the same zombie base image, but add a tin bucket shape on top var zombieGfx = self.attachAsset('zombie', { anchorX: 0.5, anchorY: 0.5 }); // Tin bucket: gray box on head var bucketGfx = self.attachAsset('buckethead_bucket', { anchorX: 0.5, anchorY: 1.0, x: zombieGfx.width / 2, y: zombieGfx.height * 0.18, // place on head scaleX: 0.7, scaleY: 0.5 }); self.addChild(bucketGfx); self.lane = 0; self.speed = 1.0 + Math.random() * 1.5; // Slightly slower than normal zombie self.originalSpeed = self.speed; self.slowTimer = 0; self.hp = 30; // Much more HP self.eating = false; self.targetPlant = null; self.update = function () { if (self.slowTimer && self.slowTimer > 0) { self.slowTimer--; if (self.slowTimer === 0) { self.speed = self.originalSpeed; } } if (self.eating && self.targetPlant && !self.targetPlant.destroyed) { if (LK.ticks % 30 === 0) { self.targetPlant.takeDamage(1); LK.getSound('zombie_eat').play(); } if (self.targetPlant.destroyed) { self.eating = false; self.targetPlant.destroy(); plants.splice(plants.indexOf(self.targetPlant), 1); self.targetPlant = null; } } else { self.x -= self.speed; } }; self.takeDamage = function (dmg) { self.hp -= dmg; if (self.hp <= 0) { self.destroyed = true; } }; return self; }); // Register bucket asset (gray box) // Pea projectile var Pea = Container.expand(function () { var self = Container.call(this); var peaGfx = self.attachAsset('pea', { anchorX: 0.5, anchorY: 0.5 }); self.speed = 18; self.lane = 0; self.update = function () { self.x += self.speed; }; return self; }); // Peashooter plant var Peashooter = Container.expand(function () { var self = Container.call(this); var plantGfx = self.attachAsset('plant_peashooter', { anchorX: 0.5, anchorY: 0.5 }); self.lane = 0; self.shootCooldown = 0; self.update = function () { if (self.shootCooldown > 0) { self.shootCooldown--; } }; // Called by game when it's time to shoot self.shoot = function () { if (self.shootCooldown <= 0) { var pea = new Pea(); pea.x = self.x + 60; pea.y = self.y; pea.lane = self.lane; pea.lastX = pea.x; pea.lastIntersecting = false; peas.push(pea); game.addChild(pea); LK.getSound('pea_shoot').play(); self.shootCooldown = 40; // About 0.66s at 60fps } }; // Add takeDamage method so zombies can attack peashooters self.takeDamage = function (dmg) { // Peashooters have 10 HP by default if (typeof self.hp === "undefined") self.hp = 10; self.hp -= dmg; if (self.hp <= 0) { self.destroyed = true; } }; return self; }); // Sun (currency) var Sun = Container.expand(function () { var self = Container.call(this); var sunGfx = self.attachAsset('sun', { anchorX: 0.5, anchorY: 0.5 }); self.fallSpeed = 4; self.update = function () { self.y += self.fallSpeed; }; return self; }); // Wall-nut plant (blocks zombies) var Wallnut = Container.expand(function () { var self = Container.call(this); var plantGfx = self.attachAsset('plant_wallnut', { anchorX: 0.5, anchorY: 0.5 }); self.lane = 0; self.hp = 20; self.update = function () {}; self.takeDamage = function (dmg) { self.hp -= dmg; if (self.hp <= 0) { self.destroyed = true; } }; return self; }); // Zombie var Zombie = Container.expand(function () { var self = Container.call(this); var zombieGfx = self.attachAsset('zombie', { anchorX: 0.5, anchorY: 0.5 }); self.lane = 0; self.speed = 1.0 + Math.random() * 2.0; // Random speed between 1.0 and 3.0 for more variation self.originalSpeed = self.speed; self.slowTimer = 0; self.hp = 10; self.eating = false; self.targetPlant = null; self.update = function () { // Handle slow effect timer if (self.slowTimer && self.slowTimer > 0) { self.slowTimer--; if (self.slowTimer === 0) { self.speed = self.originalSpeed; } } if (self.eating && self.targetPlant && !self.targetPlant.destroyed) { // Eat plant if (LK.ticks % 30 === 0) { self.targetPlant.takeDamage(1); LK.getSound('zombie_eat').play(); } if (self.targetPlant.destroyed) { self.eating = false; self.targetPlant.destroy(); plants.splice(plants.indexOf(self.targetPlant), 1); self.targetPlant = null; } } else { self.x -= self.speed; } }; self.takeDamage = function (dmg) { self.hp -= dmg; if (self.hp <= 0) { self.destroyed = true; } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x3e7d2c }); /**** * Game Code ****/ // Register bucket asset (gray box) // This flag signals the game is ready for publishing. // --- PUBLISH FLAG --- // Sound // Sun (currency) // Lawn tile // Zombie // Pea projectile // Plants // --- Game constants --- var PUBLISH_READY = true; var NUM_LANES = 5; var LANE_HEIGHT = 2732 / NUM_LANES; var TILE_SIZE = 140; var BOARD_LEFT = 220; var BOARD_RIGHT = 2048 - 80; var BOARD_TOP = 80; var BOARD_BOTTOM = 2732 - 80; var TILES_PER_LANE = 9; var PLANT_COST = { peashooter: 100, wallnut: 50 }; var INITIAL_SUN = 150; var ZOMBIE_SPAWN_INTERVAL = 120; // 2s (initial, will decrease as waves progress) var MAX_WAVES = 10; var ZOMBIES_PER_WAVE = 6; // initial, will increase as waves progress // --- Game state --- var boardTiles = []; var plants = []; var zombies = []; var peas = []; var suns = []; var sunPoints = INITIAL_SUN; var selectedPlantType = null; var dragPlantGhost = null; var placingPlant = false; var lastZombieSpawnTick = 0; var currentWave = 1; var zombiesSpawnedThisWave = 0; var zombiesDefeated = 0; var gameOver = false; var youWin = false; var zombiesEscaped = 0; // --- GUI elements --- var scoreTxt = new Text2('0', { size: 100, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); var sunTxt = new Text2(sunPoints + '', { size: 80, fill: 0xFFE600 }); sunTxt.anchor.set(0, 0); LK.gui.topRight.addChild(sunTxt); // Plant selection buttons var plantBtns = []; function createPlantBtn(type, x, y, color, label) { var btn = LK.getAsset(type === 'peashooter' ? 'plant_peashooter' : 'plant_wallnut', { anchorX: 0.5, anchorY: 0.5, x: x, y: y, scaleX: 0.8, scaleY: 0.8 }); var txt = new Text2(label, { size: 40, fill: "#fff" }); txt.anchor.set(0.5, 0.5); txt.x = btn.width / 2; txt.y = btn.height / 2; btn.addChild(txt); btn.type = type; btn.down = function (x, y, obj) { selectedPlantType = type; if (dragPlantGhost) dragPlantGhost.destroy(); dragPlantGhost = LK.getAsset(type === 'peashooter' ? 'plant_peashooter' : 'plant_wallnut', { anchorX: 0.5, anchorY: 0.5, x: x, y: y, alpha: 0.6, scaleX: 0.8, scaleY: 0.8 }); game.addChild(dragPlantGhost); placingPlant = true; }; plantBtns.push(btn); LK.gui.left.addChild(btn); } createPlantBtn('peashooter', 100, 300, 0x4caf50, '100'); createPlantBtn('wallnut', 100, 500, 0x8d6e63, '50'); // --- Board setup --- for (var lane = 0; lane < NUM_LANES; lane++) { boardTiles[lane] = []; for (var col = 0; col < TILES_PER_LANE; col++) { var tileX = BOARD_LEFT + col * TILE_SIZE + TILE_SIZE / 2; var tileY = BOARD_TOP + lane * LANE_HEIGHT + LANE_HEIGHT / 2; var tile = LK.getAsset('tile', { anchorX: 0.5, anchorY: 0.5, x: tileX, y: tileY, scaleX: 1, scaleY: 1 }); tile.lane = lane; tile.col = col; tile.x = tileX; tile.y = tileY; boardTiles[lane][col] = tile; game.addChild(tile); } } // --- Sun spawning --- function spawnSun() { var col = Math.floor(Math.random() * TILES_PER_LANE); var lane = Math.floor(Math.random() * NUM_LANES); var tile = boardTiles[lane][col]; var sun = new Sun(); sun.x = tile.x; sun.y = tile.y - 200; sun.lastY = sun.y; suns.push(sun); game.addChild(sun); } // --- Zombie spawning --- function spawnZombie() { var lane = Math.floor(Math.random() * NUM_LANES); // 25% chance to spawn a BucketheadZombie, but only after wave 2 var zombie; if (currentWave >= 2 && Math.random() < 0.25) { zombie = new BucketheadZombie(); } else { zombie = new Zombie(); } zombie.lane = lane; zombie.x = BOARD_RIGHT + 80; zombie.y = BOARD_TOP + lane * LANE_HEIGHT + LANE_HEIGHT / 2; zombie.lastX = zombie.x; zombie.lastIntersecting = false; zombies.push(zombie); game.addChild(zombie); zombiesSpawnedThisWave++; } // --- Plant placement logic --- function getTileAt(x, y) { for (var lane = 0; lane < NUM_LANES; lane++) { for (var col = 0; col < TILES_PER_LANE; col++) { var tile = boardTiles[lane][col]; var dx = x - tile.x; var dy = y - tile.y; if (Math.abs(dx) < TILE_SIZE / 2 && Math.abs(dy) < TILE_SIZE / 2) { return { tile: tile, lane: lane, col: col }; } } } return null; } function isTileOccupied(lane, col) { for (var i = 0; i < plants.length; i++) { if (plants[i].lane === lane && plants[i].col === col) return true; } return false; } // --- Game move/drag logic --- game.move = function (x, y, obj) { if (placingPlant && dragPlantGhost) { dragPlantGhost.x = x; dragPlantGhost.y = y; } }; // --- Game down/up logic --- game.down = function (x, y, obj) { // Check if clicking on plant button handled by button itself if (placingPlant && selectedPlantType && dragPlantGhost) { var tileInfo = getTileAt(x, y); if (tileInfo && !isTileOccupied(tileInfo.lane, tileInfo.col)) { // Place plant if enough sun var cost = PLANT_COST[selectedPlantType]; if (sunPoints >= cost) { var plant; if (selectedPlantType === 'peashooter') { plant = new Peashooter(); } else if (selectedPlantType === 'wallnut') { plant = new Wallnut(); } plant.x = tileInfo.tile.x; plant.y = tileInfo.tile.y; plant.lane = tileInfo.lane; plant.col = tileInfo.col; plants.push(plant); game.addChild(plant); sunPoints -= cost; sunTxt.setText(sunPoints + ''); LK.getSound('plant').play(); } } dragPlantGhost.destroy(); dragPlantGhost = null; placingPlant = false; selectedPlantType = null; } else { // Check if clicking on a sun for (var i = suns.length - 1; i >= 0; i--) { var sun = suns[i]; var dx = x - sun.x; var dy = y - sun.y; if (dx * dx + dy * dy < 60 * 60) { sunPoints += 25; sunTxt.setText(sunPoints + ''); sun.destroy(); suns.splice(i, 1); break; } } } }; game.up = function (x, y, obj) { // No drag logic for now }; // --- Main game update loop --- game.update = function () { if (gameOver || youWin) return; // --- Sun logic --- if (LK.ticks % 120 === 0) { spawnSun(); } for (var i = suns.length - 1; i >= 0; i--) { var sun = suns[i]; sun.update(); if (sun.lastY === undefined) sun.lastY = sun.y; if (sun.lastY < BOARD_BOTTOM && sun.y >= BOARD_BOTTOM) { sun.destroy(); suns.splice(i, 1); continue; } sun.lastY = sun.y; } // --- Plant logic --- for (var i = plants.length - 1; i >= 0; i--) { var plant = plants[i]; plant.update(); if (plant.destroyed) { plant.destroy(); plants.splice(i, 1); continue; } // Peashooter: shoot if zombie in lane if (plant instanceof Peashooter) { for (var j = 0; j < zombies.length; j++) { var zombie = zombies[j]; if (zombie.lane === plant.lane && zombie.x > plant.x) { plant.shoot(); break; } } } } // --- Pea logic --- for (var i = peas.length - 1; i >= 0; i--) { var pea = peas[i]; pea.update(); if (pea.lastX === undefined) pea.lastX = pea.x; if (pea.x > BOARD_RIGHT + 100) { pea.destroy(); peas.splice(i, 1); continue; } // Check collision with zombies in same lane for (var j = 0; j < zombies.length; j++) { var zombie = zombies[j]; if (zombie.lane === pea.lane && Math.abs(zombie.x - pea.x) < 60) { zombie.takeDamage(3); // No slow effect on zombie when hit by pea pea.destroy(); peas.splice(i, 1); if (zombie.hp <= 0) { LK.getSound('zombie_die').play(); zombie.destroyed = true; LK.setScore(LK.getScore() + 1); scoreTxt.setText(LK.getScore()); zombiesDefeated++; } break; } } pea.lastX = pea.x; } // --- Zombie logic --- for (var i = zombies.length - 1; i >= 0; i--) { var zombie = zombies[i]; zombie.update(); if (zombie.lastX === undefined) zombie.lastX = zombie.x; if (zombie.destroyed) { zombie.destroy(); zombies.splice(i, 1); continue; } // Check collision with plants in same lane if (!zombie.eating) { for (var j = 0; j < plants.length; j++) { var plant = plants[j]; if (plant.lane === zombie.lane && Math.abs(plant.x - zombie.x) < 60) { zombie.eating = true; zombie.targetPlant = plant; break; } } } // Check if zombie reached left edge if (zombie.x < BOARD_LEFT - 60) { if (typeof zombiesEscaped === "undefined") zombiesEscaped = 0; zombiesEscaped++; zombie.destroy(); zombies.splice(i, 1); if (zombiesEscaped >= 3) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); gameOver = true; return; } continue; } zombie.lastX = zombie.x; } // --- Zombie wave logic --- // Dynamically adjust spawn interval and zombies per wave as waves progress // Make zombies come faster and in greater numbers as time goes on var minSpawnInterval = 40; // minimum interval (faster) var maxZombiesPerWave = 20; // cap for zombies per wave // Calculate current values based on wave var currentSpawnInterval = Math.max(ZOMBIE_SPAWN_INTERVAL - (currentWave - 1) * 10, minSpawnInterval); var currentZombiesPerWave = Math.min(ZOMBIES_PER_WAVE + (currentWave - 1) * 2, maxZombiesPerWave); if (currentWave <= MAX_WAVES) { if (zombiesSpawnedThisWave < currentZombiesPerWave) { if (LK.ticks - lastZombieSpawnTick > currentSpawnInterval) { spawnZombie(); lastZombieSpawnTick = LK.ticks; } } else if (zombies.length === 0 && zombiesSpawnedThisWave === currentZombiesPerWave) { // Next wave currentWave++; zombiesSpawnedThisWave = 0; lastZombieSpawnTick = LK.ticks; } } else if (zombies.length === 0 && zombiesSpawnedThisWave === currentZombiesPerWave) { // Win condition LK.effects.flashScreen(0x00ff00, 1000); LK.showYouWin(); youWin = true; return; } };
===================================================================
--- original.js
+++ change.js
@@ -5,8 +5,65 @@
/****
* Classes
****/
+// BucketheadZombie: stronger zombie with a tin bucket on its head
+var BucketheadZombie = Container.expand(function () {
+ var self = Container.call(this);
+ // Use the same zombie base image, but add a tin bucket shape on top
+ var zombieGfx = self.attachAsset('zombie', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ // Tin bucket: gray box on head
+ var bucketGfx = self.attachAsset('buckethead_bucket', {
+ anchorX: 0.5,
+ anchorY: 1.0,
+ x: zombieGfx.width / 2,
+ y: zombieGfx.height * 0.18,
+ // place on head
+ scaleX: 0.7,
+ scaleY: 0.5
+ });
+ self.addChild(bucketGfx);
+ self.lane = 0;
+ self.speed = 1.0 + Math.random() * 1.5; // Slightly slower than normal zombie
+ self.originalSpeed = self.speed;
+ self.slowTimer = 0;
+ self.hp = 30; // Much more HP
+ self.eating = false;
+ self.targetPlant = null;
+ self.update = function () {
+ if (self.slowTimer && self.slowTimer > 0) {
+ self.slowTimer--;
+ if (self.slowTimer === 0) {
+ self.speed = self.originalSpeed;
+ }
+ }
+ if (self.eating && self.targetPlant && !self.targetPlant.destroyed) {
+ if (LK.ticks % 30 === 0) {
+ self.targetPlant.takeDamage(1);
+ LK.getSound('zombie_eat').play();
+ }
+ if (self.targetPlant.destroyed) {
+ self.eating = false;
+ self.targetPlant.destroy();
+ plants.splice(plants.indexOf(self.targetPlant), 1);
+ self.targetPlant = null;
+ }
+ } else {
+ self.x -= self.speed;
+ }
+ };
+ self.takeDamage = function (dmg) {
+ self.hp -= dmg;
+ if (self.hp <= 0) {
+ self.destroyed = true;
+ }
+ };
+ return self;
+});
+// Register bucket asset (gray box)
// Pea projectile
var Pea = Container.expand(function () {
var self = Container.call(this);
var peaGfx = self.attachAsset('pea', {
@@ -147,8 +204,9 @@
/****
* Game Code
****/
+// Register bucket asset (gray box)
// This flag signals the game is ready for publishing.
// --- PUBLISH FLAG ---
// Sound
// Sun (currency)
@@ -280,9 +338,15 @@
}
// --- Zombie spawning ---
function spawnZombie() {
var lane = Math.floor(Math.random() * NUM_LANES);
- var zombie = new Zombie();
+ // 25% chance to spawn a BucketheadZombie, but only after wave 2
+ var zombie;
+ if (currentWave >= 2 && Math.random() < 0.25) {
+ zombie = new BucketheadZombie();
+ } else {
+ zombie = new Zombie();
+ }
zombie.lane = lane;
zombie.x = BOARD_RIGHT + 80;
zombie.y = BOARD_TOP + lane * LANE_HEIGHT + LANE_HEIGHT / 2;
zombie.lastX = zombie.x;
PLANT VS ZOMBİ DEKİ ZOMBİ. In-Game asset. 2d. High contrast. No shadows
PLANT VS ZOMBİ DEKİ BEZELYE. In-Game asset. 2d. High contrast. No shadows
PLANT VS ZOMBİ DEKİ GÜNEŞ. In-Game asset. 2d. High contrast. No shadows
PLANT VS ZOMBİ DEKİ ÇİM. In-Game asset. 2d. High contrast. No shadows
PLANT VS ZOMBİ DEKİ CEVİZ. In-Game asset. 2d. High contrast. No shadows
PLANT VS ZOMBİ DEKİ KAFASINDA TENEKE OLAN ZOMBİ. In-Game asset. 2d. High contrast. No shadows