/****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// Arrow projectile
var Arrow = Container.expand(function () {
var self = Container.call(this);
self.type = 'arrow';
self.speed = 38;
self.damage = 18;
self.target = null;
self.lastX = 0;
self.lastY = 0;
self.attachAsset('wood', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.2
});
self.children[0].tint = 0xffe066;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
if (self.target) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 2) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
}
};
return self;
});
// Bow weapon
var Bow = Container.expand(function () {
var self = Container.call(this);
self.type = 'bow';
self.damage = 18;
self.range = 600;
self.cooldown = 50;
self.lastAttackTick = -1000;
self.attachAsset('wood', {
anchorX: 0.5,
anchorY: 0.5
});
self.children[0].tint = 0x8fd3ff;
return self;
});
// Bush (for berries)
var Bush = Container.expand(function () {
var self = Container.call(this);
self.type = 'bush';
self.attachAsset('bush', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Cow (passive animal)
var Cow = Container.expand(function () {
var self = Container.call(this);
self.type = 'cow';
self.speed = 2 + Math.random() * 1.5;
self.lastX = 0;
self.lastY = 0;
self.attachAsset('cow', {
anchorX: 0.5,
anchorY: 0.5
});
// Add a simple face (optional, for fun)
// self.children[0].tint = 0xffffff; // already white
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
// Simple random walk
if (!self._moveDir || LK.ticks % 120 === 0) {
var angle = Math.random() * Math.PI * 2;
self._moveDir = {
x: Math.cos(angle),
y: Math.sin(angle)
};
}
self.x += self._moveDir.x * self.speed;
self.y += self._moveDir.y * self.speed;
// Stay in bounds
if (self.x < 120) {
self.x = 120;
self._moveDir.x *= -1;
}
if (self.x > 2048 - 120) {
self.x = 2048 - 120;
self._moveDir.x *= -1;
}
if (self.y < 200) {
self.y = 200;
self._moveDir.y *= -1;
}
if (self.y > 2732 - 120) {
self.y = 2732 - 120;
self._moveDir.y *= -1;
}
};
return self;
});
var Piranha = Container.expand(function () {
var self = Container.call(this);
self.type = 'piranha';
self.speed = 3 + Math.random() * 2.5;
self.lastX = 0;
self.lastY = 0;
self._moveDir = null;
self.damage = 18;
self.attachAsset('berry', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 0.7
});
self.children[0].tint = 0xff2222;
// Platform bounds (same as in game.move)
var platX = 2048 / 2;
var platY = 2732 - 180;
var platW = 350; // seaSafePlatform.width * 0.5 - 40, but static for logic
var platH = 110; // seaSafePlatform.height * 0.5 - 20, but static for logic
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
// Only move if in sea and not in mine
if (inSea && !inMine) {
// Random walk like cow
if (!self._moveDir || LK.ticks % 120 === 0) {
var angle = Math.random() * Math.PI * 2;
self._moveDir = {
x: Math.cos(angle),
y: Math.sin(angle)
};
}
self.x += self._moveDir.x * self.speed;
self.y += self._moveDir.y * self.speed;
// Clamp to sea region (bottom 350px)
if (self.x < 0) {
self.x = 0;
self._moveDir.x *= -1;
}
if (self.x > 2048) {
self.x = 2048;
self._moveDir.x *= -1;
}
if (self.y < 2732 - 350) {
self.y = 2732 - 350;
self._moveDir.y *= -1;
}
if (self.y > 2732) {
self.y = 2732;
self._moveDir.y *= -1;
}
// Avoid safe platform: if inside platform area, bounce out
if (self.x >= platX - platW && self.x <= platX + platW && self.y >= platY - platH && self.y <= platY + platH) {
// Move away from platform center
var dx = self.x - platX;
var dy = self.y - platY;
var dist = Math.sqrt(dx * dx + dy * dy) || 1;
self.x = platX + dx / dist * (platW + 10);
self.y = platY + dy / dist * (platH + 10);
// Change direction
var angle = Math.atan2(dy, dx) + (Math.random() - 0.5) * 0.7;
self._moveDir = {
x: Math.cos(angle),
y: Math.sin(angle)
};
}
}
};
return self;
});
// Spawn piranhas in sea region
// Player class
var Player = Container.expand(function () {
var self = Container.call(this);
var playerSprite = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 18;
self.inventory = {
wood: 0,
stone: 0,
berry: 0,
meat: 0,
iron: 0,
gold: 0,
diamond: 0,
ruby: 0,
emerald: 0,
coal: 0,
arrow: 0,
// arrows for bow
// Workstations
workbench: 0,
furnace: 0,
armorbench: 0,
weaponbench: 0
};
self.health = 100;
self.hunger = 100;
self.hasShelter = false;
self.hasRaft = false;
self.update = function () {};
return self;
});
// Raft
var Raft = Container.expand(function () {
var self = Container.call(this);
self.attachAsset('raft', {
anchorX: 0.5,
anchorY: 1
});
return self;
});
// Resource base class
var Resource = Container.expand(function () {
var self = Container.call(this);
self.type = '';
self.collected = false;
self.update = function () {};
return self;
});
// Wood resource
var Wood = Resource.expand(function () {
var self = Resource.call(this);
self.type = 'wood';
self.attachAsset('wood', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Stone resource
var Stone = Resource.expand(function () {
var self = Resource.call(this);
self.type = 'stone';
self.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Meat resource (from cow)
var Meat = Resource.expand(function () {
var self = Resource.call(this);
self.type = 'meat';
self.attachAsset('berry', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 0.8
});
self.children[0].tint = 0xffa07a; // salmon color for meat
return self;
});
// --- Add fish resource type ---
var Fish = Resource.expand(function () {
var self = Resource.call(this);
self.type = 'fish';
self.attachAsset('berry', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 0.7
});
self.children[0].tint = 0x3fa7d6;
return self;
});
// --- Initial Island ---
// Berry resource
var Berry = Resource.expand(function () {
var self = Resource.call(this);
self.type = 'berry';
self.attachAsset('berry', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Rock (for stone)
var Rock = Container.expand(function () {
var self = Container.call(this);
self.type = 'rock';
self.attachAsset('rock', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Shelter
var Shelter = Container.expand(function () {
var self = Container.call(this);
self.attachAsset('shelter', {
anchorX: 0.5,
anchorY: 1
});
return self;
});
// Skeleton enemy (shoots arrows at player in mine)
var Skeleton = Container.expand(function () {
var self = Container.call(this);
self.type = 'skeleton';
self.speed = 3 + Math.random() * 1.5;
self.target = null;
self.damage = 10;
self.lastX = 0;
self.lastY = 0;
self.shootCooldown = 90 + Math.floor(Math.random() * 60);
self.lastShootTick = -1000;
self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.children[0].tint = 0xffffff; // white skeleton
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
if (self.target) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 2) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
// Shoot arrow at player if cooldown
if (LK.ticks - self.lastShootTick > self.shootCooldown && dist < 800) {
var arrow = new Arrow();
arrow.x = self.x;
arrow.y = self.y;
arrow.target = self.target;
arrow.speed = 22;
arrow.damage = 12;
arrow.isEnemy = true;
arrows.push(arrow);
game.addChild(arrow);
self.lastShootTick = LK.ticks;
}
}
};
return self;
});
// Sword weapon
var Sword = Container.expand(function () {
var self = Container.call(this);
self.type = 'sword';
self.damage = 30;
self.range = 180;
self.cooldown = 30;
self.lastAttackTick = -1000;
self.attachAsset('wood', {
anchorX: 0.5,
anchorY: 0.5
});
self.children[0].tint = 0xcccccc;
return self;
});
// Tree (for wood)
var Tree = Container.expand(function () {
var self = Container.call(this);
self.type = 'tree';
self.attachAsset('tree', {
anchorX: 0.5,
anchorY: 1
});
return self;
});
// Wood Golem boss (appears on day 3, drops Magic Infused Wood)
var WoodGolem = Container.expand(function () {
var self = Container.call(this);
self.type = 'woodgolem';
self.maxHealth = 300;
self.health = self.maxHealth;
self.speed = 2.2;
self.target = null;
self.damage = 30;
self.lastX = 0;
self.lastY = 0;
self.lastWasIntersecting = false;
self.resistantToBow = true;
self.attachAsset('wood', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.2,
scaleY: 2.2
});
self.children[0].tint = 0x7c4f19; // dark wood color
// Health bar
var barBg = new Container();
var bar = LK.getAsset('wood', {
anchorX: 0,
anchorY: 0,
scaleX: 1,
scaleY: 0.15
});
bar.tint = 0x333333;
barBg.addChild(bar);
var barFg = LK.getAsset('wood', {
anchorX: 0,
anchorY: 0,
scaleX: 1,
scaleY: 0.15
});
barFg.tint = 0x00ff00;
barBg.addChild(barFg);
barBg.y = -120;
barBg.x = -60;
self.addChild(barBg);
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
if (self.target) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 2) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
}
// Update health bar
barFg.scaleX = Math.max(0, self.health / self.maxHealth);
};
// Take damage (returns true if dead)
self.takeDamage = function (amount, type) {
// If hit by bow, take only 10% damage
if (type === 'bow' && self.resistantToBow) {
amount = Math.ceil(amount * 0.1);
}
self.health -= amount;
if (self.health <= 0) {
self.health = 0;
return true;
}
return false;
};
return self;
});
// Zombie enemy (for night on island)
var Zombie = Container.expand(function () {
var self = Container.call(this);
self.type = 'zombie';
self.speed = 3 + Math.random() * 1.5;
self.target = null;
self.damage = 12;
self.lastX = 0;
self.lastY = 0;
self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.children[0].tint = 0x228b22; // greenish for zombie
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
if (self.target) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 2) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb // Sky blue for day
});
/****
* Game Code
****/
// Shapes for resources, player, and environment
// --- Global variables ---
var player;
var resources = [];
var interactables = [];
var cows = [];
var shelter = null;
var raft = null;
var day = 1;
var isNight = false;
var nightOverlay;
var hungerTimer;
var dayNightTimer;
var dragging = false;
var dragOffset = {
x: 0,
y: 0
};
var selectedInteractable = null;
// --- Mine dimension ---
var inMine = false;
var mineBtn = null;
var mineResources = [];
var mineInteractables = [];
// --- Zombies, weapons, arrows ---
var zombies = [];
var zombieSpawnTimer = null;
var playerWeapon = null;
var arrows = [];
// --- UI Elements ---
var healthTxt = new Text2('Health: 100', {
size: 40,
fill: "#fff"
});
healthTxt.anchor.set(0, 0);
LK.gui.top.addChild(healthTxt);
var hungerTxt = new Text2('Hunger: 100', {
size: 40,
fill: "#fff"
});
hungerTxt.anchor.set(0, 0);
LK.gui.top.addChild(hungerTxt);
hungerTxt.y = 50;
var dayTxt = new Text2('Day: 1', {
size: 40,
fill: "#fff"
});
dayTxt.anchor.set(0, 0);
LK.gui.top.addChild(dayTxt);
dayTxt.y = 100;
// --- Inventory UI for all resources ---
// --- Inventory UI for all resources ---
// --- Inventory Toggle Button ---
var inventoryOpen = true;
var inventoryBtn = new Text2('Inventory', {
size: 44,
fill: "#fff"
});
inventoryBtn.anchor.set(0.5, 0);
// Move inventory button to top left, but not in 100x100 area
inventoryBtn.x = 180;
inventoryBtn.y = 120;
LK.gui.top.addChild(inventoryBtn);
inventoryBtn.down = function (x, y, obj) {
inventoryOpen = !inventoryOpen;
// Toggle visibility of inventory icons/texts
for (var i = 0; i < invIcons.length; i++) {
invIcons[i].visible = inventoryOpen && (invIcons[i].visible || false);
invTexts[i].visible = inventoryOpen && (invTexts[i].visible || false);
}
if (extraInventoryPanel) {
extraInventoryPanel.visible = inventoryOpen && extraInventoryPanel._shouldBeVisible;
}
};
// --- Extra Inventory Button and Panel for Crafted Items ---
var extraInventoryOpen = false;
var extraInventoryBtn = new Text2('Extra Inv', {
size: 44,
fill: "#fff"
});
extraInventoryBtn.anchor.set(0.5, 0);
extraInventoryBtn.x = 420;
extraInventoryBtn.y = 120;
LK.gui.top.addChild(extraInventoryBtn);
var extraInventoryPanel = new Container();
extraInventoryPanel.visible = false;
extraInventoryPanel._shouldBeVisible = false;
LK.gui.top.addChild(extraInventoryPanel);
// Layout for extra inventory panel
var extraInvStartY = 200;
var extraInvSpacing = 90;
var extraInvSlots = [{
key: 'sword',
label: 'Sword',
asset: 'wood',
tint: 0xcccccc
}, {
key: 'bow',
label: 'Bow',
asset: 'wood',
tint: 0x8fd3ff
}, {
key: 'fishingrod',
label: 'Fishing Rod',
asset: 'wood',
tint: 0x3fa7d6
}];
var extraInvIcons = [];
var extraInvTexts = [];
for (var i = 0; i < extraInvSlots.length; i++) {
var slot = extraInvSlots[i];
var yPos = extraInvStartY + i * extraInvSpacing;
var icon = LK.getAsset(slot.asset, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.9,
scaleY: 0.9,
x: 60,
y: yPos
});
icon.tint = slot.tint;
extraInventoryPanel.addChild(icon);
extraInvIcons.push(icon);
var txt = new Text2(slot.label, {
size: 32,
fill: "#fff"
});
txt.anchor.set(0, 0.5);
txt.x = 110;
txt.y = yPos;
extraInventoryPanel.addChild(txt);
extraInvTexts.push(txt);
// --- Kuşan and İncele buttons ---
var kusanBtn = new Text2('Kuşan', {
size: 28,
fill: 0xB084FF
});
kusanBtn.anchor.set(0, 0.5);
kusanBtn.x = 320;
kusanBtn.y = yPos - 18;
extraInventoryPanel.addChild(kusanBtn);
var inceleBtn = new Text2('İncele', {
size: 28,
fill: 0xB084FF
});
inceleBtn.anchor.set(0, 0.5);
inceleBtn.x = 320;
inceleBtn.y = yPos + 18;
extraInventoryPanel.addChild(inceleBtn);
// Kuşan logic: set as selected tool in tool bar and weaponToolSelected
(function (slot, i, kusanBtn) {
kusanBtn.down = function (x, y, obj) {
// Only allow if player has the item
var canEquip = false;
if (slot.key === 'sword' && playerWeapon && playerWeapon.type === 'sword') canEquip = true;else if (slot.key === 'bow' && playerWeapon && playerWeapon.type === 'bow') canEquip = true;else if (slot.key === 'fishingrod' && player && player.inventory && player.inventory.fishingrod > 0) canEquip = true;
if (!canEquip) {
LK.effects.flashObject(kusanBtn, 0xff4444, 400);
return;
}
// Find tool bar slot for this item and select it
for (var j = 0; j < toolBarKeys.length; j++) {
if (toolBarKeys[j] === slot.key) {
toolBarSelected = j;
for (var k = 0; k < toolBarIcons.length; k++) {
toolBarIcons[k].alpha = k === j ? 1.0 : 0.5;
}
weaponToolSelected = slot.key;
updateUI();
break;
}
}
};
})(slot, i, kusanBtn);
// İncele logic: show popup with description
(function (slot, i, inceleBtn) {
inceleBtn.down = function (x, y, obj) {
var desc = "";
if (slot.key === 'sword') {
desc = "Kılıç: Yakın dövüş silahı. Zombilere ve düşmanlara yüksek hasar verir.\n\nKullanım: Düşmanlara yaklaşarak saldırabilirsin. Dayanıklıdır ve yakın mesafede etkilidir.";
} else if (slot.key === 'bow') {
desc = "Yay: Uzaktan saldırı silahı. Ok ile ateş eder, menzili yüksektir.\n\nKullanım: Uzak mesafedeki düşmanlara ok fırlatabilirsin. Ok sayın kadar kullanabilirsin.";
} else if (slot.key === 'fishingrod') {
desc = "Olta: Deniz bölgesinde balık tutmak için kullanılır.\n\nKullanım: Deniz platformunda oltayı kullanarak balık yakalayabilirsin. Balıklar açlığını azaltır.";
} else {
desc = "Alet açıklaması bulunamadı.";
}
// Show popup
var popup = new Container();
var bg = LK.getAsset('wood', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 5,
scaleY: 2,
x: 2048 / 2,
y: 2732 / 2
});
bg.alpha = 0.92;
popup.addChild(bg);
var txt = new Text2(desc, {
size: 44,
fill: "#fff"
});
txt.anchor.set(0.5, 0.5);
txt.x = 2048 / 2;
txt.y = 2732 / 2;
popup.addChild(txt);
// Kapat button
var closeBtn = new Text2('Kapat', {
size: 36,
fill: 0xB084FF
});
closeBtn.anchor.set(0.5, 0.5);
closeBtn.x = 2048 / 2;
closeBtn.y = 2732 / 2 + 120;
popup.addChild(closeBtn);
closeBtn.down = function () {
popup.destroy();
};
LK.gui.center.addChild(popup);
};
})(slot, i, inceleBtn);
}
// Show/hide logic for extra inventory
extraInventoryBtn.down = function (x, y, obj) {
extraInventoryOpen = !extraInventoryOpen;
// Always show the panel when Extra Inv is open, regardless of inventoryOpen
extraInventoryPanel.visible = extraInventoryOpen;
extraInventoryPanel._shouldBeVisible = extraInventoryOpen;
updateExtraInventoryPanel();
};
// Update function for extra inventory panel
function updateExtraInventoryPanel() {
for (var i = 0; i < extraInvSlots.length; i++) {
var slot = extraInvSlots[i];
var icon = extraInvIcons[i];
var txt = extraInvTexts[i];
var hasItem = false;
if (slot.key === 'sword' && playerWeapon && playerWeapon.type === 'sword') hasItem = true;else if (slot.key === 'bow' && playerWeapon && playerWeapon.type === 'bow') hasItem = true;else if (slot.key === 'fishingrod' && player && player.inventory && player.inventory.fishingrod > 0) hasItem = true;
icon.visible = hasItem;
txt.visible = hasItem;
if (slot.key === 'fishingrod') {
txt.setText(slot.label + (player.inventory.fishingrod > 1 ? ' x' + player.inventory.fishingrod : ''));
} else {
txt.setText(slot.label);
}
}
}
// Patch updateUI to also update extra inventory panel
var _oldUpdateUI2 = updateUI;
updateUI = function updateUI() {
_oldUpdateUI2();
updateExtraInventoryPanel();
if (extraInventoryPanel) {
// Always show the panel if Extra Inv is open, regardless of inventoryOpen
extraInventoryPanel.visible = extraInventoryOpen && extraInventoryPanel._shouldBeVisible;
}
};
var resourceList = [{
key: 'wood',
label: 'Wood',
asset: 'wood',
tint: 0x8b5a2b
}, {
key: 'stone',
label: 'Stone',
asset: 'stone',
tint: 0x888888
}, {
key: 'berry',
label: 'Berries',
asset: 'berry',
tint: 0xc0392b
}, {
key: 'meat',
label: 'Meat',
asset: 'berry',
tint: 0xffa07a
}, {
key: 'fish',
label: 'Fish',
asset: 'berry',
tint: 0x3fa7d6
}, {
key: 'iron',
label: 'Iron',
asset: 'stone',
tint: 0xaaaaaa
}, {
key: 'gold',
label: 'Gold',
asset: 'stone',
tint: 0xffd700
}, {
key: 'diamond',
label: 'Diamond',
asset: 'stone',
tint: 0x00ffff
}, {
key: 'ruby',
label: 'Ruby',
asset: 'stone',
tint: 0xff0044
}, {
key: 'emerald',
label: 'Emerald',
asset: 'stone',
tint: 0x00ff44
}, {
key: 'coal',
label: 'Coal',
asset: 'stone',
tint: 0x222222
}, {
key: 'arrow',
label: 'Arrows',
asset: 'wood',
tint: 0xffe066
}, {
key: 'magicwood',
label: 'MagicWood',
asset: 'wood',
tint: 0x8e44ad
}, {
key: 'magicrealmportal',
label: 'MagicRealmPortal',
asset: 'wood',
tint: 0xB084FF
}];
// --- 5-slot tool inventory bar at bottom center (Minecraft-style) ---
var toolBarSlots = 5;
var toolBarKeys = ['sword', 'bow', 'fishingrod', 'axe', 'pickaxe'];
var toolBarIcons = [];
var toolBarSelected = 0; // index of selected slot
// Move tool bar to a more visible location: above bottom, centered horizontally
var toolBarY = -260; // higher up from the bottom, so it's not hidden by hands or overlays
var toolBarSpacing = 180;
var toolBarStartX = 2048 / 2 - (toolBarSlots - 1) * toolBarSpacing / 2;
// Tool asset/tint mapping
var toolBarInfo = {
sword: {
asset: 'wood',
tint: 0xcccccc
},
bow: {
asset: 'wood',
tint: 0x8fd3ff
},
fishingrod: {
asset: 'wood',
tint: 0x3fa7d6
},
axe: {
asset: 'wood',
tint: 0xdeb887
},
pickaxe: {
asset: 'stone',
tint: 0xaaaaaa
}
};
for (var i = 0; i < toolBarSlots; i++) {
var key = toolBarKeys[i];
var info = toolBarInfo[key];
var icon = LK.getAsset(info.asset, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 1.1,
x: toolBarStartX + i * toolBarSpacing,
y: toolBarY
});
icon.tint = info.tint;
icon.alpha = 0.5;
LK.gui.bottom.addChild(icon);
toolBarIcons.push(icon);
// Selection logic for each slot
(function (i, key, icon) {
icon.down = function (x, y, obj) {
// Only allow selection if player has the tool
var hasTool = false;
if (key === 'sword' && playerWeapon && playerWeapon.type === 'sword') hasTool = true;else if (key === 'bow' && playerWeapon && playerWeapon.type === 'bow') hasTool = true;else if (key === 'fishingrod' && player && player.inventory && player.inventory.fishingrod > 0) hasTool = true;else if (key === 'axe' && player && player.inventory && player.inventory.axe > 0) hasTool = true;else if (key === 'pickaxe' && player && player.inventory && player.inventory.pickaxe > 0) hasTool = true;
if (!hasTool) {
LK.effects.flashObject(icon, 0xff4444, 400);
return;
}
toolBarSelected = i;
for (var j = 0; j < toolBarIcons.length; j++) {
toolBarIcons[j].alpha = j === i ? 1.0 : 0.5;
}
// Set weaponToolSelected for compatibility
weaponToolSelected = key;
updateUI();
};
})(i, key, icon);
}
// Set initial selection highlight
toolBarIcons[toolBarSelected].alpha = 1.0;
// --- Weapon/Tool Selection UI ---
// Move tool/weapon inventory to right side
var weaponToolList = [{
key: 'sword',
label: 'Sword',
asset: 'wood',
tint: 0xcccccc
}, {
key: 'bow',
label: 'Bow',
asset: 'wood',
tint: 0x8fd3ff
}, {
key: 'fishingrod',
label: 'Fishing Rod',
asset: 'wood',
tint: 0x3fa7d6
}];
var weaponToolIcons = [];
var weaponToolSelected = null;
var weaponToolStartY = 120;
var weaponToolSpacing = 110;
for (var i = 0; i < weaponToolList.length; i++) {
var w = weaponToolList[i];
var icon = LK.getAsset(w.asset, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.9,
scaleY: 0.9,
x: 2048 - 120,
y: weaponToolStartY + i * weaponToolSpacing
});
icon.tint = w.tint;
icon.alpha = 0.5;
icon.visible = false;
LK.gui.right.addChild(icon);
weaponToolIcons.push(icon);
// Selection logic
(function (i, w, icon) {
icon.down = function (x, y, obj) {
// Only allow selection if player has the item
if (w.key === 'sword' && playerWeapon && playerWeapon.type === 'sword') {
weaponToolSelected = 'sword';
} else if (w.key === 'bow' && playerWeapon && playerWeapon.type === 'bow') {
weaponToolSelected = 'bow';
} else if (w.key === 'fishingrod' && player.inventory.fishingrod > 0) {
weaponToolSelected = 'fishingrod';
} else {
LK.effects.flashObject(icon, 0xff4444, 400);
return;
}
// Highlight selected
for (var j = 0; j < weaponToolIcons.length; j++) {
weaponToolIcons[j].alpha = j === i ? 1.0 : 0.5;
}
};
})(i, w, icon);
}
var invIcons = [];
var invTexts = [];
var invStartY = 120;
var invSpacing = 70;
for (var i = 0; i < resourceList.length; i++) {
var r = resourceList[i];
var icon = LK.getAsset(r.asset, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 0.7,
x: 60,
y: invStartY + i * invSpacing
});
icon.tint = r.tint;
LK.gui.topLeft.addChild(icon);
invIcons.push(icon);
var txt = new Text2(r.label + ': 0', {
size: 32,
fill: "#fff"
});
txt.anchor.set(0, 0.5);
txt.x = 110;
txt.y = invStartY + i * invSpacing;
LK.gui.topLeft.addChild(txt);
invTexts.push(txt);
}
// --- Crafting UI for workstations ---
// --- Helper functions ---
function updateUI() {
healthTxt.setText('Health: ' + Math.max(0, Math.round(player.health)));
hungerTxt.setText('Hunger: ' + Math.max(0, Math.round(player.hunger)));
dayTxt.setText('Day: ' + day);
// Count cooked meat on ground (not in inventory)
var cookedMeatCount = 0;
for (var i = 0; i < resources.length; i++) {
if (resources[i].type === 'meat' && resources[i].cookedMeat) cookedMeatCount++;
}
// Update new vertical inventory UI
for (var i = 0; i < resourceList.length; i++) {
var r = resourceList[i];
var val = player && player.inventory && typeof player.inventory[r.key] !== "undefined" ? player.inventory[r.key] : 0;
// Special case for meat: show cooked count if any
if (r.key === 'meat') {
invTexts[i].setText(r.label + ': ' + val + (cookedMeatCount > 0 ? ' (Cooked: ' + cookedMeatCount + ')' : ''));
} else if (r.key === 'magicrealmportal') {
if (val > 0) {
invTexts[i].setText(r.label + ': ' + val);
invIcons[i].visible = inventoryOpen;
invTexts[i].visible = inventoryOpen;
} else {
invTexts[i].setText(r.label + ': 0');
invIcons[i].visible = false;
invTexts[i].visible = false;
}
} else {
invTexts[i].setText(r.label + ': ' + val);
// Always show MagicWood, hide other icons/texts if not yet discovered
if (r.key === 'magicwood' || val > 0) {
invIcons[i].visible = inventoryOpen;
invTexts[i].visible = inventoryOpen;
} else if (r.key !== 'magicwood') {
invIcons[i].visible = false;
invTexts[i].visible = false;
}
}
}
}
// Update tool bar slot visibility and highlight
for (var i = 0; i < toolBarSlots; i++) {
var key = toolBarKeys[i];
var icon = toolBarIcons[i];
var hasTool = false;
if (key === 'sword' && playerWeapon && playerWeapon.type === 'sword') hasTool = true;else if (key === 'bow' && playerWeapon && playerWeapon.type === 'bow') hasTool = true;else if (key === 'fishingrod' && player && player.inventory && player.inventory.fishingrod > 0) hasTool = true;else if (key === 'axe' && player && player.inventory && player.inventory.axe > 0) hasTool = true;else if (key === 'pickaxe' && player && player.inventory && player.inventory.pickaxe > 0) hasTool = true;
icon.alpha = i === toolBarSelected && hasTool ? 1.0 : hasTool ? 0.7 : 0.2;
icon.visible = hasTool;
}
// Set weaponToolSelected to selected tool bar slot for game logic compatibility
if (toolBarSelected >= 0 && toolBarSelected < toolBarKeys.length) {
weaponToolSelected = toolBarKeys[toolBarSelected];
}
function spawnResource(type, x, y) {
var res;
if (type === 'wood') {
res = new Wood();
} else if (type === 'stone') {
res = new Stone();
} else if (type === 'berry') {
res = new Berry();
} else if (type === 'iron') {
res = new Resource();
res.type = 'iron';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0xaaaaaa;
} else if (type === 'gold') {
res = new Resource();
res.type = 'gold';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0xffd700;
} else if (type === 'diamond') {
res = new Resource();
res.type = 'diamond';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0x00ffff;
} else if (type === 'ruby') {
res = new Resource();
res.type = 'ruby';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0xff0044;
} else if (type === 'emerald') {
res = new Resource();
res.type = 'emerald';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0x00ff44;
} else if (type === 'coal') {
res = new Resource();
res.type = 'coal';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0x222222;
}
res.x = x;
res.y = y;
resources.push(res);
game.addChild(res);
}
function spawnInteractable(type, x, y) {
var obj;
if (type === 'tree') {
obj = new Tree();
} else if (type === 'rock') {
obj = new Rock();
} else if (type === 'bush') {
obj = new Bush();
}
obj.x = x;
obj.y = y;
interactables.push(obj);
game.addChild(obj);
}
function removeResource(res) {
res.destroy();
var idx = resources.indexOf(res);
if (idx !== -1) resources.splice(idx, 1);
}
function removeInteractable(obj) {
obj.destroy();
var idx = interactables.indexOf(obj);
if (idx !== -1) interactables.splice(idx, 1);
}
function showNightOverlay() {
if (!nightOverlay) {
nightOverlay = LK.getAsset('nightOverlay', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
nightOverlay.alpha = 0.5;
game.addChild(nightOverlay);
} else {
nightOverlay.alpha = 0.5;
}
}
function hideNightOverlay() {
if (nightOverlay) nightOverlay.alpha = 0;
}
// --- Zombie spawning and cleanup ---
function spawnZombie() {
var z;
if (inMine) {
z = new Skeleton();
} else {
z = new Zombie();
}
// Spawn at random edge
var edge = Math.floor(Math.random() * 4);
if (edge === 0) {
// left
z.x = 0;
z.y = 400 + Math.random() * 1800;
} else if (edge === 1) {
// right
z.x = 2048;
z.y = 400 + Math.random() * 1800;
} else if (edge === 2) {
// top
z.x = 200 + Math.random() * 1600;
z.y = 0;
} else {
// bottom
z.x = 200 + Math.random() * 1600;
z.y = 2732;
}
z.target = player;
zombies.push(z);
game.addChild(z);
}
function clearZombies() {
for (var i = 0; i < zombies.length; i++) {
zombies[i].destroy();
}
zombies = [];
}
function startZombieSpawning() {
zombieSpawnTimer = LK.setInterval(function () {
if (isNight) {
spawnZombie();
}
}, 2500);
}
function stopZombieSpawning() {
if (zombieSpawnTimer) LK.clearInterval(zombieSpawnTimer);
clearZombies();
}
function startDayNightCycle() {
dayNightTimer = LK.setInterval(function () {
isNight = !isNight;
if (isNight) {
showNightOverlay();
// On night of day 3, spawn Wood Golem boss
if (day === 3) {
// Remove all zombies before boss
clearZombies();
// Spawn Wood Golem near player
var golem = new WoodGolem();
golem.x = player.x + 400;
golem.y = player.y;
golem.target = player;
zombies.push(golem);
game.addChild(golem);
// Show boss message
var bossMsg = new Text2('A Wood Golem has appeared!', {
size: 60,
fill: 0xFFCC00
});
bossMsg.anchor.set(0.5, 0.5);
bossMsg.x = 2048 / 2;
bossMsg.y = 2732 / 2 - 200;
LK.gui.center.addChild(bossMsg);
LK.setTimeout(function () {
bossMsg.destroy();
}, 3000);
} else {
startZombieSpawning();
}
} else {
hideNightOverlay();
stopZombieSpawning();
day += 1;
updateUI();
}
}, 20000); // 20 seconds per phase
}
function stopDayNightCycle() {
if (dayNightTimer) LK.clearInterval(dayNightTimer);
}
function startHunger() {
hungerTimer = LK.setInterval(function () {
if (isNight && !player.hasShelter) {
player.health -= 2;
}
player.hunger -= 1;
if (player.hunger <= 0) {
player.health -= 2;
}
if (player.health <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
updateUI();
}, 1200);
}
function stopHunger() {
if (hungerTimer) LK.clearInterval(hungerTimer);
}
function tryCollectResource(res) {
if (res.type === 'wood') {
player.inventory.wood += 1;
} else if (res.type === 'stone') {
player.inventory.stone += 1;
} else if (res.type === 'berry') {
player.inventory.berry += 1;
player.hunger = Math.min(100, player.hunger + 10);
} else if (res.type === 'iron') {
player.inventory.iron += 1;
} else if (res.type === 'gold') {
player.inventory.gold += 1;
} else if (res.type === 'diamond') {
player.inventory.diamond += 1;
} else if (res.type === 'ruby') {
player.inventory.ruby += 1;
} else if (res.type === 'emerald') {
player.inventory.emerald += 1;
} else if (res.type === 'coal') {
player.inventory.coal += 1;
} else if (res.type === 'magicwood') {
player.inventory.magicwood = (player.inventory.magicwood || 0) + 1;
// Show Magic Realm button if not already present
if (!window.magicRealmBtn) {
window.magicRealmBtn = new Text2('Magic Realm: Locked', {
size: 48,
fill: 0xB084FF
});
window.magicRealmBtn.anchor.set(0.5, 0);
// Place just above the Enter Mine button (mineBtn.y = -380)
window.magicRealmBtn.y = -420;
window.magicRealmBtn.x = 640;
LK.gui.bottom.addChild(window.magicRealmBtn);
// Button is locked until magicwood is collected
window.magicRealmBtn._unlocked = false;
window.magicRealmBtn.down = function (x, y, obj) {
if (!window.magicRealmBtn._unlocked) {
// Optionally flash or show a message
LK.effects.flashObject(window.magicRealmBtn, 0xff4444, 400);
return;
}
// Enter Magic Realm logic (placeholder)
var msg = new Text2('You have entered the Magic Realm!\n(More content coming soon)', {
size: 54,
fill: 0xB084FF
});
msg.anchor.set(0.5, 0.5);
msg.x = 2048 / 2;
msg.y = 2732 / 2;
LK.gui.center.addChild(msg);
LK.setTimeout(function () {
msg.destroy();
}, 3500);
};
}
// Unlock the button and update text if not already unlocked
if (window.magicRealmBtn && !window.magicRealmBtn._unlocked) {
window.magicRealmBtn.setText('Magic Realm: Unlocked');
window.magicRealmBtn._unlocked = true;
}
} else if (res.type === 'meat') {
// Check if cooked (cookedMeat property set by furnace)
if (res.cookedMeat) {
player.inventory.meat = (player.inventory.meat || 0) + 1;
player.hunger = Math.min(100, player.hunger + 60);
player.health = Math.min(100, player.health + 40);
} else {
player.inventory.meat = (player.inventory.meat || 0) + 1;
player.hunger = Math.min(100, player.hunger + 50);
player.health = Math.min(100, player.health + 20);
}
} else if (res.type === 'fish') {
player.inventory.fish = (player.inventory.fish || 0) + 1;
player.hunger = Math.min(100, player.hunger + 30);
player.health = Math.min(100, player.health + 10);
}
removeResource(res);
updateUI();
}
function tryInteract(obj) {
if (obj.type === 'tree') {
spawnResource('wood', obj.x + Math.random() * 60 - 30, obj.y + 80);
removeInteractable(obj);
} else if (obj.type === 'rock') {
spawnResource('stone', obj.x, obj.y + 40);
removeInteractable(obj);
} else if (obj.type === 'bush') {
spawnResource('berry', obj.x, obj.y + 20);
removeInteractable(obj);
}
// Furnace: cook meat if player has raw meat
else if (obj.type === 'furnace') {
if (player.inventory.meat && player.inventory.meat > 0) {
// Remove 1 raw meat, add 1 cooked meat resource at furnace position
player.inventory.meat -= 1;
var cookedMeat = new Meat();
cookedMeat.x = obj.x;
cookedMeat.y = obj.y + 40;
cookedMeat.cookedMeat = true; // Mark as cooked
// Tint to look cooked
cookedMeat.children[0].tint = 0xff6600;
resources.push(cookedMeat);
game.addChild(cookedMeat);
updateUI();
}
}
}
function canBuildShelter() {
return !player.hasShelter && player.inventory.wood >= 5 && player.inventory.stone >= 3;
}
function buildShelter() {
player.inventory.wood -= 5;
player.inventory.stone -= 3;
player.hasShelter = true;
shelter = new Shelter();
shelter.x = player.x + 180;
shelter.y = player.y + 100;
game.addChild(shelter);
updateUI();
}
function canBuildRaft() {
return !player.hasRaft && player.inventory.wood >= 10 && player.inventory.stone >= 5;
}
function buildRaft() {
player.inventory.wood -= 10;
player.inventory.stone -= 5;
player.hasRaft = true;
raft = new Raft();
raft.x = 2048 - 300;
raft.y = 2732 - 200;
game.addChild(raft);
updateUI();
}
function tryEscape() {
if (player.hasRaft && Math.abs(player.x - raft.x) < 150 && Math.abs(player.y - raft.y) < 150) {
LK.showYouWin();
}
}
// --- Placeable Furnace ---
var furnaces = [];
function placeFurnace(x, y) {
var furnace = new Container();
furnace.type = 'furnace';
furnace.attachAsset('rock', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 0.8
});
furnace.children[0].tint = 0x444444;
furnace.x = x;
furnace.y = y;
furnaces.push(furnace);
game.addChild(furnace);
return furnace;
}
// Place furnace on tap if player has one in inventory
game.down = function (origDown) {
return function (x, y, obj) {
// Place furnace if player has one and tap is not on UI
if (player.inventory.furnace && player.inventory.furnace > 0 && y > 120) {
placeFurnace(x, y);
player.inventory.furnace -= 1;
updateUI();
return;
}
origDown.call(this, x, y, obj);
};
}(game.down);
// --- Game Setup ---
function setupIsland() {
// Place trees, rocks, bushes randomly
for (var i = 0; i < 6; i++) {
spawnInteractable('tree', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
}
for (var i = 0; i < 5; i++) {
spawnInteractable('rock', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
}
for (var i = 0; i < 4; i++) {
spawnInteractable('bush', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
}
// New resource spawns
for (var i = 0; i < 3; i++) {
spawnResource('iron', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
spawnResource('gold', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
spawnResource('diamond', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
spawnResource('ruby', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
spawnResource('emerald', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
spawnResource('coal', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
}
// Spawn cows
for (var i = 0; i < 3; i++) {
var cow = new Cow();
cow.x = 300 + Math.random() * 1500;
cow.y = 500 + Math.random() * 1700;
cows.push(cow);
game.addChild(cow);
}
}
// --- Player Setup ---
player = new Player();
player.x = 2048 / 2;
player.y = 2732 / 2;
game.addChild(player);
// --- Sea region (bottom of map) ---
var seaY = 2732 - 350;
var seaHeight = 350;
var sea = LK.getAsset('nightOverlay', {
anchorX: 0,
anchorY: 0,
x: 0,
y: seaY,
scaleX: 1,
scaleY: seaHeight / 2732
});
sea.alpha = 0.7;
sea.tint = 0x1e90ff;
game.addChild(sea);
// --- Sea region (bottom of map) ---
var seaSafePlatform = LK.getAsset('raft', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 1.5,
x: 2048 / 2,
y: 2732 - 180
});
seaSafePlatform.tint = 0xdeb887;
seaSafePlatform.visible = false; // Hide by default, only show in sea
game.addChild(seaSafePlatform);
setupIsland();
updateUI();
startDayNightCycle();
startHunger();
// --- Mine Button ---
mineBtn = new Text2('Enter Mine', {
size: 36,
fill: 0xeeeeee
});
mineBtn.anchor.set(0.5, 0);
mineBtn.y = -380;
mineBtn.x = 640;
LK.gui.bottom.addChild(mineBtn);
// --- Sea Button ---
var seaBtn = new Text2('Enter Sea', {
size: 36,
fill: 0x1e90ff
});
seaBtn.anchor.set(0.5, 0);
seaBtn.y = -320;
seaBtn.x = 640;
LK.gui.bottom.addChild(seaBtn);
var inSea = false;
// --- Setup Mine ---
function setupMine() {
// Clear previous mine resources/interactables
for (var i = 0; i < mineResources.length; i++) {
mineResources[i].destroy();
}
for (var i = 0; i < mineInteractables.length; i++) {
mineInteractables[i].destroy();
}
mineResources = [];
mineInteractables = [];
// Spawn lots of stone, iron, diamond, coal, ruby (no wood or berries in mine)
for (var i = 0; i < 18; i++) {
var t = Math.random();
var type = 'stone';
if (t < 0.18) type = 'iron';else if (t < 0.36) type = 'diamond';else if (t < 0.54) type = 'coal';else if (t < 0.72) type = 'ruby';
// else stone
var x = 200 + Math.random() * 1600;
var y = 400 + Math.random() * 1800;
var res = null;
if (type === 'stone') {
res = new Stone();
} else if (type === 'iron') {
res = new Resource();
res.type = 'iron';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0xaaaaaa;
} else if (type === 'diamond') {
res = new Resource();
res.type = 'diamond';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0x00ffff;
} else if (type === 'coal') {
res = new Resource();
res.type = 'coal';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0x222222;
} else if (type === 'ruby') {
res = new Resource();
res.type = 'ruby';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0xff0044;
}
res.x = x;
res.y = y;
mineResources.push(res);
}
// Add to game
for (var i = 0; i < mineResources.length; i++) {
game.addChild(mineResources[i]);
}
// Add some rocks as interactables (no trees or bushes in mine)
for (var i = 0; i < 6; i++) {
var rock = new Rock();
rock.x = 200 + Math.random() * 1600;
rock.y = 400 + Math.random() * 1800;
mineInteractables.push(rock);
game.addChild(rock);
}
}
// --- Touch Controls ---
// Mine button logic
mineBtn.down = function (x, y, obj) {
if (!inMine) {
// Enter mine
inMine = true;
inSea = false; // Exiting sea if in it
seaSafePlatform.visible = false; // Hide platform in mine
game.setBackgroundColor(0x000000);
// Hide all island resources/interactables
for (var i = 0; i < resources.length; i++) {
resources[i].visible = false;
}
for (var i = 0; i < interactables.length; i++) {
interactables[i].visible = false;
}
if (shelter) shelter.visible = false;
if (raft) raft.visible = false;
// Remove zombies from screen
for (var i = 0; i < zombies.length; i++) {
zombies[i].visible = false;
}
// Remove arrows from screen
for (var i = 0; i < arrows.length; i++) {
arrows[i].visible = false;
}
// Setup mine
setupMine();
// Move player to mine entrance
player.x = 2048 / 2;
player.y = 2732 / 2;
player.visible = true;
// Change button text
mineBtn.setText('Exit Mine');
seaBtn.setText('Enter Sea');
} else {
// Exit mine
inMine = false;
// Restore background to sky blue for island
game.setBackgroundColor(0x87ceeb);
// Remove mine resources/interactables
for (var i = 0; i < mineResources.length; i++) {
mineResources[i].destroy();
}
for (var i = 0; i < mineInteractables.length; i++) {
mineInteractables[i].destroy();
}
mineResources = [];
mineInteractables = [];
// Show all island resources/interactables
for (var i = 0; i < resources.length; i++) {
resources[i].visible = true;
}
for (var i = 0; i < interactables.length; i++) {
interactables[i].visible = true;
}
if (shelter) shelter.visible = true;
if (raft) raft.visible = true;
seaSafePlatform.visible = false; // Hide platform on island
// Show zombies/arrows again
for (var i = 0; i < zombies.length; i++) {
zombies[i].visible = true;
}
for (var i = 0; i < arrows.length; i++) {
arrows[i].visible = true;
}
// Move player to island center
player.x = 2048 / 2;
player.y = 2732 / 2;
player.visible = true;
// Change button text
mineBtn.setText('Enter Mine');
seaBtn.setText('Enter Sea');
}
};
// Sea button logic
seaBtn.down = function (x, y, obj) {
if (!inSea) {
// Enter sea region
inSea = true;
inMine = false; // Exiting mine if in it
// Hide all island resources/interactables
for (var i = 0; i < resources.length; i++) {
resources[i].visible = false;
}
for (var i = 0; i < interactables.length; i++) {
interactables[i].visible = false;
}
if (shelter) shelter.visible = false;
if (raft) raft.visible = false;
// Remove zombies from screen
for (var i = 0; i < zombies.length; i++) {
zombies[i].visible = false;
}
// Remove arrows from screen
for (var i = 0; i < arrows.length; i++) {
arrows[i].visible = false;
}
// Remove mine resources/interactables if coming from mine
for (var i = 0; i < mineResources.length; i++) {
mineResources[i].visible = false;
}
for (var i = 0; i < mineInteractables.length; i++) {
mineInteractables[i].visible = false;
}
// Show safe platform ONLY in sea
seaSafePlatform.visible = true;
// Make sure player is visible
player.visible = true;
// Move player to sea region (bottom center, on platform)
player.x = 2048 / 2;
player.y = 2732 - 180;
// Set background to sea blue
game.setBackgroundColor(0x1e90ff);
seaBtn.setText('Exit Sea');
mineBtn.setText('Enter Mine');
} else {
// Exit sea region, return to island
inSea = false;
// Hide safe platform ONLY when leaving sea
seaSafePlatform.visible = false;
// Restore background to sky blue for island
game.setBackgroundColor(0x87ceeb);
// Show all island resources/interactables
for (var i = 0; i < resources.length; i++) {
resources[i].visible = true;
}
for (var i = 0; i < interactables.length; i++) {
interactables[i].visible = true;
}
if (shelter) shelter.visible = true;
if (raft) raft.visible = true;
// Show zombies/arrows again
for (var i = 0; i < zombies.length; i++) {
zombies[i].visible = true;
}
for (var i = 0; i < arrows.length; i++) {
arrows[i].visible = true;
}
// Show mine resources/interactables if coming from mine
for (var i = 0; i < mineResources.length; i++) {
mineResources[i].visible = false;
}
for (var i = 0; i < mineInteractables.length; i++) {
mineInteractables[i].visible = false;
}
// Move player to island center
player.x = 2048 / 2;
player.y = 2732 / 2;
player.visible = true;
seaBtn.setText('Enter Sea');
mineBtn.setText('Enter Mine');
}
};
game.down = function (x, y, obj) {
// Don't allow dragging from top left 100x100
if (x < 100 && y < 100) return;
// --- FISHING LOGIC ---
if (!inMine && weaponToolSelected === 'fishingrod' && player.inventory.fishingrod && inSea && seaSafePlatform.visible) {
// Only allow fishing if on platform
var platX = 2048 / 2;
var platY = 2732 - 180;
var platW = seaSafePlatform.width * 0.5 - 40;
var platH = seaSafePlatform.height * 0.5 - 20;
if (player.x >= platX - platW && player.x <= platX + platW && player.y >= platY - platH && player.y <= platY + platH) {
// 30% chance to catch a fish
if (Math.random() < 0.3) {
var fish = new Fish();
fish.x = player.x;
fish.y = y;
resources.push(fish);
game.addChild(fish);
// Instantly collect
tryCollectResource(fish);
// Show message
var fishMsg = new Text2('You caught a fish!', {
size: 40,
fill: 0x3fa7d6
});
fishMsg.anchor.set(0.5, 0.5);
fishMsg.x = 2048 / 2;
fishMsg.y = 2732 / 2 - 300;
LK.gui.center.addChild(fishMsg);
LK.setTimeout(function () {
fishMsg.destroy();
}, 1200);
} else {
// Show fail message
var failMsg = new Text2('No fish this time...', {
size: 32,
fill: 0x888888
});
failMsg.anchor.set(0.5, 0.5);
failMsg.x = 2048 / 2;
failMsg.y = 2732 / 2 - 300;
LK.gui.center.addChild(failMsg);
LK.setTimeout(function () {
failMsg.destroy();
}, 900);
}
return;
}
}
// --- WEAPON ATTACK ---
if (playerWeapon && weaponToolSelected === playerWeapon.type) {
// Sword: tap near player to attack
if (playerWeapon.type === 'sword') {
if (LK.ticks - playerWeapon.lastAttackTick > playerWeapon.cooldown) {
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 < playerWeapon.range) {
z.destroy();
zombies.splice(i, 1);
playerWeapon.lastAttackTick = LK.ticks;
LK.effects.flashObject(playerWeapon, 0xffff00, 200);
break;
}
}
}
}
// Bow: tap anywhere to shoot arrow toward tap
else if (playerWeapon.type === 'bow') {
if (LK.ticks - playerWeapon.lastAttackTick > playerWeapon.cooldown) {
// Require at least 1 arrow in inventory to shoot
if (player.inventory.arrow && player.inventory.arrow > 0) {
// Find closest zombie or cow in range
var closest = null;
var minDist = 99999;
// Check zombies
for (var i = 0; i < zombies.length; 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 < playerWeapon.range && dist < minDist) {
closest = z;
minDist = dist;
}
}
// Check cows if no zombie is closer
for (var i = 0; i < cows.length; i++) {
var cow = cows[i];
var dx = cow.x - player.x;
var dy = cow.y - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < playerWeapon.range && dist < minDist) {
closest = cow;
minDist = dist;
}
}
if (closest) {
var arrow = new Arrow();
arrow.x = player.x + 60;
arrow.y = player.y;
arrow.target = closest;
arrows.push(arrow);
game.addChild(arrow);
player.inventory.arrow -= 1;
updateUI();
playerWeapon.lastAttackTick = LK.ticks;
LK.effects.flashObject(playerWeapon, 0x66ccff, 200);
}
}
}
}
}
// Check if touching interactable
if (!inMine) {
for (var i = 0; i < interactables.length; i++) {
var it = interactables[i];
if (player.intersects(it)) {
selectedInteractable = it;
return;
}
}
// Check if touching cow
// (No longer collect cows by touch; must use arrows to hunt)
// Check if touching resource
for (var j = 0; j < resources.length; j++) {
var res = resources[j];
if (player.intersects(res)) {
tryCollectResource(res);
return;
}
}
} else {
// In mine: check mine interactables/resources
for (var i = 0; i < mineInteractables.length; i++) {
var it = mineInteractables[i];
if (player.intersects(it)) {
// Use same logic as rocks
spawnResource('stone', it.x, it.y + 40);
it.destroy();
mineInteractables.splice(i, 1);
updateUI();
return;
}
}
for (var j = 0; j < mineResources.length; j++) {
var res = mineResources[j];
if (player.intersects(res)) {
// Use tryCollectResource logic, but remove from mineResources
if (res.type === 'wood') {
player.inventory.wood += 1;
} else if (res.type === 'stone') {
player.inventory.stone += 1;
} else if (res.type === 'berry') {
player.inventory.berry += 1;
player.hunger = Math.min(100, player.hunger + 10);
} else if (res.type === 'iron') {
player.inventory.iron += 1;
} else if (res.type === 'gold') {
player.inventory.gold += 1;
} else if (res.type === 'diamond') {
player.inventory.diamond += 1;
} else if (res.type === 'ruby') {
player.inventory.ruby += 1;
} else if (res.type === 'emerald') {
player.inventory.emerald += 1;
} else if (res.type === 'coal') {
player.inventory.coal += 1;
}
res.destroy();
mineResources.splice(j, 1);
updateUI();
return;
}
}
}
// Check if touching raft
if (raft && player.intersects(raft)) {
tryEscape();
return;
}
// Start dragging player
dragging = true;
dragOffset.x = x - player.x;
dragOffset.y = y - player.y;
};
// --- Restrict player to central island, surrounded by sea ---
// Define island bounds (oval/ellipse for more natural shape)
var islandCenterX = 2048 / 2;
var islandCenterY = 2732 / 2 + 100;
var islandRadiusX = 700;
var islandRadiusY = 900;
// --- Piranha enemy for sea region ---
var piranhas = [];
var piranhaSpawnTimer = null;
// Spawn piranhas in sea region
function spawnPiranha() {
// Only spawn if in sea
if (!inSea || inMine) return;
var p = new Piranha();
// Spawn at random edge of sea region (bottom 350px)
var edge = Math.floor(Math.random() * 4);
if (edge === 0) {
// left
p.x = 0;
p.y = 2732 - 350 + Math.random() * 350;
} else if (edge === 1) {
// right
p.x = 2048;
p.y = 2732 - 350 + Math.random() * 350;
} else if (edge === 2) {
// top
p.x = Math.random() * 2048;
p.y = 2732 - 350;
} else {
// bottom
p.x = Math.random() * 2048;
p.y = 2732;
}
piranhas.push(p);
game.addChild(p);
}
// Start/stop piranha spawning
function startPiranhaSpawning() {
if (piranhaSpawnTimer) return;
piranhaSpawnTimer = LK.setInterval(function () {
// Only spawn if player is in sea region
if (!inMine && inSea) {
spawnPiranha();
}
}, 1800);
}
function stopPiranhaSpawning() {
if (piranhaSpawnTimer) LK.clearInterval(piranhaSpawnTimer);
for (var i = 0; i < piranhas.length; i++) {
piranhas[i].destroy();
}
piranhas = [];
}
// Helper: is player on island (no longer restricts with ellipse, always true if not in sea or mine)
function isPlayerOnIsland() {
return !inSea && !inMine;
}
// Restrict player to island area
game.move = function (x, y, obj) {
if (dragging) {
// Calculate intended position
var px = x - dragOffset.x;
var py = y - dragOffset.y;
// Clamp to game bounds first
px = Math.max(60, Math.min(2048 - 60, px));
py = Math.max(120, Math.min(2732 - 60, py));
if (inSea && !inMine) {
// Restrict to safe platform in sea ONLY, no ellipse logic
var platX = 2048 / 2;
var platY = 2732 - 180;
var platW = seaSafePlatform.width * 0.5 - 40;
var platH = seaSafePlatform.height * 0.5 - 20;
px = Math.max(platX - platW, Math.min(platX + platW, px));
py = Math.max(platY - platH, Math.min(platY + platH, py));
} else {
// No ellipse boundary for island or mine, allow full movement except for game bounds
}
player.x = px;
player.y = py;
// If shelter exists, keep it near player
if (shelter) {
shelter.x = player.x + 180;
shelter.y = player.y + 100;
}
}
};
// Start piranha spawning on game start
startPiranhaSpawning();
game.up = function (x, y, obj) {
dragging = false;
if (selectedInteractable) {
if (player.intersects(selectedInteractable)) {
tryInteract(selectedInteractable);
}
selectedInteractable = null;
}
};
// --- New Craft Panel on left side ---
var craftPanelContainer = new Container();
LK.gui.left.addChild(craftPanelContainer);
// Panel title
var craftPanelTitle = new Text2('Craft', {
size: 54,
fill: "#fff"
});
craftPanelTitle.anchor.set(0, 0);
craftPanelTitle.x = 0;
craftPanelTitle.y = 120;
craftPanelContainer.addChild(craftPanelTitle);
// Craftable items for the panel (benches, weapons, tools)
var craftPanelItems = [{
key: 'shelter',
name: 'Shelter',
icon: 'shelter',
cost: [{
key: 'wood',
label: 'Wood',
amount: 5
}, {
key: 'stone',
label: 'Stone',
amount: 3
}],
canCraft: canBuildShelter,
craft: function craft() {
if (canBuildShelter()) buildShelter();
}
}, {
key: 'raft',
name: 'Raft',
icon: 'raft',
cost: [{
key: 'wood',
label: 'Wood',
amount: 10
}, {
key: 'stone',
label: 'Stone',
amount: 5
}],
canCraft: canBuildRaft,
craft: function craft() {
if (canBuildRaft()) buildRaft();
}
}, {
key: 'fishingrod',
name: 'Fishing Rod',
icon: 'wood',
cost: [{
key: 'wood',
label: 'Wood',
amount: 3
}, {
key: 'stone',
label: 'Stone',
amount: 1
}],
canCraft: canCraftFishingRod,
craft: craftFishingRod
}, {
key: 'sword',
name: 'Sword',
icon: 'wood',
cost: [{
key: 'wood',
label: 'Wood',
amount: 3
}, {
key: 'stone',
label: 'Stone',
amount: 2
}],
canCraft: canCraftSword,
craft: craftSword
}, {
key: 'bow',
name: 'Bow',
icon: 'wood',
cost: [{
key: 'wood',
label: 'Wood',
amount: 4
}, {
key: 'berry',
label: 'Berries',
amount: 2
}],
canCraft: canCraftBow,
craft: craftBow
}, {
key: 'arrows',
name: '5 Arrows',
icon: 'wood',
cost: [{
key: 'wood',
label: 'Wood',
amount: 1
}, {
key: 'stone',
label: 'Stone',
amount: 1
}],
canCraft: canCraftArrows,
craft: craftArrows
}, {
key: 'workbench',
name: 'Workbench',
icon: 'wood',
cost: [{
key: 'wood',
label: 'Wood',
amount: 6
}, {
key: 'stone',
label: 'Stone',
amount: 2
}],
canCraft: canCraftWorkbench,
craft: craftWorkbench
}, {
key: 'furnace',
name: 'Furnace',
icon: 'rock',
cost: [{
key: 'stone',
label: 'Stone',
amount: 8
}, {
key: 'coal',
label: 'Coal',
amount: 2
}],
canCraft: canCraftFurnace,
craft: craftFurnace
}, {
key: 'armorbench',
name: 'Armor Bench',
icon: 'wood',
cost: [{
key: 'wood',
label: 'Wood',
amount: 4
}, {
key: 'iron',
label: 'Iron',
amount: 2
}],
canCraft: canCraftArmorBench,
craft: craftArmorBench
}, {
key: 'weaponbench',
name: 'Weapon Bench',
icon: 'wood',
cost: [{
key: 'wood',
label: 'Wood',
amount: 4
}, {
key: 'stone',
label: 'Stone',
amount: 2
}, {
key: 'iron',
label: 'Iron',
amount: 1
}],
canCraft: canCraftWeaponBench,
craft: craftWeaponBench
}];
// Layout for craft panel with vertical scroll
var panelStartY = 200;
var panelSpacing = 120;
var craftPanelScrollY = 0;
var craftPanelMinScroll = 0;
var craftPanelMaxScroll = Math.max(0, craftPanelItems.length * panelSpacing + panelStartY - (2048 - 200)); // 2048 is game height, 200 is top margin
// Store all craft panel item containers for scrolling
var craftPanelItemContainers = [];
for (var i = 0; i < craftPanelItems.length; i++) {
(function (i) {
var item = craftPanelItems[i];
var y = panelStartY + i * panelSpacing;
// Container for this craft item row
var rowContainer = new Container();
rowContainer.y = y;
craftPanelContainer.addChild(rowContainer);
craftPanelItemContainers.push(rowContainer);
// Box background
var box = LK.getAsset('wood', {
anchorX: 0,
anchorY: 0,
scaleX: 3.2,
scaleY: 1.2,
x: 0,
y: 0
});
box.alpha = 0.7;
rowContainer.addChild(box);
// Icon
var icon = LK.getAsset(item.icon, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 1.1,
x: 90,
y: 60
});
if (item.key === 'furnace') icon.tint = 0x444444;
rowContainer.addChild(icon);
// Name
var nameTxt = new Text2(item.name, {
size: 38,
fill: "#fff"
});
nameTxt.anchor.set(0, 0.5);
nameTxt.x = 180;
nameTxt.y = 36;
rowContainer.addChild(nameTxt);
// Cost
var costStr = '';
for (var c = 0; c < item.cost.length; c++) {
var cost = item.cost[c];
var have = player.inventory[cost.key] || 0;
costStr += cost.label + ': ' + have + '/' + cost.amount;
if (c < item.cost.length - 1) costStr += ' ';
}
var costTxt = new Text2(costStr, {
size: 28,
fill: "#fff"
});
costTxt.anchor.set(0, 0.5);
costTxt.x = 180;
costTxt.y = 80;
rowContainer.addChild(costTxt);
// Craft button
var btn = new Text2('Craft', {
size: 34,
fill: item.canCraft() ? 0xB084FF : 0x888888
});
btn.anchor.set(0, 0.5);
btn.x = 30;
btn.y = 60;
rowContainer.addChild(btn);
btn.down = function (x, y, obj) {
if (item.canCraft()) {
item.craft();
updateCraftPanel();
} else {
LK.effects.flashObject(btn, 0xff4444, 400);
}
};
// Store for update
item._costTxt = costTxt;
item._btn = btn;
})(i);
}
// --- Craft Panel Scrolling Logic ---
// Touch drag scroll
var craftPanelDragging = false;
var craftPanelLastY = 0;
var craftPanelStartScrollY = 0;
// Touch start
craftPanelContainer.down = function (x, y, obj) {
// Only start drag if not on a button (avoid conflict)
craftPanelDragging = true;
craftPanelLastY = y;
craftPanelStartScrollY = craftPanelScrollY;
};
// Touch move
craftPanelContainer.move = function (x, y, obj) {
if (craftPanelDragging) {
var dy = y - craftPanelLastY;
craftPanelScrollY = craftPanelStartScrollY + dy;
// Clamp scroll
craftPanelScrollY = Math.max(-((craftPanelItems.length - 1) * panelSpacing), Math.min(0, craftPanelScrollY));
// Apply scroll to all rows
for (var i = 0; i < craftPanelItemContainers.length; i++) {
craftPanelItemContainers[i].y = panelStartY + i * panelSpacing + craftPanelScrollY;
}
}
};
// Touch end
craftPanelContainer.up = function (x, y, obj) {
craftPanelDragging = false;
};
// Mouse wheel scroll (desktop)
craftPanelContainer.event = function (obj) {
if (obj.event && obj.event.type === 'wheel') {
var delta = obj.event.deltaY || obj.event.detail || 0;
craftPanelScrollY -= delta * 0.5;
// Clamp scroll
craftPanelScrollY = Math.max(-((craftPanelItems.length - 1) * panelSpacing), Math.min(0, craftPanelScrollY));
for (var i = 0; i < craftPanelItemContainers.length; i++) {
craftPanelItemContainers[i].y = panelStartY + i * panelSpacing + craftPanelScrollY;
}
}
};
// Register wheel event on LK.gui.left (for desktop)
if (typeof LK.gui.left.event === "undefined") {
LK.gui.left.event = function (obj) {
if (obj.event && obj.event.type === 'wheel') {
craftPanelContainer.event(obj);
}
};
}
// Initial scroll position
for (var i = 0; i < craftPanelItemContainers.length; i++) {
craftPanelItemContainers[i].y = panelStartY + i * panelSpacing + craftPanelScrollY;
}
// Update function for craft panel
function updateCraftPanel() {
for (var i = 0; i < craftPanelItems.length; i++) {
var item = craftPanelItems[i];
// Update cost
var costStr = '';
for (var c = 0; c < item.cost.length; c++) {
var cost = item.cost[c];
var have = player.inventory[cost.key] || 0;
costStr += cost.label + ': ' + have + '/' + cost.amount;
if (c < item.cost.length - 1) costStr += ' ';
}
if (item._costTxt) item._costTxt.setText(costStr);
// Update button color
if (item._btn) item._btn.fill = item.canCraft() ? 0xB084FF : 0x888888;
}
}
// Patch updateUI to also update craft panel
var _oldUpdateUI = updateUI;
updateUI = function updateUI() {
_oldUpdateUI();
updateCraftPanel();
};
// --- Craft Sword and Bow Buttons (hidden, replaced by menu) ---
var craftShelterBtn = new Text2('Build Shelter', {
size: 40,
fill: 0xFFE4B5
});
craftShelterBtn.anchor.set(0.5, 0);
craftShelterBtn.y = -180;
craftShelterBtn.x = 0;
craftShelterBtn.visible = false;
LK.gui.bottom.addChild(craftShelterBtn);
var craftRaftBtn = new Text2('Build Raft', {
size: 40,
fill: 0xFFE4B5
});
craftRaftBtn.anchor.set(0.5, 0);
craftRaftBtn.y = -220;
craftRaftBtn.x = 0;
craftRaftBtn.visible = false;
LK.gui.bottom.addChild(craftRaftBtn);
var craftSwordBtn = new Text2('Craft Sword', {
size: 40,
fill: 0xeeeeee
});
craftSwordBtn.anchor.set(0.5, 0);
craftSwordBtn.y = -260;
craftSwordBtn.x = 0;
craftSwordBtn.visible = false;
LK.gui.bottom.addChild(craftSwordBtn);
var craftBowBtn = new Text2('Craft Bow', {
size: 40,
fill: 0xeeeeee
});
craftBowBtn.anchor.set(0.5, 0);
craftBowBtn.y = -300;
craftBowBtn.x = 0;
craftBowBtn.visible = false;
LK.gui.bottom.addChild(craftBowBtn);
// --- Crafting logic for workstations ---
function canCraftWorkbench() {
return player.inventory.wood >= 6 && player.inventory.stone >= 2;
}
function canCraftFurnace() {
return player.inventory.stone >= 8 && player.inventory.coal >= 2;
}
function canCraftArmorBench() {
return player.inventory.wood >= 4 && player.inventory.iron >= 2;
}
function canCraftWeaponBench() {
return player.inventory.wood >= 4 && player.inventory.stone >= 2 && player.inventory.iron >= 1;
}
function craftWorkbench() {
player.inventory.wood -= 6;
player.inventory.stone -= 2;
player.inventory.workbench += 1;
updateUI();
}
function craftFurnace() {
player.inventory.stone -= 8;
player.inventory.coal -= 2;
player.inventory.furnace += 1;
updateUI();
}
function craftArmorBench() {
player.inventory.wood -= 4;
player.inventory.iron -= 2;
player.inventory.armorbench += 1;
updateUI();
}
function craftWeaponBench() {
player.inventory.wood -= 4;
player.inventory.stone -= 2;
player.inventory.iron -= 1;
player.inventory.weaponbench += 1;
updateUI();
}
craftShelterBtn.down = function (x, y, obj) {
if (canBuildShelter()) {
buildShelter();
}
};
craftRaftBtn.down = function (x, y, obj) {
if (canBuildRaft()) {
buildRaft();
}
};
// --- Crafting logic for sword, bow, and arrows ---
function canCraftSword() {
return (!playerWeapon || playerWeapon.type !== 'sword') && player.inventory.wood >= 3 && player.inventory.stone >= 2;
}
function canCraftBow() {
return (!playerWeapon || playerWeapon.type !== 'bow') && player.inventory.wood >= 4 && player.inventory.berry >= 2;
}
// Craft 5 arrows for 1 wood and 1 stone
function canCraftArrows() {
return player.inventory.wood >= 1 && player.inventory.stone >= 1;
}
// --- Fishing Rod Crafting ---
function canCraftFishingRod() {
return (player.inventory.fishingrod || 0) < 1 && player.inventory.wood >= 3 && player.inventory.stone >= 1;
}
function craftFishingRod() {
player.inventory.wood -= 3;
player.inventory.stone -= 1;
player.inventory.fishingrod = (player.inventory.fishingrod || 0) + 1;
// No need to add to hand, just update inventory/tool bar
updateUI();
}
// --- Magic Realm Portal Crafting ---
function canCraftMagicRealmPortal() {
return (player.inventory.magicwood || 0) >= 10 && player.inventory.wood >= 10 && player.inventory.stone >= 5 && player.inventory.ruby >= 1;
}
function craftMagicRealmPortal() {
player.inventory.magicwood -= 10;
player.inventory.wood -= 10;
player.inventory.stone -= 5;
player.inventory.ruby -= 1;
player.inventory.magicrealmportal = (player.inventory.magicrealmportal || 0) + 1;
updateUI();
// Show message
var msg = new Text2('Magic Realm Portal crafted!\nUse it from your inventory.', {
size: 48,
fill: 0xB084FF
});
msg.anchor.set(0.5, 0.5);
msg.x = 2048 / 2;
msg.y = 2732 / 2 - 100;
LK.gui.center.addChild(msg);
LK.setTimeout(function () {
msg.destroy();
}, 2500);
}
// Magic Realm Portal Craft Button
var craftMagicRealmPortalBtn = new Text2('Craft Magic Realm Portal', {
size: 40,
fill: 0xB084FF
});
craftMagicRealmPortalBtn.anchor.set(0.5, 0);
craftMagicRealmPortalBtn.y = -360;
craftMagicRealmPortalBtn.x = 640;
LK.gui.bottom.addChild(craftMagicRealmPortalBtn);
craftMagicRealmPortalBtn.down = function (x, y, obj) {
if (canCraftMagicRealmPortal()) {
craftMagicRealmPortal();
} else {
LK.effects.flashObject(craftMagicRealmPortalBtn, 0xff4444, 400);
}
};
function craftSword() {
player.inventory.wood -= 3;
player.inventory.stone -= 2;
// Remove old sword if any
if (playerWeapon && playerWeapon.type === 'sword') {
playerWeapon.destroy();
playerWeapon = null;
}
// Add sword to extra inventory (not to hand or tool bar)
playerWeapon = new Sword();
playerWeapon.x = -9999; // Hide offscreen, not in hand
playerWeapon.y = -9999;
game.addChild(playerWeapon);
updateUI();
}
function craftBow() {
player.inventory.wood -= 4;
player.inventory.berry -= 2;
// Remove old bow if any
if (playerWeapon && playerWeapon.type === 'bow') {
playerWeapon.destroy();
playerWeapon = null;
}
// Add bow to extra inventory (not to hand or tool bar)
playerWeapon = new Bow();
playerWeapon.x = -9999; // Hide offscreen, not in hand
playerWeapon.y = -9999;
game.addChild(playerWeapon);
updateUI();
}
function craftArrows() {
player.inventory.wood -= 1;
player.inventory.stone -= 1;
player.inventory.arrow += 5;
updateUI();
}
craftSwordBtn.down = function (x, y, obj) {
if (canCraftSword()) {
craftSword();
}
};
craftBowBtn.down = function (x, y, obj) {
if (canCraftBow()) {
craftBow();
}
};
// Arrow crafting button
var craftArrowBtn = new Text2('Craft 5 Arrows', {
size: 40,
fill: 0xeeeeee
});
craftArrowBtn.anchor.set(0.5, 0);
craftArrowBtn.y = -340;
craftArrowBtn.x = 320;
LK.gui.bottom.addChild(craftArrowBtn);
craftArrowBtn.down = function (x, y, obj) {
if (canCraftArrows()) {
craftArrows();
}
};
// --- Game Update Loop ---
game.update = function () {
// Randomly respawn resources
if (LK.ticks % 180 === 0) {
var t = Math.random();
if (t < 0.33) {
spawnInteractable('tree', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
} else if (t < 0.66) {
spawnInteractable('rock', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
} else {
spawnInteractable('bush', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
}
}
// --- COW LOGIC ---
for (var i = 0; i < cows.length; i++) {
cows[i].update();
}
// --- ZOMBIE LOGIC ---
for (var i = zombies.length - 1; i >= 0; i--) {
var z = zombies[i];
z.update();
// If zombie reaches player
if (z.lastWasIntersecting === undefined) z.lastWasIntersecting = false;
var nowIntersect = z.intersects(player);
if (!z.lastWasIntersecting && nowIntersect) {
if (!player.hasShelter) {
player.health -= z.damage;
LK.effects.flashObject(player, 0xff0000, 400);
updateUI();
if (player.health <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
}
}
z.lastWasIntersecting = nowIntersect;
// Remove zombie if dead or off screen
if (z.x < -100 || z.x > 2148 || z.y < -100 || z.y > 2832) {
z.destroy();
zombies.splice(i, 1);
}
}
// --- ARROW LOGIC ---
for (var j = arrows.length - 1; j >= 0; j--) {
var a = arrows[j];
a.update();
// Hit zombie or Wood Golem?
var arrowHit = false;
for (var k = zombies.length - 1; k >= 0; k--) {
var z = zombies[k];
if (a.intersects(z)) {
// If Wood Golem
if (z.type === 'woodgolem') {
// Only take full damage from sword, reduced from bow
var isBow = a.type === 'arrow';
var dmg = a.damage || 18;
var dead = z.takeDamage(dmg, isBow ? 'bow' : 'sword');
LK.effects.flashObject(z, 0x00ff00, 200);
a.destroy();
arrows.splice(j, 1);
arrowHit = true;
if (dead) {
// Drop 20 Magic Infused Wood at golem's position
for (var mw = 0; mw < 20; mw++) {
var magicWood = new Resource();
magicWood.type = 'magicwood';
magicWood.attachAsset('wood', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
magicWood.children[0].tint = 0x8e44ad; // purple tint
magicWood.x = z.x + (Math.random() - 0.5) * 80;
magicWood.y = z.y + 80 + (Math.random() - 0.5) * 40;
resources.push(magicWood);
game.addChild(magicWood);
}
// Drop 20 Wood
for (var wd = 0; wd < 20; wd++) {
var woodDrop = new Wood();
woodDrop.x = z.x + (Math.random() - 0.5) * 120;
woodDrop.y = z.y + 100 + (Math.random() - 0.5) * 60;
resources.push(woodDrop);
game.addChild(woodDrop);
}
// Drop 20 Berries
for (var bd = 0; bd < 20; bd++) {
var berryDrop = new Berry();
berryDrop.x = z.x + (Math.random() - 0.5) * 120;
berryDrop.y = z.y + 120 + (Math.random() - 0.5) * 60;
resources.push(berryDrop);
game.addChild(berryDrop);
}
// Drop 1 Ruby
var rubyDrop = new Resource();
rubyDrop.type = 'ruby';
rubyDrop.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
rubyDrop.children[0].tint = 0xff0044;
rubyDrop.x = z.x + (Math.random() - 0.5) * 60;
rubyDrop.y = z.y + 140;
resources.push(rubyDrop);
game.addChild(rubyDrop);
// Drop 1 Stone
var stoneDrop = new Stone();
stoneDrop.x = z.x + (Math.random() - 0.5) * 60;
stoneDrop.y = z.y + 160;
resources.push(stoneDrop);
game.addChild(stoneDrop);
// Show message for Magic Realm Portal craft
var msg = new Text2('You obtained Magic Infused Wood!\nYou can now craft the Magic Realm Portal!', {
size: 54,
fill: 0xB084FF
});
msg.anchor.set(0.5, 0.5);
msg.x = 2048 / 2;
msg.y = 2732 / 2 - 200;
LK.gui.center.addChild(msg);
LK.setTimeout(function () {
msg.destroy();
}, 3500);
z.destroy();
zombies.splice(k, 1);
}
break;
} else {
z.destroy();
zombies.splice(k, 1);
a.destroy();
arrows.splice(j, 1);
arrowHit = true;
break;
}
}
}
// Hit cow?
if (!arrowHit) {
for (var c = cows.length - 1; c >= 0; c--) {
var cow = cows[c];
if (a.intersects(cow)) {
// Drop meat at cow's position
var meat = new Meat();
meat.x = cow.x;
meat.y = cow.y;
resources.push(meat);
game.addChild(meat);
cow.destroy();
cows.splice(c, 1);
a.destroy();
arrows.splice(j, 1);
arrowHit = true;
break;
}
}
}
// Remove arrow if off screen
if (!arrowHit && (a.x < -100 || a.x > 2148 || a.y < -100 || a.y > 2832)) {
a.destroy();
arrows.splice(j, 1);
}
}
// --- WEAPON FOLLOW PLAYER ---
if (playerWeapon) {
playerWeapon.x = player.x + 60;
playerWeapon.y = player.y;
}
// --- PLAYER COLOR LOGIC FOR SEA ---
if (player && player.children && player.children[0]) {
if (inSea && !inMine) {
player.children[0].tint = 0x00ff44; // green in sea
} else {
player.children[0].tint = 0x2d8cff; // blue elsewhere
}
}
// --- PIRANHA LOGIC ---
// Only active if player is in sea (on platform)
if (!inMine && inSea) {
// Show warning
healthTxt.tint = 0xff2222;
// Platform bounds (same as in Piranha)
var platX = 2048 / 2;
var platY = 2732 - 180;
var platW = 350;
var platH = 110;
// Check if player is on platform
var onPlatform = player.x >= platX - platW && player.x <= platX + platW && player.y >= platY - platH && player.y <= platY + platH;
// If player is off platform, apply sea damage
if (!onPlatform) {
player.health -= 0.5;
if (player.health < 0) player.health = 0;
}
// Piranha movement and collision
for (var i = piranhas.length - 1; i >= 0; i--) {
var p = piranhas[i];
p.update();
if (p.lastWasIntersecting === undefined) p.lastWasIntersecting = false;
// Only check collision if player is NOT on platform
var nowIntersect = !onPlatform && p.intersects(player);
if (!p.lastWasIntersecting && nowIntersect) {
player.health -= p.damage;
LK.effects.flashObject(player, 0xff2222, 400);
if (player.health <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
}
p.lastWasIntersecting = nowIntersect;
// Remove piranha if off screen (sea region is bottom 350px)
if (p.y < 2732 - 350 || p.x < -200 || p.x > 2248 || p.y > 2932) {
p.destroy();
piranhas.splice(i, 1);
}
}
} else {
// Not in sea, reset health color and remove piranhas
healthTxt.tint = isNight && !player.hasShelter ? 0xff4444 : 0xffffff;
for (var i = 0; i < piranhas.length; i++) {
piranhas[i].destroy();
}
piranhas = [];
}
// If night and no shelter, health drops faster
if (isNight && !player.hasShelter && isPlayerOnIsland()) {
healthTxt.tint = 0xff4444;
} else if (isPlayerOnIsland()) {
healthTxt.tint = 0xffffff;
}
// If raft built, show escape hint
if (player.hasRaft && raft) {
// Optionally, could show a message
}
};
// --- Cleanup on Game Over/Win ---
LK.on('gameover', function () {
stopDayNightCycle();
stopHunger();
stopZombieSpawning();
clearZombies();
for (var i = 0; i < arrows.length; i++) {
arrows[i].destroy();
}
arrows = [];
if (playerWeapon) {
playerWeapon.destroy();
playerWeapon = null;
}
stopPiranhaSpawning();
});
LK.on('youwin', function () {
stopDayNightCycle();
stopHunger();
stopZombieSpawning();
clearZombies();
for (var i = 0; i < arrows.length; i++) {
arrows[i].destroy();
}
arrows = [];
if (playerWeapon) {
playerWeapon.destroy();
playerWeapon = null;
}
stopPiranhaSpawning();
}); /****
* Plugins
****/
var tween = LK.import("@upit/tween.v1");
var storage = LK.import("@upit/storage.v1");
/****
* Classes
****/
// Arrow projectile
var Arrow = Container.expand(function () {
var self = Container.call(this);
self.type = 'arrow';
self.speed = 38;
self.damage = 18;
self.target = null;
self.lastX = 0;
self.lastY = 0;
self.attachAsset('wood', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.5,
scaleY: 0.2
});
self.children[0].tint = 0xffe066;
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
if (self.target) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 2) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
}
};
return self;
});
// Bow weapon
var Bow = Container.expand(function () {
var self = Container.call(this);
self.type = 'bow';
self.damage = 18;
self.range = 600;
self.cooldown = 50;
self.lastAttackTick = -1000;
self.attachAsset('wood', {
anchorX: 0.5,
anchorY: 0.5
});
self.children[0].tint = 0x8fd3ff;
return self;
});
// Bush (for berries)
var Bush = Container.expand(function () {
var self = Container.call(this);
self.type = 'bush';
self.attachAsset('bush', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Cow (passive animal)
var Cow = Container.expand(function () {
var self = Container.call(this);
self.type = 'cow';
self.speed = 2 + Math.random() * 1.5;
self.lastX = 0;
self.lastY = 0;
self.attachAsset('cow', {
anchorX: 0.5,
anchorY: 0.5
});
// Add a simple face (optional, for fun)
// self.children[0].tint = 0xffffff; // already white
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
// Simple random walk
if (!self._moveDir || LK.ticks % 120 === 0) {
var angle = Math.random() * Math.PI * 2;
self._moveDir = {
x: Math.cos(angle),
y: Math.sin(angle)
};
}
self.x += self._moveDir.x * self.speed;
self.y += self._moveDir.y * self.speed;
// Stay in bounds
if (self.x < 120) {
self.x = 120;
self._moveDir.x *= -1;
}
if (self.x > 2048 - 120) {
self.x = 2048 - 120;
self._moveDir.x *= -1;
}
if (self.y < 200) {
self.y = 200;
self._moveDir.y *= -1;
}
if (self.y > 2732 - 120) {
self.y = 2732 - 120;
self._moveDir.y *= -1;
}
};
return self;
});
var Piranha = Container.expand(function () {
var self = Container.call(this);
self.type = 'piranha';
self.speed = 3 + Math.random() * 2.5;
self.lastX = 0;
self.lastY = 0;
self._moveDir = null;
self.damage = 18;
self.attachAsset('berry', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 0.7
});
self.children[0].tint = 0xff2222;
// Platform bounds (same as in game.move)
var platX = 2048 / 2;
var platY = 2732 - 180;
var platW = 350; // seaSafePlatform.width * 0.5 - 40, but static for logic
var platH = 110; // seaSafePlatform.height * 0.5 - 20, but static for logic
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
// Only move if in sea and not in mine
if (inSea && !inMine) {
// Random walk like cow
if (!self._moveDir || LK.ticks % 120 === 0) {
var angle = Math.random() * Math.PI * 2;
self._moveDir = {
x: Math.cos(angle),
y: Math.sin(angle)
};
}
self.x += self._moveDir.x * self.speed;
self.y += self._moveDir.y * self.speed;
// Clamp to sea region (bottom 350px)
if (self.x < 0) {
self.x = 0;
self._moveDir.x *= -1;
}
if (self.x > 2048) {
self.x = 2048;
self._moveDir.x *= -1;
}
if (self.y < 2732 - 350) {
self.y = 2732 - 350;
self._moveDir.y *= -1;
}
if (self.y > 2732) {
self.y = 2732;
self._moveDir.y *= -1;
}
// Avoid safe platform: if inside platform area, bounce out
if (self.x >= platX - platW && self.x <= platX + platW && self.y >= platY - platH && self.y <= platY + platH) {
// Move away from platform center
var dx = self.x - platX;
var dy = self.y - platY;
var dist = Math.sqrt(dx * dx + dy * dy) || 1;
self.x = platX + dx / dist * (platW + 10);
self.y = platY + dy / dist * (platH + 10);
// Change direction
var angle = Math.atan2(dy, dx) + (Math.random() - 0.5) * 0.7;
self._moveDir = {
x: Math.cos(angle),
y: Math.sin(angle)
};
}
}
};
return self;
});
// Spawn piranhas in sea region
// Player class
var Player = Container.expand(function () {
var self = Container.call(this);
var playerSprite = self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.speed = 18;
self.inventory = {
wood: 0,
stone: 0,
berry: 0,
meat: 0,
iron: 0,
gold: 0,
diamond: 0,
ruby: 0,
emerald: 0,
coal: 0,
arrow: 0,
// arrows for bow
// Workstations
workbench: 0,
furnace: 0,
armorbench: 0,
weaponbench: 0
};
self.health = 100;
self.hunger = 100;
self.hasShelter = false;
self.hasRaft = false;
self.update = function () {};
return self;
});
// Raft
var Raft = Container.expand(function () {
var self = Container.call(this);
self.attachAsset('raft', {
anchorX: 0.5,
anchorY: 1
});
return self;
});
// Resource base class
var Resource = Container.expand(function () {
var self = Container.call(this);
self.type = '';
self.collected = false;
self.update = function () {};
return self;
});
// Wood resource
var Wood = Resource.expand(function () {
var self = Resource.call(this);
self.type = 'wood';
self.attachAsset('wood', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Stone resource
var Stone = Resource.expand(function () {
var self = Resource.call(this);
self.type = 'stone';
self.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Meat resource (from cow)
var Meat = Resource.expand(function () {
var self = Resource.call(this);
self.type = 'meat';
self.attachAsset('berry', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 0.8
});
self.children[0].tint = 0xffa07a; // salmon color for meat
return self;
});
// --- Add fish resource type ---
var Fish = Resource.expand(function () {
var self = Resource.call(this);
self.type = 'fish';
self.attachAsset('berry', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 0.7
});
self.children[0].tint = 0x3fa7d6;
return self;
});
// --- Initial Island ---
// Berry resource
var Berry = Resource.expand(function () {
var self = Resource.call(this);
self.type = 'berry';
self.attachAsset('berry', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Rock (for stone)
var Rock = Container.expand(function () {
var self = Container.call(this);
self.type = 'rock';
self.attachAsset('rock', {
anchorX: 0.5,
anchorY: 0.5
});
return self;
});
// Shelter
var Shelter = Container.expand(function () {
var self = Container.call(this);
self.attachAsset('shelter', {
anchorX: 0.5,
anchorY: 1
});
return self;
});
// Skeleton enemy (shoots arrows at player in mine)
var Skeleton = Container.expand(function () {
var self = Container.call(this);
self.type = 'skeleton';
self.speed = 3 + Math.random() * 1.5;
self.target = null;
self.damage = 10;
self.lastX = 0;
self.lastY = 0;
self.shootCooldown = 90 + Math.floor(Math.random() * 60);
self.lastShootTick = -1000;
self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.children[0].tint = 0xffffff; // white skeleton
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
if (self.target) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 2) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
// Shoot arrow at player if cooldown
if (LK.ticks - self.lastShootTick > self.shootCooldown && dist < 800) {
var arrow = new Arrow();
arrow.x = self.x;
arrow.y = self.y;
arrow.target = self.target;
arrow.speed = 22;
arrow.damage = 12;
arrow.isEnemy = true;
arrows.push(arrow);
game.addChild(arrow);
self.lastShootTick = LK.ticks;
}
}
};
return self;
});
// Sword weapon
var Sword = Container.expand(function () {
var self = Container.call(this);
self.type = 'sword';
self.damage = 30;
self.range = 180;
self.cooldown = 30;
self.lastAttackTick = -1000;
self.attachAsset('wood', {
anchorX: 0.5,
anchorY: 0.5
});
self.children[0].tint = 0xcccccc;
return self;
});
// Tree (for wood)
var Tree = Container.expand(function () {
var self = Container.call(this);
self.type = 'tree';
self.attachAsset('tree', {
anchorX: 0.5,
anchorY: 1
});
return self;
});
// Wood Golem boss (appears on day 3, drops Magic Infused Wood)
var WoodGolem = Container.expand(function () {
var self = Container.call(this);
self.type = 'woodgolem';
self.maxHealth = 300;
self.health = self.maxHealth;
self.speed = 2.2;
self.target = null;
self.damage = 30;
self.lastX = 0;
self.lastY = 0;
self.lastWasIntersecting = false;
self.resistantToBow = true;
self.attachAsset('wood', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.2,
scaleY: 2.2
});
self.children[0].tint = 0x7c4f19; // dark wood color
// Health bar
var barBg = new Container();
var bar = LK.getAsset('wood', {
anchorX: 0,
anchorY: 0,
scaleX: 1,
scaleY: 0.15
});
bar.tint = 0x333333;
barBg.addChild(bar);
var barFg = LK.getAsset('wood', {
anchorX: 0,
anchorY: 0,
scaleX: 1,
scaleY: 0.15
});
barFg.tint = 0x00ff00;
barBg.addChild(barFg);
barBg.y = -120;
barBg.x = -60;
self.addChild(barBg);
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
if (self.target) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 2) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
}
// Update health bar
barFg.scaleX = Math.max(0, self.health / self.maxHealth);
};
// Take damage (returns true if dead)
self.takeDamage = function (amount, type) {
// If hit by bow, take only 10% damage
if (type === 'bow' && self.resistantToBow) {
amount = Math.ceil(amount * 0.1);
}
self.health -= amount;
if (self.health <= 0) {
self.health = 0;
return true;
}
return false;
};
return self;
});
// Zombie enemy (for night on island)
var Zombie = Container.expand(function () {
var self = Container.call(this);
self.type = 'zombie';
self.speed = 3 + Math.random() * 1.5;
self.target = null;
self.damage = 12;
self.lastX = 0;
self.lastY = 0;
self.attachAsset('player', {
anchorX: 0.5,
anchorY: 0.5
});
self.children[0].tint = 0x228b22; // greenish for zombie
self.update = function () {
self.lastX = self.x;
self.lastY = self.y;
if (self.target) {
var dx = self.target.x - self.x;
var dy = self.target.y - self.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist > 2) {
self.x += dx / dist * self.speed;
self.y += dy / dist * self.speed;
}
}
};
return self;
});
/****
* Initialize Game
****/
var game = new LK.Game({
backgroundColor: 0x87ceeb // Sky blue for day
});
/****
* Game Code
****/
// Shapes for resources, player, and environment
// --- Global variables ---
var player;
var resources = [];
var interactables = [];
var cows = [];
var shelter = null;
var raft = null;
var day = 1;
var isNight = false;
var nightOverlay;
var hungerTimer;
var dayNightTimer;
var dragging = false;
var dragOffset = {
x: 0,
y: 0
};
var selectedInteractable = null;
// --- Mine dimension ---
var inMine = false;
var mineBtn = null;
var mineResources = [];
var mineInteractables = [];
// --- Zombies, weapons, arrows ---
var zombies = [];
var zombieSpawnTimer = null;
var playerWeapon = null;
var arrows = [];
// --- UI Elements ---
var healthTxt = new Text2('Health: 100', {
size: 40,
fill: "#fff"
});
healthTxt.anchor.set(0, 0);
LK.gui.top.addChild(healthTxt);
var hungerTxt = new Text2('Hunger: 100', {
size: 40,
fill: "#fff"
});
hungerTxt.anchor.set(0, 0);
LK.gui.top.addChild(hungerTxt);
hungerTxt.y = 50;
var dayTxt = new Text2('Day: 1', {
size: 40,
fill: "#fff"
});
dayTxt.anchor.set(0, 0);
LK.gui.top.addChild(dayTxt);
dayTxt.y = 100;
// --- Inventory UI for all resources ---
// --- Inventory UI for all resources ---
// --- Inventory Toggle Button ---
var inventoryOpen = true;
var inventoryBtn = new Text2('Inventory', {
size: 44,
fill: "#fff"
});
inventoryBtn.anchor.set(0.5, 0);
// Move inventory button to top left, but not in 100x100 area
inventoryBtn.x = 180;
inventoryBtn.y = 120;
LK.gui.top.addChild(inventoryBtn);
inventoryBtn.down = function (x, y, obj) {
inventoryOpen = !inventoryOpen;
// Toggle visibility of inventory icons/texts
for (var i = 0; i < invIcons.length; i++) {
invIcons[i].visible = inventoryOpen && (invIcons[i].visible || false);
invTexts[i].visible = inventoryOpen && (invTexts[i].visible || false);
}
if (extraInventoryPanel) {
extraInventoryPanel.visible = inventoryOpen && extraInventoryPanel._shouldBeVisible;
}
};
// --- Extra Inventory Button and Panel for Crafted Items ---
var extraInventoryOpen = false;
var extraInventoryBtn = new Text2('Extra Inv', {
size: 44,
fill: "#fff"
});
extraInventoryBtn.anchor.set(0.5, 0);
extraInventoryBtn.x = 420;
extraInventoryBtn.y = 120;
LK.gui.top.addChild(extraInventoryBtn);
var extraInventoryPanel = new Container();
extraInventoryPanel.visible = false;
extraInventoryPanel._shouldBeVisible = false;
LK.gui.top.addChild(extraInventoryPanel);
// Layout for extra inventory panel
var extraInvStartY = 200;
var extraInvSpacing = 90;
var extraInvSlots = [{
key: 'sword',
label: 'Sword',
asset: 'wood',
tint: 0xcccccc
}, {
key: 'bow',
label: 'Bow',
asset: 'wood',
tint: 0x8fd3ff
}, {
key: 'fishingrod',
label: 'Fishing Rod',
asset: 'wood',
tint: 0x3fa7d6
}];
var extraInvIcons = [];
var extraInvTexts = [];
for (var i = 0; i < extraInvSlots.length; i++) {
var slot = extraInvSlots[i];
var yPos = extraInvStartY + i * extraInvSpacing;
var icon = LK.getAsset(slot.asset, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.9,
scaleY: 0.9,
x: 60,
y: yPos
});
icon.tint = slot.tint;
extraInventoryPanel.addChild(icon);
extraInvIcons.push(icon);
var txt = new Text2(slot.label, {
size: 32,
fill: "#fff"
});
txt.anchor.set(0, 0.5);
txt.x = 110;
txt.y = yPos;
extraInventoryPanel.addChild(txt);
extraInvTexts.push(txt);
// --- Kuşan and İncele buttons ---
var kusanBtn = new Text2('Kuşan', {
size: 28,
fill: 0xB084FF
});
kusanBtn.anchor.set(0, 0.5);
kusanBtn.x = 320;
kusanBtn.y = yPos - 18;
extraInventoryPanel.addChild(kusanBtn);
var inceleBtn = new Text2('İncele', {
size: 28,
fill: 0xB084FF
});
inceleBtn.anchor.set(0, 0.5);
inceleBtn.x = 320;
inceleBtn.y = yPos + 18;
extraInventoryPanel.addChild(inceleBtn);
// Kuşan logic: set as selected tool in tool bar and weaponToolSelected
(function (slot, i, kusanBtn) {
kusanBtn.down = function (x, y, obj) {
// Only allow if player has the item
var canEquip = false;
if (slot.key === 'sword' && playerWeapon && playerWeapon.type === 'sword') canEquip = true;else if (slot.key === 'bow' && playerWeapon && playerWeapon.type === 'bow') canEquip = true;else if (slot.key === 'fishingrod' && player && player.inventory && player.inventory.fishingrod > 0) canEquip = true;
if (!canEquip) {
LK.effects.flashObject(kusanBtn, 0xff4444, 400);
return;
}
// Find tool bar slot for this item and select it
for (var j = 0; j < toolBarKeys.length; j++) {
if (toolBarKeys[j] === slot.key) {
toolBarSelected = j;
for (var k = 0; k < toolBarIcons.length; k++) {
toolBarIcons[k].alpha = k === j ? 1.0 : 0.5;
}
weaponToolSelected = slot.key;
updateUI();
break;
}
}
};
})(slot, i, kusanBtn);
// İncele logic: show popup with description
(function (slot, i, inceleBtn) {
inceleBtn.down = function (x, y, obj) {
var desc = "";
if (slot.key === 'sword') {
desc = "Kılıç: Yakın dövüş silahı. Zombilere ve düşmanlara yüksek hasar verir.\n\nKullanım: Düşmanlara yaklaşarak saldırabilirsin. Dayanıklıdır ve yakın mesafede etkilidir.";
} else if (slot.key === 'bow') {
desc = "Yay: Uzaktan saldırı silahı. Ok ile ateş eder, menzili yüksektir.\n\nKullanım: Uzak mesafedeki düşmanlara ok fırlatabilirsin. Ok sayın kadar kullanabilirsin.";
} else if (slot.key === 'fishingrod') {
desc = "Olta: Deniz bölgesinde balık tutmak için kullanılır.\n\nKullanım: Deniz platformunda oltayı kullanarak balık yakalayabilirsin. Balıklar açlığını azaltır.";
} else {
desc = "Alet açıklaması bulunamadı.";
}
// Show popup
var popup = new Container();
var bg = LK.getAsset('wood', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 5,
scaleY: 2,
x: 2048 / 2,
y: 2732 / 2
});
bg.alpha = 0.92;
popup.addChild(bg);
var txt = new Text2(desc, {
size: 44,
fill: "#fff"
});
txt.anchor.set(0.5, 0.5);
txt.x = 2048 / 2;
txt.y = 2732 / 2;
popup.addChild(txt);
// Kapat button
var closeBtn = new Text2('Kapat', {
size: 36,
fill: 0xB084FF
});
closeBtn.anchor.set(0.5, 0.5);
closeBtn.x = 2048 / 2;
closeBtn.y = 2732 / 2 + 120;
popup.addChild(closeBtn);
closeBtn.down = function () {
popup.destroy();
};
LK.gui.center.addChild(popup);
};
})(slot, i, inceleBtn);
}
// Show/hide logic for extra inventory
extraInventoryBtn.down = function (x, y, obj) {
extraInventoryOpen = !extraInventoryOpen;
// Always show the panel when Extra Inv is open, regardless of inventoryOpen
extraInventoryPanel.visible = extraInventoryOpen;
extraInventoryPanel._shouldBeVisible = extraInventoryOpen;
updateExtraInventoryPanel();
};
// Update function for extra inventory panel
function updateExtraInventoryPanel() {
for (var i = 0; i < extraInvSlots.length; i++) {
var slot = extraInvSlots[i];
var icon = extraInvIcons[i];
var txt = extraInvTexts[i];
var hasItem = false;
if (slot.key === 'sword' && playerWeapon && playerWeapon.type === 'sword') hasItem = true;else if (slot.key === 'bow' && playerWeapon && playerWeapon.type === 'bow') hasItem = true;else if (slot.key === 'fishingrod' && player && player.inventory && player.inventory.fishingrod > 0) hasItem = true;
icon.visible = hasItem;
txt.visible = hasItem;
if (slot.key === 'fishingrod') {
txt.setText(slot.label + (player.inventory.fishingrod > 1 ? ' x' + player.inventory.fishingrod : ''));
} else {
txt.setText(slot.label);
}
}
}
// Patch updateUI to also update extra inventory panel
var _oldUpdateUI2 = updateUI;
updateUI = function updateUI() {
_oldUpdateUI2();
updateExtraInventoryPanel();
if (extraInventoryPanel) {
// Always show the panel if Extra Inv is open, regardless of inventoryOpen
extraInventoryPanel.visible = extraInventoryOpen && extraInventoryPanel._shouldBeVisible;
}
};
var resourceList = [{
key: 'wood',
label: 'Wood',
asset: 'wood',
tint: 0x8b5a2b
}, {
key: 'stone',
label: 'Stone',
asset: 'stone',
tint: 0x888888
}, {
key: 'berry',
label: 'Berries',
asset: 'berry',
tint: 0xc0392b
}, {
key: 'meat',
label: 'Meat',
asset: 'berry',
tint: 0xffa07a
}, {
key: 'fish',
label: 'Fish',
asset: 'berry',
tint: 0x3fa7d6
}, {
key: 'iron',
label: 'Iron',
asset: 'stone',
tint: 0xaaaaaa
}, {
key: 'gold',
label: 'Gold',
asset: 'stone',
tint: 0xffd700
}, {
key: 'diamond',
label: 'Diamond',
asset: 'stone',
tint: 0x00ffff
}, {
key: 'ruby',
label: 'Ruby',
asset: 'stone',
tint: 0xff0044
}, {
key: 'emerald',
label: 'Emerald',
asset: 'stone',
tint: 0x00ff44
}, {
key: 'coal',
label: 'Coal',
asset: 'stone',
tint: 0x222222
}, {
key: 'arrow',
label: 'Arrows',
asset: 'wood',
tint: 0xffe066
}, {
key: 'magicwood',
label: 'MagicWood',
asset: 'wood',
tint: 0x8e44ad
}, {
key: 'magicrealmportal',
label: 'MagicRealmPortal',
asset: 'wood',
tint: 0xB084FF
}];
// --- 5-slot tool inventory bar at bottom center (Minecraft-style) ---
var toolBarSlots = 5;
var toolBarKeys = ['sword', 'bow', 'fishingrod', 'axe', 'pickaxe'];
var toolBarIcons = [];
var toolBarSelected = 0; // index of selected slot
// Move tool bar to a more visible location: above bottom, centered horizontally
var toolBarY = -260; // higher up from the bottom, so it's not hidden by hands or overlays
var toolBarSpacing = 180;
var toolBarStartX = 2048 / 2 - (toolBarSlots - 1) * toolBarSpacing / 2;
// Tool asset/tint mapping
var toolBarInfo = {
sword: {
asset: 'wood',
tint: 0xcccccc
},
bow: {
asset: 'wood',
tint: 0x8fd3ff
},
fishingrod: {
asset: 'wood',
tint: 0x3fa7d6
},
axe: {
asset: 'wood',
tint: 0xdeb887
},
pickaxe: {
asset: 'stone',
tint: 0xaaaaaa
}
};
for (var i = 0; i < toolBarSlots; i++) {
var key = toolBarKeys[i];
var info = toolBarInfo[key];
var icon = LK.getAsset(info.asset, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 1.1,
x: toolBarStartX + i * toolBarSpacing,
y: toolBarY
});
icon.tint = info.tint;
icon.alpha = 0.5;
LK.gui.bottom.addChild(icon);
toolBarIcons.push(icon);
// Selection logic for each slot
(function (i, key, icon) {
icon.down = function (x, y, obj) {
// Only allow selection if player has the tool
var hasTool = false;
if (key === 'sword' && playerWeapon && playerWeapon.type === 'sword') hasTool = true;else if (key === 'bow' && playerWeapon && playerWeapon.type === 'bow') hasTool = true;else if (key === 'fishingrod' && player && player.inventory && player.inventory.fishingrod > 0) hasTool = true;else if (key === 'axe' && player && player.inventory && player.inventory.axe > 0) hasTool = true;else if (key === 'pickaxe' && player && player.inventory && player.inventory.pickaxe > 0) hasTool = true;
if (!hasTool) {
LK.effects.flashObject(icon, 0xff4444, 400);
return;
}
toolBarSelected = i;
for (var j = 0; j < toolBarIcons.length; j++) {
toolBarIcons[j].alpha = j === i ? 1.0 : 0.5;
}
// Set weaponToolSelected for compatibility
weaponToolSelected = key;
updateUI();
};
})(i, key, icon);
}
// Set initial selection highlight
toolBarIcons[toolBarSelected].alpha = 1.0;
// --- Weapon/Tool Selection UI ---
// Move tool/weapon inventory to right side
var weaponToolList = [{
key: 'sword',
label: 'Sword',
asset: 'wood',
tint: 0xcccccc
}, {
key: 'bow',
label: 'Bow',
asset: 'wood',
tint: 0x8fd3ff
}, {
key: 'fishingrod',
label: 'Fishing Rod',
asset: 'wood',
tint: 0x3fa7d6
}];
var weaponToolIcons = [];
var weaponToolSelected = null;
var weaponToolStartY = 120;
var weaponToolSpacing = 110;
for (var i = 0; i < weaponToolList.length; i++) {
var w = weaponToolList[i];
var icon = LK.getAsset(w.asset, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.9,
scaleY: 0.9,
x: 2048 - 120,
y: weaponToolStartY + i * weaponToolSpacing
});
icon.tint = w.tint;
icon.alpha = 0.5;
icon.visible = false;
LK.gui.right.addChild(icon);
weaponToolIcons.push(icon);
// Selection logic
(function (i, w, icon) {
icon.down = function (x, y, obj) {
// Only allow selection if player has the item
if (w.key === 'sword' && playerWeapon && playerWeapon.type === 'sword') {
weaponToolSelected = 'sword';
} else if (w.key === 'bow' && playerWeapon && playerWeapon.type === 'bow') {
weaponToolSelected = 'bow';
} else if (w.key === 'fishingrod' && player.inventory.fishingrod > 0) {
weaponToolSelected = 'fishingrod';
} else {
LK.effects.flashObject(icon, 0xff4444, 400);
return;
}
// Highlight selected
for (var j = 0; j < weaponToolIcons.length; j++) {
weaponToolIcons[j].alpha = j === i ? 1.0 : 0.5;
}
};
})(i, w, icon);
}
var invIcons = [];
var invTexts = [];
var invStartY = 120;
var invSpacing = 70;
for (var i = 0; i < resourceList.length; i++) {
var r = resourceList[i];
var icon = LK.getAsset(r.asset, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 0.7,
scaleY: 0.7,
x: 60,
y: invStartY + i * invSpacing
});
icon.tint = r.tint;
LK.gui.topLeft.addChild(icon);
invIcons.push(icon);
var txt = new Text2(r.label + ': 0', {
size: 32,
fill: "#fff"
});
txt.anchor.set(0, 0.5);
txt.x = 110;
txt.y = invStartY + i * invSpacing;
LK.gui.topLeft.addChild(txt);
invTexts.push(txt);
}
// --- Crafting UI for workstations ---
// --- Helper functions ---
function updateUI() {
healthTxt.setText('Health: ' + Math.max(0, Math.round(player.health)));
hungerTxt.setText('Hunger: ' + Math.max(0, Math.round(player.hunger)));
dayTxt.setText('Day: ' + day);
// Count cooked meat on ground (not in inventory)
var cookedMeatCount = 0;
for (var i = 0; i < resources.length; i++) {
if (resources[i].type === 'meat' && resources[i].cookedMeat) cookedMeatCount++;
}
// Update new vertical inventory UI
for (var i = 0; i < resourceList.length; i++) {
var r = resourceList[i];
var val = player && player.inventory && typeof player.inventory[r.key] !== "undefined" ? player.inventory[r.key] : 0;
// Special case for meat: show cooked count if any
if (r.key === 'meat') {
invTexts[i].setText(r.label + ': ' + val + (cookedMeatCount > 0 ? ' (Cooked: ' + cookedMeatCount + ')' : ''));
} else if (r.key === 'magicrealmportal') {
if (val > 0) {
invTexts[i].setText(r.label + ': ' + val);
invIcons[i].visible = inventoryOpen;
invTexts[i].visible = inventoryOpen;
} else {
invTexts[i].setText(r.label + ': 0');
invIcons[i].visible = false;
invTexts[i].visible = false;
}
} else {
invTexts[i].setText(r.label + ': ' + val);
// Always show MagicWood, hide other icons/texts if not yet discovered
if (r.key === 'magicwood' || val > 0) {
invIcons[i].visible = inventoryOpen;
invTexts[i].visible = inventoryOpen;
} else if (r.key !== 'magicwood') {
invIcons[i].visible = false;
invTexts[i].visible = false;
}
}
}
}
// Update tool bar slot visibility and highlight
for (var i = 0; i < toolBarSlots; i++) {
var key = toolBarKeys[i];
var icon = toolBarIcons[i];
var hasTool = false;
if (key === 'sword' && playerWeapon && playerWeapon.type === 'sword') hasTool = true;else if (key === 'bow' && playerWeapon && playerWeapon.type === 'bow') hasTool = true;else if (key === 'fishingrod' && player && player.inventory && player.inventory.fishingrod > 0) hasTool = true;else if (key === 'axe' && player && player.inventory && player.inventory.axe > 0) hasTool = true;else if (key === 'pickaxe' && player && player.inventory && player.inventory.pickaxe > 0) hasTool = true;
icon.alpha = i === toolBarSelected && hasTool ? 1.0 : hasTool ? 0.7 : 0.2;
icon.visible = hasTool;
}
// Set weaponToolSelected to selected tool bar slot for game logic compatibility
if (toolBarSelected >= 0 && toolBarSelected < toolBarKeys.length) {
weaponToolSelected = toolBarKeys[toolBarSelected];
}
function spawnResource(type, x, y) {
var res;
if (type === 'wood') {
res = new Wood();
} else if (type === 'stone') {
res = new Stone();
} else if (type === 'berry') {
res = new Berry();
} else if (type === 'iron') {
res = new Resource();
res.type = 'iron';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0xaaaaaa;
} else if (type === 'gold') {
res = new Resource();
res.type = 'gold';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0xffd700;
} else if (type === 'diamond') {
res = new Resource();
res.type = 'diamond';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0x00ffff;
} else if (type === 'ruby') {
res = new Resource();
res.type = 'ruby';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0xff0044;
} else if (type === 'emerald') {
res = new Resource();
res.type = 'emerald';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0x00ff44;
} else if (type === 'coal') {
res = new Resource();
res.type = 'coal';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0x222222;
}
res.x = x;
res.y = y;
resources.push(res);
game.addChild(res);
}
function spawnInteractable(type, x, y) {
var obj;
if (type === 'tree') {
obj = new Tree();
} else if (type === 'rock') {
obj = new Rock();
} else if (type === 'bush') {
obj = new Bush();
}
obj.x = x;
obj.y = y;
interactables.push(obj);
game.addChild(obj);
}
function removeResource(res) {
res.destroy();
var idx = resources.indexOf(res);
if (idx !== -1) resources.splice(idx, 1);
}
function removeInteractable(obj) {
obj.destroy();
var idx = interactables.indexOf(obj);
if (idx !== -1) interactables.splice(idx, 1);
}
function showNightOverlay() {
if (!nightOverlay) {
nightOverlay = LK.getAsset('nightOverlay', {
anchorX: 0,
anchorY: 0,
x: 0,
y: 0
});
nightOverlay.alpha = 0.5;
game.addChild(nightOverlay);
} else {
nightOverlay.alpha = 0.5;
}
}
function hideNightOverlay() {
if (nightOverlay) nightOverlay.alpha = 0;
}
// --- Zombie spawning and cleanup ---
function spawnZombie() {
var z;
if (inMine) {
z = new Skeleton();
} else {
z = new Zombie();
}
// Spawn at random edge
var edge = Math.floor(Math.random() * 4);
if (edge === 0) {
// left
z.x = 0;
z.y = 400 + Math.random() * 1800;
} else if (edge === 1) {
// right
z.x = 2048;
z.y = 400 + Math.random() * 1800;
} else if (edge === 2) {
// top
z.x = 200 + Math.random() * 1600;
z.y = 0;
} else {
// bottom
z.x = 200 + Math.random() * 1600;
z.y = 2732;
}
z.target = player;
zombies.push(z);
game.addChild(z);
}
function clearZombies() {
for (var i = 0; i < zombies.length; i++) {
zombies[i].destroy();
}
zombies = [];
}
function startZombieSpawning() {
zombieSpawnTimer = LK.setInterval(function () {
if (isNight) {
spawnZombie();
}
}, 2500);
}
function stopZombieSpawning() {
if (zombieSpawnTimer) LK.clearInterval(zombieSpawnTimer);
clearZombies();
}
function startDayNightCycle() {
dayNightTimer = LK.setInterval(function () {
isNight = !isNight;
if (isNight) {
showNightOverlay();
// On night of day 3, spawn Wood Golem boss
if (day === 3) {
// Remove all zombies before boss
clearZombies();
// Spawn Wood Golem near player
var golem = new WoodGolem();
golem.x = player.x + 400;
golem.y = player.y;
golem.target = player;
zombies.push(golem);
game.addChild(golem);
// Show boss message
var bossMsg = new Text2('A Wood Golem has appeared!', {
size: 60,
fill: 0xFFCC00
});
bossMsg.anchor.set(0.5, 0.5);
bossMsg.x = 2048 / 2;
bossMsg.y = 2732 / 2 - 200;
LK.gui.center.addChild(bossMsg);
LK.setTimeout(function () {
bossMsg.destroy();
}, 3000);
} else {
startZombieSpawning();
}
} else {
hideNightOverlay();
stopZombieSpawning();
day += 1;
updateUI();
}
}, 20000); // 20 seconds per phase
}
function stopDayNightCycle() {
if (dayNightTimer) LK.clearInterval(dayNightTimer);
}
function startHunger() {
hungerTimer = LK.setInterval(function () {
if (isNight && !player.hasShelter) {
player.health -= 2;
}
player.hunger -= 1;
if (player.hunger <= 0) {
player.health -= 2;
}
if (player.health <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
updateUI();
}, 1200);
}
function stopHunger() {
if (hungerTimer) LK.clearInterval(hungerTimer);
}
function tryCollectResource(res) {
if (res.type === 'wood') {
player.inventory.wood += 1;
} else if (res.type === 'stone') {
player.inventory.stone += 1;
} else if (res.type === 'berry') {
player.inventory.berry += 1;
player.hunger = Math.min(100, player.hunger + 10);
} else if (res.type === 'iron') {
player.inventory.iron += 1;
} else if (res.type === 'gold') {
player.inventory.gold += 1;
} else if (res.type === 'diamond') {
player.inventory.diamond += 1;
} else if (res.type === 'ruby') {
player.inventory.ruby += 1;
} else if (res.type === 'emerald') {
player.inventory.emerald += 1;
} else if (res.type === 'coal') {
player.inventory.coal += 1;
} else if (res.type === 'magicwood') {
player.inventory.magicwood = (player.inventory.magicwood || 0) + 1;
// Show Magic Realm button if not already present
if (!window.magicRealmBtn) {
window.magicRealmBtn = new Text2('Magic Realm: Locked', {
size: 48,
fill: 0xB084FF
});
window.magicRealmBtn.anchor.set(0.5, 0);
// Place just above the Enter Mine button (mineBtn.y = -380)
window.magicRealmBtn.y = -420;
window.magicRealmBtn.x = 640;
LK.gui.bottom.addChild(window.magicRealmBtn);
// Button is locked until magicwood is collected
window.magicRealmBtn._unlocked = false;
window.magicRealmBtn.down = function (x, y, obj) {
if (!window.magicRealmBtn._unlocked) {
// Optionally flash or show a message
LK.effects.flashObject(window.magicRealmBtn, 0xff4444, 400);
return;
}
// Enter Magic Realm logic (placeholder)
var msg = new Text2('You have entered the Magic Realm!\n(More content coming soon)', {
size: 54,
fill: 0xB084FF
});
msg.anchor.set(0.5, 0.5);
msg.x = 2048 / 2;
msg.y = 2732 / 2;
LK.gui.center.addChild(msg);
LK.setTimeout(function () {
msg.destroy();
}, 3500);
};
}
// Unlock the button and update text if not already unlocked
if (window.magicRealmBtn && !window.magicRealmBtn._unlocked) {
window.magicRealmBtn.setText('Magic Realm: Unlocked');
window.magicRealmBtn._unlocked = true;
}
} else if (res.type === 'meat') {
// Check if cooked (cookedMeat property set by furnace)
if (res.cookedMeat) {
player.inventory.meat = (player.inventory.meat || 0) + 1;
player.hunger = Math.min(100, player.hunger + 60);
player.health = Math.min(100, player.health + 40);
} else {
player.inventory.meat = (player.inventory.meat || 0) + 1;
player.hunger = Math.min(100, player.hunger + 50);
player.health = Math.min(100, player.health + 20);
}
} else if (res.type === 'fish') {
player.inventory.fish = (player.inventory.fish || 0) + 1;
player.hunger = Math.min(100, player.hunger + 30);
player.health = Math.min(100, player.health + 10);
}
removeResource(res);
updateUI();
}
function tryInteract(obj) {
if (obj.type === 'tree') {
spawnResource('wood', obj.x + Math.random() * 60 - 30, obj.y + 80);
removeInteractable(obj);
} else if (obj.type === 'rock') {
spawnResource('stone', obj.x, obj.y + 40);
removeInteractable(obj);
} else if (obj.type === 'bush') {
spawnResource('berry', obj.x, obj.y + 20);
removeInteractable(obj);
}
// Furnace: cook meat if player has raw meat
else if (obj.type === 'furnace') {
if (player.inventory.meat && player.inventory.meat > 0) {
// Remove 1 raw meat, add 1 cooked meat resource at furnace position
player.inventory.meat -= 1;
var cookedMeat = new Meat();
cookedMeat.x = obj.x;
cookedMeat.y = obj.y + 40;
cookedMeat.cookedMeat = true; // Mark as cooked
// Tint to look cooked
cookedMeat.children[0].tint = 0xff6600;
resources.push(cookedMeat);
game.addChild(cookedMeat);
updateUI();
}
}
}
function canBuildShelter() {
return !player.hasShelter && player.inventory.wood >= 5 && player.inventory.stone >= 3;
}
function buildShelter() {
player.inventory.wood -= 5;
player.inventory.stone -= 3;
player.hasShelter = true;
shelter = new Shelter();
shelter.x = player.x + 180;
shelter.y = player.y + 100;
game.addChild(shelter);
updateUI();
}
function canBuildRaft() {
return !player.hasRaft && player.inventory.wood >= 10 && player.inventory.stone >= 5;
}
function buildRaft() {
player.inventory.wood -= 10;
player.inventory.stone -= 5;
player.hasRaft = true;
raft = new Raft();
raft.x = 2048 - 300;
raft.y = 2732 - 200;
game.addChild(raft);
updateUI();
}
function tryEscape() {
if (player.hasRaft && Math.abs(player.x - raft.x) < 150 && Math.abs(player.y - raft.y) < 150) {
LK.showYouWin();
}
}
// --- Placeable Furnace ---
var furnaces = [];
function placeFurnace(x, y) {
var furnace = new Container();
furnace.type = 'furnace';
furnace.attachAsset('rock', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 0.8
});
furnace.children[0].tint = 0x444444;
furnace.x = x;
furnace.y = y;
furnaces.push(furnace);
game.addChild(furnace);
return furnace;
}
// Place furnace on tap if player has one in inventory
game.down = function (origDown) {
return function (x, y, obj) {
// Place furnace if player has one and tap is not on UI
if (player.inventory.furnace && player.inventory.furnace > 0 && y > 120) {
placeFurnace(x, y);
player.inventory.furnace -= 1;
updateUI();
return;
}
origDown.call(this, x, y, obj);
};
}(game.down);
// --- Game Setup ---
function setupIsland() {
// Place trees, rocks, bushes randomly
for (var i = 0; i < 6; i++) {
spawnInteractable('tree', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
}
for (var i = 0; i < 5; i++) {
spawnInteractable('rock', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
}
for (var i = 0; i < 4; i++) {
spawnInteractable('bush', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
}
// New resource spawns
for (var i = 0; i < 3; i++) {
spawnResource('iron', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
spawnResource('gold', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
spawnResource('diamond', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
spawnResource('ruby', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
spawnResource('emerald', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
spawnResource('coal', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
}
// Spawn cows
for (var i = 0; i < 3; i++) {
var cow = new Cow();
cow.x = 300 + Math.random() * 1500;
cow.y = 500 + Math.random() * 1700;
cows.push(cow);
game.addChild(cow);
}
}
// --- Player Setup ---
player = new Player();
player.x = 2048 / 2;
player.y = 2732 / 2;
game.addChild(player);
// --- Sea region (bottom of map) ---
var seaY = 2732 - 350;
var seaHeight = 350;
var sea = LK.getAsset('nightOverlay', {
anchorX: 0,
anchorY: 0,
x: 0,
y: seaY,
scaleX: 1,
scaleY: seaHeight / 2732
});
sea.alpha = 0.7;
sea.tint = 0x1e90ff;
game.addChild(sea);
// --- Sea region (bottom of map) ---
var seaSafePlatform = LK.getAsset('raft', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 2.5,
scaleY: 1.5,
x: 2048 / 2,
y: 2732 - 180
});
seaSafePlatform.tint = 0xdeb887;
seaSafePlatform.visible = false; // Hide by default, only show in sea
game.addChild(seaSafePlatform);
setupIsland();
updateUI();
startDayNightCycle();
startHunger();
// --- Mine Button ---
mineBtn = new Text2('Enter Mine', {
size: 36,
fill: 0xeeeeee
});
mineBtn.anchor.set(0.5, 0);
mineBtn.y = -380;
mineBtn.x = 640;
LK.gui.bottom.addChild(mineBtn);
// --- Sea Button ---
var seaBtn = new Text2('Enter Sea', {
size: 36,
fill: 0x1e90ff
});
seaBtn.anchor.set(0.5, 0);
seaBtn.y = -320;
seaBtn.x = 640;
LK.gui.bottom.addChild(seaBtn);
var inSea = false;
// --- Setup Mine ---
function setupMine() {
// Clear previous mine resources/interactables
for (var i = 0; i < mineResources.length; i++) {
mineResources[i].destroy();
}
for (var i = 0; i < mineInteractables.length; i++) {
mineInteractables[i].destroy();
}
mineResources = [];
mineInteractables = [];
// Spawn lots of stone, iron, diamond, coal, ruby (no wood or berries in mine)
for (var i = 0; i < 18; i++) {
var t = Math.random();
var type = 'stone';
if (t < 0.18) type = 'iron';else if (t < 0.36) type = 'diamond';else if (t < 0.54) type = 'coal';else if (t < 0.72) type = 'ruby';
// else stone
var x = 200 + Math.random() * 1600;
var y = 400 + Math.random() * 1800;
var res = null;
if (type === 'stone') {
res = new Stone();
} else if (type === 'iron') {
res = new Resource();
res.type = 'iron';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0xaaaaaa;
} else if (type === 'diamond') {
res = new Resource();
res.type = 'diamond';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0x00ffff;
} else if (type === 'coal') {
res = new Resource();
res.type = 'coal';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0x222222;
} else if (type === 'ruby') {
res = new Resource();
res.type = 'ruby';
res.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
res.children[0].tint = 0xff0044;
}
res.x = x;
res.y = y;
mineResources.push(res);
}
// Add to game
for (var i = 0; i < mineResources.length; i++) {
game.addChild(mineResources[i]);
}
// Add some rocks as interactables (no trees or bushes in mine)
for (var i = 0; i < 6; i++) {
var rock = new Rock();
rock.x = 200 + Math.random() * 1600;
rock.y = 400 + Math.random() * 1800;
mineInteractables.push(rock);
game.addChild(rock);
}
}
// --- Touch Controls ---
// Mine button logic
mineBtn.down = function (x, y, obj) {
if (!inMine) {
// Enter mine
inMine = true;
inSea = false; // Exiting sea if in it
seaSafePlatform.visible = false; // Hide platform in mine
game.setBackgroundColor(0x000000);
// Hide all island resources/interactables
for (var i = 0; i < resources.length; i++) {
resources[i].visible = false;
}
for (var i = 0; i < interactables.length; i++) {
interactables[i].visible = false;
}
if (shelter) shelter.visible = false;
if (raft) raft.visible = false;
// Remove zombies from screen
for (var i = 0; i < zombies.length; i++) {
zombies[i].visible = false;
}
// Remove arrows from screen
for (var i = 0; i < arrows.length; i++) {
arrows[i].visible = false;
}
// Setup mine
setupMine();
// Move player to mine entrance
player.x = 2048 / 2;
player.y = 2732 / 2;
player.visible = true;
// Change button text
mineBtn.setText('Exit Mine');
seaBtn.setText('Enter Sea');
} else {
// Exit mine
inMine = false;
// Restore background to sky blue for island
game.setBackgroundColor(0x87ceeb);
// Remove mine resources/interactables
for (var i = 0; i < mineResources.length; i++) {
mineResources[i].destroy();
}
for (var i = 0; i < mineInteractables.length; i++) {
mineInteractables[i].destroy();
}
mineResources = [];
mineInteractables = [];
// Show all island resources/interactables
for (var i = 0; i < resources.length; i++) {
resources[i].visible = true;
}
for (var i = 0; i < interactables.length; i++) {
interactables[i].visible = true;
}
if (shelter) shelter.visible = true;
if (raft) raft.visible = true;
seaSafePlatform.visible = false; // Hide platform on island
// Show zombies/arrows again
for (var i = 0; i < zombies.length; i++) {
zombies[i].visible = true;
}
for (var i = 0; i < arrows.length; i++) {
arrows[i].visible = true;
}
// Move player to island center
player.x = 2048 / 2;
player.y = 2732 / 2;
player.visible = true;
// Change button text
mineBtn.setText('Enter Mine');
seaBtn.setText('Enter Sea');
}
};
// Sea button logic
seaBtn.down = function (x, y, obj) {
if (!inSea) {
// Enter sea region
inSea = true;
inMine = false; // Exiting mine if in it
// Hide all island resources/interactables
for (var i = 0; i < resources.length; i++) {
resources[i].visible = false;
}
for (var i = 0; i < interactables.length; i++) {
interactables[i].visible = false;
}
if (shelter) shelter.visible = false;
if (raft) raft.visible = false;
// Remove zombies from screen
for (var i = 0; i < zombies.length; i++) {
zombies[i].visible = false;
}
// Remove arrows from screen
for (var i = 0; i < arrows.length; i++) {
arrows[i].visible = false;
}
// Remove mine resources/interactables if coming from mine
for (var i = 0; i < mineResources.length; i++) {
mineResources[i].visible = false;
}
for (var i = 0; i < mineInteractables.length; i++) {
mineInteractables[i].visible = false;
}
// Show safe platform ONLY in sea
seaSafePlatform.visible = true;
// Make sure player is visible
player.visible = true;
// Move player to sea region (bottom center, on platform)
player.x = 2048 / 2;
player.y = 2732 - 180;
// Set background to sea blue
game.setBackgroundColor(0x1e90ff);
seaBtn.setText('Exit Sea');
mineBtn.setText('Enter Mine');
} else {
// Exit sea region, return to island
inSea = false;
// Hide safe platform ONLY when leaving sea
seaSafePlatform.visible = false;
// Restore background to sky blue for island
game.setBackgroundColor(0x87ceeb);
// Show all island resources/interactables
for (var i = 0; i < resources.length; i++) {
resources[i].visible = true;
}
for (var i = 0; i < interactables.length; i++) {
interactables[i].visible = true;
}
if (shelter) shelter.visible = true;
if (raft) raft.visible = true;
// Show zombies/arrows again
for (var i = 0; i < zombies.length; i++) {
zombies[i].visible = true;
}
for (var i = 0; i < arrows.length; i++) {
arrows[i].visible = true;
}
// Show mine resources/interactables if coming from mine
for (var i = 0; i < mineResources.length; i++) {
mineResources[i].visible = false;
}
for (var i = 0; i < mineInteractables.length; i++) {
mineInteractables[i].visible = false;
}
// Move player to island center
player.x = 2048 / 2;
player.y = 2732 / 2;
player.visible = true;
seaBtn.setText('Enter Sea');
mineBtn.setText('Enter Mine');
}
};
game.down = function (x, y, obj) {
// Don't allow dragging from top left 100x100
if (x < 100 && y < 100) return;
// --- FISHING LOGIC ---
if (!inMine && weaponToolSelected === 'fishingrod' && player.inventory.fishingrod && inSea && seaSafePlatform.visible) {
// Only allow fishing if on platform
var platX = 2048 / 2;
var platY = 2732 - 180;
var platW = seaSafePlatform.width * 0.5 - 40;
var platH = seaSafePlatform.height * 0.5 - 20;
if (player.x >= platX - platW && player.x <= platX + platW && player.y >= platY - platH && player.y <= platY + platH) {
// 30% chance to catch a fish
if (Math.random() < 0.3) {
var fish = new Fish();
fish.x = player.x;
fish.y = y;
resources.push(fish);
game.addChild(fish);
// Instantly collect
tryCollectResource(fish);
// Show message
var fishMsg = new Text2('You caught a fish!', {
size: 40,
fill: 0x3fa7d6
});
fishMsg.anchor.set(0.5, 0.5);
fishMsg.x = 2048 / 2;
fishMsg.y = 2732 / 2 - 300;
LK.gui.center.addChild(fishMsg);
LK.setTimeout(function () {
fishMsg.destroy();
}, 1200);
} else {
// Show fail message
var failMsg = new Text2('No fish this time...', {
size: 32,
fill: 0x888888
});
failMsg.anchor.set(0.5, 0.5);
failMsg.x = 2048 / 2;
failMsg.y = 2732 / 2 - 300;
LK.gui.center.addChild(failMsg);
LK.setTimeout(function () {
failMsg.destroy();
}, 900);
}
return;
}
}
// --- WEAPON ATTACK ---
if (playerWeapon && weaponToolSelected === playerWeapon.type) {
// Sword: tap near player to attack
if (playerWeapon.type === 'sword') {
if (LK.ticks - playerWeapon.lastAttackTick > playerWeapon.cooldown) {
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 < playerWeapon.range) {
z.destroy();
zombies.splice(i, 1);
playerWeapon.lastAttackTick = LK.ticks;
LK.effects.flashObject(playerWeapon, 0xffff00, 200);
break;
}
}
}
}
// Bow: tap anywhere to shoot arrow toward tap
else if (playerWeapon.type === 'bow') {
if (LK.ticks - playerWeapon.lastAttackTick > playerWeapon.cooldown) {
// Require at least 1 arrow in inventory to shoot
if (player.inventory.arrow && player.inventory.arrow > 0) {
// Find closest zombie or cow in range
var closest = null;
var minDist = 99999;
// Check zombies
for (var i = 0; i < zombies.length; 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 < playerWeapon.range && dist < minDist) {
closest = z;
minDist = dist;
}
}
// Check cows if no zombie is closer
for (var i = 0; i < cows.length; i++) {
var cow = cows[i];
var dx = cow.x - player.x;
var dy = cow.y - player.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < playerWeapon.range && dist < minDist) {
closest = cow;
minDist = dist;
}
}
if (closest) {
var arrow = new Arrow();
arrow.x = player.x + 60;
arrow.y = player.y;
arrow.target = closest;
arrows.push(arrow);
game.addChild(arrow);
player.inventory.arrow -= 1;
updateUI();
playerWeapon.lastAttackTick = LK.ticks;
LK.effects.flashObject(playerWeapon, 0x66ccff, 200);
}
}
}
}
}
// Check if touching interactable
if (!inMine) {
for (var i = 0; i < interactables.length; i++) {
var it = interactables[i];
if (player.intersects(it)) {
selectedInteractable = it;
return;
}
}
// Check if touching cow
// (No longer collect cows by touch; must use arrows to hunt)
// Check if touching resource
for (var j = 0; j < resources.length; j++) {
var res = resources[j];
if (player.intersects(res)) {
tryCollectResource(res);
return;
}
}
} else {
// In mine: check mine interactables/resources
for (var i = 0; i < mineInteractables.length; i++) {
var it = mineInteractables[i];
if (player.intersects(it)) {
// Use same logic as rocks
spawnResource('stone', it.x, it.y + 40);
it.destroy();
mineInteractables.splice(i, 1);
updateUI();
return;
}
}
for (var j = 0; j < mineResources.length; j++) {
var res = mineResources[j];
if (player.intersects(res)) {
// Use tryCollectResource logic, but remove from mineResources
if (res.type === 'wood') {
player.inventory.wood += 1;
} else if (res.type === 'stone') {
player.inventory.stone += 1;
} else if (res.type === 'berry') {
player.inventory.berry += 1;
player.hunger = Math.min(100, player.hunger + 10);
} else if (res.type === 'iron') {
player.inventory.iron += 1;
} else if (res.type === 'gold') {
player.inventory.gold += 1;
} else if (res.type === 'diamond') {
player.inventory.diamond += 1;
} else if (res.type === 'ruby') {
player.inventory.ruby += 1;
} else if (res.type === 'emerald') {
player.inventory.emerald += 1;
} else if (res.type === 'coal') {
player.inventory.coal += 1;
}
res.destroy();
mineResources.splice(j, 1);
updateUI();
return;
}
}
}
// Check if touching raft
if (raft && player.intersects(raft)) {
tryEscape();
return;
}
// Start dragging player
dragging = true;
dragOffset.x = x - player.x;
dragOffset.y = y - player.y;
};
// --- Restrict player to central island, surrounded by sea ---
// Define island bounds (oval/ellipse for more natural shape)
var islandCenterX = 2048 / 2;
var islandCenterY = 2732 / 2 + 100;
var islandRadiusX = 700;
var islandRadiusY = 900;
// --- Piranha enemy for sea region ---
var piranhas = [];
var piranhaSpawnTimer = null;
// Spawn piranhas in sea region
function spawnPiranha() {
// Only spawn if in sea
if (!inSea || inMine) return;
var p = new Piranha();
// Spawn at random edge of sea region (bottom 350px)
var edge = Math.floor(Math.random() * 4);
if (edge === 0) {
// left
p.x = 0;
p.y = 2732 - 350 + Math.random() * 350;
} else if (edge === 1) {
// right
p.x = 2048;
p.y = 2732 - 350 + Math.random() * 350;
} else if (edge === 2) {
// top
p.x = Math.random() * 2048;
p.y = 2732 - 350;
} else {
// bottom
p.x = Math.random() * 2048;
p.y = 2732;
}
piranhas.push(p);
game.addChild(p);
}
// Start/stop piranha spawning
function startPiranhaSpawning() {
if (piranhaSpawnTimer) return;
piranhaSpawnTimer = LK.setInterval(function () {
// Only spawn if player is in sea region
if (!inMine && inSea) {
spawnPiranha();
}
}, 1800);
}
function stopPiranhaSpawning() {
if (piranhaSpawnTimer) LK.clearInterval(piranhaSpawnTimer);
for (var i = 0; i < piranhas.length; i++) {
piranhas[i].destroy();
}
piranhas = [];
}
// Helper: is player on island (no longer restricts with ellipse, always true if not in sea or mine)
function isPlayerOnIsland() {
return !inSea && !inMine;
}
// Restrict player to island area
game.move = function (x, y, obj) {
if (dragging) {
// Calculate intended position
var px = x - dragOffset.x;
var py = y - dragOffset.y;
// Clamp to game bounds first
px = Math.max(60, Math.min(2048 - 60, px));
py = Math.max(120, Math.min(2732 - 60, py));
if (inSea && !inMine) {
// Restrict to safe platform in sea ONLY, no ellipse logic
var platX = 2048 / 2;
var platY = 2732 - 180;
var platW = seaSafePlatform.width * 0.5 - 40;
var platH = seaSafePlatform.height * 0.5 - 20;
px = Math.max(platX - platW, Math.min(platX + platW, px));
py = Math.max(platY - platH, Math.min(platY + platH, py));
} else {
// No ellipse boundary for island or mine, allow full movement except for game bounds
}
player.x = px;
player.y = py;
// If shelter exists, keep it near player
if (shelter) {
shelter.x = player.x + 180;
shelter.y = player.y + 100;
}
}
};
// Start piranha spawning on game start
startPiranhaSpawning();
game.up = function (x, y, obj) {
dragging = false;
if (selectedInteractable) {
if (player.intersects(selectedInteractable)) {
tryInteract(selectedInteractable);
}
selectedInteractable = null;
}
};
// --- New Craft Panel on left side ---
var craftPanelContainer = new Container();
LK.gui.left.addChild(craftPanelContainer);
// Panel title
var craftPanelTitle = new Text2('Craft', {
size: 54,
fill: "#fff"
});
craftPanelTitle.anchor.set(0, 0);
craftPanelTitle.x = 0;
craftPanelTitle.y = 120;
craftPanelContainer.addChild(craftPanelTitle);
// Craftable items for the panel (benches, weapons, tools)
var craftPanelItems = [{
key: 'shelter',
name: 'Shelter',
icon: 'shelter',
cost: [{
key: 'wood',
label: 'Wood',
amount: 5
}, {
key: 'stone',
label: 'Stone',
amount: 3
}],
canCraft: canBuildShelter,
craft: function craft() {
if (canBuildShelter()) buildShelter();
}
}, {
key: 'raft',
name: 'Raft',
icon: 'raft',
cost: [{
key: 'wood',
label: 'Wood',
amount: 10
}, {
key: 'stone',
label: 'Stone',
amount: 5
}],
canCraft: canBuildRaft,
craft: function craft() {
if (canBuildRaft()) buildRaft();
}
}, {
key: 'fishingrod',
name: 'Fishing Rod',
icon: 'wood',
cost: [{
key: 'wood',
label: 'Wood',
amount: 3
}, {
key: 'stone',
label: 'Stone',
amount: 1
}],
canCraft: canCraftFishingRod,
craft: craftFishingRod
}, {
key: 'sword',
name: 'Sword',
icon: 'wood',
cost: [{
key: 'wood',
label: 'Wood',
amount: 3
}, {
key: 'stone',
label: 'Stone',
amount: 2
}],
canCraft: canCraftSword,
craft: craftSword
}, {
key: 'bow',
name: 'Bow',
icon: 'wood',
cost: [{
key: 'wood',
label: 'Wood',
amount: 4
}, {
key: 'berry',
label: 'Berries',
amount: 2
}],
canCraft: canCraftBow,
craft: craftBow
}, {
key: 'arrows',
name: '5 Arrows',
icon: 'wood',
cost: [{
key: 'wood',
label: 'Wood',
amount: 1
}, {
key: 'stone',
label: 'Stone',
amount: 1
}],
canCraft: canCraftArrows,
craft: craftArrows
}, {
key: 'workbench',
name: 'Workbench',
icon: 'wood',
cost: [{
key: 'wood',
label: 'Wood',
amount: 6
}, {
key: 'stone',
label: 'Stone',
amount: 2
}],
canCraft: canCraftWorkbench,
craft: craftWorkbench
}, {
key: 'furnace',
name: 'Furnace',
icon: 'rock',
cost: [{
key: 'stone',
label: 'Stone',
amount: 8
}, {
key: 'coal',
label: 'Coal',
amount: 2
}],
canCraft: canCraftFurnace,
craft: craftFurnace
}, {
key: 'armorbench',
name: 'Armor Bench',
icon: 'wood',
cost: [{
key: 'wood',
label: 'Wood',
amount: 4
}, {
key: 'iron',
label: 'Iron',
amount: 2
}],
canCraft: canCraftArmorBench,
craft: craftArmorBench
}, {
key: 'weaponbench',
name: 'Weapon Bench',
icon: 'wood',
cost: [{
key: 'wood',
label: 'Wood',
amount: 4
}, {
key: 'stone',
label: 'Stone',
amount: 2
}, {
key: 'iron',
label: 'Iron',
amount: 1
}],
canCraft: canCraftWeaponBench,
craft: craftWeaponBench
}];
// Layout for craft panel with vertical scroll
var panelStartY = 200;
var panelSpacing = 120;
var craftPanelScrollY = 0;
var craftPanelMinScroll = 0;
var craftPanelMaxScroll = Math.max(0, craftPanelItems.length * panelSpacing + panelStartY - (2048 - 200)); // 2048 is game height, 200 is top margin
// Store all craft panel item containers for scrolling
var craftPanelItemContainers = [];
for (var i = 0; i < craftPanelItems.length; i++) {
(function (i) {
var item = craftPanelItems[i];
var y = panelStartY + i * panelSpacing;
// Container for this craft item row
var rowContainer = new Container();
rowContainer.y = y;
craftPanelContainer.addChild(rowContainer);
craftPanelItemContainers.push(rowContainer);
// Box background
var box = LK.getAsset('wood', {
anchorX: 0,
anchorY: 0,
scaleX: 3.2,
scaleY: 1.2,
x: 0,
y: 0
});
box.alpha = 0.7;
rowContainer.addChild(box);
// Icon
var icon = LK.getAsset(item.icon, {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.1,
scaleY: 1.1,
x: 90,
y: 60
});
if (item.key === 'furnace') icon.tint = 0x444444;
rowContainer.addChild(icon);
// Name
var nameTxt = new Text2(item.name, {
size: 38,
fill: "#fff"
});
nameTxt.anchor.set(0, 0.5);
nameTxt.x = 180;
nameTxt.y = 36;
rowContainer.addChild(nameTxt);
// Cost
var costStr = '';
for (var c = 0; c < item.cost.length; c++) {
var cost = item.cost[c];
var have = player.inventory[cost.key] || 0;
costStr += cost.label + ': ' + have + '/' + cost.amount;
if (c < item.cost.length - 1) costStr += ' ';
}
var costTxt = new Text2(costStr, {
size: 28,
fill: "#fff"
});
costTxt.anchor.set(0, 0.5);
costTxt.x = 180;
costTxt.y = 80;
rowContainer.addChild(costTxt);
// Craft button
var btn = new Text2('Craft', {
size: 34,
fill: item.canCraft() ? 0xB084FF : 0x888888
});
btn.anchor.set(0, 0.5);
btn.x = 30;
btn.y = 60;
rowContainer.addChild(btn);
btn.down = function (x, y, obj) {
if (item.canCraft()) {
item.craft();
updateCraftPanel();
} else {
LK.effects.flashObject(btn, 0xff4444, 400);
}
};
// Store for update
item._costTxt = costTxt;
item._btn = btn;
})(i);
}
// --- Craft Panel Scrolling Logic ---
// Touch drag scroll
var craftPanelDragging = false;
var craftPanelLastY = 0;
var craftPanelStartScrollY = 0;
// Touch start
craftPanelContainer.down = function (x, y, obj) {
// Only start drag if not on a button (avoid conflict)
craftPanelDragging = true;
craftPanelLastY = y;
craftPanelStartScrollY = craftPanelScrollY;
};
// Touch move
craftPanelContainer.move = function (x, y, obj) {
if (craftPanelDragging) {
var dy = y - craftPanelLastY;
craftPanelScrollY = craftPanelStartScrollY + dy;
// Clamp scroll
craftPanelScrollY = Math.max(-((craftPanelItems.length - 1) * panelSpacing), Math.min(0, craftPanelScrollY));
// Apply scroll to all rows
for (var i = 0; i < craftPanelItemContainers.length; i++) {
craftPanelItemContainers[i].y = panelStartY + i * panelSpacing + craftPanelScrollY;
}
}
};
// Touch end
craftPanelContainer.up = function (x, y, obj) {
craftPanelDragging = false;
};
// Mouse wheel scroll (desktop)
craftPanelContainer.event = function (obj) {
if (obj.event && obj.event.type === 'wheel') {
var delta = obj.event.deltaY || obj.event.detail || 0;
craftPanelScrollY -= delta * 0.5;
// Clamp scroll
craftPanelScrollY = Math.max(-((craftPanelItems.length - 1) * panelSpacing), Math.min(0, craftPanelScrollY));
for (var i = 0; i < craftPanelItemContainers.length; i++) {
craftPanelItemContainers[i].y = panelStartY + i * panelSpacing + craftPanelScrollY;
}
}
};
// Register wheel event on LK.gui.left (for desktop)
if (typeof LK.gui.left.event === "undefined") {
LK.gui.left.event = function (obj) {
if (obj.event && obj.event.type === 'wheel') {
craftPanelContainer.event(obj);
}
};
}
// Initial scroll position
for (var i = 0; i < craftPanelItemContainers.length; i++) {
craftPanelItemContainers[i].y = panelStartY + i * panelSpacing + craftPanelScrollY;
}
// Update function for craft panel
function updateCraftPanel() {
for (var i = 0; i < craftPanelItems.length; i++) {
var item = craftPanelItems[i];
// Update cost
var costStr = '';
for (var c = 0; c < item.cost.length; c++) {
var cost = item.cost[c];
var have = player.inventory[cost.key] || 0;
costStr += cost.label + ': ' + have + '/' + cost.amount;
if (c < item.cost.length - 1) costStr += ' ';
}
if (item._costTxt) item._costTxt.setText(costStr);
// Update button color
if (item._btn) item._btn.fill = item.canCraft() ? 0xB084FF : 0x888888;
}
}
// Patch updateUI to also update craft panel
var _oldUpdateUI = updateUI;
updateUI = function updateUI() {
_oldUpdateUI();
updateCraftPanel();
};
// --- Craft Sword and Bow Buttons (hidden, replaced by menu) ---
var craftShelterBtn = new Text2('Build Shelter', {
size: 40,
fill: 0xFFE4B5
});
craftShelterBtn.anchor.set(0.5, 0);
craftShelterBtn.y = -180;
craftShelterBtn.x = 0;
craftShelterBtn.visible = false;
LK.gui.bottom.addChild(craftShelterBtn);
var craftRaftBtn = new Text2('Build Raft', {
size: 40,
fill: 0xFFE4B5
});
craftRaftBtn.anchor.set(0.5, 0);
craftRaftBtn.y = -220;
craftRaftBtn.x = 0;
craftRaftBtn.visible = false;
LK.gui.bottom.addChild(craftRaftBtn);
var craftSwordBtn = new Text2('Craft Sword', {
size: 40,
fill: 0xeeeeee
});
craftSwordBtn.anchor.set(0.5, 0);
craftSwordBtn.y = -260;
craftSwordBtn.x = 0;
craftSwordBtn.visible = false;
LK.gui.bottom.addChild(craftSwordBtn);
var craftBowBtn = new Text2('Craft Bow', {
size: 40,
fill: 0xeeeeee
});
craftBowBtn.anchor.set(0.5, 0);
craftBowBtn.y = -300;
craftBowBtn.x = 0;
craftBowBtn.visible = false;
LK.gui.bottom.addChild(craftBowBtn);
// --- Crafting logic for workstations ---
function canCraftWorkbench() {
return player.inventory.wood >= 6 && player.inventory.stone >= 2;
}
function canCraftFurnace() {
return player.inventory.stone >= 8 && player.inventory.coal >= 2;
}
function canCraftArmorBench() {
return player.inventory.wood >= 4 && player.inventory.iron >= 2;
}
function canCraftWeaponBench() {
return player.inventory.wood >= 4 && player.inventory.stone >= 2 && player.inventory.iron >= 1;
}
function craftWorkbench() {
player.inventory.wood -= 6;
player.inventory.stone -= 2;
player.inventory.workbench += 1;
updateUI();
}
function craftFurnace() {
player.inventory.stone -= 8;
player.inventory.coal -= 2;
player.inventory.furnace += 1;
updateUI();
}
function craftArmorBench() {
player.inventory.wood -= 4;
player.inventory.iron -= 2;
player.inventory.armorbench += 1;
updateUI();
}
function craftWeaponBench() {
player.inventory.wood -= 4;
player.inventory.stone -= 2;
player.inventory.iron -= 1;
player.inventory.weaponbench += 1;
updateUI();
}
craftShelterBtn.down = function (x, y, obj) {
if (canBuildShelter()) {
buildShelter();
}
};
craftRaftBtn.down = function (x, y, obj) {
if (canBuildRaft()) {
buildRaft();
}
};
// --- Crafting logic for sword, bow, and arrows ---
function canCraftSword() {
return (!playerWeapon || playerWeapon.type !== 'sword') && player.inventory.wood >= 3 && player.inventory.stone >= 2;
}
function canCraftBow() {
return (!playerWeapon || playerWeapon.type !== 'bow') && player.inventory.wood >= 4 && player.inventory.berry >= 2;
}
// Craft 5 arrows for 1 wood and 1 stone
function canCraftArrows() {
return player.inventory.wood >= 1 && player.inventory.stone >= 1;
}
// --- Fishing Rod Crafting ---
function canCraftFishingRod() {
return (player.inventory.fishingrod || 0) < 1 && player.inventory.wood >= 3 && player.inventory.stone >= 1;
}
function craftFishingRod() {
player.inventory.wood -= 3;
player.inventory.stone -= 1;
player.inventory.fishingrod = (player.inventory.fishingrod || 0) + 1;
// No need to add to hand, just update inventory/tool bar
updateUI();
}
// --- Magic Realm Portal Crafting ---
function canCraftMagicRealmPortal() {
return (player.inventory.magicwood || 0) >= 10 && player.inventory.wood >= 10 && player.inventory.stone >= 5 && player.inventory.ruby >= 1;
}
function craftMagicRealmPortal() {
player.inventory.magicwood -= 10;
player.inventory.wood -= 10;
player.inventory.stone -= 5;
player.inventory.ruby -= 1;
player.inventory.magicrealmportal = (player.inventory.magicrealmportal || 0) + 1;
updateUI();
// Show message
var msg = new Text2('Magic Realm Portal crafted!\nUse it from your inventory.', {
size: 48,
fill: 0xB084FF
});
msg.anchor.set(0.5, 0.5);
msg.x = 2048 / 2;
msg.y = 2732 / 2 - 100;
LK.gui.center.addChild(msg);
LK.setTimeout(function () {
msg.destroy();
}, 2500);
}
// Magic Realm Portal Craft Button
var craftMagicRealmPortalBtn = new Text2('Craft Magic Realm Portal', {
size: 40,
fill: 0xB084FF
});
craftMagicRealmPortalBtn.anchor.set(0.5, 0);
craftMagicRealmPortalBtn.y = -360;
craftMagicRealmPortalBtn.x = 640;
LK.gui.bottom.addChild(craftMagicRealmPortalBtn);
craftMagicRealmPortalBtn.down = function (x, y, obj) {
if (canCraftMagicRealmPortal()) {
craftMagicRealmPortal();
} else {
LK.effects.flashObject(craftMagicRealmPortalBtn, 0xff4444, 400);
}
};
function craftSword() {
player.inventory.wood -= 3;
player.inventory.stone -= 2;
// Remove old sword if any
if (playerWeapon && playerWeapon.type === 'sword') {
playerWeapon.destroy();
playerWeapon = null;
}
// Add sword to extra inventory (not to hand or tool bar)
playerWeapon = new Sword();
playerWeapon.x = -9999; // Hide offscreen, not in hand
playerWeapon.y = -9999;
game.addChild(playerWeapon);
updateUI();
}
function craftBow() {
player.inventory.wood -= 4;
player.inventory.berry -= 2;
// Remove old bow if any
if (playerWeapon && playerWeapon.type === 'bow') {
playerWeapon.destroy();
playerWeapon = null;
}
// Add bow to extra inventory (not to hand or tool bar)
playerWeapon = new Bow();
playerWeapon.x = -9999; // Hide offscreen, not in hand
playerWeapon.y = -9999;
game.addChild(playerWeapon);
updateUI();
}
function craftArrows() {
player.inventory.wood -= 1;
player.inventory.stone -= 1;
player.inventory.arrow += 5;
updateUI();
}
craftSwordBtn.down = function (x, y, obj) {
if (canCraftSword()) {
craftSword();
}
};
craftBowBtn.down = function (x, y, obj) {
if (canCraftBow()) {
craftBow();
}
};
// Arrow crafting button
var craftArrowBtn = new Text2('Craft 5 Arrows', {
size: 40,
fill: 0xeeeeee
});
craftArrowBtn.anchor.set(0.5, 0);
craftArrowBtn.y = -340;
craftArrowBtn.x = 320;
LK.gui.bottom.addChild(craftArrowBtn);
craftArrowBtn.down = function (x, y, obj) {
if (canCraftArrows()) {
craftArrows();
}
};
// --- Game Update Loop ---
game.update = function () {
// Randomly respawn resources
if (LK.ticks % 180 === 0) {
var t = Math.random();
if (t < 0.33) {
spawnInteractable('tree', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
} else if (t < 0.66) {
spawnInteractable('rock', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
} else {
spawnInteractable('bush', 200 + Math.random() * 1600, 400 + Math.random() * 1800);
}
}
// --- COW LOGIC ---
for (var i = 0; i < cows.length; i++) {
cows[i].update();
}
// --- ZOMBIE LOGIC ---
for (var i = zombies.length - 1; i >= 0; i--) {
var z = zombies[i];
z.update();
// If zombie reaches player
if (z.lastWasIntersecting === undefined) z.lastWasIntersecting = false;
var nowIntersect = z.intersects(player);
if (!z.lastWasIntersecting && nowIntersect) {
if (!player.hasShelter) {
player.health -= z.damage;
LK.effects.flashObject(player, 0xff0000, 400);
updateUI();
if (player.health <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
}
}
z.lastWasIntersecting = nowIntersect;
// Remove zombie if dead or off screen
if (z.x < -100 || z.x > 2148 || z.y < -100 || z.y > 2832) {
z.destroy();
zombies.splice(i, 1);
}
}
// --- ARROW LOGIC ---
for (var j = arrows.length - 1; j >= 0; j--) {
var a = arrows[j];
a.update();
// Hit zombie or Wood Golem?
var arrowHit = false;
for (var k = zombies.length - 1; k >= 0; k--) {
var z = zombies[k];
if (a.intersects(z)) {
// If Wood Golem
if (z.type === 'woodgolem') {
// Only take full damage from sword, reduced from bow
var isBow = a.type === 'arrow';
var dmg = a.damage || 18;
var dead = z.takeDamage(dmg, isBow ? 'bow' : 'sword');
LK.effects.flashObject(z, 0x00ff00, 200);
a.destroy();
arrows.splice(j, 1);
arrowHit = true;
if (dead) {
// Drop 20 Magic Infused Wood at golem's position
for (var mw = 0; mw < 20; mw++) {
var magicWood = new Resource();
magicWood.type = 'magicwood';
magicWood.attachAsset('wood', {
anchorX: 0.5,
anchorY: 0.5,
scaleX: 1.2,
scaleY: 1.2
});
magicWood.children[0].tint = 0x8e44ad; // purple tint
magicWood.x = z.x + (Math.random() - 0.5) * 80;
magicWood.y = z.y + 80 + (Math.random() - 0.5) * 40;
resources.push(magicWood);
game.addChild(magicWood);
}
// Drop 20 Wood
for (var wd = 0; wd < 20; wd++) {
var woodDrop = new Wood();
woodDrop.x = z.x + (Math.random() - 0.5) * 120;
woodDrop.y = z.y + 100 + (Math.random() - 0.5) * 60;
resources.push(woodDrop);
game.addChild(woodDrop);
}
// Drop 20 Berries
for (var bd = 0; bd < 20; bd++) {
var berryDrop = new Berry();
berryDrop.x = z.x + (Math.random() - 0.5) * 120;
berryDrop.y = z.y + 120 + (Math.random() - 0.5) * 60;
resources.push(berryDrop);
game.addChild(berryDrop);
}
// Drop 1 Ruby
var rubyDrop = new Resource();
rubyDrop.type = 'ruby';
rubyDrop.attachAsset('stone', {
anchorX: 0.5,
anchorY: 0.5
});
rubyDrop.children[0].tint = 0xff0044;
rubyDrop.x = z.x + (Math.random() - 0.5) * 60;
rubyDrop.y = z.y + 140;
resources.push(rubyDrop);
game.addChild(rubyDrop);
// Drop 1 Stone
var stoneDrop = new Stone();
stoneDrop.x = z.x + (Math.random() - 0.5) * 60;
stoneDrop.y = z.y + 160;
resources.push(stoneDrop);
game.addChild(stoneDrop);
// Show message for Magic Realm Portal craft
var msg = new Text2('You obtained Magic Infused Wood!\nYou can now craft the Magic Realm Portal!', {
size: 54,
fill: 0xB084FF
});
msg.anchor.set(0.5, 0.5);
msg.x = 2048 / 2;
msg.y = 2732 / 2 - 200;
LK.gui.center.addChild(msg);
LK.setTimeout(function () {
msg.destroy();
}, 3500);
z.destroy();
zombies.splice(k, 1);
}
break;
} else {
z.destroy();
zombies.splice(k, 1);
a.destroy();
arrows.splice(j, 1);
arrowHit = true;
break;
}
}
}
// Hit cow?
if (!arrowHit) {
for (var c = cows.length - 1; c >= 0; c--) {
var cow = cows[c];
if (a.intersects(cow)) {
// Drop meat at cow's position
var meat = new Meat();
meat.x = cow.x;
meat.y = cow.y;
resources.push(meat);
game.addChild(meat);
cow.destroy();
cows.splice(c, 1);
a.destroy();
arrows.splice(j, 1);
arrowHit = true;
break;
}
}
}
// Remove arrow if off screen
if (!arrowHit && (a.x < -100 || a.x > 2148 || a.y < -100 || a.y > 2832)) {
a.destroy();
arrows.splice(j, 1);
}
}
// --- WEAPON FOLLOW PLAYER ---
if (playerWeapon) {
playerWeapon.x = player.x + 60;
playerWeapon.y = player.y;
}
// --- PLAYER COLOR LOGIC FOR SEA ---
if (player && player.children && player.children[0]) {
if (inSea && !inMine) {
player.children[0].tint = 0x00ff44; // green in sea
} else {
player.children[0].tint = 0x2d8cff; // blue elsewhere
}
}
// --- PIRANHA LOGIC ---
// Only active if player is in sea (on platform)
if (!inMine && inSea) {
// Show warning
healthTxt.tint = 0xff2222;
// Platform bounds (same as in Piranha)
var platX = 2048 / 2;
var platY = 2732 - 180;
var platW = 350;
var platH = 110;
// Check if player is on platform
var onPlatform = player.x >= platX - platW && player.x <= platX + platW && player.y >= platY - platH && player.y <= platY + platH;
// If player is off platform, apply sea damage
if (!onPlatform) {
player.health -= 0.5;
if (player.health < 0) player.health = 0;
}
// Piranha movement and collision
for (var i = piranhas.length - 1; i >= 0; i--) {
var p = piranhas[i];
p.update();
if (p.lastWasIntersecting === undefined) p.lastWasIntersecting = false;
// Only check collision if player is NOT on platform
var nowIntersect = !onPlatform && p.intersects(player);
if (!p.lastWasIntersecting && nowIntersect) {
player.health -= p.damage;
LK.effects.flashObject(player, 0xff2222, 400);
if (player.health <= 0) {
LK.effects.flashScreen(0xff0000, 1000);
LK.showGameOver();
}
}
p.lastWasIntersecting = nowIntersect;
// Remove piranha if off screen (sea region is bottom 350px)
if (p.y < 2732 - 350 || p.x < -200 || p.x > 2248 || p.y > 2932) {
p.destroy();
piranhas.splice(i, 1);
}
}
} else {
// Not in sea, reset health color and remove piranhas
healthTxt.tint = isNight && !player.hasShelter ? 0xff4444 : 0xffffff;
for (var i = 0; i < piranhas.length; i++) {
piranhas[i].destroy();
}
piranhas = [];
}
// If night and no shelter, health drops faster
if (isNight && !player.hasShelter && isPlayerOnIsland()) {
healthTxt.tint = 0xff4444;
} else if (isPlayerOnIsland()) {
healthTxt.tint = 0xffffff;
}
// If raft built, show escape hint
if (player.hasRaft && raft) {
// Optionally, could show a message
}
};
// --- Cleanup on Game Over/Win ---
LK.on('gameover', function () {
stopDayNightCycle();
stopHunger();
stopZombieSpawning();
clearZombies();
for (var i = 0; i < arrows.length; i++) {
arrows[i].destroy();
}
arrows = [];
if (playerWeapon) {
playerWeapon.destroy();
playerWeapon = null;
}
stopPiranhaSpawning();
});
LK.on('youwin', function () {
stopDayNightCycle();
stopHunger();
stopZombieSpawning();
clearZombies();
for (var i = 0; i < arrows.length; i++) {
arrows[i].destroy();
}
arrows = [];
if (playerWeapon) {
playerWeapon.destroy();
playerWeapon = null;
}
stopPiranhaSpawning();
});