class UIScene extends Phaser.Scene { constructor() { super({ key: 'UIScene' }); } create() { console.log('🖥️ UIScene: Initialized!'); // Pridobi reference na GameScene podatke (ko bodo na voljo) this.gameScene = this.scene.get('GameScene'); // Setup UI Container this.width = this.cameras.main.width; this.height = this.cameras.main.height; this.createStatusBars(); this.createInventoryBar(); this.createGoldDisplay(); this.createClock(); this.createDebugInfo(); // Listen for events from GameScene if needed } createStatusBars() { const x = 20; const y = 20; const width = 200; const height = 20; const padding = 10; // Style const boxStyle = { fillStyle: { color: 0x000000, alpha: 0.5 }, lineStyle: { width: 2, color: 0xffffff, alpha: 0.8 } }; // 1. Health Bar this.add.text(x, y - 5, 'HP', { fontSize: '12px', fontFamily: 'Courier New', fill: '#ffffff' }); this.healthBar = this.createBar(x + 30, y, width, height, 0xff0000); this.setBarValue(this.healthBar, 100); // 2. Hunger Bar this.add.text(x, y + height + padding - 5, 'HUN', { fontSize: '12px', fontFamily: 'Courier New', fill: '#ffffff' }); this.hungerBar = this.createBar(x + 30, y + height + padding, width, height, 0xff8800); this.setBarValue(this.hungerBar, 80); // 3. Thirst Bar this.add.text(x, y + (height + padding) * 2 - 5, 'H2O', { fontSize: '12px', fontFamily: 'Courier New', fill: '#ffffff' }); this.thirstBar = this.createBar(x + 30, y + (height + padding) * 2, width, height, 0x0088ff); this.setBarValue(this.thirstBar, 90); } createBar(x, y, width, height, color) { // Background const bg = this.add.graphics(); bg.fillStyle(0x000000, 0.5); bg.fillRect(x, y, width, height); bg.lineStyle(2, 0xffffff, 0.2); bg.strokeRect(x, y, width, height); // Fill const fill = this.add.graphics(); fill.fillStyle(color, 1); fill.fillRect(x + 2, y + 2, width - 4, height - 4); return { bg, fill, x, y, width, height, color }; } setBarValue(bar, percent) { // Clamp 0-100 percent = Phaser.Math.Clamp(percent, 0, 100); bar.fill.clear(); bar.fill.fillStyle(bar.color, 1); const maxWidth = bar.width - 4; const currentWidth = (maxWidth * percent) / 100; bar.fill.fillRect(bar.x + 2, bar.y + 2, currentWidth, bar.height - 4); } createInventoryBar() { const slotCount = 9; const slotSize = 48; // 48x48 sloti const padding = 5; const totalWidth = (slotCount * slotSize) + ((slotCount - 1) * padding); const startX = (this.width - totalWidth) / 2; const startY = this.height - slotSize - 20; this.inventorySlots = []; this.selectedSlot = 0; for (let i = 0; i < slotCount; i++) { const x = startX + i * (slotSize + padding); // Slot Background const slot = this.add.graphics(); // Draw function to update style based on selection slot.userData = { x, y: startY, size: slotSize, index: i }; this.drawSlot(slot, false); // Add number text this.add.text(x + 2, startY + 2, (i + 1).toString(), { fontSize: '10px', fontFamily: 'monospace', fill: '#ffffff' }); this.inventorySlots.push(slot); } // Select first one initially this.selectSlot(0); // Keyboard inputs 1-9 this.input.keyboard.on('keydown', (event) => { const num = parseInt(event.key); if (!isNaN(num) && num >= 1 && num <= 9) { this.selectSlot(num - 1); } }); // Mouse scroll for inventory (optional) this.input.on('wheel', (pointer, gameObjects, deltaX, deltaY, deltaZ) => { if (deltaY > 0) { this.selectSlot((this.selectedSlot + 1) % slotCount); } else if (deltaY < 0) { this.selectSlot((this.selectedSlot - 1 + slotCount) % slotCount); } }); } drawSlot(graphics, isSelected) { const { x, y, size } = graphics.userData; graphics.clear(); // Background graphics.fillStyle(0x000000, 0.6); graphics.fillRect(x, y, size, size); // Border if (isSelected) { graphics.lineStyle(3, 0xffff00, 1); // Yellow thick border for selection } else { graphics.lineStyle(2, 0x888888, 0.5); // Grey thin border } graphics.strokeRect(x, y, size, size); } selectSlot(index) { // Deselect current if (this.inventorySlots[this.selectedSlot]) { this.drawSlot(this.inventorySlots[this.selectedSlot], false); } this.selectedSlot = index; // Select new this.drawSlot(this.inventorySlots[this.selectedSlot], true); } updateInventory(slots) { if (!this.inventorySlots) return; for (let i = 0; i < this.inventorySlots.length; i++) { const slotGraphics = this.inventorySlots[i]; // Clear previous item info (we stored it in container? No, just graphics) // Ideally slots should be containers. // For now, let's just redraw the slot and add text on top. // To do this cleanly, let's remove old item text/sprites if we track them. if (slotGraphics.itemText) slotGraphics.itemText.destroy(); if (slots[i]) { const { x, y, size } = slotGraphics.userData; // Simple representation: Text const text = this.add.text(x + size / 2, y + size / 2, `${slots[i].type.substring(0, 2)}\n${slots[i].count}`, { fontSize: '10px', align: 'center', color: '#ffff00' } ).setOrigin(0.5); slotGraphics.itemText = text; } } } createClock() { // Clock box top right const x = this.width - 150; const y = 20; // Background const bg = this.add.graphics(); bg.fillStyle(0x000000, 0.5); bg.fillRect(x, y, 130, 40); bg.lineStyle(2, 0xffffff, 0.8); bg.strokeRect(x, y, 130, 40); this.clockText = this.add.text(x + 65, y + 20, 'Day 1 - 08:00', { fontSize: '14px', fontFamily: 'Courier New', fill: '#ffffff', fontStyle: 'bold' }); this.clockText.setOrigin(0.5, 0.5); } createGoldDisplay() { const x = this.width - 150; const y = 70; // Below clock // Background const bg = this.add.graphics(); bg.fillStyle(0xDAA520, 0.2); // Goldish bg bg.fillRect(x, y, 130, 30); bg.lineStyle(2, 0xFFD700, 0.8); bg.strokeRect(x, y, 130, 30); this.goldText = this.add.text(x + 65, y + 15, 'GOLD: 0', { fontSize: '16px', fontFamily: 'Courier New', fill: '#FFD700', // Gold color fontStyle: 'bold' }); this.goldText.setOrigin(0.5, 0.5); } updateGold(amount) { if (this.goldText) { this.goldText.setText(`GOLD: ${amount}`); } } createDebugInfo() { this.debugText = this.add.text(10, 100, '', { fontSize: '12px', fontFamily: 'monospace', fill: '#00ff00' }); } update() { // Here we could update bars based on player stats // if (this.gameScene && this.gameScene.player) { ... } } toggleBuildMenu(isVisible) { if (!this.buildMenuContainer) { this.createBuildMenuInfo(); } this.buildMenuContainer.setVisible(isVisible); } createBuildMenuInfo() { this.buildMenuContainer = this.add.container(this.width / 2, 100); const bg = this.add.graphics(); bg.fillStyle(0x000000, 0.7); bg.fillRect(-150, 0, 300, 100); bg.lineStyle(2, 0x00FF00, 1); bg.strokeRect(-150, 0, 300, 100); this.buildMenuContainer.add(bg); const title = this.add.text(0, 10, 'BUILD MODE [B]', { fontSize: '18px', fill: '#00FF00', fontStyle: 'bold' }).setOrigin(0.5, 0); this.buildMenuContainer.add(title); const info = this.add.text(0, 40, '[1] Fence (2 Wood)\n[2] Wall (2 Stone)\n[3] House (20W 20S 50G)', { fontSize: '14px', fill: '#ffffff', align: 'center' } ).setOrigin(0.5, 0); this.buildMenuContainer.add(info); this.selectedBuildingText = this.add.text(0, 80, 'Selected: Fence', { fontSize: '14px', fill: '#FFFF00' }).setOrigin(0.5, 0); this.buildMenuContainer.add(this.selectedBuildingText); this.buildMenuContainer.setVisible(false); } updateBuildSelection(name) { if (this.selectedBuildingText) { this.selectedBuildingText.setText(`Selected: ${name.toUpperCase()}`); } } showProjectMenu(ruinData, onContribute) { if (!this.projectMenuContainer) { this.createProjectMenu(); } // Update info const costText = `Req: ${ruinData.reqWood} Wood, ${ruinData.reqStone} Stone`; this.projectInfoText.setText(`RESTORING RUINS\n${costText}`); this.onContributeCallback = onContribute; this.projectMenuContainer.setVisible(true); this.projectMenuContainer.setDepth(10000); } createProjectMenu() { this.projectMenuContainer = this.add.container(this.width / 2, this.height / 2); // BG const bg = this.add.graphics(); bg.fillStyle(0x222222, 0.9); bg.fillRect(-150, -100, 300, 200); bg.lineStyle(2, 0x00FFFF, 1); bg.strokeRect(-150, -100, 300, 200); this.projectMenuContainer.add(bg); // Title const title = this.add.text(0, -80, 'PROJECT: RESTORATION', { fontSize: '20px', fill: '#00FFFF', fontStyle: 'bold' }).setOrigin(0.5); this.projectMenuContainer.add(title); // Info this.projectInfoText = this.add.text(0, -20, 'Req: ???', { fontSize: '16px', fill: '#ffffff', align: 'center' }).setOrigin(0.5); this.projectMenuContainer.add(this.projectInfoText); // Button const btnBg = this.add.rectangle(0, 50, 200, 40, 0x00aa00); btnBg.setInteractive(); btnBg.on('pointerdown', () => { if (this.onContributeCallback) this.onContributeCallback(); // Close menu? Or keep open to see result? // For now close this.projectMenuContainer.setVisible(false); }); this.projectMenuContainer.add(btnBg); const btnText = this.add.text(0, 50, 'CONTRIBUTE', { fontSize: '18px', fill: '#ffffff' }).setOrigin(0.5); this.projectMenuContainer.add(btnText); // Close Button const closeBtn = this.add.text(130, -90, 'X', { fontSize: '20px', fill: '#ff0000' }).setOrigin(0.5); closeBtn.setInteractive(); closeBtn.on('pointerdown', () => this.projectMenuContainer.setVisible(false)); this.projectMenuContainer.add(closeBtn); this.projectMenuContainer.setVisible(false); } showTradeMenu(inventorySystem) { if (!this.tradeMenuContainer) { this.createTradeMenu(inventorySystem); } this.updateTradeMenu(inventorySystem); this.tradeMenuContainer.setVisible(true); this.tradeMenuContainer.setDepth(10000); } createTradeMenu(inventorySystem) { this.tradeMenuContainer = this.add.container(this.width / 2, this.height / 2); // BG const bg = this.add.graphics(); bg.fillStyle(0x222222, 0.95); bg.fillRect(-200, -150, 400, 300); bg.lineStyle(2, 0xFFD700, 1); // Gold border bg.strokeRect(-200, -150, 400, 300); this.tradeMenuContainer.add(bg); // Title const title = this.add.text(0, -130, 'MERCHANT SHOP', { fontSize: '24px', fill: '#FFD700', fontStyle: 'bold' }).setOrigin(0.5); this.tradeMenuContainer.add(title); // Close Button const closeBtn = this.add.text(180, -140, 'X', { fontSize: '20px', fill: '#ff0000', fontStyle: 'bold' }).setOrigin(0.5); closeBtn.setInteractive({ useHandCursor: true }); closeBtn.on('pointerdown', () => this.tradeMenuContainer.setVisible(false)); this.tradeMenuContainer.add(closeBtn); // Content Container (for items) this.tradeItemsContainer = this.add.container(0, 0); this.tradeMenuContainer.add(this.tradeItemsContainer); } updateTradeMenu(inventorySystem) { this.tradeItemsContainer.removeAll(true); // Items to Sell (Player has -> Merchant wants) // Hardcoded prices for now const prices = { 'wheat': { price: 10, type: 'sell' }, 'wood': { price: 2, type: 'sell' }, 'seeds': { price: 5, type: 'buy' } }; const startY = -80; let index = 0; // Header const header = this.add.text(-180, startY, 'ITEM PRICE ACTION', { fontSize: '16px', fill: '#888888' }); this.tradeItemsContainer.add(header); // 1. Sell Wheat this.createTradeRow(inventorySystem, 'wheat', prices.wheat.price, 'SELL', index++, startY + 30); // 2. Sell Wood this.createTradeRow(inventorySystem, 'wood', prices.wood.price, 'SELL', index++, startY + 30); // 3. Buy Seeds this.createTradeRow(inventorySystem, 'seeds', prices.seeds.price, 'BUY', index++, startY + 30); } createTradeRow(inv, itemKey, price, action, index, yOffset) { const y = yOffset + (index * 40); // Name const name = this.add.text(-180, y, itemKey.toUpperCase(), { fontSize: '18px', fill: '#ffffff' }); this.tradeItemsContainer.add(name); // Price const priceText = this.add.text(-50, y, `${price}g`, { fontSize: '18px', fill: '#FFD700' }); this.tradeItemsContainer.add(priceText); // Button const btnX = 100; const btnBg = this.add.rectangle(btnX, y + 10, 80, 30, action === 'BUY' ? 0x008800 : 0x880000); btnBg.setInteractive({ useHandCursor: true }); const btnLabel = this.add.text(btnX, y + 10, action, { fontSize: '16px', fill: '#ffffff' }).setOrigin(0.5); btnBg.on('pointerdown', () => { if (action === 'SELL') { if (inv.hasItem(itemKey, 1)) { inv.removeItem(itemKey, 1); inv.gold += price; inv.updateUI(); // Refresh visuals? } else { // Fail feedback btnLabel.setText('NO ITEM'); this.scene.time.delayedCall(500, () => btnLabel.setText(action)); } } else if (action === 'BUY') { if (inv.gold >= price) { inv.gold -= price; inv.addItem(itemKey, 1); inv.updateUI(); } else { // Fail feedback btnLabel.setText('NO GOLD'); this.scene.time.delayedCall(500, () => btnLabel.setText(action)); } } }); this.tradeItemsContainer.add(btnBg); this.tradeItemsContainer.add(btnLabel); } }