User prompt
75 coıne can yenıleme ekleyelım
User prompt
kulenın canını arttıralım ve parasını 30 yapıp otyuncu her silah guceldirdiginde kulenınde silahı guçlensın
User prompt
ve ondan sonrada 2 nın katları şeklinde gitsin ve her deferinde 100 coın daha pahalı olsun
User prompt
oyuncu 1.5 x parayı adlıktan sonra onun yerine 2x para gelsin ve o da 100 coin olsun
User prompt
checkpoint i kaldıralım
User prompt
oyundakı tum yazıları ingilizce yapalım
User prompt
arkaplana bir orman çiz
User prompt
arka plan resmini ortala
User prompt
arkaplana bir askeriye koy
User prompt
arkaplanı siyah yerine zombi salgınına ugramış ve terk edilmiş bir askeriye yapalım
User prompt
butonlardaki mavı rengi kaldır
User prompt
yon tusları ve satın alma kutularınn rengini gri yap
User prompt
yön tuşlarının arkasını gri yap
User prompt
kutulardaki resimleri eski haline getir aam duvar kalsın
User prompt
kalpleri iraz daha küçültelim mobil için
User prompt
karakterin hareketi için sanal sag sol on arka tusları ekliyelim
User prompt
mausenın 3. tuşu ile hareket ettirelim
User prompt
karakteri masuenın sol tuşu ile hareket ettirelim
User prompt
kalpleri biraz küçültelim
User prompt
kalpleri ortaya alalım
User prompt
kalpleri sola alalım
User prompt
en sola alalım
User prompt
biraz daha sola alalım
User prompt
en sol uste alalım
User prompt
biraz daha sola
/**** 
* Plugins
****/ 
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/**** 
* Classes
****/ 
// BossZombie class
var BossZombie = Container.expand(function () {
	var self = Container.call(this);
	var bossSprite = self.attachAsset('zombie', {
		anchorX: 0.5,
		anchorY: 0.5,
		scaleX: 1.7,
		scaleY: 1.7,
		color: 0x8e44ad // purple tint for boss
	});
	self.radius = bossSprite.width / 2;
	var bossPowerLevel = Math.floor((currentWave - 1) / 3);
	self.speed = 1.5 + bossPowerLevel * 0.5;
	self.hp = 10 + bossPowerLevel * 5;
	self.maxHp = self.hp;
	self.target = null;
	self.lastHitTick = 0;
	self.update = function () {
		// Move towards player
		var tx = player.x;
		var ty = player.y;
		// If wall/trap/tower is closer, target that
		var minDist = Math.sqrt((self.x - tx) * (self.x - tx) + (self.y - ty) * (self.y - ty));
		var targetObj = player;
		for (var i = 0; i < defenses.length; i++) {
			var d = defenses[i];
			var dist = Math.sqrt((self.x - d.x) * (self.x - d.x) + (self.y - d.y) * (self.y - d.y));
			if (dist < minDist) {
				minDist = dist;
				targetObj = d;
			}
		}
		self.target = targetObj;
		var dx = targetObj.x - self.x;
		var dy = targetObj.y - self.y;
		var len = Math.sqrt(dx * dx + dy * dy);
		if (len > 0) {
			dx /= len;
			dy /= len;
			self.x += dx * self.speed;
			self.y += dy * self.speed;
		}
		// Attack if close
		if (len < self.radius + targetObj.radius + 10) {
			if (LK.ticks - self.lastHitTick > 30) {
				if (targetObj === player) {
					player.takeDamage(2); // Boss does more damage
				} else if (targetObj.takeDamage) {
					targetObj.takeDamage(2);
				}
				self.lastHitTick = LK.ticks;
			}
		}
	};
	self.takeDamage = function (amount) {
		self.hp -= amount;
		if (self.hp <= 0) {
			self.die();
		} else {
			LK.effects.flashObject(self, 0xff00ff, 300);
		}
	};
	self.die = function () {
		LK.getSound('zombie_die').play();
		// Drop 5 coins
		var coinCount = 5;
		if (typeof coinMultiplierEnabled !== "undefined" && coinMultiplierEnabled) {
			coinCount = Math.round(5 * 1.5);
		}
		for (var i = 0; i < coinCount; i++) {
			var coin = new Coin();
			// Spread coins a bit
			var angle = Math.PI * 2 * i / coinCount;
			coin.x = self.x + Math.cos(angle) * 60;
			coin.y = self.y + Math.sin(angle) * 60;
			coins.push(coin);
			game.addChild(coin);
		}
		self.destroy();
		var idx = zombies.indexOf(self);
		if (idx !== -1) zombies.splice(idx, 1);
		zombiesKilledThisWave++;
	};
	return self;
});
// Bullet class
var Bullet = Container.expand(function () {
	var self = Container.call(this);
	var bulletSprite = self.attachAsset('bullet', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.radius = bulletSprite.width / 2;
	self.vx = 0;
	self.vy = 0;
	self.damage = 1;
	self.update = function () {
		self.x += self.vx;
		self.y += self.vy;
	};
	return self;
});
// Coin class
var Coin = Container.expand(function () {
	var self = Container.call(this);
	var coinSprite = self.attachAsset('coin', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.radius = coinSprite.width * 1.5; // Even further increase hitbox radius for much easier collection
	// Remove vy and falling logic so coin stays at spawn position
	self.collected = false;
	self.update = function () {
		// No falling, coin stays at its spawn position
	};
	self.collect = function () {
		if (self.collected) return;
		self.collected = true;
		LK.getSound('coin').play();
		// Animate to coinText
		var guiPos = LK.gui.topRight.toLocal(game.toGlobal({
			x: self.x,
			y: self.y
		}));
		var startX = self.x,
			startY = self.y;
		var endX = 2048 - 200,
			endY = 80;
		tween(self, {
			x: endX,
			y: endY,
			alpha: 0
		}, {
			duration: 400,
			easing: tween.cubicIn,
			onFinish: function onFinish() {
				self.destroy();
				var idx = coins.indexOf(self);
				if (idx !== -1) coins.splice(idx, 1);
				if (typeof coinMultiplierLevel !== "undefined" && coinMultiplierLevel > 0) {
					coinsCollected += Math.pow(2, coinMultiplierLevel);
				} else {
					coinsCollected++;
				}
				coinsCollected = Math.floor(coinsCollected);
				updateCoinText();
			}
		});
	};
	return self;
});
// Player class
var Player = Container.expand(function () {
	var self = Container.call(this);
	var playerSprite = self.attachAsset('player', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.radius = playerSprite.width / 2;
	self.hp = 10;
	self.maxHp = 10;
	self.shootCooldown = 0;
	self.shootDelay = 20; // frames
	self.weaponLevel = 1;
	self.lastShotTick = 0;
	// For drag
	self.down = function (x, y, obj) {};
	self.up = function (x, y, obj) {};
	self.update = function () {
		if (self.shootCooldown > 0) self.shootCooldown--;
	};
	// Shoot method
	self.shoot = function (targetX, targetY) {
		if (self.shootCooldown > 0) return;
		var dx = targetX - self.x;
		var dy = targetY - self.y;
		var len = Math.sqrt(dx * dx + dy * dy);
		if (len === 0) return;
		dx /= len;
		dy /= len;
		var bullet = new Bullet();
		bullet.x = self.x + dx * (self.radius + 30);
		bullet.y = self.y + dy * (self.radius + 30);
		bullet.vx = dx * (22 + self.weaponLevel * 2);
		bullet.vy = dy * (22 + self.weaponLevel * 2);
		bullet.damage = self.weaponLevel;
		// Set bullet rotation so the tip faces the direction of movement
		if (bullet.children && bullet.children.length > 0) {
			bullet.children[0].rotation = Math.atan2(bullet.vy, bullet.vx);
		}
		bullets.push(bullet);
		game.addChild(bullet);
		LK.getSound('shoot').play();
		self.shootCooldown = self.shootDelay;
	};
	// Take damage
	self.takeDamage = function (amount) {
		self.hp -= amount;
		if (self.hp < 0) self.hp = 0;
		LK.effects.flashObject(self, 0xff0000, 300);
		updateHpBar();
		if (self.hp <= 0) {
			LK.effects.flashScreen(0xff0000, 1000);
			LK.showGameOver();
		}
	};
	return self;
});
// Tower class
var Tower = Container.expand(function () {
	var self = Container.call(this);
	var towerSprite = self.attachAsset('tower', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.radius = Math.max(towerSprite.width, towerSprite.height) / 2;
	self.hp = 20;
	self.maxHp = 20;
	self.shootCooldown = 0;
	self.shootDelay = 40;
	self.takeDamage = function (amount) {
		self.hp -= amount;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.hp <= 0) {
			self.destroy();
			var idx = defenses.indexOf(self);
			if (idx !== -1) defenses.splice(idx, 1);
		}
	};
	self.update = function () {
		if (self.shootCooldown > 0) self.shootCooldown--;
		// Find nearest zombie
		var nearest = null,
			minDist = 99999;
		for (var i = 0; i < zombies.length; i++) {
			var z = zombies[i];
			var dx = z.x - self.x;
			var dy = z.y - self.y;
			var dist = dx * dx + dy * dy;
			if (dist < minDist) {
				minDist = dist;
				nearest = z;
			}
		}
		if (nearest && self.shootCooldown <= 0) {
			// Shoot at nearest zombie
			var dx = nearest.x - self.x;
			var dy = nearest.y - self.y;
			var len = Math.sqrt(dx * dx + dy * dy);
			if (len > 0) {
				dx /= len;
				dy /= len;
				var bullet = new Bullet();
				bullet.x = self.x + dx * (self.radius + 20);
				bullet.y = self.y + dy * (self.radius + 20);
				var towerWeaponLevel = typeof self.weaponLevel !== "undefined" ? self.weaponLevel : 1;
				bullet.vx = dx * (18 + towerWeaponLevel * 2);
				bullet.vy = dy * (18 + towerWeaponLevel * 2);
				bullet.damage = towerWeaponLevel;
				// Set bullet rotation so the tip faces the direction of movement
				if (bullet.children && bullet.children.length > 0) {
					bullet.children[0].rotation = Math.atan2(bullet.vy, bullet.vx);
				}
				bullets.push(bullet);
				game.addChild(bullet);
				LK.getSound('shoot').play();
				self.shootCooldown = self.shootDelay;
			}
		}
	};
	return self;
});
// Trap class
var Trap = Container.expand(function () {
	var self = Container.call(this);
	var trapSprite = self.attachAsset('trap', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.radius = Math.max(trapSprite.width, trapSprite.height) / 2;
	self.hp = 2;
	self.maxHp = 2;
	self.takeDamage = function (amount) {
		self.hp -= amount;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.hp <= 0) {
			self.destroy();
			var idx = defenses.indexOf(self);
			if (idx !== -1) defenses.splice(idx, 1);
		}
	};
	return self;
});
// Wall class
var Wall = Container.expand(function () {
	var self = Container.call(this);
	var wallSprite = self.attachAsset('wall', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.radius = Math.max(wallSprite.width, wallSprite.height) / 2;
	self.hp = 6;
	self.maxHp = 6;
	self.takeDamage = function (amount) {
		self.hp -= amount;
		LK.effects.flashObject(self, 0xff0000, 200);
		if (self.hp <= 0) {
			self.destroy();
			var idx = defenses.indexOf(self);
			if (idx !== -1) defenses.splice(idx, 1);
		}
	};
	return self;
});
// Zombie class
var Zombie = Container.expand(function () {
	var self = Container.call(this);
	var zombieSprite = self.attachAsset('zombie', {
		anchorX: 0.5,
		anchorY: 0.5
	});
	self.radius = zombieSprite.width / 2;
	// Zombies get stronger only every 3 waves
	var zombiePowerLevel = Math.floor((currentWave - 1) / 3);
	self.speed = 2 + zombiePowerLevel * 0.9;
	self.hp = 1 + zombiePowerLevel;
	self.maxHp = self.hp;
	self.target = null;
	self.lastHitTick = 0;
	self.update = function () {
		// Move towards player
		var tx = player.x;
		var ty = player.y;
		// If wall/trap/tower is closer, target that
		var minDist = Math.sqrt((self.x - tx) * (self.x - tx) + (self.y - ty) * (self.y - ty));
		var targetObj = player;
		for (var i = 0; i < defenses.length; i++) {
			var d = defenses[i];
			var dist = Math.sqrt((self.x - d.x) * (self.x - d.x) + (self.y - d.y) * (self.y - d.y));
			if (dist < minDist) {
				minDist = dist;
				targetObj = d;
			}
		}
		self.target = targetObj;
		var dx = targetObj.x - self.x;
		var dy = targetObj.y - self.y;
		var len = Math.sqrt(dx * dx + dy * dy);
		if (len > 0) {
			dx /= len;
			dy /= len;
			self.x += dx * self.speed;
			self.y += dy * self.speed;
		}
		// Attack if close
		if (len < self.radius + targetObj.radius + 10) {
			if (LK.ticks - self.lastHitTick > 30) {
				if (targetObj === player) {
					player.takeDamage(1);
				} else if (targetObj.takeDamage) {
					targetObj.takeDamage(1);
				}
				self.lastHitTick = LK.ticks;
			}
		}
	};
	self.takeDamage = function (amount) {
		self.hp -= amount;
		if (self.hp <= 0) {
			self.die();
		} else {
			LK.effects.flashObject(self, 0xff0000, 200);
		}
	};
	self.die = function () {
		LK.getSound('zombie_die').play();
		// Drop coin
		var coin = new Coin();
		coin.x = self.x;
		coin.y = self.y;
		coins.push(coin);
		game.addChild(coin);
		self.destroy();
		var idx = zombies.indexOf(self);
		if (idx !== -1) zombies.splice(idx, 1);
		zombiesKilledThisWave++;
	};
	return self;
});
/**** 
* Initialize Game
****/ 
var game = new LK.Game({
	backgroundColor: 0x000000
});
/**** 
* Game Code
****/ 
// Sounds
// Tower
// Trap
// Wall
// Coin
// Bullet
// Zombie
// Character (player)
// Global variables
var player;
var zombies = [];
var bullets = [];
var coins = [];
var defenses = [];
var coinsCollected = 0;
var autoCollectEnabled = false;
var coinMultiplierEnabled = false;
var coinMultiplier2Enabled = false;
var currentWave = 1;
var zombiesToSpawn = 0;
var zombiesSpawnedThisWave = 0;
var zombiesKilledThisWave = 0;
var waveInProgress = false;
var dragNode = null;
var buildMode = null; // 'wall', 'trap', 'tower', 'upgrade', 'autocollect', 'coinmult'
var buildPreview = null;
var buildCost = {
	wall: 5,
	trap: 7,
	tower: 30,
	upgrade: 10,
	autocollect: 20,
	coinmult: 50
};
var buildNames = {
	wall: "Duvar",
	trap: "Tuzak",
	tower: "Kule",
	upgrade: "Silah+",
	autocollect: "Oto-Para",
	coinmult: "Para x2"
};
// Track current coin multiplier and its cost
var coinMultiplierLevel = 1; // 1 means 2x, 2 means 4x, etc.
var coinMultiplierCost = 100; // Cost for next multiplier (starts at 100 for 2x)
// buildDesc removed
var hpBar,
	coinText,
	waveText,
	buildPanel,
	buildButtons = [];
var lastTouchX = 0,
	lastTouchY = 0;
// UI: HP Bar
function updateHpBar() {
	if (!hpBar) return;
	var txt = "";
	for (var i = 0; i < player.maxHp; i++) {
		txt += i < player.hp ? "♥ " : "♡ ";
	}
	hpBar.setText(txt);
}
// UI: Coin Text
function updateCoinText() {
	if (coinText) coinText.setText("₺ " + coinsCollected);
	// Rebuild build panel to update overlays/locks if it exists
	if (typeof buildPanel !== "undefined" && buildPanel) {
		buildPanel.destroy();
		buildButtons = [];
		createBuildPanel();
	}
}
// UI: Wave Text
function updateWaveText() {
	if (waveText) waveText.setText("Dalga: " + currentWave);
}
// UI: Build Panel
function createBuildPanel() {
	buildPanel = new Container();
	buildPanel.y = 0;
	buildPanel.x = 0;
	var btnW = 140,
		btnH = 56,
		gap = 18;
	// Dynamically build types array based on upgrade state
	var types = ['wall', 'trap', 'tower', 'upgrade', 'heal'];
	if (!autoCollectEnabled) {
		types.push('autocollect');
	} else {
		types.push('coinmult');
	}
	// If coinmult is present, we will handle its label and cost dynamically below
	for (var i = 0; i < types.length; i++) {
		(function (type, idx) {
			var btn = new Container();
			// Use original images for each type except for upgrade/autocollect/coinmult/checkpoint
			var assetId = 'wall';
			if (type === 'trap') assetId = 'trap';else if (type === 'tower') assetId = 'tower';
			// Remove blue color, always use gray for button backgrounds
			var bg = LK.getAsset(assetId, {
				width: btnW,
				height: btnH,
				color: 0x888888,
				anchorX: 0,
				anchorY: 0
			});
			btn.addChild(bg);
			var label, cost;
			if (type === 'coinmult') {
				// Show next multiplier (2x, 4x, 8x, ...) and its cost
				var nextMult = Math.pow(2, coinMultiplierLevel + 1);
				label = "Para x" + nextMult;
				cost = coinMultiplierCost;
			} else if (type === 'heal') {
				label = "Can +1";
				cost = 75;
			} else {
				label = buildNames[type] ? buildNames[type] : type;
				cost = buildCost[type] ? buildCost[type] : 0;
			}
			var txt = new Text2(label + "\n₺" + cost, {
				size: 32,
				fill: "#fff"
			});
			txt.x = btnW / 2;
			txt.y = 12;
			txt.anchor.set(0.5, 0);
			btn.addChild(txt);
			btn.x = idx * (btnW + gap) - 10; // Move each button 10px to the left (was 100px)
			btn.y = 0;
			btn.type = type;
			// Check if player can afford this item
			var canAfford = coinsCollected >= cost;
			if (!canAfford) {
				// Add a semi-transparent black overlay
				// Remove blue color, always use gray for lock overlays
				var overlay = LK.getAsset('wall', {
					width: btnW,
					height: btnH,
					color: 0x888888,
					anchorX: 0,
					anchorY: 0
				});
				overlay.alpha = 0.45;
				btn.addChild(overlay);
				// Add a lock icon (use a Text2 lock emoji for simplicity)
				var lockIcon = new Text2("🔒", {
					size: 38,
					fill: "#fff"
				});
				lockIcon.x = btnW / 2;
				lockIcon.y = btnH / 2 - 18;
				lockIcon.anchor.set(0.5, 0.5);
				btn.addChild(lockIcon);
				// Disable interaction
				btn.down = function () {};
			} else {
				btn.down = function (x, y, obj) {
					setBuildMode(type);
				};
			}
			buildPanel.addChild(btn);
			buildButtons.push(btn);
		})(types[i], i);
	}
	buildPanel.y = -120; // Move the build panel further up by 120px (closer to bottom)
	buildPanel.x = -320; // Move the build panel to the right (was -540)
	LK.gui.bottom.addChild(buildPanel);
}
// Set build mode
function setBuildMode(type) {
	buildMode = type;
	if (buildPreview) {
		buildPreview.destroy();
		buildPreview = null;
	}
	if (type === 'wall') {
		buildPreview = new Wall();
	} else if (type === 'trap') {
		buildPreview = new Trap();
	} else if (type === 'tower') {
		buildPreview = new Tower();
	} else if (type === 'upgrade' || type === 'autocollect') {
		buildPreview = null;
	}
	if (buildPreview) {
		buildPreview.alpha = 0.5;
		game.addChild(buildPreview);
	}
}
// Remove build preview
function clearBuildPreview() {
	if (buildPreview) {
		buildPreview.destroy();
		buildPreview = null;
	}
	buildMode = null;
}
// Start new wave
function startWave() {
	zombiesToSpawn = 5 + currentWave * 2;
	zombiesSpawnedThisWave = 0;
	zombiesKilledThisWave = 0;
	waveInProgress = true;
	updateWaveText();
	// Spawn boss every 3 waves
	if (currentWave % 3 === 0) {
		// Boss will be spawned after all regular zombies
		zombiesToSpawn += 1;
	}
}
// Spawn zombie
function spawnZombie() {
	// Spawn at random edge
	var edge = Math.floor(Math.random() * 4);
	var zx, zy;
	if (edge === 0) {
		// top
		zx = 200 + Math.random() * (2048 - 400);
		zy = -60;
	} else if (edge === 1) {
		// right
		zx = 2048 + 60;
		zy = 200 + Math.random() * (2732 - 400);
	} else if (edge === 2) {
		// bottom
		zx = 200 + Math.random() * (2048 - 400);
		zy = 2732 + 60;
	} else {
		// left
		zx = -60;
		zy = 200 + Math.random() * (2732 - 400);
	}
	// If this is a boss wave and this is the last zombie, spawn boss
	var isBossWave = currentWave % 3 === 0;
	var isLastZombie = zombiesSpawnedThisWave === zombiesToSpawn - 1 && isBossWave;
	var z;
	if (isLastZombie) {
		z = new BossZombie();
	} else {
		z = new Zombie();
	}
	z.x = zx;
	z.y = zy;
	zombies.push(z);
	game.addChild(z);
	zombiesSpawnedThisWave++;
}
// Build defense
function buildDefense(type, x, y) {
	if (coinsCollected < buildCost[type]) return false;
	var obj;
	if (type === 'wall') {
		obj = new Wall();
	} else if (type === 'trap') {
		obj = new Trap();
	} else if (type === 'tower') {
		obj = new Tower();
	}
	if (obj) {
		obj.x = x;
		obj.y = y;
		defenses.push(obj);
		game.addChild(obj);
		coinsCollected -= buildCost[type];
		updateCoinText();
		LK.getSound('build').play();
		return true;
	}
	return false;
}
// Upgrade weapon
function upgradeWeapon() {
	if (coinsCollected < buildCost.upgrade) return false;
	player.weaponLevel++;
	// Upgrade all towers' shoot power
	for (var i = 0; i < defenses.length; i++) {
		if (defenses[i] && defenses[i] instanceof Tower) {
			// Increase tower bullet damage and speed with each upgrade
			if (typeof defenses[i].weaponLevel === "undefined") {
				defenses[i].weaponLevel = 1;
			}
			defenses[i].weaponLevel++;
		}
	}
	coinsCollected -= buildCost.upgrade;
	updateCoinText();
	LK.effects.flashObject(player, 0xffff00, 600);
	LK.getSound('build').play();
	return true;
}
// Handle move (drag, build preview, collect coin)
function handleMove(x, y, obj) {
	lastTouchX = x;
	lastTouchY = y;
	// Drag player
	if (dragNode === player) {
		// Clamp to game area
		var r = player.radius + 10;
		player.x = Math.max(r, Math.min(2048 - r, x));
		player.y = Math.max(r, Math.min(2732 - r, y));
	}
	// Build preview follows finger
	if (buildPreview) {
		buildPreview.x = x;
		buildPreview.y = y;
	}
	// Coin collection
	for (var i = coins.length - 1; i >= 0; i--) {
		var c = coins[i];
		var dx = c.x - x,
			dy = c.y - y;
		if (!c.collected && dx * dx + dy * dy < c.radius * c.radius + 1200) {
			c.collect();
		}
	}
}
// Handle down (start drag, build, upgrade)
game.down = function (x, y, obj) {
	// If build mode is active
	if (buildMode) {
		if (buildMode === 'upgrade') {
			if (upgradeWeapon()) {
				clearBuildPreview();
			}
		} else if (buildMode === 'autocollect') {
			if (!autoCollectEnabled && coinsCollected >= buildCost.autocollect) {
				coinsCollected -= buildCost.autocollect;
				updateCoinText();
				autoCollectEnabled = true;
				LK.effects.flashObject(player, 0x00ffcc, 600);
				LK.getSound('build').play();
				clearBuildPreview();
				// Recreate build panel to remove autocollect and add coinmult
				if (buildPanel) {
					buildPanel.destroy();
					buildButtons = [];
					createBuildPanel();
				}
			}
		} else if (buildMode === 'coinmult') {
			if (coinsCollected >= coinMultiplierCost) {
				coinsCollected -= coinMultiplierCost;
				updateCoinText();
				coinMultiplierLevel++;
				coinMultiplierCost += 100;
				LK.effects.flashObject(player, 0xffe066, 600);
				LK.getSound('build').play();
				clearBuildPreview();
				// Recreate build panel to update multiplier label/cost
				if (buildPanel) {
					buildPanel.destroy();
					buildButtons = [];
					createBuildPanel();
				}
			}
		} else if (buildMode === 'heal') {
			if (coinsCollected >= 75 && player.hp < player.maxHp) {
				coinsCollected -= 75;
				player.hp += 1;
				if (player.hp > player.maxHp) player.hp = player.maxHp;
				updateCoinText();
				updateHpBar();
				LK.effects.flashObject(player, 0x00ff44, 600);
				LK.getSound('build').play();
				clearBuildPreview();
			}
		} else {
			// Place defense if possible
			if (buildPreview) {
				// Don't allow build on player or on top of other defenses
				var canBuild = true;
				var dx = player.x - x,
					dy = player.y - y;
				if (dx * dx + dy * dy < (player.radius + buildPreview.radius + 40) * (player.radius + buildPreview.radius + 40)) {
					canBuild = false;
				}
				for (var i = 0; i < defenses.length; i++) {
					var d = defenses[i];
					var ddx = d.x - x,
						ddy = d.y - y;
					if (ddx * ddx + ddy * ddy < (d.radius + buildPreview.radius + 30) * (d.radius + buildPreview.radius + 30)) {
						canBuild = false;
						break;
					}
				}
				if (canBuild && buildDefense(buildMode, x, y)) {
					clearBuildPreview();
				}
			}
		}
		return;
	}
	// Only handle mouse/touch events with event object
	var event = obj && obj.event ? obj.event : null;
	var isLeftClick = false;
	var isMiddleClick = false;
	// Mouse events
	if (event && typeof event.button !== "undefined") {
		// 0: left, 1: middle
		if (event.button === 0) isLeftClick = true;
		if (event.button === 1) isMiddleClick = true;
	} else {
		// Touch events: treat as left click (drag/shoot)
		isLeftClick = true;
	}
	if (isMiddleClick) {
		// Teleport player to clicked position, clamp to game area
		var r = player.radius + 10;
		player.x = Math.max(r, Math.min(2048 - r, x));
		player.y = Math.max(r, Math.min(2732 - r, y));
	} else if (isLeftClick) {
		// If click/touch is on player, start drag
		var dx = player.x - x,
			dy = player.y - y;
		if (dx * dx + dy * dy < player.radius * player.radius + 2000) {
			dragNode = player;
		} else {
			// Otherwise, shoot
			player.shoot(x, y);
		}
	}
	handleMove(x, y, obj);
};
// Prevent context menu on right click for the canvas
if (typeof window !== "undefined" && typeof document !== "undefined") {
	var canvas = document.querySelector('canvas');
	if (canvas) {
		canvas.oncontextmenu = function (e) {
			e.preventDefault();
			return false;
		};
	}
}
// Handle up (stop drag, clear build preview)
game.up = function (x, y, obj) {
	dragNode = null;
	// If build preview exists, clear it if not placed
	if (buildPreview && buildMode) {
		clearBuildPreview();
	}
};
// Handle move
game.move = handleMove;
// Game update
game.update = function () {
	// --- Virtual Joystick Movement ---
	var moveSpeed = 18 + player.weaponLevel * 2;
	if (typeof vbtns !== "undefined") {
		var dx = 0,
			dy = 0;
		if (vbtns.up && vbtns.up.isDown) dy -= 1;
		if (vbtns.down && vbtns.down.isDown) dy += 1;
		if (vbtns.left && vbtns.left.isDown) dx -= 1;
		if (vbtns.right && vbtns.right.isDown) dx += 1;
		if (dx !== 0 || dy !== 0) {
			var len = Math.sqrt(dx * dx + dy * dy);
			if (len > 0) {
				dx /= len;
				dy /= len;
				// Clamp to game area
				var r = player.radius + 10;
				player.x = Math.max(r, Math.min(2048 - r, player.x + dx * moveSpeed));
				player.y = Math.max(r, Math.min(2732 - r, player.y + dy * moveSpeed));
			}
		}
	}
	// Player update
	player.update();
	// Zombies update
	for (var i = zombies.length - 1; i >= 0; i--) {
		zombies[i].update();
	}
	// Bullets update
	for (var i = bullets.length - 1; i >= 0; i--) {
		var b = bullets[i];
		b.update();
		// Remove if out of bounds
		if (b.x < -100 || b.x > 2148 || b.y < -100 || b.y > 2832) {
			b.destroy();
			bullets.splice(i, 1);
			continue;
		}
		// Check collision with zombies
		for (var j = zombies.length - 1; j >= 0; j--) {
			var z = zombies[j];
			var dx = z.x - b.x,
				dy = z.y - b.y;
			if (dx * dx + dy * dy < (z.radius + b.radius) * (z.radius + b.radius)) {
				z.takeDamage(b.damage);
				b.destroy();
				bullets.splice(i, 1);
				break;
			}
		}
	}
	// Coins update
	for (var i = coins.length - 1; i >= 0; i--) {
		coins[i].update();
		if (autoCollectEnabled && !coins[i].collected) {
			coins[i].collect();
		}
	}
	// Defenses update
	for (var i = defenses.length - 1; i >= 0; i--) {
		if (defenses[i].update) defenses[i].update();
	}
	// Wave logic
	if (waveInProgress) {
		// Spawn zombies
		if (zombiesSpawnedThisWave < zombiesToSpawn && LK.ticks % Math.max(20, 60 - currentWave * 2) === 0) {
			spawnZombie();
		}
		// Check wave end
		if (zombiesKilledThisWave >= zombiesToSpawn && zombies.length === 0) {
			waveInProgress = false;
			// Give 5 coins every 5 waves at the end of the wave
			if (currentWave % 5 === 0) {
				coinsCollected += 5;
				updateCoinText();
			}
			// Next wave after 4 seconds (4000 ms)
			LK.setTimeout(function () {
				currentWave++;
				startWave();
			}, 4000);
		}
	}
};
// --- Game Initialization ---
// Add forest background (drawn as a large green rectangle with tree-like ellipses)
var forestBg = new Container();
var bgRect = LK.getAsset('military_bg', {
	width: 2048,
	height: 2732,
	color: 0x2e4d1a,
	// deep forest green
	anchorX: 0,
	anchorY: 0,
	x: 0,
	y: 0
});
forestBg.addChild(bgRect);
// Add some tree ellipses for a forest look
for (var i = 0; i < 18; i++) {
	var tree = LK.getAsset('military_bg', {
		width: 180 + Math.floor(Math.random() * 80),
		height: 320 + Math.floor(Math.random() * 60),
		color: 0x3e7d2a + Math.floor(Math.random() * 0x002000),
		shape: 'ellipse',
		anchorX: 0.5,
		anchorY: 1,
		x: 120 + Math.random() * 1800,
		y: 400 + Math.random() * 2100
	});
	tree.alpha = 0.22 + Math.random() * 0.18;
	forestBg.addChild(tree);
}
game.addChild(forestBg);
// Place player at center
player = new Player();
player.x = 2048 / 2;
player.y = 2732 / 2;
game.addChild(player);
// --- Virtual Joystick Buttons ---
// Button size and margin
var vbtnSize = 160;
var vbtnMargin = 40;
var vbtnAlpha = 0.45;
var vbtnColor = 0x888888;
var vbtns = {};
// Helper to create a button
function createVBtn(label, x, y, dir) {
	var btn = new Container();
	// Remove blue color, always use gray for joystick button backgrounds
	var bg = LK.getAsset('wall', {
		width: vbtnSize,
		height: vbtnSize,
		color: 0x888888,
		anchorX: 0.5,
		anchorY: 0.5
	});
	bg.alpha = vbtnAlpha;
	btn.addChild(bg);
	var txt = new Text2(label, {
		size: 80,
		fill: "#fff"
	});
	txt.anchor.set(0.5, 0.5);
	txt.x = 0;
	txt.y = 0;
	btn.addChild(txt);
	btn.x = x;
	btn.y = y;
	btn.dir = dir;
	btn.isDown = false;
	btn.down = function () {
		btn.isDown = true;
	};
	btn.up = function () {
		btn.isDown = false;
	};
	LK.gui.bottomLeft.addChild(btn);
	return btn;
}
// Positioning for bottom left corner
var baseX = vbtnSize + vbtnMargin;
var baseY = -vbtnSize - vbtnMargin;
// Up
vbtns.up = createVBtn("▲", baseX, baseY - vbtnSize, "up");
// Down
vbtns.down = createVBtn("▼", baseX, baseY + vbtnSize, "down");
// Left
vbtns.left = createVBtn("◀", baseX - vbtnSize, baseY, "left");
// Right
vbtns.right = createVBtn("▶", baseX + vbtnSize, baseY, "right");
// UI: HP Bar
hpBar = new Text2("", {
	size: 38,
	fill: 0xFF4444
});
// Move hearts to the absolute left (x=0), keep y=20
hpBar.anchor.set(0, 0);
LK.gui.top.addChild(hpBar);
hpBar.x = 0;
hpBar.y = 20;
updateHpBar();
// UI: Coin Text
coinText = new Text2("₺ 0", {
	size: 70,
	fill: 0xFFE066
});
coinText.anchor.set(1, 0);
LK.gui.topRight.addChild(coinText);
coinText.x = -40;
coinText.y = 20;
// UI: Wave Text
waveText = new Text2("Dalga: 1", {
	size: 60,
	fill: "#fff"
});
waveText.anchor.set(0, 0);
LK.gui.top.addChild(waveText);
waveText.x = 60;
waveText.y = 120;
// UI: Build Panel
createBuildPanel();
// Start first wave
startWave();
updateCoinText();
updateWaveText(); ===================================================================
--- original.js
+++ change.js
@@ -491,9 +491,9 @@
 	var btnW = 140,
 		btnH = 56,
 		gap = 18;
 	// Dynamically build types array based on upgrade state
-	var types = ['wall', 'trap', 'tower', 'upgrade'];
+	var types = ['wall', 'trap', 'tower', 'upgrade', 'heal'];
 	if (!autoCollectEnabled) {
 		types.push('autocollect');
 	} else {
 		types.push('coinmult');
@@ -519,8 +519,11 @@
 				// Show next multiplier (2x, 4x, 8x, ...) and its cost
 				var nextMult = Math.pow(2, coinMultiplierLevel + 1);
 				label = "Para x" + nextMult;
 				cost = coinMultiplierCost;
+			} else if (type === 'heal') {
+				label = "Can +1";
+				cost = 75;
 			} else {
 				label = buildNames[type] ? buildNames[type] : type;
 				cost = buildCost[type] ? buildCost[type] : 0;
 			}
@@ -759,8 +762,19 @@
 					buildButtons = [];
 					createBuildPanel();
 				}
 			}
+		} else if (buildMode === 'heal') {
+			if (coinsCollected >= 75 && player.hp < player.maxHp) {
+				coinsCollected -= 75;
+				player.hp += 1;
+				if (player.hp > player.maxHp) player.hp = player.maxHp;
+				updateCoinText();
+				updateHpBar();
+				LK.effects.flashObject(player, 0x00ff44, 600);
+				LK.getSound('build').play();
+				clearBuildPreview();
+			}
 		} else {
 			// Place defense if possible
 			if (buildPreview) {
 				// Don't allow build on player or on top of other defenses
 9mm ammo. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
 içinde c yazan sarı renkli bir madeni para. No background. Transparent background. Blank background. No shadows. 2d. In-Game asset. flat
 clash of clans klan kalesi. In-Game asset. 2d. High contrast. No shadows
 the zombie. In-Game asset. 2d. High contrast. No shadows
 gray block. In-Game asset. 2d. High contrast. No shadows
 trap. In-Game asset. 2d. High contrast. No shadows
 arazi pxelart sadece yeşillikle dolu. In-Game asset. 2d. High contrast. No shadows
 elinde silahı olan bir asker. In-Game asset. 2d. High contrast. No shadows