User prompt
bullet yerine sağ ve sol koks yumruklari atsin ama kırmızı daire içinde
User prompt
marketi sil
User prompt
oyunu durdurunca market menüsü gelsin coin ile silah alabileyim ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
zombie 4 farkli olsun resmini degistircem
User prompt
3.zombie farkli olsun resmini deistircem
User prompt
2. zombi farkli olsun resmini degistircem ona göre
User prompt
2. bir bomzie ekle
User prompt
her 10 mermiden 3 tanesi zombie direk öldürsün
User prompt
her 10 mermiden rast gele 2 tanesi zombie direk öldürsün
User prompt
her dalgada kaç tane zombie gelecegi gösterilsin
User prompt
zombi haraketleri kırmızı alanda ve dışındaki haraketleri yer değiştir ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
kırmızı alana girince zombiler direk saldınsınlar
User prompt
son mermi zombileri direk öldürmesin.
User prompt
zombiler playere düz bir şekilde gelmesin yapay zekalı şekilse gelsin ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
zombie kirmizi alansa 3 saniye dolaşsin tekrar öyle saldirsin playere ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
zombiler playerin canını azaltınca kırmızı alanın sınıra gitsin ve tam kırmızı alanın etrafında 1 ile 5 saniye aralıklarla rast gele dolaşsın sonra tekrar saldırsın. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
zombiler ama kirmizi alandan uzaklaşmasin
User prompt
zombiler player canini azaltip kirmizi alandan cikinca farkli bir yerden kirmizi alana girip tekrar canini azaltsin. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
zombiler player canını azaltinca kırmızı alandan çıkıp tekrar saldırsın. ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
zombilerin cani gozuksun
User prompt
health sadec player üstünde yazsin
User prompt
healht sadece player üstünde gözüksün
User prompt
zombie düşen kalp rengi kırmızı
User prompt
eğer canım 100 değilse %75 ihtimalle zombie can düşsün.
User prompt
%3 ihtimalle zombilerden coin yerine can düşsün ve alınca canım %10 yükselsin.
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.velocityX = 0;
self.velocityY = 0;
self.damage = 25;
self.isInstantKill = false;
self.update = function () {
self.x += self.velocityX;
self.y += self.velocityY;
// Remove if off screen
if (self.x < -50 || self.x > 2098 || self.y < -50 || self.y > 2782) {
var index = bullets.indexOf(self);
if (index !== -1) {
bullets.splice(index, 1);
}
self.destroy();
}
};
return self;
});
var Coin = Container.expand(function () {
var self = Container.call(this);
var coinGraphics = self.attachAsset('coin', {
anchorX: 0.5,
anchorY: 0.5
});
self.value = 10;
self.lastPlayerDistance = Infinity;
// Start small and grow when spawned
self.scaleX = 0.1;
self.scaleY = 0.1;
tween(self, {
scaleX: 1.75,
scaleY: 1.75
}, {
duration: 800,
easing: tween.bounceOut
});
self.update = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Collect coin if player is close
if (self.lastPlayerDistance > 40 && distance <= 40) {
player.coins += self.value;
LK.getSound('coin').play();
// Animate coin growing before collection
tween(self, {
scaleX: 2.8,
scaleY: 2.8,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
var index = coins.indexOf(self);
if (index !== -1) {
coins.splice(index, 1);
}
self.destroy();
}
});
}
self.lastPlayerDistance = distance;
};
return self;
});
var HealthDrop = Container.expand(function () {
var self = Container.call(this);
var healthDropGraphics = self.attachAsset('healthDrop', {
anchorX: 0.5,
anchorY: 0.5
});
// Tint the health drop red to look like a heart
healthDropGraphics.tint = 0xFF0000;
self.healAmount = 10; // 10% heal
self.lastPlayerDistance = Infinity;
// Start small and grow when spawned
self.scaleX = 0.1;
self.scaleY = 0.1;
tween(self, {
scaleX: 1.75,
scaleY: 1.75
}, {
duration: 800,
easing: tween.bounceOut
});
self.update = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Collect health drop if player is close
if (self.lastPlayerDistance > 40 && distance <= 40) {
// Heal player by 10% of max health
var healAmount = Math.floor(player.maxHealth * 0.1);
player.health = Math.min(player.maxHealth, player.health + healAmount);
if (player.healthText) {
player.healthText.setText(player.health.toString());
}
LK.getSound('coin').play();
// Animate health drop growing before collection
tween(self, {
scaleX: 2.8,
scaleY: 2.8,
alpha: 0
}, {
duration: 300,
easing: tween.easeOut,
onFinish: function onFinish() {
var index = healthDrops.indexOf(self);
if (index !== -1) {
healthDrops.splice(index, 1);
}
self.destroy();
}
});
}
self.lastPlayerDistance = distance;
};
return self;
});
var MarketUI = Container.expand(function () {
var self = Container.call(this);
// Market background
var background = LK.getAsset('centerCircle', {
width: 1800,
height: 2200,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x000000,
alpha: 0.9
});
self.addChild(background);
// Market title
var titleText = new Text2('WEAPON MARKET', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
titleText.x = 0;
titleText.y = -800;
self.addChild(titleText);
// Player coins display
var coinsDisplay = new Text2('Coins: 0', {
size: 60,
fill: 0xFFD700
});
coinsDisplay.anchor.set(0.5, 0.5);
coinsDisplay.x = 0;
coinsDisplay.y = -650;
self.addChild(coinsDisplay);
self.coinsDisplay = coinsDisplay;
// Weapon options
var weapons = [{
name: 'DAMAGE +10',
cost: 50,
type: 'damage'
}, {
name: 'RANGE +50',
cost: 75,
type: 'range'
}, {
name: 'ARMOR +5',
cost: 100,
type: 'armor'
}, {
name: 'MAX HEALTH +25',
cost: 150,
type: 'health'
}];
self.weaponButtons = [];
for (var i = 0; i < weapons.length; i++) {
var weapon = weapons[i];
var yPos = -300 + i * 200;
// Weapon button background
var buttonBg = LK.getAsset('centerCircle', {
width: 1400,
height: 150,
anchorX: 0.5,
anchorY: 0.5,
tint: 0x333333
});
buttonBg.x = 0;
buttonBg.y = yPos;
self.addChild(buttonBg);
// Weapon text
var weaponText = new Text2(weapon.name + ' - ' + weapon.cost + ' coins', {
size: 50,
fill: 0xFFFFFF
});
weaponText.anchor.set(0.5, 0.5);
weaponText.x = 0;
weaponText.y = yPos;
self.addChild(weaponText);
// Store button data
buttonBg.weaponData = weapon;
buttonBg.weaponText = weaponText;
self.weaponButtons.push(buttonBg);
}
// Close button
var closeButton = LK.getAsset('centerCircle', {
width: 300,
height: 150,
anchorX: 0.5,
anchorY: 0.5,
tint: 0xFF0000
});
closeButton.x = 0;
closeButton.y = 700;
self.addChild(closeButton);
var closeText = new Text2('CLOSE', {
size: 50,
fill: 0xFFFFFF
});
closeText.anchor.set(0.5, 0.5);
closeText.x = 0;
closeText.y = 700;
self.addChild(closeText);
self.closeButton = closeButton;
// Handle button clicks
self.down = function (x, y, obj) {
var localPos = self.toLocal({
x: x,
y: y
});
// Check weapon buttons
for (var i = 0; i < self.weaponButtons.length; i++) {
var button = self.weaponButtons[i];
var dx = localPos.x - button.x;
var dy = localPos.y - button.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance < 350) {
// Button hit area
self.buyWeapon(button.weaponData);
return;
}
}
// Check close button
var closeDx = localPos.x - closeButton.x;
var closeDy = localPos.y - closeButton.y;
var closeDistance = Math.sqrt(closeDx * closeDx + closeDy * closeDy);
if (closeDistance < 150) {
self.close();
}
};
self.buyWeapon = function (weapon) {
if (player.coins >= weapon.cost) {
player.coins -= weapon.cost;
// Apply weapon upgrade
switch (weapon.type) {
case 'damage':
player.damage += 10;
break;
case 'range':
player.range += 50;
// Update range circle
var rangeCircle = player.children[0];
if (rangeCircle) {
rangeCircle.width = player.range * 2;
rangeCircle.height = player.range * 2;
}
break;
case 'armor':
player.armor += 5;
break;
case 'health':
player.maxHealth += 25;
player.health = Math.min(player.maxHealth, player.health + 25);
if (player.healthText) {
player.healthText.setText(player.health.toString());
}
break;
}
// Save upgrades to storage
storage.playerUpgrades = {
damage: player.damage - 25,
// Base damage is 25
range: player.range - 375,
// Base range is 375
armor: player.armor,
// Base armor is 0
maxHealth: player.maxHealth - 100 // Base health is 100
};
storage.playerCoins = player.coins;
// Update coins display
self.updateDisplay();
// Visual feedback
LK.effects.flashScreen(0x00FF00, 300);
} else {
// Not enough coins - flash red
LK.effects.flashScreen(0xFF0000, 300);
}
};
self.updateDisplay = function () {
self.coinsDisplay.setText('Coins: ' + player.coins);
// Update button colors based on affordability
for (var i = 0; i < self.weaponButtons.length; i++) {
var button = self.weaponButtons[i];
var weapon = button.weaponData;
if (player.coins >= weapon.cost) {
button.tint = 0x006600; // Green if affordable
button.weaponText.fill = 0xFFFFFF;
} else {
button.tint = 0x660000; // Red if not affordable
button.weaponText.fill = 0x888888;
}
}
};
self.close = function () {
marketUI.visible = false;
gameIsPaused = false;
};
return self;
});
// Game arrays
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.speed = 5;
self.damage = 25;
self.armor = 0;
self.coins = 0;
self.shootCooldown = 0;
self.range = 375;
// Create range circle
var rangeCircle = self.attachAsset('rangeCircle', {
anchorX: 0.5,
anchorY: 0.5,
alpha: 0.2
});
rangeCircle.width = self.range * 2;
rangeCircle.height = self.range * 2;
// Create health text above player
var healthText = new Text2(self.health.toString(), {
size: 60,
fill: 0x00FF00
});
healthText.anchor.set(0.5, 1);
healthText.x = 0;
healthText.y = -100;
self.addChild(healthText);
self.healthText = healthText;
self.update = function () {
if (self.shootCooldown > 0) {
self.shootCooldown--;
}
};
self.takeDamage = function (damage) {
var actualDamage = Math.max(1, damage - self.armor);
self.health -= actualDamage;
if (self.healthText) {
self.healthText.setText(Math.max(0, self.health).toString());
}
if (self.health <= 0) {
self.health = 0;
LK.showGameOver();
}
};
self.shoot = function (targetX, targetY) {
if (self.shootCooldown > 0 || bulletCount <= 0 || isReloading) return;
var dx = targetX - self.x;
var dy = targetY - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Check if target is within range
if (distance > self.range) return;
var bullet = new Bullet();
bullet.x = self.x;
bullet.y = self.y;
bullet.velocityX = dx / distance * 15;
bullet.velocityY = dy / distance * 15;
bullet.damage = self.damage;
// Track bullets fired and assign instant kill property
bulletsFired++;
if (bulletsFired % 10 === 1) {
// Every 10 bullets, randomly select 3 positions for instant kills
instantKillBullets = [];
var positions = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
for (var k = 0; k < 3; k++) {
var randomIndex = Math.floor(Math.random() * positions.length);
instantKillBullets.push(positions[randomIndex]);
positions.splice(randomIndex, 1);
}
}
// Check if this bullet should be instant kill
var currentBulletPosition = (bulletsFired - 1) % 10 + 1;
bullet.isInstantKill = instantKillBullets.indexOf(currentBulletPosition) !== -1;
bullets.push(bullet);
game.addChild(bullet);
LK.getSound('shoot').play();
self.shootCooldown = 10;
bulletCount--;
// Start reloading if out of bullets
if (bulletCount <= 0) {
isReloading = true;
reloadTimer = 180; // 3 seconds at 60fps
}
};
return self;
});
var Zombie = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 100;
self.maxHealth = 100;
self.speed = 2;
self.damage = 20;
self.coinValue = 10;
self.lastPlayerDistance = Infinity;
self.isPatrolling = false;
self.patrolTimer = 0;
self.patrolDuration = 0;
self.targetX = 0;
self.targetY = 0;
self.waypoints = [];
self.currentWaypointIndex = 0;
self.pathUpdateTimer = 0;
self.lastPlayerX = 0;
self.lastPlayerY = 0;
// Create health text above zombie
var healthText = new Text2(self.health.toString(), {
size: 40,
fill: 0xFF0000
});
healthText.anchor.set(0.5, 1);
healthText.x = 0;
healthText.y = -80;
self.addChild(healthText);
self.healthText = healthText;
self.update = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Check if zombie is inside red area (player range)
var insideRedArea = distance <= player.range;
// If zombie enters red area while patrolling, stop patrolling and attack
if (self.isPatrolling && insideRedArea) {
self.isPatrolling = false;
}
if (insideRedArea) {
// Inside red area - use AI pathfinding behavior
self.pathUpdateTimer++;
// Update path every 30 frames (0.5 seconds) or if player moved significantly
var playerMoved = Math.abs(player.x - self.lastPlayerX) > 50 || Math.abs(player.y - self.lastPlayerY) > 50;
if (self.pathUpdateTimer >= 30 || playerMoved || self.waypoints.length === 0) {
self.pathUpdateTimer = 0;
self.lastPlayerX = player.x;
self.lastPlayerY = player.y;
// Generate waypoints for AI movement
self.waypoints = [];
self.currentWaypointIndex = 0;
// Create 2-4 waypoints between zombie and player
var waypointCount = Math.floor(Math.random() * 3) + 2; // 2-4 waypoints
var stepX = (player.x - self.x) / (waypointCount + 1);
var stepY = (player.y - self.y) / (waypointCount + 1);
for (var w = 1; w <= waypointCount; w++) {
var baseX = self.x + stepX * w;
var baseY = self.y + stepY * w;
// Add random offset to create non-linear path
var offsetRange = 150;
var offsetX = (Math.random() - 0.5) * offsetRange;
var offsetY = (Math.random() - 0.5) * offsetRange;
var waypointX = Math.max(50, Math.min(1998, baseX + offsetX));
var waypointY = Math.max(50, Math.min(2682, baseY + offsetY));
self.waypoints.push({
x: waypointX,
y: waypointY
});
}
// Add final waypoint near player
self.waypoints.push({
x: player.x,
y: player.y
});
}
// Move towards current waypoint
if (self.waypoints.length > 0 && self.currentWaypointIndex < self.waypoints.length) {
var currentWaypoint = self.waypoints[self.currentWaypointIndex];
var waypointDx = currentWaypoint.x - self.x;
var waypointDy = currentWaypoint.y - self.y;
var waypointDistance = Math.sqrt(waypointDx * waypointDx + waypointDy * waypointDy);
if (waypointDistance > 20) {
// Move towards waypoint with slight speed variation for more natural movement
var speedVariation = 0.8 + Math.random() * 0.4; // 0.8 to 1.2 speed multiplier
self.x += waypointDx / waypointDistance * self.speed * speedVariation;
self.y += waypointDy / waypointDistance * self.speed * speedVariation;
} else {
// Reached waypoint, move to next one
self.currentWaypointIndex++;
}
} else {
// Fallback to direct movement if no waypoints
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
} else if (self.isPatrolling) {
// Outside red area - use patrol behavior
// Move towards target patrol position
var targetDx = self.targetX - self.x;
var targetDy = self.targetY - self.y;
var targetDistance = Math.sqrt(targetDx * targetDx + targetDy * targetDy);
if (targetDistance > 5) {
self.x += targetDx / targetDistance * self.speed;
self.y += targetDy / targetDistance * self.speed;
}
// Update patrol duration
self.patrolDuration--;
if (self.patrolDuration <= 0) {
self.isPatrolling = false;
} else {
// Update patrol timer for position changes
self.patrolTimer--;
if (self.patrolTimer <= 0) {
// Choose new patrol position around red area border
var angle = Math.random() * Math.PI * 2;
var radius = player.range + 20; // Just outside red area
self.targetX = player.x + Math.cos(angle) * radius;
self.targetY = player.y + Math.sin(angle) * radius;
// Keep patrol position within screen bounds
self.targetX = Math.max(50, Math.min(1998, self.targetX));
self.targetY = Math.max(50, Math.min(2682, self.targetY));
// Set new patrol timer (1-5 seconds)
self.patrolTimer = Math.floor(Math.random() * 240) + 60; // 60-300 frames (1-5 seconds)
}
}
} else {
// Outside red area and not patrolling - direct movement towards player
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
// Check collision with player
if (self.lastPlayerDistance > 30 && distance <= 30 && !self.isPatrolling) {
player.takeDamage(self.damage);
LK.getSound('hit').play();
// Add visual feedback with tween
tween(self, {
alpha: 0.5
}, {
duration: 200
});
tween(self, {
alpha: 1
}, {
duration: 200,
onFinish: function onFinish() {}
});
// Start patrolling after damaging player
self.isPatrolling = true;
self.patrolDuration = 180; // 3 seconds at 60 FPS
var angle = Math.random() * Math.PI * 2;
var radius = player.range + 20; // Just outside red area
self.targetX = player.x + Math.cos(angle) * radius;
self.targetY = player.y + Math.sin(angle) * radius;
// Keep patrol position within screen bounds
self.targetX = Math.max(50, Math.min(1998, self.targetX));
self.targetY = Math.max(50, Math.min(2682, self.targetY));
// Set patrol timer (1-5 seconds)
self.patrolTimer = Math.floor(Math.random() * 240) + 60; // 60-300 frames (1-5 seconds)
}
self.lastPlayerDistance = distance;
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.healthText) {
self.healthText.setText(Math.max(0, self.health).toString());
}
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
// If player health is not 100, 75% chance to drop health, otherwise drop coin
// If player health is 100, 3% chance to drop health, otherwise drop coin
var healthDropChance = player.health < 100 ? 0.75 : 0.03;
if (Math.random() < healthDropChance) {
var healthDrop = new HealthDrop();
healthDrop.x = self.x;
healthDrop.y = self.y;
healthDrops.push(healthDrop);
game.addChild(healthDrop);
} else {
var coin = new Coin();
coin.x = self.x;
coin.y = self.y;
coin.value = self.coinValue;
coins.push(coin);
game.addChild(coin);
}
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 zombieGraphics = self.attachAsset('zombie2', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 150; // More health than regular zombie
self.maxHealth = 150;
self.speed = 3; // Faster than regular zombie
self.damage = 30; // More damage than regular zombie
self.coinValue = 15; // More coins when killed
self.lastPlayerDistance = Infinity;
self.isPatrolling = false;
self.patrolTimer = 0;
self.patrolDuration = 0;
self.targetX = 0;
self.targetY = 0;
self.waypoints = [];
self.currentWaypointIndex = 0;
self.pathUpdateTimer = 0;
self.lastPlayerX = 0;
self.lastPlayerY = 0;
// Create health text above zombie (orange to match stronger zombie)
var healthText = new Text2(self.health.toString(), {
size: 40,
fill: 0xFF8800
});
healthText.anchor.set(0.5, 1);
healthText.x = 0;
healthText.y = -80;
self.addChild(healthText);
self.healthText = healthText;
self.update = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Check if zombie is inside red area (player range)
var insideRedArea = distance <= player.range;
// If zombie enters red area while patrolling, stop patrolling and attack
if (self.isPatrolling && insideRedArea) {
self.isPatrolling = false;
}
if (insideRedArea) {
// Inside red area - use AI pathfinding behavior
self.pathUpdateTimer++;
// Update path every 30 frames (0.5 seconds) or if player moved significantly
var playerMoved = Math.abs(player.x - self.lastPlayerX) > 50 || Math.abs(player.y - self.lastPlayerY) > 50;
if (self.pathUpdateTimer >= 30 || playerMoved || self.waypoints.length === 0) {
self.pathUpdateTimer = 0;
self.lastPlayerX = player.x;
self.lastPlayerY = player.y;
// Generate waypoints for AI movement
self.waypoints = [];
self.currentWaypointIndex = 0;
// Create 2-4 waypoints between zombie and player
var waypointCount = Math.floor(Math.random() * 3) + 2; // 2-4 waypoints
var stepX = (player.x - self.x) / (waypointCount + 1);
var stepY = (player.y - self.y) / (waypointCount + 1);
for (var w = 1; w <= waypointCount; w++) {
var baseX = self.x + stepX * w;
var baseY = self.y + stepY * w;
// Add random offset to create non-linear path
var offsetRange = 150;
var offsetX = (Math.random() - 0.5) * offsetRange;
var offsetY = (Math.random() - 0.5) * offsetRange;
var waypointX = Math.max(50, Math.min(1998, baseX + offsetX));
var waypointY = Math.max(50, Math.min(2682, baseY + offsetY));
self.waypoints.push({
x: waypointX,
y: waypointY
});
}
// Add final waypoint near player
self.waypoints.push({
x: player.x,
y: player.y
});
}
// Move towards current waypoint
if (self.waypoints.length > 0 && self.currentWaypointIndex < self.waypoints.length) {
var currentWaypoint = self.waypoints[self.currentWaypointIndex];
var waypointDx = currentWaypoint.x - self.x;
var waypointDy = currentWaypoint.y - self.y;
var waypointDistance = Math.sqrt(waypointDx * waypointDx + waypointDy * waypointDy);
if (waypointDistance > 20) {
// Move towards waypoint with slight speed variation for more natural movement
var speedVariation = 0.8 + Math.random() * 0.4; // 0.8 to 1.2 speed multiplier
self.x += waypointDx / waypointDistance * self.speed * speedVariation;
self.y += waypointDy / waypointDistance * self.speed * speedVariation;
} else {
// Reached waypoint, move to next one
self.currentWaypointIndex++;
}
} else {
// Fallback to direct movement if no waypoints
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
} else if (self.isPatrolling) {
// Outside red area - use patrol behavior
// Move towards target patrol position
var targetDx = self.targetX - self.x;
var targetDy = self.targetY - self.y;
var targetDistance = Math.sqrt(targetDx * targetDx + targetDy * targetDy);
if (targetDistance > 5) {
self.x += targetDx / targetDistance * self.speed;
self.y += targetDy / targetDistance * self.speed;
}
// Update patrol duration
self.patrolDuration--;
if (self.patrolDuration <= 0) {
self.isPatrolling = false;
} else {
// Update patrol timer for position changes
self.patrolTimer--;
if (self.patrolTimer <= 0) {
// Choose new patrol position around red area border
var angle = Math.random() * Math.PI * 2;
var radius = player.range + 20; // Just outside red area
self.targetX = player.x + Math.cos(angle) * radius;
self.targetY = player.y + Math.sin(angle) * radius;
// Keep patrol position within screen bounds
self.targetX = Math.max(50, Math.min(1998, self.targetX));
self.targetY = Math.max(50, Math.min(2682, self.targetY));
// Set new patrol timer (1-5 seconds)
self.patrolTimer = Math.floor(Math.random() * 240) + 60; // 60-300 frames (1-5 seconds)
}
}
} else {
// Outside red area and not patrolling - direct movement towards player
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
// Check collision with player
if (self.lastPlayerDistance > 30 && distance <= 30 && !self.isPatrolling) {
player.takeDamage(self.damage);
LK.getSound('hit').play();
// Add visual feedback with tween
tween(self, {
alpha: 0.5
}, {
duration: 200
});
tween(self, {
alpha: 1
}, {
duration: 200,
onFinish: function onFinish() {}
});
// Start patrolling after damaging player
self.isPatrolling = true;
self.patrolDuration = 180; // 3 seconds at 60 FPS
var angle = Math.random() * Math.PI * 2;
var radius = player.range + 20; // Just outside red area
self.targetX = player.x + Math.cos(angle) * radius;
self.targetY = player.y + Math.sin(angle) * radius;
// Keep patrol position within screen bounds
self.targetX = Math.max(50, Math.min(1998, self.targetX));
self.targetY = Math.max(50, Math.min(2682, self.targetY));
// Set patrol timer (1-5 seconds)
self.patrolTimer = Math.floor(Math.random() * 240) + 60; // 60-300 frames (1-5 seconds)
}
self.lastPlayerDistance = distance;
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.healthText) {
self.healthText.setText(Math.max(0, self.health).toString());
}
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
// If player health is not 100, 75% chance to drop health, otherwise drop coin
// If player health is 100, 3% chance to drop health, otherwise drop coin
var healthDropChance = player.health < 100 ? 0.75 : 0.03;
if (Math.random() < healthDropChance) {
var healthDrop = new HealthDrop();
healthDrop.x = self.x;
healthDrop.y = self.y;
healthDrops.push(healthDrop);
game.addChild(healthDrop);
} else {
var coin = new Coin();
coin.x = self.x;
coin.y = self.y;
coin.value = self.coinValue;
coins.push(coin);
game.addChild(coin);
}
var index = zombies.indexOf(self);
if (index !== -1) {
zombies.splice(index, 1);
}
self.destroy();
};
return self;
});
var Zombie3 = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie3', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 200; // Even more health than zombie2
self.maxHealth = 200;
self.speed = 4; // Fastest zombie
self.damage = 40; // Highest damage
self.coinValue = 25; // Most coins when killed
self.lastPlayerDistance = Infinity;
self.isPatrolling = false;
self.patrolTimer = 0;
self.patrolDuration = 0;
self.targetX = 0;
self.targetY = 0;
self.waypoints = [];
self.currentWaypointIndex = 0;
self.pathUpdateTimer = 0;
self.lastPlayerX = 0;
self.lastPlayerY = 0;
// Create health text above zombie (purple to match strongest zombie)
var healthText = new Text2(self.health.toString(), {
size: 40,
fill: 0xFF00FF
});
healthText.anchor.set(0.5, 1);
healthText.x = 0;
healthText.y = -80;
self.addChild(healthText);
self.healthText = healthText;
self.update = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Check if zombie is inside red area (player range)
var insideRedArea = distance <= player.range;
// If zombie enters red area while patrolling, stop patrolling and attack
if (self.isPatrolling && insideRedArea) {
self.isPatrolling = false;
}
if (insideRedArea) {
// Inside red area - use AI pathfinding behavior
self.pathUpdateTimer++;
// Update path every 30 frames (0.5 seconds) or if player moved significantly
var playerMoved = Math.abs(player.x - self.lastPlayerX) > 50 || Math.abs(player.y - self.lastPlayerY) > 50;
if (self.pathUpdateTimer >= 30 || playerMoved || self.waypoints.length === 0) {
self.pathUpdateTimer = 0;
self.lastPlayerX = player.x;
self.lastPlayerY = player.y;
// Generate waypoints for AI movement
self.waypoints = [];
self.currentWaypointIndex = 0;
// Create 2-4 waypoints between zombie and player
var waypointCount = Math.floor(Math.random() * 3) + 2; // 2-4 waypoints
var stepX = (player.x - self.x) / (waypointCount + 1);
var stepY = (player.y - self.y) / (waypointCount + 1);
for (var w = 1; w <= waypointCount; w++) {
var baseX = self.x + stepX * w;
var baseY = self.y + stepY * w;
// Add random offset to create non-linear path
var offsetRange = 150;
var offsetX = (Math.random() - 0.5) * offsetRange;
var offsetY = (Math.random() - 0.5) * offsetRange;
var waypointX = Math.max(50, Math.min(1998, baseX + offsetX));
var waypointY = Math.max(50, Math.min(2682, baseY + offsetY));
self.waypoints.push({
x: waypointX,
y: waypointY
});
}
// Add final waypoint near player
self.waypoints.push({
x: player.x,
y: player.y
});
}
// Move towards current waypoint
if (self.waypoints.length > 0 && self.currentWaypointIndex < self.waypoints.length) {
var currentWaypoint = self.waypoints[self.currentWaypointIndex];
var waypointDx = currentWaypoint.x - self.x;
var waypointDy = currentWaypoint.y - self.y;
var waypointDistance = Math.sqrt(waypointDx * waypointDx + waypointDy * waypointDy);
if (waypointDistance > 20) {
// Move towards waypoint with slight speed variation for more natural movement
var speedVariation = 0.8 + Math.random() * 0.4; // 0.8 to 1.2 speed multiplier
self.x += waypointDx / waypointDistance * self.speed * speedVariation;
self.y += waypointDy / waypointDistance * self.speed * speedVariation;
} else {
// Reached waypoint, move to next one
self.currentWaypointIndex++;
}
} else {
// Fallback to direct movement if no waypoints
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
} else if (self.isPatrolling) {
// Outside red area - use patrol behavior
// Move towards target patrol position
var targetDx = self.targetX - self.x;
var targetDy = self.targetY - self.y;
var targetDistance = Math.sqrt(targetDx * targetDx + targetDy * targetDy);
if (targetDistance > 5) {
self.x += targetDx / targetDistance * self.speed;
self.y += targetDy / targetDistance * self.speed;
}
// Update patrol duration
self.patrolDuration--;
if (self.patrolDuration <= 0) {
self.isPatrolling = false;
} else {
// Update patrol timer for position changes
self.patrolTimer--;
if (self.patrolTimer <= 0) {
// Choose new patrol position around red area border
var angle = Math.random() * Math.PI * 2;
var radius = player.range + 20; // Just outside red area
self.targetX = player.x + Math.cos(angle) * radius;
self.targetY = player.y + Math.sin(angle) * radius;
// Keep patrol position within screen bounds
self.targetX = Math.max(50, Math.min(1998, self.targetX));
self.targetY = Math.max(50, Math.min(2682, self.targetY));
// Set new patrol timer (1-5 seconds)
self.patrolTimer = Math.floor(Math.random() * 240) + 60; // 60-300 frames (1-5 seconds)
}
}
} else {
// Outside red area and not patrolling - direct movement towards player
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
// Check collision with player
if (self.lastPlayerDistance > 30 && distance <= 30 && !self.isPatrolling) {
player.takeDamage(self.damage);
LK.getSound('hit').play();
// Add visual feedback with tween
tween(self, {
alpha: 0.5
}, {
duration: 200
});
tween(self, {
alpha: 1
}, {
duration: 200,
onFinish: function onFinish() {}
});
// Start patrolling after damaging player
self.isPatrolling = true;
self.patrolDuration = 180; // 3 seconds at 60 FPS
var angle = Math.random() * Math.PI * 2;
var radius = player.range + 20; // Just outside red area
self.targetX = player.x + Math.cos(angle) * radius;
self.targetY = player.y + Math.sin(angle) * radius;
// Keep patrol position within screen bounds
self.targetX = Math.max(50, Math.min(1998, self.targetX));
self.targetY = Math.max(50, Math.min(2682, self.targetY));
// Set patrol timer (1-5 seconds)
self.patrolTimer = Math.floor(Math.random() * 240) + 60; // 60-300 frames (1-5 seconds)
}
self.lastPlayerDistance = distance;
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.healthText) {
self.healthText.setText(Math.max(0, self.health).toString());
}
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
// If player health is not 100, 75% chance to drop health, otherwise drop coin
// If player health is 100, 3% chance to drop health, otherwise drop coin
var healthDropChance = player.health < 100 ? 0.75 : 0.03;
if (Math.random() < healthDropChance) {
var healthDrop = new HealthDrop();
healthDrop.x = self.x;
healthDrop.y = self.y;
healthDrops.push(healthDrop);
game.addChild(healthDrop);
} else {
var coin = new Coin();
coin.x = self.x;
coin.y = self.y;
coin.value = self.coinValue;
coins.push(coin);
game.addChild(coin);
}
var index = zombies.indexOf(self);
if (index !== -1) {
zombies.splice(index, 1);
}
self.destroy();
};
return self;
});
var Zombie4 = Container.expand(function () {
var self = Container.call(this);
var zombieGraphics = self.attachAsset('zombie4', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 250; // Highest health
self.maxHealth = 250;
self.speed = 5; // Very fast
self.damage = 50; // Highest damage
self.coinValue = 35; // Most coins when killed
self.lastPlayerDistance = Infinity;
self.isPatrolling = false;
self.patrolTimer = 0;
self.patrolDuration = 0;
self.targetX = 0;
self.targetY = 0;
self.waypoints = [];
self.currentWaypointIndex = 0;
self.pathUpdateTimer = 0;
self.lastPlayerX = 0;
self.lastPlayerY = 0;
// Create health text above zombie (cyan to match elite zombie)
var healthText = new Text2(self.health.toString(), {
size: 40,
fill: 0x00FFFF
});
healthText.anchor.set(0.5, 1);
healthText.x = 0;
healthText.y = -80;
self.addChild(healthText);
self.healthText = healthText;
self.update = function () {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
// Check if zombie is inside red area (player range)
var insideRedArea = distance <= player.range;
// If zombie enters red area while patrolling, stop patrolling and attack
if (self.isPatrolling && insideRedArea) {
self.isPatrolling = false;
}
if (insideRedArea) {
// Inside red area - use AI pathfinding behavior
self.pathUpdateTimer++;
// Update path every 30 frames (0.5 seconds) or if player moved significantly
var playerMoved = Math.abs(player.x - self.lastPlayerX) > 50 || Math.abs(player.y - self.lastPlayerY) > 50;
if (self.pathUpdateTimer >= 30 || playerMoved || self.waypoints.length === 0) {
self.pathUpdateTimer = 0;
self.lastPlayerX = player.x;
self.lastPlayerY = player.y;
// Generate waypoints for AI movement
self.waypoints = [];
self.currentWaypointIndex = 0;
// Create 2-4 waypoints between zombie and player
var waypointCount = Math.floor(Math.random() * 3) + 2; // 2-4 waypoints
var stepX = (player.x - self.x) / (waypointCount + 1);
var stepY = (player.y - self.y) / (waypointCount + 1);
for (var w = 1; w <= waypointCount; w++) {
var baseX = self.x + stepX * w;
var baseY = self.y + stepY * w;
// Add random offset to create non-linear path
var offsetRange = 150;
var offsetX = (Math.random() - 0.5) * offsetRange;
var offsetY = (Math.random() - 0.5) * offsetRange;
var waypointX = Math.max(50, Math.min(1998, baseX + offsetX));
var waypointY = Math.max(50, Math.min(2682, baseY + offsetY));
self.waypoints.push({
x: waypointX,
y: waypointY
});
}
// Add final waypoint near player
self.waypoints.push({
x: player.x,
y: player.y
});
}
// Move towards current waypoint
if (self.waypoints.length > 0 && self.currentWaypointIndex < self.waypoints.length) {
var currentWaypoint = self.waypoints[self.currentWaypointIndex];
var waypointDx = currentWaypoint.x - self.x;
var waypointDy = currentWaypoint.y - self.y;
var waypointDistance = Math.sqrt(waypointDx * waypointDx + waypointDy * waypointDy);
if (waypointDistance > 20) {
// Move towards waypoint with slight speed variation for more natural movement
var speedVariation = 0.8 + Math.random() * 0.4; // 0.8 to 1.2 speed multiplier
self.x += waypointDx / waypointDistance * self.speed * speedVariation;
self.y += waypointDy / waypointDistance * self.speed * speedVariation;
} else {
// Reached waypoint, move to next one
self.currentWaypointIndex++;
}
} else {
// Fallback to direct movement if no waypoints
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
} else if (self.isPatrolling) {
// Outside red area - use patrol behavior
// Move towards target patrol position
var targetDx = self.targetX - self.x;
var targetDy = self.targetY - self.y;
var targetDistance = Math.sqrt(targetDx * targetDx + targetDy * targetDy);
if (targetDistance > 5) {
self.x += targetDx / targetDistance * self.speed;
self.y += targetDy / targetDistance * self.speed;
}
// Update patrol duration
self.patrolDuration--;
if (self.patrolDuration <= 0) {
self.isPatrolling = false;
} else {
// Update patrol timer for position changes
self.patrolTimer--;
if (self.patrolTimer <= 0) {
// Choose new patrol position around red area border
var angle = Math.random() * Math.PI * 2;
var radius = player.range + 20; // Just outside red area
self.targetX = player.x + Math.cos(angle) * radius;
self.targetY = player.y + Math.sin(angle) * radius;
// Keep patrol position within screen bounds
self.targetX = Math.max(50, Math.min(1998, self.targetX));
self.targetY = Math.max(50, Math.min(2682, self.targetY));
// Set new patrol timer (1-5 seconds)
self.patrolTimer = Math.floor(Math.random() * 240) + 60; // 60-300 frames (1-5 seconds)
}
}
} else {
// Outside red area and not patrolling - direct movement towards player
if (distance > 5) {
self.x += dx / distance * self.speed;
self.y += dy / distance * self.speed;
}
}
// Check collision with player
if (self.lastPlayerDistance > 30 && distance <= 30 && !self.isPatrolling) {
player.takeDamage(self.damage);
LK.getSound('hit').play();
// Add visual feedback with tween
tween(self, {
alpha: 0.5
}, {
duration: 200
});
tween(self, {
alpha: 1
}, {
duration: 200,
onFinish: function onFinish() {}
});
// Start patrolling after damaging player
self.isPatrolling = true;
self.patrolDuration = 180; // 3 seconds at 60 FPS
var angle = Math.random() * Math.PI * 2;
var radius = player.range + 20; // Just outside red area
self.targetX = player.x + Math.cos(angle) * radius;
self.targetY = player.y + Math.sin(angle) * radius;
// Keep patrol position within screen bounds
self.targetX = Math.max(50, Math.min(1998, self.targetX));
self.targetY = Math.max(50, Math.min(2682, self.targetY));
// Set patrol timer (1-5 seconds)
self.patrolTimer = Math.floor(Math.random() * 240) + 60; // 60-300 frames (1-5 seconds)
}
self.lastPlayerDistance = distance;
};
self.takeDamage = function (damage) {
self.health -= damage;
if (self.healthText) {
self.healthText.setText(Math.max(0, self.health).toString());
}
if (self.health <= 0) {
self.die();
}
};
self.die = function () {
// If player health is not 100, 75% chance to drop health, otherwise drop coin
// If player health is 100, 3% chance to drop health, otherwise drop coin
var healthDropChance = player.health < 100 ? 0.75 : 0.03;
if (Math.random() < healthDropChance) {
var healthDrop = new HealthDrop();
healthDrop.x = self.x;
healthDrop.y = self.y;
healthDrops.push(healthDrop);
game.addChild(healthDrop);
} else {
var coin = new Coin();
coin.x = self.x;
coin.y = self.y;
coin.value = self.coinValue;
coins.push(coin);
game.addChild(coin);
}
var index = zombies.indexOf(self);
if (index !== -1) {
zombies.splice(index, 1);
}
self.destroy();
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2a2a2a
});
/****
* Game Code
****/
// Game state
var gameStarted = false;
var gameIsPaused = false;
var marketUI = null;
var bulletCount = 10;
var maxBullets = 10;
var isReloading = false;
var reloadTimer = 0;
var fireButtonActive = false;
var bulletsFired = 0;
var instantKillBullets = [];
// Start menu elements
var titleText = new Text2('ZOMBIE SURVIVAL', {
size: 80,
fill: 0xFFFFFF
});
titleText.anchor.set(0.5, 0.5);
LK.gui.center.addChild(titleText);
titleText.y = -200;
var playButton = new Text2('TAP TO START', {
size: 60,
fill: 0x00FF00
});
playButton.anchor.set(0.5, 0.5);
LK.gui.center.addChild(playButton);
playButton.y = 100;
// Game arrays
var zombies = [];
var bullets = [];
var coins = [];
var healthDrops = [];
// Game variables
var waveNumber = 1;
var zombiesPerWave = 5;
var spawnTimer = 0;
var zombiesSpawned = 0;
// Player variable (will be created when game starts)
var player = null;
// UI Elements (will be created when game starts)
var healthText = null;
var coinsText = null;
var waveText = null;
var bulletText = null;
function startGame() {
gameStarted = true;
// Hide start menu
titleText.visible = false;
playButton.visible = false;
// Create player
player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
// Load saved upgrades and coins from storage
var savedUpgrades = storage.playerUpgrades || {
damage: 0,
range: 0,
armor: 0,
maxHealth: 0
};
var savedCoins = storage.playerCoins || 0;
// Apply saved upgrades
player.damage += savedUpgrades.damage;
player.range += savedUpgrades.range;
player.armor += savedUpgrades.armor;
player.maxHealth += savedUpgrades.maxHealth;
player.health = player.maxHealth; // Start with full health
player.coins = savedCoins;
// Update range circle if range was upgraded
var rangeCircle = player.children[0];
if (rangeCircle && savedUpgrades.range > 0) {
rangeCircle.width = player.range * 2;
rangeCircle.height = player.range * 2;
}
// Update health text
if (player.healthText) {
player.healthText.setText(player.health.toString());
}
// Create market UI
marketUI = new MarketUI();
marketUI.x = 1024;
marketUI.y = 1366;
marketUI.visible = false;
game.addChild(marketUI);
// Create UI Elements
healthText = new Text2('Health: 100/100', {
size: 40,
fill: 0xFF0000
});
healthText.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthText);
healthText.x = 120;
healthText.y = 20;
coinsText = new Text2('Coins: 0', {
size: 40,
fill: 0xFFD700
});
coinsText.anchor.set(0, 0);
LK.gui.topRight.addChild(coinsText);
coinsText.x = -200;
coinsText.y = 20;
waveText = new Text2('Wave: 1 (5 zombies)', {
size: 40,
fill: 0xFFFFFF
});
waveText.anchor.set(0.5, 0);
LK.gui.top.addChild(waveText);
waveText.y = 20;
bulletText = new Text2('', {
size: 40,
fill: 0x00FFFF
});
bulletText.anchor.set(0.5, 0);
player.addChild(bulletText);
bulletText.x = 0;
bulletText.y = 120;
// Create pause/market button
var pauseButton = new Text2('MARKET', {
size: 50,
fill: 0xFFD700
});
pauseButton.anchor.set(1, 0);
LK.gui.topRight.addChild(pauseButton);
pauseButton.x = -20;
pauseButton.y = 80;
}
// Touch controls
var touchStartX = 0;
var touchStartY = 0;
var isMoving = false;
game.down = function (x, y, obj) {
if (!gameStarted) {
startGame();
return;
}
// Check if market button was clicked
if (gameStarted && !gameIsPaused) {
var guiPos = LK.gui.topRight.toLocal({
x: x,
y: y
});
if (guiPos.x >= -270 && guiPos.x <= -20 && guiPos.y >= 80 && guiPos.y <= 130) {
// Open market
gameIsPaused = true;
marketUI.visible = true;
marketUI.updateDisplay();
return;
}
}
// If market is open, let market handle the click
if (gameIsPaused && marketUI.visible) {
return;
}
touchStartX = x;
touchStartY = y;
isMoving = true;
// Shoot at nearest zombie or forward if no zombies
if (player && bulletCount > 0 && !isReloading) {
// Find nearest zombie within range as target
var nearestZombie = null;
var minDistance = Infinity;
for (var i = 0; i < zombies.length; i++) {
var zombie = zombies[i];
var dx = zombie.x - player.x;
var dy = zombie.y - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance <= player.range && distance < minDistance) {
minDistance = distance;
nearestZombie = zombie;
}
}
// Shoot at nearest zombie within range only
if (nearestZombie) {
player.shoot(nearestZombie.x, nearestZombie.y);
}
}
};
game.move = function (x, y, obj) {
if (!gameStarted || !player || gameIsPaused) return;
if (isMoving) {
var dx = x - touchStartX;
var dy = y - touchStartY;
var newX = player.x + dx * 0.5;
var newY = player.y + dy * 0.5;
// Keep player within bounds
player.x = Math.max(30, Math.min(2018, newX));
player.y = Math.max(30, Math.min(2702, newY));
touchStartX = x;
touchStartY = y;
}
};
game.up = function (x, y, obj) {
if (!gameStarted) return;
if (gameIsPaused) return;
isMoving = false;
};
// Game update loop
game.update = function () {
if (!gameStarted || !player || gameIsPaused) return;
// Handle reloading
if (isReloading) {
reloadTimer--;
if (reloadTimer <= 0) {
bulletCount = maxBullets;
isReloading = false;
}
}
// Update UI
if (healthText && coinsText && waveText && bulletText) {
healthText.setText('Health: ' + player.health + '/' + player.maxHealth);
coinsText.setText('Coins: ' + player.coins);
var remainingZombies = zombiesPerWave - zombiesSpawned + zombies.length;
waveText.setText('Wave: ' + waveNumber + ' (' + remainingZombies + ' zombies)');
if (isReloading) {
var reloadTimeLeft = Math.ceil(reloadTimer / 60);
bulletText.setText('Reloading... ' + reloadTimeLeft + 's');
} else {
bulletText.setText('Bullets: ' + bulletCount + '/' + maxBullets);
}
}
// Spawn zombies
if (zombiesSpawned < zombiesPerWave) {
spawnTimer++;
if (spawnTimer >= 60) {
// Spawn every second
spawnTimer = 0;
spawnZombie();
zombiesSpawned++;
}
} else if (zombies.length === 0) {
// Start next wave
waveNumber++;
zombiesPerWave += 2;
zombiesSpawned = 0;
}
// Check bullet-zombie collisions
for (var i = bullets.length - 1; i >= 0; i--) {
var bullet = bullets[i];
var bulletHit = false;
for (var j = zombies.length - 1; j >= 0; j--) {
var zombie = zombies[j];
if (bullet.intersects(zombie)) {
if (bullet.isInstantKill) {
// Instant kill bullet
zombie.takeDamage(zombie.health);
} else {
// Random damage between 1 and zombie's current health (can kill in one shot)
var randomDamage = Math.floor(Math.random() * zombie.health) + 1;
zombie.takeDamage(randomDamage);
}
bullets.splice(i, 1);
bullet.destroy();
bulletHit = true;
break;
}
}
}
};
function spawnZombie() {
// Randomly spawn zombies with different probabilities
var rand = Math.random();
var zombie;
if (rand < 0.15) {
// 15% chance for zombie4 (elite)
zombie = new Zombie4();
} else if (rand < 0.35) {
// 20% chance for zombie3 (strongest)
zombie = new Zombie3();
} else if (rand < 0.65) {
// 30% chance for zombie2 (medium strength)
zombie = new Zombie2();
} else {
// 35% chance for regular zombie (weakest)
zombie = new Zombie();
}
// Spawn at random edge of screen
var side = Math.floor(Math.random() * 4);
switch (side) {
case 0:
// Top
zombie.x = Math.random() * 2048;
zombie.y = -50;
break;
case 1:
// Right
zombie.x = 2098;
zombie.y = Math.random() * 2732;
break;
case 2:
// Bottom
zombie.x = Math.random() * 2048;
zombie.y = 2782;
break;
case 3:
// Left
zombie.x = -50;
zombie.y = Math.random() * 2732;
break;
}
zombie.health += (waveNumber - 1) * 10; // Increase health with waves
zombie.maxHealth = zombie.health;
zombie.coinValue += Math.floor((waveNumber - 1) * 2);
// Update health text to show new health value
if (zombie.healthText) {
zombie.healthText.setText(zombie.health.toString());
}
zombies.push(zombie);
game.addChild(zombie);
} ===================================================================
--- original.js
+++ change.js
@@ -1,8 +1,9 @@
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
+var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
@@ -130,8 +131,201 @@
self.lastPlayerDistance = distance;
};
return self;
});
+var MarketUI = Container.expand(function () {
+ var self = Container.call(this);
+ // Market background
+ var background = LK.getAsset('centerCircle', {
+ width: 1800,
+ height: 2200,
+ anchorX: 0.5,
+ anchorY: 0.5,
+ tint: 0x000000,
+ alpha: 0.9
+ });
+ self.addChild(background);
+ // Market title
+ var titleText = new Text2('WEAPON MARKET', {
+ size: 80,
+ fill: 0xFFFFFF
+ });
+ titleText.anchor.set(0.5, 0.5);
+ titleText.x = 0;
+ titleText.y = -800;
+ self.addChild(titleText);
+ // Player coins display
+ var coinsDisplay = new Text2('Coins: 0', {
+ size: 60,
+ fill: 0xFFD700
+ });
+ coinsDisplay.anchor.set(0.5, 0.5);
+ coinsDisplay.x = 0;
+ coinsDisplay.y = -650;
+ self.addChild(coinsDisplay);
+ self.coinsDisplay = coinsDisplay;
+ // Weapon options
+ var weapons = [{
+ name: 'DAMAGE +10',
+ cost: 50,
+ type: 'damage'
+ }, {
+ name: 'RANGE +50',
+ cost: 75,
+ type: 'range'
+ }, {
+ name: 'ARMOR +5',
+ cost: 100,
+ type: 'armor'
+ }, {
+ name: 'MAX HEALTH +25',
+ cost: 150,
+ type: 'health'
+ }];
+ self.weaponButtons = [];
+ for (var i = 0; i < weapons.length; i++) {
+ var weapon = weapons[i];
+ var yPos = -300 + i * 200;
+ // Weapon button background
+ var buttonBg = LK.getAsset('centerCircle', {
+ width: 1400,
+ height: 150,
+ anchorX: 0.5,
+ anchorY: 0.5,
+ tint: 0x333333
+ });
+ buttonBg.x = 0;
+ buttonBg.y = yPos;
+ self.addChild(buttonBg);
+ // Weapon text
+ var weaponText = new Text2(weapon.name + ' - ' + weapon.cost + ' coins', {
+ size: 50,
+ fill: 0xFFFFFF
+ });
+ weaponText.anchor.set(0.5, 0.5);
+ weaponText.x = 0;
+ weaponText.y = yPos;
+ self.addChild(weaponText);
+ // Store button data
+ buttonBg.weaponData = weapon;
+ buttonBg.weaponText = weaponText;
+ self.weaponButtons.push(buttonBg);
+ }
+ // Close button
+ var closeButton = LK.getAsset('centerCircle', {
+ width: 300,
+ height: 150,
+ anchorX: 0.5,
+ anchorY: 0.5,
+ tint: 0xFF0000
+ });
+ closeButton.x = 0;
+ closeButton.y = 700;
+ self.addChild(closeButton);
+ var closeText = new Text2('CLOSE', {
+ size: 50,
+ fill: 0xFFFFFF
+ });
+ closeText.anchor.set(0.5, 0.5);
+ closeText.x = 0;
+ closeText.y = 700;
+ self.addChild(closeText);
+ self.closeButton = closeButton;
+ // Handle button clicks
+ self.down = function (x, y, obj) {
+ var localPos = self.toLocal({
+ x: x,
+ y: y
+ });
+ // Check weapon buttons
+ for (var i = 0; i < self.weaponButtons.length; i++) {
+ var button = self.weaponButtons[i];
+ var dx = localPos.x - button.x;
+ var dy = localPos.y - button.y;
+ var distance = Math.sqrt(dx * dx + dy * dy);
+ if (distance < 350) {
+ // Button hit area
+ self.buyWeapon(button.weaponData);
+ return;
+ }
+ }
+ // Check close button
+ var closeDx = localPos.x - closeButton.x;
+ var closeDy = localPos.y - closeButton.y;
+ var closeDistance = Math.sqrt(closeDx * closeDx + closeDy * closeDy);
+ if (closeDistance < 150) {
+ self.close();
+ }
+ };
+ self.buyWeapon = function (weapon) {
+ if (player.coins >= weapon.cost) {
+ player.coins -= weapon.cost;
+ // Apply weapon upgrade
+ switch (weapon.type) {
+ case 'damage':
+ player.damage += 10;
+ break;
+ case 'range':
+ player.range += 50;
+ // Update range circle
+ var rangeCircle = player.children[0];
+ if (rangeCircle) {
+ rangeCircle.width = player.range * 2;
+ rangeCircle.height = player.range * 2;
+ }
+ break;
+ case 'armor':
+ player.armor += 5;
+ break;
+ case 'health':
+ player.maxHealth += 25;
+ player.health = Math.min(player.maxHealth, player.health + 25);
+ if (player.healthText) {
+ player.healthText.setText(player.health.toString());
+ }
+ break;
+ }
+ // Save upgrades to storage
+ storage.playerUpgrades = {
+ damage: player.damage - 25,
+ // Base damage is 25
+ range: player.range - 375,
+ // Base range is 375
+ armor: player.armor,
+ // Base armor is 0
+ maxHealth: player.maxHealth - 100 // Base health is 100
+ };
+ storage.playerCoins = player.coins;
+ // Update coins display
+ self.updateDisplay();
+ // Visual feedback
+ LK.effects.flashScreen(0x00FF00, 300);
+ } else {
+ // Not enough coins - flash red
+ LK.effects.flashScreen(0xFF0000, 300);
+ }
+ };
+ self.updateDisplay = function () {
+ self.coinsDisplay.setText('Coins: ' + player.coins);
+ // Update button colors based on affordability
+ for (var i = 0; i < self.weaponButtons.length; i++) {
+ var button = self.weaponButtons[i];
+ var weapon = button.weaponData;
+ if (player.coins >= weapon.cost) {
+ button.tint = 0x006600; // Green if affordable
+ button.weaponText.fill = 0xFFFFFF;
+ } else {
+ button.tint = 0x660000; // Red if not affordable
+ button.weaponText.fill = 0x888888;
+ }
+ }
+ };
+ self.close = function () {
+ marketUI.visible = false;
+ gameIsPaused = false;
+ };
+ return self;
+});
// Game arrays
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
@@ -1045,8 +1239,10 @@
* Game Code
****/
// Game state
var gameStarted = false;
+var gameIsPaused = false;
+var marketUI = null;
var bulletCount = 10;
var maxBullets = 10;
var isReloading = false;
var reloadTimer = 0;
@@ -1093,8 +1289,39 @@
// Create player
player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
+ // Load saved upgrades and coins from storage
+ var savedUpgrades = storage.playerUpgrades || {
+ damage: 0,
+ range: 0,
+ armor: 0,
+ maxHealth: 0
+ };
+ var savedCoins = storage.playerCoins || 0;
+ // Apply saved upgrades
+ player.damage += savedUpgrades.damage;
+ player.range += savedUpgrades.range;
+ player.armor += savedUpgrades.armor;
+ player.maxHealth += savedUpgrades.maxHealth;
+ player.health = player.maxHealth; // Start with full health
+ player.coins = savedCoins;
+ // Update range circle if range was upgraded
+ var rangeCircle = player.children[0];
+ if (rangeCircle && savedUpgrades.range > 0) {
+ rangeCircle.width = player.range * 2;
+ rangeCircle.height = player.range * 2;
+ }
+ // Update health text
+ if (player.healthText) {
+ player.healthText.setText(player.health.toString());
+ }
+ // Create market UI
+ marketUI = new MarketUI();
+ marketUI.x = 1024;
+ marketUI.y = 1366;
+ marketUI.visible = false;
+ game.addChild(marketUI);
// Create UI Elements
healthText = new Text2('Health: 100/100', {
size: 40,
fill: 0xFF0000
@@ -1125,8 +1352,17 @@
bulletText.anchor.set(0.5, 0);
player.addChild(bulletText);
bulletText.x = 0;
bulletText.y = 120;
+ // Create pause/market button
+ var pauseButton = new Text2('MARKET', {
+ size: 50,
+ fill: 0xFFD700
+ });
+ pauseButton.anchor.set(1, 0);
+ LK.gui.topRight.addChild(pauseButton);
+ pauseButton.x = -20;
+ pauseButton.y = 80;
}
// Touch controls
var touchStartX = 0;
var touchStartY = 0;
@@ -1135,8 +1371,26 @@
if (!gameStarted) {
startGame();
return;
}
+ // Check if market button was clicked
+ if (gameStarted && !gameIsPaused) {
+ var guiPos = LK.gui.topRight.toLocal({
+ x: x,
+ y: y
+ });
+ if (guiPos.x >= -270 && guiPos.x <= -20 && guiPos.y >= 80 && guiPos.y <= 130) {
+ // Open market
+ gameIsPaused = true;
+ marketUI.visible = true;
+ marketUI.updateDisplay();
+ return;
+ }
+ }
+ // If market is open, let market handle the click
+ if (gameIsPaused && marketUI.visible) {
+ return;
+ }
touchStartX = x;
touchStartY = y;
isMoving = true;
// Shoot at nearest zombie or forward if no zombies
@@ -1160,9 +1414,9 @@
}
}
};
game.move = function (x, y, obj) {
- if (!gameStarted || !player) return;
+ if (!gameStarted || !player || gameIsPaused) return;
if (isMoving) {
var dx = x - touchStartX;
var dy = y - touchStartY;
var newX = player.x + dx * 0.5;
@@ -1175,13 +1429,14 @@
}
};
game.up = function (x, y, obj) {
if (!gameStarted) return;
+ if (gameIsPaused) return;
isMoving = false;
};
// Game update loop
game.update = function () {
- if (!gameStarted || !player) return;
+ if (!gameStarted || !player || gameIsPaused) return;
// Handle reloading
if (isReloading) {
reloadTimer--;
if (reloadTimer <= 0) {
bitcoin sembollü sarı eski madeni para. In-Game asset. 2d. High contrast. No shadows
kırmızı kalp. In-Game asset. 2d. High contrast. No shadows
kadın zombi. In-Game asset. 2d. High contrast. No shadows
daire kırmıza alan. In-Game asset. 2d. High contrast. No shadows
boss zombie şişko. In-Game asset. 2d. High contrast. No shadows
boss zombie şişko kadın makyajlı. In-Game asset. 2d. High contrast. No shadows
tek yumruk boks eldiveni. In-Game asset. 2d. High contrast. No shadows
şakaci komik yüzlü salak gözüken ama cesur bir karakter pistol tutuyor.
boss zombi çok kaslı akıllı ve silahlı sinirli kızgın ve ten rengi kırmızı. In-Game asset. 2d. High contrast. No shadows