User prompt
"sadece ilk atışta 13 dalga atlansın devamında dalga normaldeki gibi atlansın" özelliğini kaldır
User prompt
"iceMonster" öldüğünde "iceMhit" dosyası kullanılsın
User prompt
bitiş ekranını tekrar düzenle
User prompt
iceBoss öldürüldükten sonra gelen kazanma ekranında "NEXT LEVEL" yazmasın
User prompt
iceBoss daha büyük olsun
User prompt
iceBoss çok daha büyük olsun
User prompt
iceBoss daha büyük olsun
User prompt
iceBoss "player"dan 1,5 kat daha büyük olsun
User prompt
"iceBoss" "bossZombie" kadar büyük olsun
User prompt
"secondMap"te eski boss yerine "iceBoss" gelsin
User prompt
ikinci map sadece "secondMap"ten oluşssun
User prompt
"forestMap"te sadece zombiler gelsin
User prompt
"secondMap" haritasına geçildiğinde harita sabitlensin ve sonraki boss dalgası kazanılana kadar değişmesin
User prompt
yeni harita ekranı tamamen kaplasın
User prompt
"secondMap" haritasına geçildikten sonra oyuncu her öldüğünde bu haritada başlasın ve bu haritadaki canavarlar gelsin
User prompt
boss öldükten sonra "NEXT MAP" seçeneği kullanılırsa "secondMap" kullanılarak yeni bir harita oluşturulsun ve önceki haritadaki düşmanlar yerine "iceMonster" canavarları gelmeye başlasın
User prompt
boss öldükten sonra "RESTART" seçeneği kullanılırsa 1. dalgadan tekrar başlansın.
User prompt
boss öldükten sonra tekrar boss gelmesin
User prompt
"NEXT MAP" butonuna basıldığında açılacak harita için yeni bir asset oluştur
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1", {
healthUpgrades: 0,
ammoUpgrades: 0,
speedUpgrades: 0,
coins: 0,
healthUpgradeCost: 200,
ammoUpgradeCost: 100,
speedUpgradeCost: 300,
hasShotgun: false,
hasMachinegun: false
});
/****
* Classes
****/
var BossZombie = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('bossZombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 0.5 + Math.random() * 0.3; // Slower than normal zombies
self.health = 10; // Much higher health
self.damage = 25; // Higher damage
self.lastPlayerCollision = false;
self.scaleX = 1.0; // Normal size
self.scaleY = 1.0;
self.update = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
var currentCollision = self.intersects(player);
if (!self.lastPlayerCollision && currentCollision) {
player.takeDamage(self.damage);
// Boss zombie dies from collision but doesn't give coins
self.health = 0;
LK.effects.flashObject(self, 0xffffff, 100);
var index = zombies.indexOf(self);
if (index > -1) {
zombies.splice(index, 1);
}
self.destroy();
}
self.lastPlayerCollision = currentCollision;
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
LK.effects.flashObject(self, 0xffffff, 100);
LK.setScore(LK.getScore() + 10000); // 10000 score for boss
storage.coins += 10000; // 10000 coins for boss
if (soundEnabled) LK.getSound('zombieHit').play();
var index = zombies.indexOf(self);
if (index > -1) {
zombies.splice(index, 1);
}
self.destroy();
// Show custom congratulations screen when boss is killed
showCongratulations();
}
};
return self;
});
var Bullet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 8;
self.dx = 0;
self.dy = 0;
self.lifetime = 120;
self.update = function () {
self.x += self.dx * self.speed;
self.y += self.dy * self.speed;
// Rotate bullet to face movement direction
graphics.rotation = Math.atan2(self.dy, self.dx);
self.lifetime--;
if (self.lifetime <= 0 || self.isOutOfBounds()) {
self.remove();
return;
}
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
if (self.intersects(zombie)) {
zombie.takeDamage(1);
self.remove();
return;
}
}
};
self.isOutOfBounds = function () {
return self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732;
};
self.remove = function () {
var index = bullets.indexOf(self);
if (index > -1) {
bullets.splice(index, 1);
}
self.destroy();
};
return self;
});
var IceMonster = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('iceMonster', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.tint = 0x87CEEB; // Light blue tint for ice effect
self.speed = 1.5 + Math.random() * 0.7; // Slightly faster than normal zombies
self.health = 2; // Higher health than normal zombies
self.damage = 15; // Higher damage than normal zombies
self.lastPlayerCollision = false;
self.update = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
var currentCollision = self.intersects(player);
if (!self.lastPlayerCollision && currentCollision) {
player.takeDamage(self.damage);
// Ice monster dies from collision but doesn't give coins
self.health = 0;
LK.effects.flashObject(self, 0x87CEEB, 100);
var index = zombies.indexOf(self);
if (index > -1) {
zombies.splice(index, 1);
}
self.destroy();
}
self.lastPlayerCollision = currentCollision;
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
LK.effects.flashObject(self, 0x87CEEB, 100);
LK.setScore(LK.getScore() + 15);
storage.coins += 150;
zombiesKilledInWave++; // Track zombie kills
if (soundEnabled) LK.getSound('zombieHit').play();
var index = zombies.indexOf(self);
if (index > -1) {
zombies.splice(index, 1);
}
self.destroy();
}
};
return self;
});
var MachinegunBullet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('machinegunBullet', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.tint = 0x00ff00; // Green tint to differentiate from other bullets
self.speed = 12; // Faster than normal bullets
self.dx = 0;
self.dy = 0;
self.lifetime = 120; // Same lifetime as normal bullets
self.update = function () {
self.x += self.dx * self.speed;
self.y += self.dy * self.speed;
// Rotate bullet to face movement direction
graphics.rotation = Math.atan2(self.dy, self.dx);
self.lifetime--;
if (self.lifetime <= 0 || self.isOutOfBounds()) {
self.remove();
return;
}
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
if (self.intersects(zombie)) {
zombie.takeDamage(1);
self.remove();
return;
}
}
};
self.isOutOfBounds = function () {
return self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732;
};
self.remove = function () {
var index = bullets.indexOf(self);
if (index > -1) {
bullets.splice(index, 1);
}
self.destroy();
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.ammo = 30;
self.maxAmmo = 30;
self.shootCooldown = 0;
self.baseShootCooldown = 10;
self.weaponType = 'normal';
self.update = function () {
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
self.takeDamage = function (damage) {
self.health -= damage;
if (soundEnabled) LK.getSound('playerHit').play();
if (self.health <= 0) {
self.health = 0;
LK.effects.flashScreen(0xff0000, 1000);
showCustomGameOver();
} else {
LK.effects.flashObject(self, 0xff0000, 200);
}
};
self.canShoot = function () {
return self.ammo > 0 && self.shootCooldown <= 0;
};
self.shoot = function () {
if (self.canShoot()) {
self.ammo--;
if (self.weaponType === 'machinegun') {
self.shootCooldown = Math.max(1, self.baseShootCooldown - 5); // Faster fire rate
} else {
self.shootCooldown = self.baseShootCooldown;
}
return true;
}
return false;
};
return self;
});
var ShotgunBullet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('shotgunBullet', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.tint = 0xffaa00; // Orange tint to differentiate from normal bullets
self.speed = 8;
self.dx = 0;
self.dy = 0;
self.lifetime = 100; // Shorter lifetime than normal bullets
self.update = function () {
self.x += self.dx * self.speed;
self.y += self.dy * self.speed;
// Rotate bullet to face movement direction
graphics.rotation = Math.atan2(self.dy, self.dx);
self.lifetime--;
if (self.lifetime <= 0 || self.isOutOfBounds()) {
self.remove();
return;
}
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
if (self.intersects(zombie)) {
zombie.takeDamage(1);
self.remove();
return;
}
}
};
self.isOutOfBounds = function () {
return self.x < 0 || self.x > 2048 || self.y < 0 || self.y > 2732;
};
self.remove = function () {
var index = bullets.indexOf(self);
if (index > -1) {
bullets.splice(index, 1);
}
self.destroy();
};
return self;
});
var Zombie = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 1 + Math.random() * 0.5;
self.health = 1;
self.damage = 10;
self.lastPlayerCollision = false;
self.update = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
var currentCollision = self.intersects(player);
if (!self.lastPlayerCollision && currentCollision) {
player.takeDamage(self.damage);
// Zombie dies from collision but doesn't give coins
self.health = 0;
LK.effects.flashObject(self, 0xffffff, 100);
var index = zombies.indexOf(self);
if (index > -1) {
zombies.splice(index, 1);
}
self.destroy();
}
self.lastPlayerCollision = currentCollision;
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
LK.effects.flashObject(self, 0xffffff, 100);
LK.setScore(LK.getScore() + 10);
storage.coins += 100;
zombiesKilledInWave++; // Track zombie kills
if (soundEnabled) LK.getSound('zombieHit').play();
var index = zombies.indexOf(self);
if (index > -1) {
zombies.splice(index, 1);
}
self.destroy();
}
};
return self;
});
var Zombie2 = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('zombie2', {
anchorX: 0.5,
anchorY: 0.5
});
graphics.tint = 0xff6b6b; // Reddish tint to differentiate
self.speed = 1 + Math.random() * 0.5;
self.health = 1;
self.damage = 10;
self.lastPlayerCollision = false;
self.update = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
var currentCollision = self.intersects(player);
if (!self.lastPlayerCollision && currentCollision) {
player.takeDamage(self.damage);
// Zombie dies from collision but doesn't give coins
self.health = 0;
LK.effects.flashObject(self, 0xffffff, 100);
var index = zombies.indexOf(self);
if (index > -1) {
zombies.splice(index, 1);
}
self.destroy();
}
self.lastPlayerCollision = currentCollision;
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.health <= 0) {
LK.effects.flashObject(self, 0xffffff, 100);
LK.setScore(LK.getScore() + 10);
storage.coins += 100;
zombiesKilledInWave++; // Track zombie kills
if (soundEnabled) LK.getSound('zombieHit').play();
var index = zombies.indexOf(self);
if (index > -1) {
zombies.splice(index, 1);
}
self.destroy();
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2d2d2d
});
/****
* Game Code
****/
var arena = game.attachAsset('arena', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 0.15,
scaleY: 0.15
});
var player = game.addChild(new Player());
player.x = 2048 / 2;
player.y = 2732 / 2;
player.scaleX = 1.0;
player.scaleY = 1.0;
// Apply stored upgrades
player.maxHealth = 100 + storage.healthUpgrades * 20;
player.health = player.maxHealth;
player.maxAmmo = 30 + storage.ammoUpgrades * 10;
player.ammo = player.maxAmmo;
player.baseShootCooldown = Math.max(1, 10 - storage.speedUpgrades);
// Weapon status display - define early so it can be used in game.update
var weaponStatus = new Text2('Weapon: ' + (player.weaponType || 'Normal'), {
size: 60,
fill: 0xFFFFFF
});
// Function to update weapon button colors
function updateWeaponButtons() {
if (normalWeaponButton) {
normalWeaponButton.tint = player.weaponType === 'normal' ? 0x4CAF50 : 0x666666;
}
if (shotgunWeaponButton) {
shotgunWeaponButton.tint = player.weaponType === 'shotgun' ? 0x4CAF50 : 0x666666;
}
if (machinegunWeaponButton) {
machinegunWeaponButton.tint = player.weaponType === 'machinegun' ? 0x4CAF50 : 0x666666;
}
weaponStatus.setText('Weapon: ' + (player.weaponType || 'Normal'));
}
var zombies = [];
var bullets = [];
var waveNumber = 1;
var zombiesInWave = 5;
var zombiesSpawned = 0;
var spawnTimer = 0;
var gameOverScreen = null;
var showingGameOver = false;
var showingMarket = false;
var marketPanel = null;
var isPaused = false;
var pausePanel = null;
var isBossWave = false;
var isFirstShot = true;
var zombiesKilledInWave = 0;
var zombiesRequiredToKill = 8;
var isSecondMap = false; // Track which map we're on
// Upgrade costs that increase with each purchase - loaded from storage
var healthUpgradeCost = storage.healthUpgradeCost;
var ammoUpgradeCost = storage.ammoUpgradeCost;
var speedUpgradeCost = storage.speedUpgradeCost;
var healthBackground = LK.getAsset('Tahta', {
width: 300,
height: 60,
anchorX: 0,
anchorY: 1,
x: 120,
y: 0
});
healthBackground.alpha = 0.7;
LK.gui.bottomLeft.addChild(healthBackground);
var healthBar = new Text2('Health: 100', {
size: 60,
fill: 0xFF0000
});
healthBar.anchor.set(0, 1);
healthBar.x = 120; // Move away from bottom-left corner
LK.gui.bottomLeft.addChild(healthBar);
var ammoBackground = LK.getAsset('Tahta', {
width: 300,
height: 60,
anchorX: 0,
anchorY: 1,
x: 120,
y: -70
});
ammoBackground.alpha = 0.7;
LK.gui.bottomLeft.addChild(ammoBackground);
var ammoDisplay = new Text2('Ammo: 30', {
size: 60,
fill: 0x00FF00
});
ammoDisplay.anchor.set(0, 1);
ammoDisplay.x = 120; // Move away from bottom-left corner
ammoDisplay.y = -70;
LK.gui.bottomLeft.addChild(ammoDisplay);
var waveBackground = LK.getAsset('Tahta', {
width: 300,
height: 60,
anchorX: 0,
anchorY: 1,
x: 120,
y: -140
});
waveBackground.alpha = 0.7;
LK.gui.bottomLeft.addChild(waveBackground);
var waveInfo = new Text2('Wave: 1', {
size: 60,
fill: 0xFFFF00
});
waveInfo.anchor.set(0, 1);
waveInfo.x = 120; // Move away from bottom-left corner
waveInfo.y = -140;
LK.gui.bottomLeft.addChild(waveInfo);
var killProgressBackground = LK.getAsset('Tahta', {
width: 350,
height: 60,
anchorX: 0,
anchorY: 1,
x: 120,
y: -210
});
killProgressBackground.alpha = 0.7;
LK.gui.bottomLeft.addChild(killProgressBackground);
var killProgress = new Text2('Kills: 0/8', {
size: 60,
fill: 0xFF6B6B
});
killProgress.anchor.set(0, 1);
killProgress.x = 120;
killProgress.y = -210;
LK.gui.bottomLeft.addChild(killProgress);
var scoreBackground = LK.getAsset('Tahta', {
width: 350,
height: 90,
anchorX: 0.5,
anchorY: 0,
x: 0,
y: 0
});
scoreBackground.alpha = 0.7;
LK.gui.top.addChild(scoreBackground);
var scoreDisplay = new Text2('SCORE: 0', {
size: 80,
fill: 0xFFFFFF
});
scoreDisplay.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreDisplay);
var coinBackground = LK.getAsset('Tahta', {
width: 300,
height: 70,
anchorX: 0.5,
anchorY: 0,
x: 0,
y: 90
});
coinBackground.alpha = 0.7;
LK.gui.top.addChild(coinBackground);
var coinDisplay = new Text2('COIN: ' + storage.coins, {
size: 60,
fill: 0xFFD700
});
coinDisplay.anchor.set(0.5, 0);
coinDisplay.y = 90;
LK.gui.top.addChild(coinDisplay);
function showCustomGameOver() {
if (showingGameOver) return;
showingGameOver = true;
gameOverScreen = new Container();
// Semi-transparent background
var background = LK.getAsset('arena', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 4,
scaleY: 4
});
background.alpha = 0.8;
background.tint = 0x000000;
gameOverScreen.addChild(background);
// Game Over title
var gameOverTitle = new Text2('GAME OVER', {
size: 140,
fill: 0xFF0000
});
gameOverTitle.anchor.set(0.5, 0.5);
gameOverTitle.x = 2048 / 2;
gameOverTitle.y = 2732 / 2 - 200;
gameOverScreen.addChild(gameOverTitle);
// Final score display
var finalScore = new Text2('Final Score: ' + LK.getScore(), {
size: 100,
fill: 0xFFFFFF
});
finalScore.anchor.set(0.5, 0.5);
finalScore.x = 2048 / 2;
finalScore.y = 2732 / 2 - 100;
gameOverScreen.addChild(finalScore);
// Market button
var marketButton = LK.getAsset('marketButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 50
});
marketButton.tint = 0x2196F3;
marketButton.down = function (x, y, obj) {
showMarket();
};
gameOverScreen.addChild(marketButton);
var marketText = new Text2('MARKET', {
size: 80,
fill: 0xFFFFFF
});
marketText.anchor.set(0.5, 0.5);
marketText.x = 2048 / 2;
marketText.y = 2732 / 2 + 50;
gameOverScreen.addChild(marketText);
// Restart button
var restartButton = LK.getAsset('marketButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 150
});
restartButton.tint = 0xFF5722;
restartButton.down = function (x, y, obj) {
restartGame();
};
gameOverScreen.addChild(restartButton);
var restartText = new Text2('RESTART', {
size: 80,
fill: 0xFFFFFF
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 2048 / 2;
restartText.y = 2732 / 2 + 150;
gameOverScreen.addChild(restartText);
game.addChild(gameOverScreen);
}
function showCongratulations() {
if (showingGameOver) return;
showingGameOver = true;
gameOverScreen = new Container();
// Semi-transparent background
var background = LK.getAsset('arena', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 4,
scaleY: 4
});
background.alpha = 0.8;
background.tint = 0x000000;
gameOverScreen.addChild(background);
// Congratulations title
var congratsTitle = new Text2('CONGRATULATIONS', {
size: 160,
fill: 0xFFD700
});
congratsTitle.anchor.set(0.5, 0.5);
congratsTitle.x = 2048 / 2;
congratsTitle.y = 2732 / 2 - 300;
gameOverScreen.addChild(congratsTitle);
// Victory message
var victoryMessage = new Text2('BOSS DEFEATED!', {
size: 120,
fill: 0x00FF00
});
victoryMessage.anchor.set(0.5, 0.5);
victoryMessage.x = 2048 / 2;
victoryMessage.y = 2732 / 2 - 150;
gameOverScreen.addChild(victoryMessage);
// Final score display
var finalScore = new Text2('Final Score: ' + LK.getScore(), {
size: 100,
fill: 0xFFFFFF
});
finalScore.anchor.set(0.5, 0.5);
finalScore.x = 2048 / 2;
finalScore.y = 2732 / 2 - 50;
gameOverScreen.addChild(finalScore);
// Market button
var marketButton = LK.getAsset('marketButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 100
});
marketButton.tint = 0x2196F3;
marketButton.down = function (x, y, obj) {
showMarket();
};
gameOverScreen.addChild(marketButton);
var marketText = new Text2('MARKET', {
size: 80,
fill: 0xFFFFFF
});
marketText.anchor.set(0.5, 0.5);
marketText.x = 2048 / 2;
marketText.y = 2732 / 2 + 100;
gameOverScreen.addChild(marketText);
// Next Map button
var nextMapButton = LK.getAsset('marketButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 200
});
nextMapButton.tint = 0x4CAF50;
nextMapButton.down = function (x, y, obj) {
// Switch to next map - change to second map asset and restart
game.removeChild(arena);
arena = game.attachAsset('secondMap', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 1.0,
scaleY: 1.0
});
isSecondMap = true; // Set flag for second map
restartGame();
};
gameOverScreen.addChild(nextMapButton);
var nextMapText = new Text2('NEXT MAP', {
size: 80,
fill: 0xFFFFFF
});
nextMapText.anchor.set(0.5, 0.5);
nextMapText.x = 2048 / 2;
nextMapText.y = 2732 / 2 + 200;
gameOverScreen.addChild(nextMapText);
// Restart button
var restartButton = LK.getAsset('marketButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 300
});
restartButton.tint = 0xFF5722;
restartButton.down = function (x, y, obj) {
restartGame();
};
gameOverScreen.addChild(restartButton);
var restartText = new Text2('RESTART', {
size: 80,
fill: 0xFFFFFF
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 2048 / 2;
restartText.y = 2732 / 2 + 300;
gameOverScreen.addChild(restartText);
game.addChild(gameOverScreen);
}
function hideGameOver() {
if (gameOverScreen) {
gameOverScreen.destroy();
gameOverScreen = null;
}
showingGameOver = false;
}
function showMarket() {
if (showingMarket) return;
showingMarket = true;
marketPanel = new Container();
// Semi-transparent background
var background = LK.getAsset('arena', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 4,
scaleY: 4
});
background.alpha = 0.95;
background.tint = 0x1a1a1a;
marketPanel.addChild(background);
// Main market panel background
var mainPanel = LK.getAsset('Tahta', {
width: 1800,
height: 2200,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
mainPanel.alpha = 0.95;
mainPanel.tint = 0x2a2a2a;
marketPanel.addChild(mainPanel);
// Market title with enhanced styling
var marketTitle = new Text2('🛒 MARKET', {
size: 160,
fill: 0xFFD700
});
marketTitle.anchor.set(0.5, 0.5);
marketTitle.x = 2048 / 2;
marketTitle.y = 2732 / 2 - 850;
marketPanel.addChild(marketTitle);
// Current coins display with enhanced styling
var currentCoins = storage.coins;
var coinPanel = LK.getAsset('Tahta', {
width: 600,
height: 120,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 - 700
});
coinPanel.alpha = 0.9;
coinPanel.tint = 0x4a4a4a;
marketPanel.addChild(coinPanel);
var scoreText = new Text2('💰 COINS: ' + storage.coins, {
size: 100,
fill: 0xFFD700
});
scoreText.anchor.set(0.5, 0.5);
scoreText.x = 2048 / 2;
scoreText.y = 2732 / 2 - 700;
marketPanel.addChild(scoreText);
// Health upgrade section
var healthSection = LK.getAsset('Tahta', {
width: 1600,
height: 200,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 - 450
});
healthSection.alpha = 0.8;
healthSection.tint = 0x4CAF50;
marketPanel.addChild(healthSection);
var healthIcon = new Text2('❤️', {
size: 120,
fill: 0xFFFFFF
});
healthIcon.anchor.set(0.5, 0.5);
healthIcon.x = 2048 / 2 - 650;
healthIcon.y = 2732 / 2 - 450;
marketPanel.addChild(healthIcon);
var healthTitle = new Text2('HEALTH BOOST', {
size: 80,
fill: 0xFFFFFF
});
healthTitle.anchor.set(0, 0.5);
healthTitle.x = 2048 / 2 - 550;
healthTitle.y = 2732 / 2 - 480;
marketPanel.addChild(healthTitle);
var healthDesc = new Text2('+20 Max Health & Heal', {
size: 60,
fill: 0xE8F5E8
});
healthDesc.anchor.set(0, 0.5);
healthDesc.x = 2048 / 2 - 550;
healthDesc.y = 2732 / 2 - 420;
marketPanel.addChild(healthDesc);
var healthCost = new Text2('💰 ' + healthUpgradeCost, {
size: 90,
fill: storage.coins >= healthUpgradeCost ? 0xFFD700 : 0xFF4444
});
healthCost.anchor.set(1, 0.5);
healthCost.x = 2048 / 2 + 650;
healthCost.y = 2732 / 2 - 450;
marketPanel.addChild(healthCost);
var healthUpgrade = LK.getAsset('marketButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 - 450
});
healthUpgrade.alpha = 0.01;
healthUpgrade.down = function (x, y, obj) {
if (storage.coins >= healthUpgradeCost) {
storage.coins -= healthUpgradeCost;
healthUpgradeCost = Math.floor(healthUpgradeCost * 1.5); // Increase cost by 50%
storage.healthUpgradeCost = healthUpgradeCost; // Save to storage
storage.healthUpgrades++;
player.maxHealth += 20;
player.health = Math.min(player.health + 20, player.maxHealth);
coinDisplay.setText('COIN: ' + storage.coins);
LK.getSound('coinPurchase').play();
hideMarket();
showMarket(); // Refresh market display
}
};
marketPanel.addChild(healthUpgrade);
// Ammo upgrade section
var ammoSection = LK.getAsset('Tahta', {
width: 1600,
height: 200,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 - 200
});
ammoSection.alpha = 0.8;
ammoSection.tint = 0x2196F3;
marketPanel.addChild(ammoSection);
var ammoIcon = new Text2('🔫', {
size: 120,
fill: 0xFFFFFF
});
ammoIcon.anchor.set(0.5, 0.5);
ammoIcon.x = 2048 / 2 - 650;
ammoIcon.y = 2732 / 2 - 200;
marketPanel.addChild(ammoIcon);
var ammoTitle = new Text2('AMMO BOOST', {
size: 80,
fill: 0xFFFFFF
});
ammoTitle.anchor.set(0, 0.5);
ammoTitle.x = 2048 / 2 - 550;
ammoTitle.y = 2732 / 2 - 230;
marketPanel.addChild(ammoTitle);
var ammoDesc = new Text2('+10 Max Ammo & Reload', {
size: 60,
fill: 0xE3F2FD
});
ammoDesc.anchor.set(0, 0.5);
ammoDesc.x = 2048 / 2 - 550;
ammoDesc.y = 2732 / 2 - 170;
marketPanel.addChild(ammoDesc);
var ammoCost = new Text2('💰 ' + ammoUpgradeCost, {
size: 90,
fill: storage.coins >= ammoUpgradeCost ? 0xFFD700 : 0xFF4444
});
ammoCost.anchor.set(1, 0.5);
ammoCost.x = 2048 / 2 + 650;
ammoCost.y = 2732 / 2 - 200;
marketPanel.addChild(ammoCost);
var ammoUpgrade = LK.getAsset('marketButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 - 200
});
ammoUpgrade.alpha = 0.01;
ammoUpgrade.down = function (x, y, obj) {
if (storage.coins >= ammoUpgradeCost) {
storage.coins -= ammoUpgradeCost;
ammoUpgradeCost = Math.floor(ammoUpgradeCost * 1.5); // Increase cost by 50%
storage.ammoUpgradeCost = ammoUpgradeCost; // Save to storage
storage.ammoUpgrades++;
player.maxAmmo += 10;
player.ammo = Math.min(player.ammo + 10, player.maxAmmo);
coinDisplay.setText('COIN: ' + storage.coins);
LK.getSound('coinPurchase').play();
hideMarket();
showMarket(); // Refresh market display
}
};
marketPanel.addChild(ammoUpgrade);
// Speed upgrade section
var speedSection = LK.getAsset('Tahta', {
width: 1600,
height: 200,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 50
});
speedSection.alpha = 0.8;
speedSection.tint = 0xFF9800;
marketPanel.addChild(speedSection);
var speedIcon = new Text2('⚡', {
size: 120,
fill: 0xFFFFFF
});
speedIcon.anchor.set(0.5, 0.5);
speedIcon.x = 2048 / 2 - 650;
speedIcon.y = 2732 / 2 + 50;
marketPanel.addChild(speedIcon);
var speedTitle = new Text2('FIRE RATE BOOST', {
size: 80,
fill: 0xFFFFFF
});
speedTitle.anchor.set(0, 0.5);
speedTitle.x = 2048 / 2 - 550;
speedTitle.y = 2732 / 2 + 20;
marketPanel.addChild(speedTitle);
var speedDesc = new Text2('Shoot Faster!', {
size: 60,
fill: 0xFFF3E0
});
speedDesc.anchor.set(0, 0.5);
speedDesc.x = 2048 / 2 - 550;
speedDesc.y = 2732 / 2 + 80;
marketPanel.addChild(speedDesc);
var speedCost = new Text2('💰 ' + speedUpgradeCost, {
size: 90,
fill: storage.coins >= speedUpgradeCost ? 0xFFD700 : 0xFF4444
});
speedCost.anchor.set(1, 0.5);
speedCost.x = 2048 / 2 + 650;
speedCost.y = 2732 / 2 + 50;
marketPanel.addChild(speedCost);
var speedUpgrade = LK.getAsset('marketButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 50
});
speedUpgrade.alpha = 0.01;
speedUpgrade.down = function (x, y, obj) {
if (storage.coins >= speedUpgradeCost) {
storage.coins -= speedUpgradeCost;
speedUpgradeCost = Math.floor(speedUpgradeCost * 1.5); // Increase cost by 50%
storage.speedUpgradeCost = speedUpgradeCost; // Save to storage
storage.speedUpgrades++;
player.baseShootCooldown = Math.max(1, player.baseShootCooldown - 1);
coinDisplay.setText('COIN: ' + storage.coins);
LK.getSound('coinPurchase').play();
hideMarket();
showMarket(); // Refresh market display
}
};
marketPanel.addChild(speedUpgrade);
// Shotgun weapon section
var shotgunSection = LK.getAsset('Tahta', {
width: 1600,
height: 200,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 300
});
shotgunSection.alpha = 0.8;
shotgunSection.tint = 0x795548;
marketPanel.addChild(shotgunSection);
var shotgunIcon = new Text2('🔫', {
size: 120,
fill: 0xFFFFFF
});
shotgunIcon.anchor.set(0.5, 0.5);
shotgunIcon.x = 2048 / 2 - 650;
shotgunIcon.y = 2732 / 2 + 300;
marketPanel.addChild(shotgunIcon);
var shotgunTitle = new Text2('POMPALΙ TÜFEK', {
size: 80,
fill: 0xFFFFFF
});
shotgunTitle.anchor.set(0, 0.5);
shotgunTitle.x = 2048 / 2 - 550;
shotgunTitle.y = 2732 / 2 + 270;
marketPanel.addChild(shotgunTitle);
var shotgunDesc = new Text2('Spread Shot +5 Bullets', {
size: 60,
fill: 0xEFEBE9
});
shotgunDesc.anchor.set(0, 0.5);
shotgunDesc.x = 2048 / 2 - 550;
shotgunDesc.y = 2732 / 2 + 330;
marketPanel.addChild(shotgunDesc);
var shotgunCost = new Text2(storage.hasShotgun ? 'SATILDI' : '💰 500', {
size: 90,
fill: storage.hasShotgun ? 0x888888 : storage.coins >= 500 ? 0xFFD700 : 0xFF4444
});
shotgunCost.anchor.set(1, 0.5);
shotgunCost.x = 2048 / 2 + 650;
shotgunCost.y = 2732 / 2 + 300;
marketPanel.addChild(shotgunCost);
var shotgunUpgrade = LK.getAsset('marketButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 300
});
shotgunUpgrade.alpha = 0.01;
shotgunUpgrade.down = function (x, y, obj) {
if (!storage.hasShotgun && storage.coins >= 500) {
storage.coins -= 500;
storage.hasShotgun = true;
player.weaponType = 'shotgun';
coinDisplay.setText('COIN: ' + storage.coins);
LK.getSound('coinPurchase').play();
hideMarket();
showMarket(); // Refresh market display
}
};
marketPanel.addChild(shotgunUpgrade);
// Machine gun weapon section
var machinegunSection = LK.getAsset('Tahta', {
width: 1600,
height: 200,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 550
});
machinegunSection.alpha = 0.8;
machinegunSection.tint = 0x607D8B;
marketPanel.addChild(machinegunSection);
var machinegunIcon = new Text2('🔫', {
size: 120,
fill: 0xFFFFFF
});
machinegunIcon.anchor.set(0.5, 0.5);
machinegunIcon.x = 2048 / 2 - 650;
machinegunIcon.y = 2732 / 2 + 550;
marketPanel.addChild(machinegunIcon);
var machinegunTitle = new Text2('HAFİF MAKİNELİ TÜFEK', {
size: 80,
fill: 0xFFFFFF
});
machinegunTitle.anchor.set(0, 0.5);
machinegunTitle.x = 2048 / 2 - 550;
machinegunTitle.y = 2732 / 2 + 520;
marketPanel.addChild(machinegunTitle);
var machinegunDesc = new Text2('Rapid Fire Mode', {
size: 60,
fill: 0xECEFF1
});
machinegunDesc.anchor.set(0, 0.5);
machinegunDesc.x = 2048 / 2 - 550;
machinegunDesc.y = 2732 / 2 + 580;
marketPanel.addChild(machinegunDesc);
var machinegunCost = new Text2(storage.hasMachinegun ? 'SATILDI' : '💰 800', {
size: 90,
fill: storage.hasMachinegun ? 0x888888 : storage.coins >= 800 ? 0xFFD700 : 0xFF4444
});
machinegunCost.anchor.set(1, 0.5);
machinegunCost.x = 2048 / 2 + 650;
machinegunCost.y = 2732 / 2 + 550;
marketPanel.addChild(machinegunCost);
var machinegunUpgrade = LK.getAsset('marketButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 550
});
machinegunUpgrade.alpha = 0.01;
machinegunUpgrade.down = function (x, y, obj) {
if (!storage.hasMachinegun && storage.coins >= 800) {
storage.coins -= 800;
storage.hasMachinegun = true;
player.weaponType = 'machinegun';
coinDisplay.setText('COIN: ' + storage.coins);
LK.getSound('coinPurchase').play();
hideMarket();
showMarket(); // Refresh market display
}
};
marketPanel.addChild(machinegunUpgrade);
// Upgrade status display
var upgradeStatus = LK.getAsset('Tahta', {
width: 1600,
height: 150,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 750
});
upgradeStatus.alpha = 0.8;
upgradeStatus.tint = 0x333333;
marketPanel.addChild(upgradeStatus);
var statusTitle = new Text2('📊 UPGRADE STATUS', {
size: 70,
fill: 0xFFFFFF
});
statusTitle.anchor.set(0.5, 0.5);
statusTitle.x = 2048 / 2;
statusTitle.y = 2732 / 2 + 710;
marketPanel.addChild(statusTitle);
var statusText = new Text2('❤️ ' + storage.healthUpgrades + ' 🔫 ' + storage.ammoUpgrades + ' ⚡ ' + storage.speedUpgrades + ' Weapon: ' + (player.weaponType || 'Normal'), {
size: 70,
fill: 0xFFD700
});
statusText.anchor.set(0.5, 0.5);
statusText.x = 2048 / 2;
statusText.y = 2732 / 2 + 790;
marketPanel.addChild(statusText);
// Enhanced close button
var closeButtonBg = LK.getAsset('Tahta', {
width: 800,
height: 150,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 950
});
closeButtonBg.alpha = 0.9;
closeButtonBg.tint = 0x666666;
marketPanel.addChild(closeButtonBg);
var closeButton = LK.getAsset('marketButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 950
});
closeButton.alpha = 0.01;
closeButton.down = function (x, y, obj) {
hideMarket();
};
marketPanel.addChild(closeButton);
var closeText = new Text2('❌ CLOSE MARKET', {
size: 90,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeText.x = 2048 / 2;
closeText.y = 2732 / 2 + 950;
marketPanel.addChild(closeText);
game.addChild(marketPanel);
}
function hideMarket() {
if (marketPanel) {
marketPanel.destroy();
marketPanel = null;
}
showingMarket = false;
// Refresh weapon buttons if new weapons were purchased
refreshWeaponButtons();
}
function refreshWeaponButtons() {
// Remove existing weapon buttons
if (shotgunWeaponButton && !storage.hasShotgun) {
shotgunWeaponButton.destroy();
shotgunWeaponText.destroy();
shotgunWeaponButton = null;
shotgunWeaponText = null;
}
if (machinegunWeaponButton && !storage.hasMachinegun) {
machinegunWeaponButton.destroy();
machinegunWeaponText.destroy();
machinegunWeaponButton = null;
machinegunWeaponText = null;
}
// Add shotgun button if purchased and not already added
if (storage.hasShotgun && !shotgunWeaponButton) {
shotgunWeaponButton = LK.getAsset('weaponIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 - 650,
y: 2732 - 120
});
shotgunWeaponButton.tint = player.weaponType === 'shotgun' ? 0x4CAF50 : 0x666666;
bottomPanel.addChild(shotgunWeaponButton);
shotgunWeaponText = new Text2('🔫', {
size: 60,
fill: 0xFFAA00
});
shotgunWeaponText.anchor.set(0.5, 0.5);
shotgunWeaponText.x = 2048 / 2 - 650;
shotgunWeaponText.y = 2732 - 120;
bottomPanel.addChild(shotgunWeaponText);
shotgunWeaponButton.down = function (x, y, obj) {
if (!showingGameOver && !showingMarket && !isPaused) {
player.weaponType = 'shotgun';
updateWeaponButtons();
}
};
}
// Add machine gun button if purchased and not already added
if (storage.hasMachinegun && !machinegunWeaponButton) {
machinegunWeaponButton = LK.getAsset('weaponIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 - 500,
y: 2732 - 120
});
machinegunWeaponButton.tint = player.weaponType === 'machinegun' ? 0x4CAF50 : 0x666666;
bottomPanel.addChild(machinegunWeaponButton);
machinegunWeaponText = new Text2('🔫', {
size: 60,
fill: 0x00FF00
});
machinegunWeaponText.anchor.set(0.5, 0.5);
machinegunWeaponText.x = 2048 / 2 - 500;
machinegunWeaponText.y = 2732 - 120;
bottomPanel.addChild(machinegunWeaponText);
machinegunWeaponButton.down = function (x, y, obj) {
if (!showingGameOver && !showingMarket && !isPaused) {
player.weaponType = 'machinegun';
updateWeaponButtons();
}
};
}
}
function showPause() {
if (isPaused) return;
isPaused = true;
pausePanel = new Container();
// Semi-transparent background
var background = LK.getAsset('arena', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 3,
scaleY: 3
});
background.alpha = 0.8;
background.tint = 0x000000;
pausePanel.addChild(background);
// Pause menu panel with wooden background
var pauseMenuBackground = LK.getAsset('Tahta', {
width: 600,
height: 500,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2
});
pauseMenuBackground.alpha = 0.9;
pausePanel.addChild(pauseMenuBackground);
// Pause title
var pauseTitle = new Text2('PAUSE MENU', {
size: 100,
fill: 0xFFFFFF
});
pauseTitle.anchor.set(0.5, 0.5);
pauseTitle.x = 2048 / 2;
pauseTitle.y = 2732 / 2 - 180;
pausePanel.addChild(pauseTitle);
// Restart button
var restartButton = LK.getAsset('marketButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 - 80
});
restartButton.tint = 0xFF5722;
restartButton.down = function (x, y, obj) {
hidePause();
restartGame();
};
pausePanel.addChild(restartButton);
var restartText = new Text2('RESTART', {
size: 60,
fill: 0xFFFFFF
});
restartText.anchor.set(0.5, 0.5);
restartText.x = 2048 / 2;
restartText.y = 2732 / 2 - 80;
pausePanel.addChild(restartText);
// Continue button
var continueButton = LK.getAsset('marketButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 20
});
continueButton.down = function (x, y, obj) {
hidePause();
};
pausePanel.addChild(continueButton);
var continueText = new Text2('CONTINUE', {
size: 60,
fill: 0xFFFFFF
});
continueText.anchor.set(0.5, 0.5);
continueText.x = 2048 / 2;
continueText.y = 2732 / 2 + 20;
pausePanel.addChild(continueText);
// Market button
var marketButton = LK.getAsset('marketButton', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2 + 120
});
marketButton.tint = 0x2196F3;
marketButton.down = function (x, y, obj) {
hidePause();
showMarket();
};
pausePanel.addChild(marketButton);
var marketText = new Text2('MARKET', {
size: 60,
fill: 0xFFFFFF
});
marketText.anchor.set(0.5, 0.5);
marketText.x = 2048 / 2;
marketText.y = 2732 / 2 + 120;
pausePanel.addChild(marketText);
game.addChild(pausePanel);
}
function hidePause() {
if (pausePanel) {
pausePanel.destroy();
pausePanel = null;
}
isPaused = false;
}
function restartGame() {
hideGameOver();
// Reset player with upgraded stats
player.maxHealth = 100 + storage.healthUpgrades * 20;
player.health = player.maxHealth;
player.maxAmmo = 30 + storage.ammoUpgrades * 10;
player.ammo = player.maxAmmo;
player.baseShootCooldown = Math.max(1, 10 - storage.speedUpgrades);
player.x = 2048 / 2;
player.y = 2732 / 2;
// Clear all entities
for (var i = 0; i < zombies.length; i++) {
zombies[i].destroy();
}
zombies = [];
for (var i = 0; i < bullets.length; i++) {
bullets[i].destroy();
}
bullets = [];
// Reset game state
waveNumber = 1;
zombiesInWave = 5;
zombiesSpawned = 0;
spawnTimer = 0;
isFirstShot = true;
zombiesKilledInWave = 0;
zombiesRequiredToKill = 8;
isBossWave = false;
bossKilled = false;
// Reset to first map when restarting normally
if (!isSecondMap) {
game.removeChild(arena);
arena = game.attachAsset('arena', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
scaleX: 0.15,
scaleY: 0.15
});
}
LK.setScore(0);
}
function spawnZombie() {
var zombie;
// Check if this is a boss wave (every 15th wave)
if (isBossWave) {
zombie = new BossZombie();
} else if (isSecondMap) {
// On second map, spawn ice monsters instead of regular zombies
zombie = new IceMonster();
} else {
zombie = Math.random() < 0.5 ? new Zombie() : new Zombie2();
}
// Define spawn locations around the arena edges
var spawnLocations = [{
x: Math.random() * 2048,
y: 100
},
// Top edge
{
x: Math.random() * 2048,
y: 2632
},
// Bottom edge
{
x: 100,
y: Math.random() * 2732
},
// Left edge
{
x: 1948,
y: Math.random() * 2732
},
// Right edge
{
x: 300,
y: 300
},
// Top-left corner
{
x: 1748,
y: 300
},
// Top-right corner
{
x: 300,
y: 2432
},
// Bottom-left corner
{
x: 1748,
y: 2432
} // Bottom-right corner
];
// Pick a random spawn location from the predefined spots
var spawnIndex = Math.floor(Math.random() * spawnLocations.length);
var spawnPoint = spawnLocations[spawnIndex];
zombie.x = spawnPoint.x;
zombie.y = spawnPoint.y;
// Only apply scaling to non-boss zombies
if (!isBossWave) {
// Increase zombie health by 25% every 5 waves
var healthMultiplier = Math.floor(waveNumber / 5) * 0.25;
zombie.health = Math.floor(1 * (1 + healthMultiplier));
// Increase zombie speed by 25% every 15 waves
var speedMultiplier = Math.floor(waveNumber / 15) * 0.25;
zombie.speed = zombie.speed * (1 + speedMultiplier);
// Increase zombie damage by 25% every 10 waves
var damageMultiplier = Math.floor(waveNumber / 10) * 0.25;
zombie.damage = Math.floor(zombie.damage * (1 + damageMultiplier));
zombie.scaleX = 1.0;
zombie.scaleY = 1.0;
} else {
// Boss zombies get stronger each boss wave
var bossWaveNumber = Math.floor(waveNumber / 15);
zombie.health = 10 + bossWaveNumber * 5; // More health each boss wave
zombie.damage = 25 + bossWaveNumber * 10; // More damage each boss wave
}
zombies.push(zombie);
game.addChild(zombie);
}
function shootBullet(targetX, targetY) {
if (player.shoot()) {
// Kill all zombies in current wave when player shoots
for (var i = zombies.length - 1; i >= 0; i--) {
var zombie = zombies[i];
zombie.takeDamage(999); // Deal massive damage to instantly kill
}
// Advance waves when player shoots - 13 on first shot, then normal progression
if (isFirstShot) {
waveNumber += 13;
isFirstShot = false;
}
zombiesSpawned = 0;
spawnTimer = 0;
var dx = targetX - player.x;
var dy = targetY - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 0) {
// Rotate player to face shooting direction
player.rotation = Math.atan2(dy, dx);
}
if (player.weaponType === 'shotgun') {
// Shotgun fires 5 bullets in a spread pattern
for (var i = 0; i < 5; i++) {
var bullet = new ShotgunBullet();
bullet.x = player.x;
bullet.y = player.y;
var spreadAngle = (i - 2) * 0.3; // Spread bullets in a fan pattern
var angle = Math.atan2(dy, dx) + spreadAngle;
bullet.dx = Math.cos(angle);
bullet.dy = Math.sin(angle);
bullet.scaleX = 0.18;
bullet.scaleY = 0.18;
bullets.push(bullet);
game.addChild(bullet);
}
} else if (player.weaponType === 'machinegun') {
// Machine gun fires rapid bullets
var bullet = new MachinegunBullet();
bullet.x = player.x;
bullet.y = player.y;
bullet.dx = dx / distance;
bullet.dy = dy / distance;
bullet.scaleX = 0.12;
bullet.scaleY = 0.12;
bullets.push(bullet);
game.addChild(bullet);
} else {
// Normal weapon
var bullet = new Bullet();
bullet.x = player.x;
bullet.y = player.y;
bullet.dx = dx / distance;
bullet.dy = dy / distance;
bullet.scaleX = 0.15;
bullet.scaleY = 0.15;
bullets.push(bullet);
game.addChild(bullet);
}
if (soundEnabled) LK.getSound('shoot').play();
}
}
game.down = function (x, y, obj) {
// Pause menu button clicks when paused
if (isPaused) {
// Restart button click
if (x >= 2048 / 2 - 150 && x <= 2048 / 2 + 150 && y >= 2732 / 2 - 130 && y <= 2732 / 2 - 30) {
hidePause();
restartGame();
return;
}
// Continue button click
if (x >= 2048 / 2 - 150 && x <= 2048 / 2 + 150 && y >= 2732 / 2 - 30 && y <= 2732 / 2 + 70) {
hidePause();
return;
}
// Market button click
if (x >= 2048 / 2 - 150 && x <= 2048 / 2 + 150 && y >= 2732 / 2 + 70 && y <= 2732 / 2 + 170) {
hidePause();
showMarket();
return;
}
return;
}
if (showingGameOver) {
// Market button click detection
if (x >= 2048 / 2 - 150 && x <= 2048 / 2 + 150 && y >= 2732 / 2 + 10 && y <= 2732 / 2 + 90) {
showMarket();
return;
}
// Restart button click detection
if (x >= 2048 / 2 - 150 && x <= 2048 / 2 + 150 && y >= 2732 / 2 + 110 && y <= 2732 / 2 + 190) {
restartGame();
return;
}
} else if (showingMarket) {
var currentCoins = storage.coins;
// Health upgrade button click
if (x >= 2048 / 2 - 300 && x <= 2048 / 2 + 300 && y >= 2732 / 2 - 200 && y <= 2732 / 2 - 100) {
if (storage.coins >= healthUpgradeCost) {
storage.coins -= healthUpgradeCost;
healthUpgradeCost = Math.floor(healthUpgradeCost * 1.5); // Increase cost by 50%
storage.healthUpgradeCost = healthUpgradeCost; // Save to storage
storage.healthUpgrades++;
player.maxHealth += 20;
player.health = Math.min(player.health + 20, player.maxHealth);
coinDisplay.setText('COIN: ' + storage.coins);
LK.getSound('coinPurchase').play();
hideMarket();
showMarket(); // Refresh market display
}
return;
}
// Ammo upgrade button click
if (x >= 2048 / 2 - 250 && x <= 2048 / 2 + 250 && y >= 2732 / 2 - 100 && y <= 2732 / 2 + 0) {
if (storage.coins >= ammoUpgradeCost) {
storage.coins -= ammoUpgradeCost;
ammoUpgradeCost = Math.floor(ammoUpgradeCost * 1.5); // Increase cost by 50%
storage.ammoUpgradeCost = ammoUpgradeCost; // Save to storage
storage.ammoUpgrades++;
player.maxAmmo += 10;
player.ammo = Math.min(player.ammo + 10, player.maxAmmo);
coinDisplay.setText('COIN: ' + storage.coins);
LK.getSound('coinPurchase').play();
hideMarket();
showMarket(); // Refresh market display
}
return;
}
// Speed upgrade button click
if (x >= 2048 / 2 - 275 && x <= 2048 / 2 + 275 && y >= 2732 / 2 + 0 && y <= 2732 / 2 + 100) {
if (storage.coins >= speedUpgradeCost) {
storage.coins -= speedUpgradeCost;
speedUpgradeCost = Math.floor(speedUpgradeCost * 1.5); // Increase cost by 50%
storage.speedUpgradeCost = speedUpgradeCost; // Save to storage
storage.speedUpgrades++;
player.baseShootCooldown = Math.max(1, player.baseShootCooldown - 1);
coinDisplay.setText('COIN: ' + storage.coins);
LK.getSound('coinPurchase').play();
hideMarket();
showMarket(); // Refresh market display
}
return;
}
// Shotgun weapon button click
if (x >= 2048 / 2 - 300 && x <= 2048 / 2 + 300 && y >= 2732 / 2 + 250 && y <= 2732 / 2 + 350) {
if (!storage.hasShotgun && storage.coins >= 500) {
storage.coins -= 500;
storage.hasShotgun = true;
player.weaponType = 'shotgun';
coinDisplay.setText('COIN: ' + storage.coins);
LK.getSound('coinPurchase').play();
hideMarket();
showMarket(); // Refresh market display
}
return;
}
// Machine gun weapon button click
if (x >= 2048 / 2 - 300 && x <= 2048 / 2 + 300 && y >= 2732 / 2 + 500 && y <= 2732 / 2 + 600) {
if (!storage.hasMachinegun && storage.coins >= 800) {
storage.coins -= 800;
storage.hasMachinegun = true;
player.weaponType = 'machinegun';
coinDisplay.setText('COIN: ' + storage.coins);
LK.getSound('coinPurchase').play();
hideMarket();
showMarket(); // Refresh market display
}
return;
}
// Close button click
if (x >= 2048 / 2 - 200 && x <= 2048 / 2 + 200 && y >= 2732 / 2 + 900 && y <= 2732 / 2 + 1000) {
hideMarket();
return;
}
} else {
shootBullet(x, y);
}
};
game.update = function () {
if (showingGameOver || showingMarket || isPaused) {
return;
}
spawnTimer++;
if (zombiesSpawned < zombiesInWave && spawnTimer >= 60) {
spawnZombie();
zombiesSpawned++;
spawnTimer = 0;
}
// Check if required zombies killed to progress wave
if (zombiesKilledInWave >= zombiesRequiredToKill) {
waveNumber++;
zombiesKilledInWave = 0;
// Calculate new required kills (25% more than previous wave)
zombiesRequiredToKill = Math.ceil(zombiesRequiredToKill * 1.25);
// Check if current wave is a boss wave (every 15th wave)
isBossWave = waveNumber % 15 === 0;
if (isBossWave) {
zombiesInWave = 1; // Only 1 boss zombie
} else {
zombiesInWave = Math.min(5 + waveNumber * 2, 20);
}
zombiesSpawned = 0;
}
// Check if boss has been killed and prevent further spawning
var bossKilled = false;
for (var i = 0; i < zombies.length; i++) {
if (zombies[i] instanceof BossZombie) {
bossKilled = false;
break;
}
}
if (isBossWave && zombiesSpawned > 0 && zombies.length === 0) {
// Boss was killed, don't spawn more zombies
return;
}
if (zombiesSpawned >= zombiesInWave && zombies.length === 0) {
// Keep spawning zombies until kill requirement is met
zombiesSpawned = 0;
}
// Check if player has no ammo and end game
if (player.ammo <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
showCustomGameOver();
return;
}
healthBar.setText('Health: ' + player.health);
ammoDisplay.setText('Ammo: ' + player.ammo);
scoreDisplay.setText('SCORE: ' + LK.getScore());
coinDisplay.setText('COIN: ' + storage.coins);
waveInfo.setText('Wave: ' + waveNumber + (isBossWave ? ' (BOSS)' : ''));
killProgress.setText('Kills: ' + zombiesKilledInWave + '/' + zombiesRequiredToKill);
weaponStatus.setText('Weapon: ' + (player.weaponType || 'Normal'));
for (var i = bullets.length - 1; i >= 0; i--) {
bullets[i].update();
}
for (var i = zombies.length - 1; i >= 0; i--) {
zombies[i].update();
}
};
// Sound toggle button
var soundButton = LK.getAsset('Tahta', {
width: 120,
height: 120,
anchorX: 1,
anchorY: 1,
x: 0,
y: -130
});
soundButton.alpha = 0.8;
LK.gui.bottomRight.addChild(soundButton);
var soundText = new Text2('🔊', {
size: 60,
fill: 0xFFFFFF
});
soundText.anchor.set(0.5, 0.5);
soundText.x = -60;
soundText.y = -190;
LK.gui.bottomRight.addChild(soundText);
var soundEnabled = true;
soundButton.down = function (x, y, obj) {
if (soundEnabled) {
soundText.setText('🔇');
soundText.alpha = 0.5;
soundEnabled = false;
} else {
soundText.setText('🔊');
soundText.alpha = 1.0;
soundEnabled = true;
}
};
// Music toggle button
var musicButton = LK.getAsset('Tahta', {
width: 120,
height: 120,
anchorX: 1,
anchorY: 1,
x: 0,
y: 0
});
musicButton.alpha = 0.8;
LK.gui.bottomRight.addChild(musicButton);
var musicText = new Text2('♪', {
size: 80,
fill: 0xFFFFFF
});
musicText.anchor.set(0.5, 0.5);
musicText.x = -60;
musicText.y = -60;
LK.gui.bottomRight.addChild(musicText);
var musicPlaying = true;
musicButton.down = function (x, y, obj) {
if (musicPlaying) {
LK.stopMusic();
musicText.setText('♪');
musicText.alpha = 0.5;
musicPlaying = false;
} else {
// Market quick access button
var marketQuickButton = LK.getAsset('Tahta', {
width: 120,
height: 120,
anchorX: 0.5,
anchorY: 1,
x: 0,
y: 0
});
marketQuickButton.alpha = 0.8;
LK.gui.bottom.addChild(marketQuickButton);
var marketQuickText = new Text2('🛒', {
size: 80,
fill: 0xFFFFFF
});
marketQuickText.anchor.set(0.5, 0.5);
marketQuickText.x = 0;
marketQuickText.y = -60;
LK.gui.bottom.addChild(marketQuickText);
marketQuickButton.down = function (x, y, obj) {
if (!showingGameOver && !showingMarket && !isPaused) {
showMarket();
}
};
// Surrender button in top-left corner next to pause shortcut
var surrenderButton = LK.getAsset('Tahta', {
width: 120,
height: 120,
anchorX: 0,
anchorY: 0,
x: 120,
y: 0
});
surrenderButton.alpha = 0.8;
LK.gui.topLeft.addChild(surrenderButton);
var surrenderText = new Text2('🏳️', {
size: 80,
fill: 0xFFFFFF
});
surrenderText.anchor.set(0.5, 0.5);
surrenderText.x = 60;
surrenderText.y = 60;
LK.gui.topLeft.addChild(surrenderText);
surrenderButton.down = function (x, y, obj) {
if (!showingGameOver && !showingMarket && !isPaused) {
player.ammo = 0;
LK.effects.flashScreen(0xff0000, 1000);
showCustomGameOver();
}
};
// Market button in top-right corner
var topMarketButton = LK.getAsset('Tahta', {
width: 120,
height: 120,
anchorX: 1,
anchorY: 0,
x: 0,
y: 0
});
topMarketButton.alpha = 0.8;
LK.gui.topRight.addChild(topMarketButton);
var topMarketText = new Text2('🛒', {
size: 80,
fill: 0xFFFFFF
});
topMarketText.anchor.set(0.5, 0.5);
topMarketText.x = -60;
topMarketText.y = 60;
LK.gui.topRight.addChild(topMarketText);
topMarketButton.down = function (x, y, obj) {
if (!showingGameOver && !showingMarket && !isPaused) {
showMarket();
}
};
// Bottom panel for game interface
var bottomPanel = new Container();
var bottomPanelBg = LK.getAsset('Tahta', {
width: 2048,
height: 300,
anchorX: 0.5,
anchorY: 1,
x: 2048 / 2,
y: 2732
});
bottomPanelBg.alpha = 0.9;
bottomPanelBg.tint = 0x2a2a2a;
bottomPanel.addChild(bottomPanelBg);
// Panel title
var panelTitle = new Text2('GAME CONTROLS', {
size: 80,
fill: 0xFFD700
});
panelTitle.anchor.set(0.5, 0);
panelTitle.x = 2048 / 2;
panelTitle.y = 2732 - 280;
bottomPanel.addChild(panelTitle);
// Ammo reload button
var reloadButton = LK.getAsset('Tahta', {
width: 200,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 - 120
});
reloadButton.alpha = 0.8;
reloadButton.tint = 0x4CAF50;
bottomPanel.addChild(reloadButton);
var reloadText = new Text2('RELOAD', {
size: 50,
fill: 0xFFFFFF
});
reloadText.anchor.set(0.5, 0.5);
reloadText.x = 2048 / 2;
reloadText.y = 2732 - 120;
bottomPanel.addChild(reloadText);
reloadButton.down = function (x, y, obj) {
if (!showingGameOver && !showingMarket && !isPaused) {
player.ammo = player.maxAmmo;
LK.effects.flashObject(reloadButton, 0x00ff00, 200);
}
};
// Quick market access
var quickMarketButton = LK.getAsset('Tahta', {
width: 200,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 + 400,
y: 2732 - 120
});
quickMarketButton.alpha = 0.8;
quickMarketButton.tint = 0x2196F3;
bottomPanel.addChild(quickMarketButton);
var quickMarketText = new Text2('MARKET', {
size: 50,
fill: 0xFFFFFF
});
quickMarketText.anchor.set(0.5, 0.5);
quickMarketText.x = 2048 / 2 + 400;
quickMarketText.y = 2732 - 120;
bottomPanel.addChild(quickMarketText);
quickMarketButton.down = function (x, y, obj) {
if (!showingGameOver && !showingMarket && !isPaused) {
showMarket();
}
};
// Weapon selection section title
var weaponSectionTitle = new Text2('WEAPON SELECTION', {
size: 50,
fill: 0xFFD700
});
weaponSectionTitle.anchor.set(0.5, 0);
weaponSectionTitle.x = 2048 / 2 - 600;
weaponSectionTitle.y = 2732 - 200;
bottomPanel.addChild(weaponSectionTitle);
// Add weapon status to bottom panel
weaponStatus.anchor.set(0.5, 0);
weaponStatus.x = 2048 / 2 - 400;
weaponStatus.y = 2732 - 200;
bottomPanel.addChild(weaponStatus);
// Normal weapon button
normalWeaponButton = LK.getAsset('weaponIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 - 800,
y: 2732 - 120
});
normalWeaponButton.tint = player.weaponType === 'normal' ? 0x4CAF50 : 0x666666;
bottomPanel.addChild(normalWeaponButton);
normalWeaponText = new Text2('🔫', {
size: 60,
fill: 0xFFFFFF
});
normalWeaponText.anchor.set(0.5, 0.5);
normalWeaponText.x = 2048 / 2 - 800;
normalWeaponText.y = 2732 - 120;
bottomPanel.addChild(normalWeaponText);
normalWeaponButton.down = function (x, y, obj) {
if (!showingGameOver && !showingMarket && !isPaused) {
player.weaponType = 'normal';
updateWeaponButtons();
}
};
// Define weapon button variables in global scope
var shotgunWeaponButton = null;
var shotgunWeaponText = null;
var machinegunWeaponButton = null;
var machinegunWeaponText = null;
var normalWeaponButton = null;
var normalWeaponText = null;
// Shotgun weapon button (only if purchased)
if (storage.hasShotgun) {
shotgunWeaponButton = LK.getAsset('weaponIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 - 650,
y: 2732 - 120
});
shotgunWeaponButton.tint = player.weaponType === 'shotgun' ? 0x4CAF50 : 0x666666;
bottomPanel.addChild(shotgunWeaponButton);
shotgunWeaponText = new Text2('🔫', {
size: 60,
fill: 0xFFAA00
});
shotgunWeaponText.anchor.set(0.5, 0.5);
shotgunWeaponText.x = 2048 / 2 - 650;
shotgunWeaponText.y = 2732 - 120;
bottomPanel.addChild(shotgunWeaponText);
shotgunWeaponButton.down = function (x, y, obj) {
if (!showingGameOver && !showingMarket && !isPaused) {
player.weaponType = 'shotgun';
updateWeaponButtons();
}
};
}
// Machine gun weapon button (only if purchased)
if (storage.hasMachinegun) {
machinegunWeaponButton = LK.getAsset('weaponIcon', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 - 500,
y: 2732 - 120
});
machinegunWeaponButton.tint = player.weaponType === 'machinegun' ? 0x4CAF50 : 0x666666;
bottomPanel.addChild(machinegunWeaponButton);
machinegunWeaponText = new Text2('🔫', {
size: 60,
fill: 0x00FF00
});
machinegunWeaponText.anchor.set(0.5, 0.5);
machinegunWeaponText.x = 2048 / 2 - 500;
machinegunWeaponText.y = 2732 - 120;
bottomPanel.addChild(machinegunWeaponText);
machinegunWeaponButton.down = function (x, y, obj) {
if (!showingGameOver && !showingMarket && !isPaused) {
player.weaponType = 'machinegun';
updateWeaponButtons();
}
};
}
var pauseButton = LK.getAsset('Tahta', {
width: 200,
height: 80,
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2 - 400,
y: 2732 - 120
});
pauseButton.alpha = 0.8;
pauseButton.tint = 0xFF9800;
bottomPanel.addChild(pauseButton);
var pauseText = new Text2('PAUSE', {
size: 50,
fill: 0xFFFFFF
});
pauseText.anchor.set(0.5, 0.5);
pauseText.x = 2048 / 2 - 400;
pauseText.y = 2732 - 120;
bottomPanel.addChild(pauseText);
pauseButton.down = function (x, y, obj) {
if (!showingGameOver && !showingMarket && !isPaused) {
showPause();
}
};
game.addChild(bottomPanel);
LK.playMusic('bgmusic');
musicText.setText('♪');
musicText.alpha = 1.0;
musicPlaying = true;
}
};
LK.playMusic('bgmusic'); ===================================================================
--- original.js
+++ change.js
@@ -109,8 +109,58 @@
self.destroy();
};
return self;
});
+var IceMonster = Container.expand(function () {
+ var self = Container.call(this);
+ var graphics = self.attachAsset('iceMonster', {
+ anchorX: 0.5,
+ anchorY: 0.5
+ });
+ graphics.tint = 0x87CEEB; // Light blue tint for ice effect
+ self.speed = 1.5 + Math.random() * 0.7; // Slightly faster than normal zombies
+ self.health = 2; // Higher health than normal zombies
+ self.damage = 15; // Higher damage than normal zombies
+ self.lastPlayerCollision = false;
+ self.update = function () {
+ var dx = player.x - self.x;
+ var dy = player.y - self.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance > 0) {
+ self.x += dx / distance * self.speed;
+ self.y += dy / distance * self.speed;
+ }
+ var currentCollision = self.intersects(player);
+ if (!self.lastPlayerCollision && currentCollision) {
+ player.takeDamage(self.damage);
+ // Ice monster dies from collision but doesn't give coins
+ self.health = 0;
+ LK.effects.flashObject(self, 0x87CEEB, 100);
+ var index = zombies.indexOf(self);
+ if (index > -1) {
+ zombies.splice(index, 1);
+ }
+ self.destroy();
+ }
+ self.lastPlayerCollision = currentCollision;
+ };
+ self.takeDamage = function (damage) {
+ self.health -= damage;
+ if (self.health <= 0) {
+ LK.effects.flashObject(self, 0x87CEEB, 100);
+ LK.setScore(LK.getScore() + 15);
+ storage.coins += 150;
+ zombiesKilledInWave++; // Track zombie kills
+ if (soundEnabled) LK.getSound('zombieHit').play();
+ var index = zombies.indexOf(self);
+ if (index > -1) {
+ zombies.splice(index, 1);
+ }
+ self.destroy();
+ }
+ };
+ return self;
+});
var MachinegunBullet = Container.expand(function () {
var self = Container.call(this);
var graphics = self.attachAsset('machinegunBullet', {
anchorX: 0.5,
@@ -402,8 +452,9 @@
var isBossWave = false;
var isFirstShot = true;
var zombiesKilledInWave = 0;
var zombiesRequiredToKill = 8;
+var isSecondMap = false; // Track which map we're on
// Upgrade costs that increase with each purchase - loaded from storage
var healthUpgradeCost = storage.healthUpgradeCost;
var ammoUpgradeCost = storage.ammoUpgradeCost;
var speedUpgradeCost = storage.speedUpgradeCost;
@@ -658,19 +709,19 @@
y: 2732 / 2 + 200
});
nextMapButton.tint = 0x4CAF50;
nextMapButton.down = function (x, y, obj) {
- // Switch to next map - change to forest map asset and restart
+ // Switch to next map - change to second map asset and restart
game.removeChild(arena);
- arena = game.attachAsset('forestMap', {
+ arena = game.attachAsset('secondMap', {
anchorX: 0.5,
anchorY: 0.5,
x: 2048 / 2,
y: 2732 / 2,
- scaleX: 0.15,
- scaleY: 0.15
+ scaleX: 1.0,
+ scaleY: 1.0
});
- arena.tint = 0x228B22; // Forest green color for new map
+ isSecondMap = true; // Set flag for second map
restartGame();
};
gameOverScreen.addChild(nextMapButton);
var nextMapText = new Text2('NEXT MAP', {
@@ -1360,15 +1411,30 @@
zombiesKilledInWave = 0;
zombiesRequiredToKill = 8;
isBossWave = false;
bossKilled = false;
+ // Reset to first map when restarting normally
+ if (!isSecondMap) {
+ game.removeChild(arena);
+ arena = game.attachAsset('arena', {
+ anchorX: 0.5,
+ anchorY: 0.5,
+ x: 2048 / 2,
+ y: 2732 / 2,
+ scaleX: 0.15,
+ scaleY: 0.15
+ });
+ }
LK.setScore(0);
}
function spawnZombie() {
var zombie;
// Check if this is a boss wave (every 15th wave)
if (isBossWave) {
zombie = new BossZombie();
+ } else if (isSecondMap) {
+ // On second map, spawn ice monsters instead of regular zombies
+ zombie = new IceMonster();
} else {
zombie = Math.random() < 0.5 ? new Zombie() : new Zombie2();
}
// Define spawn locations around the arena edges
Üstten görünümlü zombi. In-Game asset. 2d. High contrast. No shadows
Ortasında elips şeklinde bir boşluk hariç her yeri sık ağaçlık olan bir orman. In-Game asset. 2d. High contrast. No shadows
Ahşap tema. In-Game asset. 2d. High contrast. No shadows
pompalı tüfek mermisi. In-Game asset. 2d. High contrast. No shadows
hafif makineli tüfek mermisi. In-Game asset. 2d. High contrast. No shadows
Uzi çiz. In-Game asset. 2d. High contrast. No shadows
Pompalı Tüfek. In-Game asset. 2d. High contrast. No shadows
Bunun arkaplanını sil
Arkaplanını sil
boss zombie. In-Game asset. 2d. High contrast. No shadows
dümdüz sadece buzullardan oluşsun aralarında yarıklar olmasın