/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bullet = Container.expand(function (direction) {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.direction = direction;
self.speed = 8;
self.damage = 25;
self.lifespan = 120;
self.update = function () {
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
self.lifespan--;
if (self.lifespan <= 0) {
self.destroy();
var index = bullets.indexOf(self);
if (index > -1) {
bullets.splice(index, 1);
}
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
var weaponGraphics = self.attachAsset('weapon', {
anchorX: 0.2,
anchorY: 0.5,
x: 25,
y: 0
});
self.weapon = weaponGraphics;
self.health = 100;
self.maxHealth = 100;
self.hunger = 100;
self.maxHunger = 100;
self.energy = 100;
self.maxEnergy = 100;
self.temperature = 50;
self.speed = 3;
self.inventory = {
wood: 0,
stone: 0,
food: 0
};
self.takeDamage = function (amount) {
self.health = Math.max(0, self.health - amount);
LK.effects.flashObject(self, 0xff0000, 500);
LK.getSound('hurt').play();
if (self.health <= 0) {
LK.showGameOver();
}
};
self.consumeEnergy = function (amount) {
self.energy = Math.max(0, self.energy - amount);
};
self.gatherResource = function (type, amount) {
self.inventory[type] = (self.inventory[type] || 0) + amount;
};
self.aimWeapon = function (targetX, targetY) {
var dx = targetX - self.x;
var dy = targetY - self.y;
var angle = Math.atan2(dy, dx);
self.weapon.rotation = angle;
};
return self;
});
var Resource = Container.expand(function (type) {
var self = Container.call(this);
var resourceGraphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
self.resourceType = type;
self.health = type === 'tree' ? 3 : 2;
self.maxHealth = self.health;
self.harvest = function () {
self.health--;
if (type === 'tree') {
player.gatherResource('wood', 2);
LK.getSound('chop').play();
} else if (type === 'rock') {
player.gatherResource('stone', 1);
LK.getSound('mine').play();
}
LK.effects.flashObject(self, 0xffffff, 300);
if (self.health <= 0) {
self.destroy();
var index = resources.indexOf(self);
if (index > -1) {
resources.splice(index, 1);
}
}
};
self.down = function (x, y, obj) {
var distance = Math.sqrt((player.x - self.x) * (player.x - self.x) + (player.y - self.y) * (player.y - self.y));
if (distance < 100) {
self.harvest();
}
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.maxHealth = 50;
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 = 30;
self.speed = 1.5;
self.damage = 10;
self.attackCooldown = 0;
self.isNighttime = false;
self.update = function () {
if (player) {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
var moveSpeed = self.isNighttime ? self.speed * 1.5 : self.speed;
self.x += dx / distance * moveSpeed;
self.y += dy / distance * moveSpeed;
} else if (self.attackCooldown <= 0) {
player.takeDamage(self.damage);
self.attackCooldown = 60;
}
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
}
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xffffff, 200);
if (self.health <= 0) {
self.destroy();
var index = zombies.indexOf(self);
if (index > -1) {
zombies.splice(index, 1);
}
LK.setScore(LK.getScore() + 10);
killCount++;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2d5016
});
/****
* Game Code
****/
var player = null;
var zombies = [];
var resources = [];
var bullets = [];
var structures = [];
var dayTime = 0;
var isNight = false;
var spawnTimer = 0;
var survivalTimer = 0;
var lastResourceSpawn = 0;
// UI Elements
var healthBar = new Text2('Health: 100', {
size: 40,
fill: 0xFF0000
});
healthBar.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthBar);
healthBar.x = 120;
healthBar.y = 20;
var hungerBar = new Text2('Hunger: 100', {
size: 40,
fill: 0xFFA500
});
hungerBar.anchor.set(0, 0);
LK.gui.topLeft.addChild(hungerBar);
hungerBar.x = 120;
hungerBar.y = 70;
var energyBar = new Text2('Energy: 100', {
size: 40,
fill: 0x00FF00
});
energyBar.anchor.set(0, 0);
LK.gui.topLeft.addChild(energyBar);
energyBar.x = 120;
energyBar.y = 120;
var inventoryText = new Text2('Wood: 0 | Stone: 0', {
size: 35,
fill: 0xFFFFFF
});
inventoryText.anchor.set(0, 0);
LK.gui.topLeft.addChild(inventoryText);
inventoryText.x = 120;
inventoryText.y = 170;
var dayNightText = new Text2('Day', {
size: 50,
fill: 0xFFFF00
});
dayNightText.anchor.set(0.5, 0);
LK.gui.top.addChild(dayNightText);
var scoreText = new Text2('Score: 0', {
size: 45,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
scoreText.x = -20;
scoreText.y = 20;
var killsText = new Text2('Kills: 0', {
size: 40,
fill: 0xFF6B6B
});
killsText.anchor.set(1, 0);
LK.gui.topRight.addChild(killsText);
killsText.x = -20;
killsText.y = 70;
var timeText = new Text2('Time: 0:00', {
size: 40,
fill: 0x4ECDC4
});
timeText.anchor.set(1, 0);
LK.gui.topRight.addChild(timeText);
timeText.x = -20;
timeText.y = 120;
var killCount = 0;
// Create player
player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
// Create initial resources
function spawnResource() {
if (resources.length < 15) {
var resourceType = Math.random() > 0.6 ? 'tree' : 'rock';
var resource = game.addChild(new Resource(resourceType));
resource.x = Math.random() * 1800 + 124;
resource.y = Math.random() * 2400 + 166;
resources.push(resource);
}
}
// Spawn initial resources
for (var i = 0; i < 10; i++) {
spawnResource();
}
// Zombie spawning
function spawnZombie() {
var zombie = game.addChild(new Zombie());
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.isNighttime = isNight;
zombies.push(zombie);
}
// Touch controls
var targetX = 1024;
var targetY = 1366;
var isMoving = false;
var isShooting = false;
var shootTarget = {
x: 0,
y: 0
};
game.down = function (x, y, obj) {
targetX = x;
targetY = y;
isMoving = true;
// Aim weapon at touch position
player.aimWeapon(x, y);
// Check if we can shoot (require some wood as ammo)
if (player.inventory.wood > 0) {
isShooting = true;
shootTarget.x = x;
shootTarget.y = y;
}
};
game.move = function (x, y, obj) {
if (isMoving) {
targetX = x;
targetY = y;
}
// Always aim weapon at cursor/touch position
player.aimWeapon(x, y);
};
game.up = function (x, y, obj) {
isMoving = false;
if (isShooting && player.inventory.wood > 0) {
// Create bullet
var dx = shootTarget.x - player.x;
var dy = shootTarget.y - player.y;
var angle = Math.atan2(dy, dx);
var bullet = game.addChild(new Bullet(angle));
bullet.x = player.x;
bullet.y = player.y;
bullets.push(bullet);
player.inventory.wood = Math.max(0, player.inventory.wood - 1);
LK.getSound('shoot').play();
}
isShooting = false;
};
// Game update loop
game.update = function () {
survivalTimer++;
dayTime++;
spawnTimer++;
lastResourceSpawn++;
// Day/night cycle (300 ticks = 5 seconds per cycle)
if (dayTime >= 600) {
dayTime = 0;
isNight = !isNight;
if (isNight) {
game.setBackgroundColor(0x1a1a2e);
dayNightText.setText('Night');
dayNightText.fill = "#4169e1";
} else {
game.setBackgroundColor(0x2d5016);
dayNightText.setText('Day');
dayNightText.fill = "#ffff00";
}
// Update all zombies for night mode
for (var z = 0; z < zombies.length; z++) {
zombies[z].isNighttime = isNight;
}
}
// Player movement
if (isMoving) {
var dx = targetX - player.x;
var dy = targetY - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
player.x += dx / distance * player.speed;
player.y += dy / distance * player.speed;
}
// Keep player in bounds
player.x = Math.max(30, Math.min(2018, player.x));
player.y = Math.max(30, Math.min(2702, player.y));
}
// Spawn zombies
var spawnRate = isNight ? 80 : 120;
if (spawnTimer >= spawnRate && zombies.length < (isNight ? 8 : 5)) {
spawnZombie();
spawnTimer = 0;
}
// Spawn resources
if (lastResourceSpawn >= 300) {
spawnResource();
lastResourceSpawn = 0;
}
// Survival mechanics
if (survivalTimer % 300 === 0) {
// Every 5 seconds
player.hunger = Math.max(0, player.hunger - 2);
player.temperature = Math.max(0, player.temperature - tempLoss);
if (player.hunger <= 0) {
player.takeDamage(5);
}
if (player.temperature <= 20) {
player.takeDamage(3);
}
}
// Keep energy at maximum
player.energy = player.maxEnergy;
// Adjust temperature loss based on time of day
var tempLoss = isNight ? 3 : 1;
// Bullet collision with zombies
for (var b = bullets.length - 1; b >= 0; b--) {
var bullet = bullets[b];
for (var z = 0; z < zombies.length; z++) {
var zombie = zombies[z];
if (bullet.intersects(zombie)) {
zombie.takeDamage(bullet.damage);
bullet.destroy();
bullets.splice(b, 1);
break;
}
}
// Remove bullets that go off screen
if (bullet && (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782)) {
bullet.destroy();
bullets.splice(b, 1);
}
}
// Update UI
healthBar.setText('Health: ' + Math.floor(player.health));
hungerBar.setText('Hunger: ' + Math.floor(player.hunger));
energyBar.setText('Energy: ' + Math.floor(player.energy));
inventoryText.setText('Wood: ' + player.inventory.wood + ' | Stone: ' + player.inventory.stone);
scoreText.setText('Score: ' + LK.getScore());
killsText.setText('Kills: ' + killCount);
var minutes = Math.floor(survivalTimer / 3600);
var seconds = Math.floor(survivalTimer % 3600 / 60);
timeText.setText('Time: ' + minutes + ':' + (seconds < 10 ? '0' : '') + seconds);
// Win condition (survive for 5 minutes)
if (survivalTimer >= 18000) {
LK.showYouWin();
}
};
// Start background music
LK.playMusic('background'); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
var Bullet = Container.expand(function (direction) {
var self = Container.call(this);
var bulletGraphics = self.attachAsset('bullet', {
anchorX: 0.5,
anchorY: 0.5
});
self.direction = direction;
self.speed = 8;
self.damage = 25;
self.lifespan = 120;
self.update = function () {
self.x += Math.cos(self.direction) * self.speed;
self.y += Math.sin(self.direction) * self.speed;
self.lifespan--;
if (self.lifespan <= 0) {
self.destroy();
var index = bullets.indexOf(self);
if (index > -1) {
bullets.splice(index, 1);
}
}
};
return self;
});
var Player = Container.expand(function () {
var self = Container.call(this);
var playerGraphics = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
var weaponGraphics = self.attachAsset('weapon', {
anchorX: 0.2,
anchorY: 0.5,
x: 25,
y: 0
});
self.weapon = weaponGraphics;
self.health = 100;
self.maxHealth = 100;
self.hunger = 100;
self.maxHunger = 100;
self.energy = 100;
self.maxEnergy = 100;
self.temperature = 50;
self.speed = 3;
self.inventory = {
wood: 0,
stone: 0,
food: 0
};
self.takeDamage = function (amount) {
self.health = Math.max(0, self.health - amount);
LK.effects.flashObject(self, 0xff0000, 500);
LK.getSound('hurt').play();
if (self.health <= 0) {
LK.showGameOver();
}
};
self.consumeEnergy = function (amount) {
self.energy = Math.max(0, self.energy - amount);
};
self.gatherResource = function (type, amount) {
self.inventory[type] = (self.inventory[type] || 0) + amount;
};
self.aimWeapon = function (targetX, targetY) {
var dx = targetX - self.x;
var dy = targetY - self.y;
var angle = Math.atan2(dy, dx);
self.weapon.rotation = angle;
};
return self;
});
var Resource = Container.expand(function (type) {
var self = Container.call(this);
var resourceGraphics = self.attachAsset(type, {
anchorX: 0.5,
anchorY: 0.5
});
self.resourceType = type;
self.health = type === 'tree' ? 3 : 2;
self.maxHealth = self.health;
self.harvest = function () {
self.health--;
if (type === 'tree') {
player.gatherResource('wood', 2);
LK.getSound('chop').play();
} else if (type === 'rock') {
player.gatherResource('stone', 1);
LK.getSound('mine').play();
}
LK.effects.flashObject(self, 0xffffff, 300);
if (self.health <= 0) {
self.destroy();
var index = resources.indexOf(self);
if (index > -1) {
resources.splice(index, 1);
}
}
};
self.down = function (x, y, obj) {
var distance = Math.sqrt((player.x - self.x) * (player.x - self.x) + (player.y - self.y) * (player.y - self.y));
if (distance < 100) {
self.harvest();
}
};
return self;
});
var Wall = Container.expand(function () {
var self = Container.call(this);
var wallGraphics = self.attachAsset('wall', {
anchorX: 0.5,
anchorY: 0.5
});
self.health = 50;
self.maxHealth = 50;
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 = 30;
self.speed = 1.5;
self.damage = 10;
self.attackCooldown = 0;
self.isNighttime = false;
self.update = function () {
if (player) {
var dx = player.x - self.x;
var dy = player.y - self.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
var moveSpeed = self.isNighttime ? self.speed * 1.5 : self.speed;
self.x += dx / distance * moveSpeed;
self.y += dy / distance * moveSpeed;
} else if (self.attackCooldown <= 0) {
player.takeDamage(self.damage);
self.attackCooldown = 60;
}
if (self.attackCooldown > 0) {
self.attackCooldown--;
}
}
};
self.takeDamage = function (amount) {
self.health -= amount;
LK.effects.flashObject(self, 0xffffff, 200);
if (self.health <= 0) {
self.destroy();
var index = zombies.indexOf(self);
if (index > -1) {
zombies.splice(index, 1);
}
LK.setScore(LK.getScore() + 10);
killCount++;
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x2d5016
});
/****
* Game Code
****/
var player = null;
var zombies = [];
var resources = [];
var bullets = [];
var structures = [];
var dayTime = 0;
var isNight = false;
var spawnTimer = 0;
var survivalTimer = 0;
var lastResourceSpawn = 0;
// UI Elements
var healthBar = new Text2('Health: 100', {
size: 40,
fill: 0xFF0000
});
healthBar.anchor.set(0, 0);
LK.gui.topLeft.addChild(healthBar);
healthBar.x = 120;
healthBar.y = 20;
var hungerBar = new Text2('Hunger: 100', {
size: 40,
fill: 0xFFA500
});
hungerBar.anchor.set(0, 0);
LK.gui.topLeft.addChild(hungerBar);
hungerBar.x = 120;
hungerBar.y = 70;
var energyBar = new Text2('Energy: 100', {
size: 40,
fill: 0x00FF00
});
energyBar.anchor.set(0, 0);
LK.gui.topLeft.addChild(energyBar);
energyBar.x = 120;
energyBar.y = 120;
var inventoryText = new Text2('Wood: 0 | Stone: 0', {
size: 35,
fill: 0xFFFFFF
});
inventoryText.anchor.set(0, 0);
LK.gui.topLeft.addChild(inventoryText);
inventoryText.x = 120;
inventoryText.y = 170;
var dayNightText = new Text2('Day', {
size: 50,
fill: 0xFFFF00
});
dayNightText.anchor.set(0.5, 0);
LK.gui.top.addChild(dayNightText);
var scoreText = new Text2('Score: 0', {
size: 45,
fill: 0xFFFFFF
});
scoreText.anchor.set(1, 0);
LK.gui.topRight.addChild(scoreText);
scoreText.x = -20;
scoreText.y = 20;
var killsText = new Text2('Kills: 0', {
size: 40,
fill: 0xFF6B6B
});
killsText.anchor.set(1, 0);
LK.gui.topRight.addChild(killsText);
killsText.x = -20;
killsText.y = 70;
var timeText = new Text2('Time: 0:00', {
size: 40,
fill: 0x4ECDC4
});
timeText.anchor.set(1, 0);
LK.gui.topRight.addChild(timeText);
timeText.x = -20;
timeText.y = 120;
var killCount = 0;
// Create player
player = game.addChild(new Player());
player.x = 1024;
player.y = 1366;
// Create initial resources
function spawnResource() {
if (resources.length < 15) {
var resourceType = Math.random() > 0.6 ? 'tree' : 'rock';
var resource = game.addChild(new Resource(resourceType));
resource.x = Math.random() * 1800 + 124;
resource.y = Math.random() * 2400 + 166;
resources.push(resource);
}
}
// Spawn initial resources
for (var i = 0; i < 10; i++) {
spawnResource();
}
// Zombie spawning
function spawnZombie() {
var zombie = game.addChild(new Zombie());
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.isNighttime = isNight;
zombies.push(zombie);
}
// Touch controls
var targetX = 1024;
var targetY = 1366;
var isMoving = false;
var isShooting = false;
var shootTarget = {
x: 0,
y: 0
};
game.down = function (x, y, obj) {
targetX = x;
targetY = y;
isMoving = true;
// Aim weapon at touch position
player.aimWeapon(x, y);
// Check if we can shoot (require some wood as ammo)
if (player.inventory.wood > 0) {
isShooting = true;
shootTarget.x = x;
shootTarget.y = y;
}
};
game.move = function (x, y, obj) {
if (isMoving) {
targetX = x;
targetY = y;
}
// Always aim weapon at cursor/touch position
player.aimWeapon(x, y);
};
game.up = function (x, y, obj) {
isMoving = false;
if (isShooting && player.inventory.wood > 0) {
// Create bullet
var dx = shootTarget.x - player.x;
var dy = shootTarget.y - player.y;
var angle = Math.atan2(dy, dx);
var bullet = game.addChild(new Bullet(angle));
bullet.x = player.x;
bullet.y = player.y;
bullets.push(bullet);
player.inventory.wood = Math.max(0, player.inventory.wood - 1);
LK.getSound('shoot').play();
}
isShooting = false;
};
// Game update loop
game.update = function () {
survivalTimer++;
dayTime++;
spawnTimer++;
lastResourceSpawn++;
// Day/night cycle (300 ticks = 5 seconds per cycle)
if (dayTime >= 600) {
dayTime = 0;
isNight = !isNight;
if (isNight) {
game.setBackgroundColor(0x1a1a2e);
dayNightText.setText('Night');
dayNightText.fill = "#4169e1";
} else {
game.setBackgroundColor(0x2d5016);
dayNightText.setText('Day');
dayNightText.fill = "#ffff00";
}
// Update all zombies for night mode
for (var z = 0; z < zombies.length; z++) {
zombies[z].isNighttime = isNight;
}
}
// Player movement
if (isMoving) {
var dx = targetX - player.x;
var dy = targetY - player.y;
var distance = Math.sqrt(dx * dx + dy * dy);
if (distance > 5) {
player.x += dx / distance * player.speed;
player.y += dy / distance * player.speed;
}
// Keep player in bounds
player.x = Math.max(30, Math.min(2018, player.x));
player.y = Math.max(30, Math.min(2702, player.y));
}
// Spawn zombies
var spawnRate = isNight ? 80 : 120;
if (spawnTimer >= spawnRate && zombies.length < (isNight ? 8 : 5)) {
spawnZombie();
spawnTimer = 0;
}
// Spawn resources
if (lastResourceSpawn >= 300) {
spawnResource();
lastResourceSpawn = 0;
}
// Survival mechanics
if (survivalTimer % 300 === 0) {
// Every 5 seconds
player.hunger = Math.max(0, player.hunger - 2);
player.temperature = Math.max(0, player.temperature - tempLoss);
if (player.hunger <= 0) {
player.takeDamage(5);
}
if (player.temperature <= 20) {
player.takeDamage(3);
}
}
// Keep energy at maximum
player.energy = player.maxEnergy;
// Adjust temperature loss based on time of day
var tempLoss = isNight ? 3 : 1;
// Bullet collision with zombies
for (var b = bullets.length - 1; b >= 0; b--) {
var bullet = bullets[b];
for (var z = 0; z < zombies.length; z++) {
var zombie = zombies[z];
if (bullet.intersects(zombie)) {
zombie.takeDamage(bullet.damage);
bullet.destroy();
bullets.splice(b, 1);
break;
}
}
// Remove bullets that go off screen
if (bullet && (bullet.x < -50 || bullet.x > 2098 || bullet.y < -50 || bullet.y > 2782)) {
bullet.destroy();
bullets.splice(b, 1);
}
}
// Update UI
healthBar.setText('Health: ' + Math.floor(player.health));
hungerBar.setText('Hunger: ' + Math.floor(player.hunger));
energyBar.setText('Energy: ' + Math.floor(player.energy));
inventoryText.setText('Wood: ' + player.inventory.wood + ' | Stone: ' + player.inventory.stone);
scoreText.setText('Score: ' + LK.getScore());
killsText.setText('Kills: ' + killCount);
var minutes = Math.floor(survivalTimer / 3600);
var seconds = Math.floor(survivalTimer % 3600 / 60);
timeText.setText('Time: ' + minutes + ':' + (seconds < 10 ? '0' : '') + seconds);
// Win condition (survive for 5 minutes)
if (survivalTimer >= 18000) {
LK.showYouWin();
}
};
// Start background music
LK.playMusic('background');
Fullscreen modern App Store landscape banner, 16:9, high definition, for a game titled "Last Light: 2D Survival" and with the description "Survive in a zombie-infested 2D world by gathering resources, crafting weapons, building shelter, and fighting off undead hordes. Manage hunger, health, and energy while exploring a dangerous pixel-art wasteland filled with valuable loot and deadly encounters.". No text on banner!
ZOMBİE. In-Game asset. High contrast. No shadows
TREE. In-Game asset. 2d. High contrast. No shadows
MAN. In-Game asset. 2d. High contrast. No shadows
STONE. In-Game asset. 2d. High contrast. No shadows
weapon. In-Game asset. 2d. High contrast. No shadows