/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); /**** * Classes ****/ // Bullet class var Bullet = Container.expand(function () { var self = Container.call(this); var bulletSprite = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.radius = bulletSprite.width / 2; self.vx = 0; self.vy = 0; self.speed = 38; self.update = function () { self.x += self.vx * self.speed; self.y += self.vy * self.speed; }; return self; }); // EnemyBullet class var EnemyBullet = Container.expand(function () { var self = Container.call(this); var bulletSprite = self.attachAsset('bullet', { anchorX: 0.5, anchorY: 0.5 }); self.radius = bulletSprite.width / 2; self.vx = 0; self.vy = 0; self.speed = 8; // Slower enemy bullet speed self.update = function () { self.x += self.vx * self.speed; self.y += self.vy * self.speed; }; return self; }); // Helper to spawn an enemy bullet var GunZombie = Container.expand(function () { var self = Container.call(this); self.zombieSprite = self.attachAsset('gunzombie', { // Use new gunzombie sprite anchorX: 0.5, anchorY: 0.5 }); self.radius = self.zombieSprite.width / 2; self.speed = 1.2 + Math.random() * 0.7; self.vx = 0; self.vy = 0; self.target = null; self.hp = 2; // Give GunZombie 2 HP self.fireCooldown = 120 + Math.floor(Math.random() * 60); // Slower: 2x slower than before self.fireTimer = Math.floor(Math.random() * 60); // randomize first shot self.update = function () { // Move like a normal zombie if (!self.target) return; var dx = self.target.x - self.x; var dy = self.target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.vx = dx / dist * self.speed; self.vy = dy / dist * self.speed; self.x += self.vx; self.y += self.vy; // Rotate zombie sprite to face movement direction if (typeof self.zombieSprite !== "undefined") { self.zombieSprite.rotation = Math.atan2(self.vy, self.vx); } else if (self.children && self.children.length > 0 && typeof self.children[0].rotation !== "undefined") { self.children[0].rotation = Math.atan2(self.vy, self.vx); } } // Shooting logic self.fireTimer++; if (self.fireTimer >= self.fireCooldown) { self.fireTimer = 0; // Only shoot if player is within 1200px if (dist < 1200) { spawnEnemyBullet(self.x, self.y, dx, dy); } } }; return self; }); // Heart class for health powerup var Heart = Container.expand(function () { var self = Container.call(this); var heartSprite = self.attachAsset('heart', { anchorX: 0.5, anchorY: 0.5 }); self.radius = heartSprite.width / 2; self.update = function () { // Could animate or float, but static for now }; return self; }); // Player class var Player = Container.expand(function () { var self = Container.call(this); var playerSprite = self.attachAsset('player', { anchorX: 0.5, anchorY: 0.5 }); self.radius = playerSprite.width / 2; self.speed = 16; // Max speed per frame self.vx = 0; self.vy = 0; self.hp = 5; self.invincible = false; // For hit flash self.flash = function () { if (self.invincible) return; self.invincible = true; tween(playerSprite, { tint: 0xff4444 }, { duration: 100, onFinish: function onFinish() { tween(playerSprite, { tint: 0x3498db }, { duration: 200, onFinish: function onFinish() { self.invincible = false; } }); } }); }; // Ensure playerSprite follows self.rotation self.update = function () { playerSprite.rotation = self.rotation || 0; }; return self; }); // Zombie class var Zombie = Container.expand(function () { var self = Container.call(this); var zombieSprite = self.attachAsset('zombie', { anchorX: 0.5, anchorY: 0.5 }); self.radius = zombieSprite.width / 2; self.speed = 1.2 + Math.random() * 0.7; // Slower zombies self.vx = 0; self.vy = 0; self.target = null; // Player self.update = function () { if (!self.target) return; var dx = self.target.x - self.x; var dy = self.target.y - self.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 0) { self.vx = dx / dist * self.speed; self.vy = dy / dist * self.speed; self.x += self.vx; self.y += self.vy; // Rotate zombie sprite to face movement direction zombieSprite.rotation = Math.atan2(self.vy, self.vx); } }; return self; }); /**** * Initialize Game ****/ var game = new LK.Game({ backgroundColor: 0x222222 }); /**** * Game Code ****/ // Helper to spawn an enemy bullet // Joystick knob // Joystick base // Bullet // Zombie // Character (player) // Game variables function spawnEnemyBullet(x, y, dx, dy) { var len = Math.sqrt(dx * dx + dy * dy); if (len < 0.1) return; var b = new EnemyBullet(); b.x = x; b.y = y; b.vx = dx / len; b.vy = dy / len; b.rotation = Math.atan2(dy, dx); enemyBullets.push(b); game.addChild(b); } var player; var zombies = []; var bullets = []; var enemyBullets = []; // NEW: enemy bullets array var score = 0; var scoreTxt; var hpTxt; var spawnTimer = 0; var spawnInterval = 90; // Frames between zombie spawns var lastFireTick = 0; var fireCooldown = 12; // Frames between shots // Create player player = new Player(); player.x = 2048 / 2; player.y = 2732 * 0.7; game.addChild(player); // Set initial target move position to player start game._targetMovePos = { x: player.x, y: player.y }; // Score text scoreTxt = new Text2('0', { size: 110, fill: "#fff" }); scoreTxt.anchor.set(0.5, 0); LK.gui.top.addChild(scoreTxt); // HP text hpTxt = new Text2('❤❤❤', { size: 90, fill: 0xFF4444 }); hpTxt.anchor.set(1, 0); LK.gui.topRight.addChild(hpTxt); // Helper: update HP display function updateHpTxt() { var s = ''; for (var i = 0; i < player.hp; ++i) s += '❤'; hpTxt.setText(s); } // Helper: update score display function updateScoreTxt() { scoreTxt.setText(score); } // Helper: spawn a zombie at a random edge function spawnZombie() { // Only spawn GunZombie (with 2 HP) or normal Zombie var z; if (score > 0 && score % 5 === 0) { z = new GunZombie(); } else if (Math.random() < 0.15) { z = new GunZombie(); } else { z = new Zombie(); } // Pick a random edge: 0=top, 1=bottom, 2=left, 3=right var edge = Math.floor(Math.random() * 4); var margin = 80; if (edge === 0) { // Top z.x = margin + Math.random() * (2048 - 2 * margin); z.y = -z.radius - 10; } else if (edge === 1) { // Bottom z.x = margin + Math.random() * (2048 - 2 * margin); z.y = 2732 + z.radius + 10; } else if (edge === 2) { // Left z.x = -z.radius - 10; z.y = margin + Math.random() * (2732 - 2 * margin); } else { // Right z.x = 2048 + z.radius + 10; z.y = margin + Math.random() * (2732 - 2 * margin); } z.target = player; zombies.push(z); game.addChild(z); } // Helper: fire a bullet towards a direction function fireBullet(dirX, dirY) { var len = Math.sqrt(dirX * dirX + dirY * dirY); if (len < 0.1) return; var b = new Bullet(); b.x = player.x; b.y = player.y; b.vx = dirX / len; b.vy = dirY / len; b.rotation = Math.atan2(dirY, dirX); bullets.push(b); game.addChild(b); // Rotate player to face the direction of the fired bullet player.rotation = Math.atan2(dirY, dirX); } // Game event handling game.down = function (x, y, obj) { var now = LK.ticks; if (now - lastFireTick >= fireCooldown) { fireBullet(x - player.x, y - player.y); lastFireTick = now; } // Always rotate player to face the direction of the click/touch var dx = x - player.x; var dy = y - player.y; if (Math.abs(dx) > 0.01 || Math.abs(dy) > 0.01) { player.rotation = Math.atan2(dy, dx); } }; game.move = function (x, y, obj) { // Always update target move position to follow pointer if (typeof game._targetMovePos === "undefined") { game._targetMovePos = { x: player.x, y: player.y }; } game._targetMovePos.x = x; game._targetMovePos.y = y; }; game.up = function (x, y, obj) { // No joystick logic needed }; // Main game update game.update = function () { // Player movement follows last pointer position if (typeof game._targetMovePos === "undefined") { game._targetMovePos = { x: player.x, y: player.y }; } var tx = game._targetMovePos.x; var ty = game._targetMovePos.y; var dx = tx - player.x; var dy = ty - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist > 2) { var moveDist = Math.min(player.speed, dist); player.x += dx / dist * moveDist; player.y += dy / dist * moveDist; // Clamp to arena var r = player.radius + 10; if (player.x < r) player.x = r; if (player.x > 2048 - r) player.x = 2048 - r; if (player.y < r) player.y = r; if (player.y > 2732 - r) player.y = 2732 - r; } // Always rotate player to face pointer direction if (dist > 2) { player.rotation = Math.atan2(dy, dx); } // Spawn zombies spawnTimer++; if (spawnTimer >= spawnInterval) { spawnZombie(); spawnTimer = 0; // Gradually increase spawn rate if (spawnInterval > 30) spawnInterval -= 1; } // Update zombies for (var i = zombies.length - 1; i >= 0; --i) { var z = zombies[i]; z.update(); // Remove if off screen (failsafe) if (z.x < -200 || z.x > 2248 || z.y < -200 || z.y > 2932) { z.destroy(); zombies.splice(i, 1); } } // Update bullets for (var i = bullets.length - 1; i >= 0; --i) { var b = bullets[i]; b.update(); // Remove if off screen if (b.x < -100 || b.x > 2148 || b.y < -100 || b.y > 2832) { b.destroy(); bullets.splice(i, 1); continue; } } // Update enemy bullets for (var i = enemyBullets.length - 1; i >= 0; --i) { var eb = enemyBullets[i]; eb.update(); // Remove if off screen if (eb.x < -100 || eb.x > 2148 || eb.y < -100 || eb.y > 2832) { eb.destroy(); enemyBullets.splice(i, 1); continue; } // Check collision with player var dx = eb.x - player.x; var dy = eb.y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < eb.radius + player.radius - 10) { if (!player.invincible) { player.hp -= 1; updateHpTxt(); player.flash(); if (player.hp <= 0) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } else if (player.hp === 1 && typeof heartSpawned === "undefined") { // Spawn hearts at random locations when HP drops to 1 heartSpawned = true; if (typeof hearts === "undefined") hearts = []; for (var h = 0; h < 3; ++h) { var heart = new Heart(); // Avoid spawning too close to player or outside arena var safe = false; var hx, hy; while (!safe) { hx = 150 + Math.random() * (2048 - 300); hy = 150 + Math.random() * (2732 - 300); var pdx = hx - player.x; var pdy = hy - player.y; if (Math.sqrt(pdx * pdx + pdy * pdy) > 400) safe = true; } heart.x = hx; heart.y = hy; hearts.push(heart); game.addChild(heart); } } } eb.destroy(); enemyBullets.splice(i, 1); continue; } } // Bullet-zombie collisions for (var i = bullets.length - 1; i >= 0; --i) { var b = bullets[i]; for (var j = zombies.length - 1; j >= 0; --j) { var z = zombies[j]; var dx = b.x - z.x; var dy = b.y - z.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < b.radius + z.radius - 10) { // Hit! var isGunZombie = typeof z.hp === "number" && z.hp > 0; if (isGunZombie) { z.hp -= 1; b.destroy(); bullets.splice(i, 1); if (z.hp <= 0) { z.destroy(); zombies.splice(j, 1); score += 1; updateScoreTxt(); } } else { z.destroy(); zombies.splice(j, 1); b.destroy(); bullets.splice(i, 1); score += 1; updateScoreTxt(); } break; } } } // Zombie-player collisions for (var i = zombies.length - 1; i >= 0; --i) { var z = zombies[i]; var dx = z.x - player.x; var dy = z.y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < z.radius + player.radius - 10) { if (!player.invincible) { player.hp -= 1; updateHpTxt(); player.flash(); if (player.hp <= 0) { LK.effects.flashScreen(0xff0000, 1000); LK.showGameOver(); return; } } // Push zombie away var pushDist = z.radius + player.radius - dist + 10; if (pushDist > 0) { var px = dx / dist * pushDist; var py = dy / dist * pushDist; z.x += px; z.y += py; } } } // Heart pickup logic if (typeof hearts !== "undefined" && hearts.length > 0) { for (var i = hearts.length - 1; i >= 0; --i) { var heart = hearts[i]; var dx = heart.x - player.x; var dy = heart.y - player.y; var dist = Math.sqrt(dx * dx + dy * dy); if (dist < heart.radius + player.radius - 10) { // Picked up heart: restore HP to full player.hp = 5; updateHpTxt(); // Remove all hearts for (var j = hearts.length - 1; j >= 0; --j) { hearts[j].destroy(); } hearts = []; heartSpawned = undefined; break; } } } }; // Initial UI update updateScoreTxt(); updateHpTxt(); // Timer to spawn a heart at the center area every 5 seconds if (typeof centerHeartTimer === "undefined") { centerHeartTimer = LK.setInterval(function () { if (typeof hearts === "undefined") hearts = []; // Spawn a heart at a random position near the center (±200px) var heart = new Heart(); var centerX = 2048 / 2; var centerY = 2732 / 2; var hx = centerX - 200 + Math.random() * 400; var hy = centerY - 200 + Math.random() * 400; heart.x = hx; heart.y = hy; hearts.push(heart); game.addChild(heart); }, 5000); }
/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
/****
* Classes
****/
// Bullet class
var Bullet = Container.expand(function () {
var self = Container.call(this);
var bulletSprite = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = bulletSprite.width / 2;
self.vx = 0;
self.vy = 0;
self.speed = 38;
self.update = function () {
self.x += self.vx * self.speed;
self.y += self.vy * self.speed;
};
return self;
});
// EnemyBullet class
var EnemyBullet = Container.expand(function () {
var self = Container.call(this);
var bulletSprite = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = bulletSprite.width / 2;
self.vx = 0;
self.vy = 0;
self.speed = 8; // Slower enemy bullet speed
self.update = function () {
self.x += self.vx * self.speed;
self.y += self.vy * self.speed;
};
return self;
});
// Helper to spawn an enemy bullet
var GunZombie = Container.expand(function () {
var self = Container.call(this);
self.zombieSprite = self.attachAsset('gunzombie', {
// Use new gunzombie sprite
anchorX: 0.5,
anchorY: 0.5
});
self.radius = self.zombieSprite.width / 2;
self.speed = 1.2 + Math.random() * 0.7;
self.vx = 0;
self.vy = 0;
self.target = null;
self.hp = 2; // Give GunZombie 2 HP
self.fireCooldown = 120 + Math.floor(Math.random() * 60); // Slower: 2x slower than before
self.fireTimer = Math.floor(Math.random() * 60); // randomize first shot
self.update = function () {
// Move like a normal zombie
if (!self.target) return;
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
self.vx = dx / dist * self.speed;
self.vy = dy / dist * self.speed;
self.x += self.vx;
self.y += self.vy;
// Rotate zombie sprite to face movement direction
if (typeof self.zombieSprite !== "undefined") {
self.zombieSprite.rotation = Math.atan2(self.vy, self.vx);
} else if (self.children && self.children.length > 0 && typeof self.children[0].rotation !== "undefined") {
self.children[0].rotation = Math.atan2(self.vy, self.vx);
}
}
// Shooting logic
self.fireTimer++;
if (self.fireTimer >= self.fireCooldown) {
self.fireTimer = 0;
// Only shoot if player is within 1200px
if (dist < 1200) {
spawnEnemyBullet(self.x, self.y, dx, dy);
}
}
};
return self;
});
// Heart class for health powerup
var Heart = Container.expand(function () {
var self = Container.call(this);
var heartSprite = self.attachAsset('heart', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = heartSprite.width / 2;
self.update = function () {
// Could animate or float, but static for now
};
return self;
});
// Player class
var Player = Container.expand(function () {
var self = Container.call(this);
var playerSprite = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = playerSprite.width / 2;
self.speed = 16; // Max speed per frame
self.vx = 0;
self.vy = 0;
self.hp = 5;
self.invincible = false;
// For hit flash
self.flash = function () {
if (self.invincible) return;
self.invincible = true;
tween(playerSprite, {
tint: 0xff4444
}, {
duration: 100,
onFinish: function onFinish() {
tween(playerSprite, {
tint: 0x3498db
}, {
duration: 200,
onFinish: function onFinish() {
self.invincible = false;
}
});
}
});
};
// Ensure playerSprite follows self.rotation
self.update = function () {
playerSprite.rotation = self.rotation || 0;
};
return self;
});
// Zombie class
var Zombie = Container.expand(function () {
var self = Container.call(this);
var zombieSprite = self.attachAsset('zombie', {
anchorX: 0.5,
anchorY: 0.5
});
self.radius = zombieSprite.width / 2;
self.speed = 1.2 + Math.random() * 0.7; // Slower zombies
self.vx = 0;
self.vy = 0;
self.target = null; // Player
self.update = function () {
if (!self.target) return;
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 0) {
self.vx = dx / dist * self.speed;
self.vy = dy / dist * self.speed;
self.x += self.vx;
self.y += self.vy;
// Rotate zombie sprite to face movement direction
zombieSprite.rotation = Math.atan2(self.vy, self.vx);
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x222222
});
/****
* Game Code
****/
// Helper to spawn an enemy bullet
// Joystick knob
// Joystick base
// Bullet
// Zombie
// Character (player)
// Game variables
function spawnEnemyBullet(x, y, dx, dy) {
var len = Math.sqrt(dx * dx + dy * dy);
if (len < 0.1) return;
var b = new EnemyBullet();
b.x = x;
b.y = y;
b.vx = dx / len;
b.vy = dy / len;
b.rotation = Math.atan2(dy, dx);
enemyBullets.push(b);
game.addChild(b);
}
var player;
var zombies = [];
var bullets = [];
var enemyBullets = []; // NEW: enemy bullets array
var score = 0;
var scoreTxt;
var hpTxt;
var spawnTimer = 0;
var spawnInterval = 90; // Frames between zombie spawns
var lastFireTick = 0;
var fireCooldown = 12; // Frames between shots
// Create player
player = new Player();
player.x = 2048 / 2;
player.y = 2732 * 0.7;
game.addChild(player);
// Set initial target move position to player start
game._targetMovePos = {
x: player.x,
y: player.y
};
// Score text
scoreTxt = new Text2('0', {
size: 110,
fill: "#fff"
});
scoreTxt.anchor.set(0.5, 0);
LK.gui.top.addChild(scoreTxt);
// HP text
hpTxt = new Text2('❤❤❤', {
size: 90,
fill: 0xFF4444
});
hpTxt.anchor.set(1, 0);
LK.gui.topRight.addChild(hpTxt);
// Helper: update HP display
function updateHpTxt() {
var s = '';
for (var i = 0; i < player.hp; ++i) s += '❤';
hpTxt.setText(s);
}
// Helper: update score display
function updateScoreTxt() {
scoreTxt.setText(score);
}
// Helper: spawn a zombie at a random edge
function spawnZombie() {
// Only spawn GunZombie (with 2 HP) or normal Zombie
var z;
if (score > 0 && score % 5 === 0) {
z = new GunZombie();
} else if (Math.random() < 0.15) {
z = new GunZombie();
} else {
z = new Zombie();
}
// Pick a random edge: 0=top, 1=bottom, 2=left, 3=right
var edge = Math.floor(Math.random() * 4);
var margin = 80;
if (edge === 0) {
// Top
z.x = margin + Math.random() * (2048 - 2 * margin);
z.y = -z.radius - 10;
} else if (edge === 1) {
// Bottom
z.x = margin + Math.random() * (2048 - 2 * margin);
z.y = 2732 + z.radius + 10;
} else if (edge === 2) {
// Left
z.x = -z.radius - 10;
z.y = margin + Math.random() * (2732 - 2 * margin);
} else {
// Right
z.x = 2048 + z.radius + 10;
z.y = margin + Math.random() * (2732 - 2 * margin);
}
z.target = player;
zombies.push(z);
game.addChild(z);
}
// Helper: fire a bullet towards a direction
function fireBullet(dirX, dirY) {
var len = Math.sqrt(dirX * dirX + dirY * dirY);
if (len < 0.1) return;
var b = new Bullet();
b.x = player.x;
b.y = player.y;
b.vx = dirX / len;
b.vy = dirY / len;
b.rotation = Math.atan2(dirY, dirX);
bullets.push(b);
game.addChild(b);
// Rotate player to face the direction of the fired bullet
player.rotation = Math.atan2(dirY, dirX);
}
// Game event handling
game.down = function (x, y, obj) {
var now = LK.ticks;
if (now - lastFireTick >= fireCooldown) {
fireBullet(x - player.x, y - player.y);
lastFireTick = now;
}
// Always rotate player to face the direction of the click/touch
var dx = x - player.x;
var dy = y - player.y;
if (Math.abs(dx) > 0.01 || Math.abs(dy) > 0.01) {
player.rotation = Math.atan2(dy, dx);
}
};
game.move = function (x, y, obj) {
// Always update target move position to follow pointer
if (typeof game._targetMovePos === "undefined") {
game._targetMovePos = {
x: player.x,
y: player.y
};
}
game._targetMovePos.x = x;
game._targetMovePos.y = y;
};
game.up = function (x, y, obj) {
// No joystick logic needed
};
// Main game update
game.update = function () {
// Player movement follows last pointer position
if (typeof game._targetMovePos === "undefined") {
game._targetMovePos = {
x: player.x,
y: player.y
};
}
var tx = game._targetMovePos.x;
var ty = game._targetMovePos.y;
var dx = tx - player.x;
var dy = ty - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 2) {
var moveDist = Math.min(player.speed, dist);
player.x += dx / dist * moveDist;
player.y += dy / dist * moveDist;
// Clamp to arena
var r = player.radius + 10;
if (player.x < r) player.x = r;
if (player.x > 2048 - r) player.x = 2048 - r;
if (player.y < r) player.y = r;
if (player.y > 2732 - r) player.y = 2732 - r;
}
// Always rotate player to face pointer direction
if (dist > 2) {
player.rotation = Math.atan2(dy, dx);
}
// Spawn zombies
spawnTimer++;
if (spawnTimer >= spawnInterval) {
spawnZombie();
spawnTimer = 0;
// Gradually increase spawn rate
if (spawnInterval > 30) spawnInterval -= 1;
}
// Update zombies
for (var i = zombies.length - 1; i >= 0; --i) {
var z = zombies[i];
z.update();
// Remove if off screen (failsafe)
if (z.x < -200 || z.x > 2248 || z.y < -200 || z.y > 2932) {
z.destroy();
zombies.splice(i, 1);
}
}
// Update bullets
for (var i = bullets.length - 1; i >= 0; --i) {
var b = bullets[i];
b.update();
// Remove if off screen
if (b.x < -100 || b.x > 2148 || b.y < -100 || b.y > 2832) {
b.destroy();
bullets.splice(i, 1);
continue;
}
}
// Update enemy bullets
for (var i = enemyBullets.length - 1; i >= 0; --i) {
var eb = enemyBullets[i];
eb.update();
// Remove if off screen
if (eb.x < -100 || eb.x > 2148 || eb.y < -100 || eb.y > 2832) {
eb.destroy();
enemyBullets.splice(i, 1);
continue;
}
// Check collision with player
var dx = eb.x - player.x;
var dy = eb.y - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < eb.radius + player.radius - 10) {
if (!player.invincible) {
player.hp -= 1;
updateHpTxt();
player.flash();
if (player.hp <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
} else if (player.hp === 1 && typeof heartSpawned === "undefined") {
// Spawn hearts at random locations when HP drops to 1
heartSpawned = true;
if (typeof hearts === "undefined") hearts = [];
for (var h = 0; h < 3; ++h) {
var heart = new Heart();
// Avoid spawning too close to player or outside arena
var safe = false;
var hx, hy;
while (!safe) {
hx = 150 + Math.random() * (2048 - 300);
hy = 150 + Math.random() * (2732 - 300);
var pdx = hx - player.x;
var pdy = hy - player.y;
if (Math.sqrt(pdx * pdx + pdy * pdy) > 400) safe = true;
}
heart.x = hx;
heart.y = hy;
hearts.push(heart);
game.addChild(heart);
}
}
}
eb.destroy();
enemyBullets.splice(i, 1);
continue;
}
}
// Bullet-zombie collisions
for (var i = bullets.length - 1; i >= 0; --i) {
var b = bullets[i];
for (var j = zombies.length - 1; j >= 0; --j) {
var z = zombies[j];
var dx = b.x - z.x;
var dy = b.y - z.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < b.radius + z.radius - 10) {
// Hit!
var isGunZombie = typeof z.hp === "number" && z.hp > 0;
if (isGunZombie) {
z.hp -= 1;
b.destroy();
bullets.splice(i, 1);
if (z.hp <= 0) {
z.destroy();
zombies.splice(j, 1);
score += 1;
updateScoreTxt();
}
} else {
z.destroy();
zombies.splice(j, 1);
b.destroy();
bullets.splice(i, 1);
score += 1;
updateScoreTxt();
}
break;
}
}
}
// Zombie-player collisions
for (var i = zombies.length - 1; i >= 0; --i) {
var z = zombies[i];
var dx = z.x - player.x;
var dy = z.y - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < z.radius + player.radius - 10) {
if (!player.invincible) {
player.hp -= 1;
updateHpTxt();
player.flash();
if (player.hp <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
return;
}
}
// Push zombie away
var pushDist = z.radius + player.radius - dist + 10;
if (pushDist > 0) {
var px = dx / dist * pushDist;
var py = dy / dist * pushDist;
z.x += px;
z.y += py;
}
}
}
// Heart pickup logic
if (typeof hearts !== "undefined" && hearts.length > 0) {
for (var i = hearts.length - 1; i >= 0; --i) {
var heart = hearts[i];
var dx = heart.x - player.x;
var dy = heart.y - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < heart.radius + player.radius - 10) {
// Picked up heart: restore HP to full
player.hp = 5;
updateHpTxt();
// Remove all hearts
for (var j = hearts.length - 1; j >= 0; --j) {
hearts[j].destroy();
}
hearts = [];
heartSpawned = undefined;
break;
}
}
}
};
// Initial UI update
updateScoreTxt();
updateHpTxt();
// Timer to spawn a heart at the center area every 5 seconds
if (typeof centerHeartTimer === "undefined") {
centerHeartTimer = LK.setInterval(function () {
if (typeof hearts === "undefined") hearts = [];
// Spawn a heart at a random position near the center (±200px)
var heart = new Heart();
var centerX = 2048 / 2;
var centerY = 2732 / 2;
var hx = centerX - 200 + Math.random() * 400;
var hy = centerY - 200 + Math.random() * 400;
heart.x = hx;
heart.y = hy;
hearts.push(heart);
game.addChild(heart);
}, 5000);
}
terraria oyunundaki gibi bir zombi. In-Game asset. 2d. High contrast. No shadows
pixel fireball. In-Game asset. 2d. High contrast. No shadows
aduket pozu vermiş pixel bir adam avucunun içi boş olsun. In-Game asset. 2d. High contrast. No shadows
elinde silah tutan bir zombi çiz pixel tarzı ile. In-Game asset. 2d. High contrast. No shadows
pixel heart. In-Game asset. 2d. High contrast. No shadows