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