This commit is contained in:
2025-12-12 02:41:00 +01:00
parent e15b429e75
commit 84b07bb433
13 changed files with 1917 additions and 76 deletions

View File

@@ -78,23 +78,13 @@ class BuildSystem {
this.buildMode = !this.buildMode;
console.log(`Build Mode: ${this.buildMode ? 'ON' : 'OFF'}`);
// Show tutorial on first time
if (this.buildMode && !this.tutorialShown) {
this.showTutorial();
this.tutorialShown = true;
}
// Notify UI
const uiScene = this.scene.scene.get('UIScene');
if (uiScene) {
uiScene.toggleBuildMenu(this.buildMode);
}
// Show/hide preview
if (this.buildMode) {
this.createPreview();
this.showBuildUI(); // Dodaj UI
} else {
this.destroyPreview();
this.hideBuildUI(); // Skrij UI
}
return this.buildMode;
@@ -104,16 +94,126 @@ class BuildSystem {
if (!this.buildings[buildingId]) return;
this.selectedBuilding = buildingId;
// Update UI
const uiScene = this.scene.scene.get('UIScene');
if (uiScene) {
uiScene.updateBuildSelection(this.buildings[buildingId].name);
}
// Refresh preview
if (this.buildMode) {
this.destroyPreview();
this.createPreview();
this.updateBuildUI(); // Posodobi UI
}
}
showBuildUI() {
const uiScene = this.scene.scene.get('UIScene');
if (!uiScene) return;
const width = this.scene.cameras.main.width;
const height = this.scene.cameras.main.height;
// Ustvari UI container
this.buildUIContainer = uiScene.add.container(width - 250, 100);
this.buildUIContainer.setDepth(9999);
this.buildUIContainer.setScrollFactor(0);
// Ozadje panela
const bg = uiScene.add.rectangle(0, 0, 220, 400, 0x1a1a2e, 0.95);
bg.setStrokeStyle(3, 0x00ff41);
this.buildUIContainer.add(bg);
// Naslov
const title = uiScene.add.text(0, -180, '🏗️ BUILD MODE', {
fontSize: '20px',
fontFamily: 'Courier New',
color: '#00ff41',
fontStyle: 'bold'
}).setOrigin(0.5);
this.buildUIContainer.add(title);
// Izbrana stavba
this.selectedBuildingText = uiScene.add.text(0, -150, '', {
fontSize: '14px',
fontFamily: 'Courier New',
color: '#ffffff',
align: 'center'
}).setOrigin(0.5);
this.buildUIContainer.add(this.selectedBuildingText);
// Cena
this.costText = uiScene.add.text(0, -120, '', {
fontSize: '12px',
fontFamily: 'Courier New',
color: '#ffaa00',
align: 'center'
}).setOrigin(0.5);
this.buildUIContainer.add(this.costText);
// Kontrole
const controls = [
'━━━━━━━━━━━━━━',
'CONTROLS:',
'',
'1 - Fence Post',
'2 - Fence →',
'3 - Fence ↓',
'4 - Fence ⌞',
'5 - Barn',
'',
'Click - Place',
'B - Exit',
'━━━━━━━━━━━━━━'
];
const controlsText = uiScene.add.text(0, 0, controls.join('\n'), {
fontSize: '12px',
fontFamily: 'Courier New',
color: '#aaaaaa',
align: 'center',
lineSpacing: 4
}).setOrigin(0.5);
this.buildUIContainer.add(controlsText);
// Status
this.statusText = uiScene.add.text(0, 170, '', {
fontSize: '11px',
fontFamily: 'Courier New',
color: '#ffffff',
align: 'center'
}).setOrigin(0.5);
this.buildUIContainer.add(this.statusText);
this.updateBuildUI();
}
updateBuildUI() {
if (!this.buildUIContainer) return;
const building = this.buildings[this.selectedBuilding];
// Posodobi ime
this.selectedBuildingText.setText(`Selected:\n${building.name}`);
// Posodobi ceno
let costStr = 'Cost: ';
const costs = [];
for (const [resource, amount] of Object.entries(building.cost)) {
if (resource === 'gold') {
costs.push(`${amount} Gold`);
} else {
costs.push(`${amount} ${resource}`);
}
}
costStr += costs.join(', ');
this.costText.setText(costStr);
// Preveri vire
const hasResources = this.hasResources(building.cost);
this.statusText.setText(hasResources ? '✅ Ready to build' : '❌ Not enough resources');
this.statusText.setColor(hasResources ? '#00ff41' : '#ff0000');
}
hideBuildUI() {
if (this.buildUIContainer) {
this.buildUIContainer.destroy();
this.buildUIContainer = null;
}
}
@@ -230,6 +330,146 @@ class BuildSystem {
return building ? building.collision : false;
}
/**
* Ročno postavi ograjo na natančno koordinato.
* @param {number} tileX - X koordinata ploščice (0 do 99).
* @param {number} tileY - Y koordinata ploščice (0 do 99).
* @param {string} fenceType - Tip ograje: 'fence', 'fence_post', 'fence_horizontal', 'fence_vertical', 'fence_corner'
* @param {boolean} consumeResources - Ali naj porabi vire (privzeto: false)
* @returns {boolean} - True če je bila ograja uspešno postavljena
*/
placeSingleFence(tileX, tileY, fenceType = 'fence_horizontal', consumeResources = false) {
// 1. Preveri, ali je lokacija znotraj mape
if (tileX < 0 || tileX >= 100 || tileY < 0 || tileY >= 100) {
console.error(`❌ Poskus postavitve ograje izven robov mape: (${tileX}, ${tileY})`);
return false;
}
// 2. Preveri, ali tip ograje obstaja
if (!this.buildings[fenceType]) {
console.error(`❌ Neznan tip ograje: ${fenceType}`);
return false;
}
// 3. Preveri, ali že obstaja zgradba na tej lokaciji
const exists = this.placedBuildings.find(b => b.gridX === tileX && b.gridY === tileY);
if (exists) {
console.warn(`⚠️ Na lokaciji (${tileX}, ${tileY}) že obstaja zgradba.`);
return false;
}
const building = this.buildings[fenceType];
// 4. Preveri in porabi vire (če je zahtevano)
if (consumeResources) {
if (!this.hasResources(building.cost)) {
console.warn(`⚠️ Ni dovolj virov za postavitev ${building.name}`);
return false;
}
const inv = this.scene.inventorySystem;
for (const [resource, amount] of Object.entries(building.cost)) {
if (resource === 'gold') {
inv.gold -= amount;
} else {
inv.removeItem(resource, amount);
}
}
}
// 5. Ustvari sprite
const screenPos = this.scene.iso.toScreen(tileX, tileY);
const sprite = this.scene.add.sprite(screenPos.x, screenPos.y, building.textureKey);
sprite.setOrigin(0.5, 1);
sprite.setScale(building.scale || 1.0);
sprite.setDepth(this.scene.iso.getDepth(tileX, tileY) + 5); // Nad terenom
// 6. Shrani
this.placedBuildings.push({
gridX: tileX,
gridY: tileY,
type: fenceType,
sprite,
collision: building.collision
});
console.log(`${building.name} postavljena na (${tileX}, ${tileY})`);
// 7. Posodobi UI (če so bili porabljeni viri)
if (consumeResources) {
this.scene.events.emit('update-inventory');
}
return true;
}
/**
* Postavi linijo ograj med dvema točkama.
* @param {number} startX - Začetna X koordinata
* @param {number} startY - Začetna Y koordinata
* @param {number} endX - Končna X koordinata
* @param {number} endY - Končna Y koordinata
* @param {string} fenceType - Tip ograje
* @param {boolean} consumeResources - Ali naj porabi vire
*/
placeFenceLine(startX, startY, endX, endY, fenceType = 'fence_horizontal', consumeResources = false) {
const dx = Math.abs(endX - startX);
const dy = Math.abs(endY - startY);
const sx = startX < endX ? 1 : -1;
const sy = startY < endY ? 1 : -1;
let err = dx - dy;
let x = startX;
let y = startY;
while (true) {
this.placeSingleFence(x, y, fenceType, consumeResources);
if (x === endX && y === endY) break;
const e2 = 2 * err;
if (e2 > -dy) {
err -= dy;
x += sx;
}
if (e2 < dx) {
err += dx;
y += sy;
}
}
console.log(`🔗 Linija ograj postavljena od (${startX}, ${startY}) do (${endX}, ${endY})`);
}
/**
* Postavi pravokotnik ograj.
* @param {number} x - Levi zgornji X
* @param {number} y - Levi zgornji Y
* @param {number} width - Širina
* @param {number} height - Višina
* @param {string} fenceType - Tip ograje
* @param {boolean} consumeResources - Ali naj porabi vire
*/
placeFenceRectangle(x, y, width, height, fenceType = 'fence_horizontal', consumeResources = false) {
// Zgornja linija
for (let i = 0; i < width; i++) {
this.placeSingleFence(x + i, y, fenceType, consumeResources);
}
// Spodnja linija
for (let i = 0; i < width; i++) {
this.placeSingleFence(x + i, y + height - 1, fenceType, consumeResources);
}
// Leva linija
for (let i = 1; i < height - 1; i++) {
this.placeSingleFence(x, y + i, fenceType, consumeResources);
}
// Desna linija
for (let i = 1; i < height - 1; i++) {
this.placeSingleFence(x + width - 1, y + i, fenceType, consumeResources);
}
console.log(`📦 Pravokotnik ograj postavljen na (${x}, ${y}) velikosti ${width}x${height}`);
}
showTutorial() {
const uiScene = this.scene.scene.get('UIScene');
if (!uiScene) return;

View File

@@ -81,14 +81,9 @@ class SaveSystem {
}
loadGame() {
console.log('📂 Loading game...');
let rawData = localStorage.getItem(this.storageKey);
if (!rawData) {
console.log('⚠️ No save file found.');
this.showNotification('NO SAVE FOUND');
return false;
}
console.log('📂 Loading game... DISABLED - Fresh start!');
// ONEMOGOČENO - vedno vrne false za fresh start
return false;
try {
let jsonString = rawData;

View File

@@ -16,7 +16,7 @@ const ABANDONED_HOUSES = [
// ========================================================
// GOZD KONSTANTE - STARDEW VALLEY STYLE (OPTIMIZIRANO)
// ========================================================
const TREE_DENSITY = 0.01; // 1% chance za drevo (zelo nizka gostota)
const TREE_DENSITY = 0.0; // 0% - BREZ DREVES!
const PURPLE_TREE_CHANCE = 0.30; // 30% vijolčnih dreves
const FRUIT_TREE_CHANCE = 0.20; // 20% sadnih dreves
const ROCK_DENSITY_THRESHOLD = 0.60; // Prag za skupine skal
@@ -29,6 +29,13 @@ const TILE_MINE_WALL = 81; // ID za zid rudnika
const TILE_STONE_ORE = 82; // ID za navadni kamen
const TILE_IRON_ORE = 83; // ID za železovo rudo
// ========================================================
// RIBNIK KONSTANTE
// ========================================================
const POND_CENTER_X = 30; // Center ribnika
const POND_CENTER_Y = 30; // Center ribnika
const POND_RADIUS = 4; // Radij ribnika (8x8)
// Terrain Generator System
class TerrainSystem {
constructor(scene, width = 100, height = 100) {
@@ -53,6 +60,10 @@ class TerrainSystem {
this.waterTiles = []; // Array za water tiles
this.waterAnimationTimer = 0;
// Rain particles za ribnik
this.rainEmitter = null;
this.splashEmitters = []; // Array splash emitterjev
this.tilePool = {
active: [],
inactive: [],
@@ -168,6 +179,32 @@ class TerrainSystem {
const types = Object.values(this.terrainTypes);
// POSEBNA OBDELAVA ZA VODO - 2D Stardew Valley Style!
if (!this.scene.textures.exists('water')) {
const waterGraphics = this.scene.make.graphics({ x: 0, y: 0, add: false });
// TEMNA MODRA VODA - dobro vidna!
waterGraphics.fillGradientStyle(
0x0a3d62, 0x0a3d62, // Temno modra (zgoraj)
0x1e5f8c, 0x1e5f8c // Srednje modra (spodaj)
);
waterGraphics.fillRect(0, 0, 48, 48);
// Svetli highlights za valovanje
waterGraphics.fillStyle(0x3a8fc2, 0.5);
waterGraphics.fillCircle(12, 12, 10);
waterGraphics.fillCircle(36, 28, 8);
waterGraphics.fillCircle(24, 38, 6);
// Temnejši border za kontrast
waterGraphics.lineStyle(2, 0x062a40, 1);
waterGraphics.strokeRect(0, 0, 48, 48);
waterGraphics.generateTexture('water', 48, 48);
waterGraphics.destroy();
console.log('🌊 2D Water texture created (Stardew Valley style)!');
}
types.forEach((type) => {
if (this.scene.textures.exists(type.name)) return;
@@ -355,6 +392,7 @@ class TerrainSystem {
generate() {
this.createTileTextures();
this.createWaterFrames(); // Ustvari water animation frames!
console.log('🌍 Initializing World (Zone Streaming Mode)...');
@@ -421,6 +459,15 @@ class TerrainSystem {
}
});
// RIBNIK - okrogel ribnik z vodo!
const distToPond = Math.sqrt(
Math.pow(x - POND_CENTER_X, 2) +
Math.pow(y - POND_CENTER_Y, 2)
);
if (distToPond <= POND_RADIUS) {
terrainType = this.terrainTypes.WATER; // Voda!
}
// Create Tile Data
this.tiles[y][x] = {
type: terrainType.name,
@@ -563,8 +610,45 @@ class TerrainSystem {
init(offsetX, offsetY) {
this.offsetX = offsetX;
this.offsetY = offsetY;
// Ustvari rain particles nad ribnikom
this.createRainOnPond();
}
createRainOnPond() {
// Izračunaj screen pozicijo ribnika
const pondScreenPos = this.iso.toScreen(POND_CENTER_X, POND_CENTER_Y);
const pondX = pondScreenPos.x + this.offsetX;
const pondY = pondScreenPos.y + this.offsetY;
// Ustvari particle texture (modra kapljica)
const graphics = this.scene.make.graphics({ x: 0, y: 0, add: false });
graphics.fillStyle(0x4488ff, 1);
graphics.fillCircle(2, 2, 2);
graphics.generateTexture('raindrop', 4, 4);
graphics.destroy();
// Rain emitter - pada v ribnik
this.rainEmitter = this.scene.add.particles(pondX, pondY - 100, 'raindrop', {
x: { min: -50, max: 50 },
y: 0,
lifespan: 1000,
speedY: { min: 200, max: 300 },
scale: { start: 0.5, end: 0.2 },
alpha: { start: 0.8, end: 0.3 },
frequency: 100,
blendMode: 'ADD'
});
// Dodaj rain sound effect
if (this.scene.soundManager) {
this.scene.soundManager.playRainSound();
}
console.log('🌧️ Rain particles created over pond!');
}
setTile(x, y, type) {
if (x >= 0 && x < this.width && y >= 0 && y < this.height) {
this.tiles[y][x].type = type;
@@ -887,15 +971,17 @@ class TerrainSystem {
// Use water texture with animation support
if (tile.type === 'water') {
// Check if water frames exist
if (this.scene.textures.exists('water_frame_0')) {
sprite.setTexture('water_frame_0');
// Mark sprite for animation
sprite.isWater = true;
sprite.waterFrame = 0;
} else {
sprite.setTexture('water');
}
sprite.setTexture('water');
// ANIMACIJA: Dodaj alpha tween za valovanje
this.scene.tweens.add({
targets: sprite,
alpha: 0.7,
duration: 1000,
yoyo: true,
repeat: -1,
ease: 'Sine.easeInOut'
});
} else {
sprite.setTexture(tile.type);
}
@@ -1086,43 +1172,9 @@ class TerrainSystem {
return true; // Out of bounds = solid
}
// Water Animation Update
// Water Animation Update - DISABLED (using tweens now)
update(time, delta) {
// Posodobi water animation timer
this.waterAnimationTimer += delta;
// Water frame animacija (vsake 150ms = ~6.6 FPS za smooth flow)
if (this.waterAnimationTimer > 150) {
this.waterAnimationTimer = 0;
// Increment frame counter
if (!this.waterCurrentFrame) this.waterCurrentFrame = 0;
this.waterCurrentFrame = (this.waterCurrentFrame + 1) % 4; // Cycle 0-3
// DEBUG
let waterTileCount = 0;
// Update vse visible water tiles s novim frame-om
this.visibleTiles.forEach((sprite, key) => {
const coords = key.split(',');
const x = parseInt(coords[0]);
const y = parseInt(coords[1]);
if (this.tiles[y] && this.tiles[y][x] && this.tiles[y][x].type === 'water') {
sprite.setTexture(`water_frame_${this.waterCurrentFrame}`);
waterTileCount++;
}
});
// DEBUG LOG
if (waterTileCount > 0) {
console.log(`🌊 Water animation: frame ${this.waterCurrentFrame} updated ${waterTileCount} tiles`);
} else {
console.warn('⚠️ No water tiles found in visibleTiles!', {
visibleTilesCount: this.visibleTiles.size,
currentFrame: this.waterCurrentFrame
});
}
}
// Water animation je zdaj implementirana z Phaser tweens
// Ni potrebe po ročnem frame update-u
}
}