dreva in kamni top
This commit is contained in:
BIN
assets/tree_blue_final.png
Normal file
BIN
assets/tree_blue_final.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 150 KiB |
BIN
assets/tree_dead_final.png
Normal file
BIN
assets/tree_dead_final.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 147 KiB |
BIN
assets/tree_green_final.png
Normal file
BIN
assets/tree_green_final.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 209 KiB |
@@ -493,7 +493,10 @@ class NPC {
|
|||||||
if (!this.sprite) return;
|
if (!this.sprite) return;
|
||||||
|
|
||||||
if (this.lastDepthY === undefined || Math.abs(this.sprite.y - this.lastDepthY) > 0.1) {
|
if (this.lastDepthY === undefined || Math.abs(this.sprite.y - this.lastDepthY) > 0.1) {
|
||||||
this.sprite.setDepth(this.sprite.y);
|
const layerBase = this.iso.LAYER_OBJECTS || 200000;
|
||||||
|
const depth = layerBase + this.sprite.y;
|
||||||
|
|
||||||
|
this.sprite.setDepth(depth);
|
||||||
this.lastDepthY = this.sprite.y;
|
this.lastDepthY = this.sprite.y;
|
||||||
|
|
||||||
// Update attached elements depth
|
// Update attached elements depth
|
||||||
|
|||||||
@@ -133,6 +133,51 @@ class Player {
|
|||||||
left: Phaser.Input.Keyboard.KeyCodes.A,
|
left: Phaser.Input.Keyboard.KeyCodes.A,
|
||||||
right: Phaser.Input.Keyboard.KeyCodes.D
|
right: Phaser.Input.Keyboard.KeyCodes.D
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Gamepad Events
|
||||||
|
this.scene.input.gamepad.on('connected', (pad) => {
|
||||||
|
this.setupGamepadEvents(pad);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (this.scene.input.gamepad.total > 0) {
|
||||||
|
this.setupGamepadEvents(this.scene.input.gamepad.getPad(0));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setupGamepadEvents(pad) {
|
||||||
|
if (!pad) return;
|
||||||
|
console.log('🎮 Gamepad Connected:', pad.id);
|
||||||
|
|
||||||
|
pad.on('down', (index) => {
|
||||||
|
if (this.isDead) return;
|
||||||
|
|
||||||
|
// A Button (0) - Attack
|
||||||
|
if (index === 0) {
|
||||||
|
this.attack();
|
||||||
|
}
|
||||||
|
|
||||||
|
// X Button (2) - Interact (Pick/Tame)
|
||||||
|
if (index === 2) {
|
||||||
|
const targetX = this.gridX + this.lastDir.x;
|
||||||
|
const targetY = this.gridY + this.lastDir.y;
|
||||||
|
if (this.scene.interactionSystem) {
|
||||||
|
this.scene.interactionSystem.handleInteraction(targetX, targetY);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Y Button (3) - Crafting
|
||||||
|
if (index === 3) {
|
||||||
|
// Zahteva, da UIScene posluša ta event, ali pa direktni klic
|
||||||
|
const ui = this.scene.scene.get('UIScene');
|
||||||
|
if (ui) ui.toggleCrafting();
|
||||||
|
}
|
||||||
|
|
||||||
|
// B Button (1) - Inventory
|
||||||
|
if (index === 1) {
|
||||||
|
const ui = this.scene.scene.get('UIScene');
|
||||||
|
if (ui) ui.toggleInventory();
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
attack() {
|
attack() {
|
||||||
@@ -224,6 +269,24 @@ class Player {
|
|||||||
if (ui.virtualJoystick.right) right = true;
|
if (ui.virtualJoystick.right) right = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Check Gamepad Input (Xbox Controller)
|
||||||
|
if (this.scene.input.gamepad && this.scene.input.gamepad.total > 0) {
|
||||||
|
const pad = this.scene.input.gamepad.getPad(0);
|
||||||
|
if (pad) {
|
||||||
|
const threshold = 0.3;
|
||||||
|
if (pad.leftStick.y < -threshold) up = true;
|
||||||
|
if (pad.leftStick.y > threshold) down = true;
|
||||||
|
if (pad.leftStick.x < -threshold) left = true;
|
||||||
|
if (pad.leftStick.x > threshold) right = true;
|
||||||
|
|
||||||
|
// D-Pad support
|
||||||
|
if (pad.up) up = true;
|
||||||
|
if (pad.down) down = true;
|
||||||
|
if (pad.left) left = true;
|
||||||
|
if (pad.right) right = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Apply
|
// Apply
|
||||||
let dx = 0;
|
let dx = 0;
|
||||||
let dy = 0;
|
let dy = 0;
|
||||||
@@ -354,8 +417,12 @@ class Player {
|
|||||||
|
|
||||||
// Optimization: Create dirty check
|
// Optimization: Create dirty check
|
||||||
if (this.lastDepthY === undefined || Math.abs(this.sprite.y - this.lastDepthY) > 0.1) {
|
if (this.lastDepthY === undefined || Math.abs(this.sprite.y - this.lastDepthY) > 0.1) {
|
||||||
this.sprite.setDepth(this.sprite.y);
|
// Uporabi LAYER_OBJECTS da se pravilno sortira z drevesi/kamni
|
||||||
if (this.handSprite) this.handSprite.setDepth(this.sprite.y + 1);
|
const layerBase = this.iso.LAYER_OBJECTS || 200000;
|
||||||
|
const depth = layerBase + this.sprite.y;
|
||||||
|
|
||||||
|
this.sprite.setDepth(depth);
|
||||||
|
if (this.handSprite) this.handSprite.setDepth(depth + 1);
|
||||||
this.lastDepthY = this.sprite.y;
|
this.lastDepthY = this.sprite.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,6 +40,12 @@ class BootScene extends Phaser.Scene {
|
|||||||
console.log('✅ BootScene: Complete!');
|
console.log('✅ BootScene: Complete!');
|
||||||
window.gameState.currentScene = 'BootScene';
|
window.gameState.currentScene = 'BootScene';
|
||||||
|
|
||||||
|
// Global Constants for Sprites
|
||||||
|
window.SPRITE_TREE_HEALTHY = 'tree_green_final';
|
||||||
|
window.SPRITE_TREE_BLUE = 'tree_blue_final';
|
||||||
|
window.SPRITE_TREE_DEAD = 'tree_dead_final';
|
||||||
|
window.SPRITE_TREE_SAPLING = 'tree_sapling';
|
||||||
|
|
||||||
// Takoj po bootu gremo v PreloadScene
|
// Takoj po bootu gremo v PreloadScene
|
||||||
this.time.delayedCall(100, () => {
|
this.time.delayedCall(100, () => {
|
||||||
this.scene.start('PreloadScene');
|
this.scene.start('PreloadScene');
|
||||||
|
|||||||
@@ -265,9 +265,10 @@ class GameScene extends Phaser.Scene {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Terrain Culling
|
// Terrain Culling & Update
|
||||||
if (this.terrainSystem) {
|
if (this.terrainSystem) {
|
||||||
this.terrainSystem.updateCulling(this.cameras.main);
|
this.terrainSystem.updateCulling(this.cameras.main);
|
||||||
|
this.terrainSystem.update(delta);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Clouds
|
// Clouds
|
||||||
|
|||||||
@@ -36,11 +36,18 @@ class PreloadScene extends Phaser.Scene {
|
|||||||
this.load.image('tree_dead', 'assets/tree_dead.png');
|
this.load.image('tree_dead', 'assets/tree_dead.png');
|
||||||
this.load.image('rock_asset', 'assets/rock_asset.png');
|
this.load.image('rock_asset', 'assets/rock_asset.png');
|
||||||
|
|
||||||
|
// FINAL TREES (User Uploaded)
|
||||||
|
this.load.image('tree_green_final', 'assets/tree_green_final.png');
|
||||||
|
this.load.image('tree_blue_final', 'assets/tree_blue_final.png');
|
||||||
|
this.load.image('tree_dead_final', 'assets/tree_dead_final.png');
|
||||||
|
|
||||||
// NEW transparent tree/rock assets
|
// NEW transparent tree/rock assets
|
||||||
this.load.image('tree_blue_new', 'assets/tree_blue_new.png');
|
this.load.image('tree_blue_new', 'assets/tree_blue_new.png'); // Keep for backup
|
||||||
|
|
||||||
this.load.image('tree_green_new', 'assets/tree_green_new.png');
|
this.load.image('tree_green_new', 'assets/tree_green_new.png');
|
||||||
this.load.image('rock_1', 'assets/rock_1.png');
|
this.load.image('rock_1', 'assets/rock_1.png');
|
||||||
this.load.image('rock_2', 'assets/rock_2.png');
|
this.load.image('rock_2', 'assets/rock_2.png');
|
||||||
|
this.load.image('rock_small', 'assets/rock_small.png');
|
||||||
this.load.image('tree_dead_new', 'assets/tree_dead_new.png');
|
this.load.image('tree_dead_new', 'assets/tree_dead_new.png');
|
||||||
this.load.image('flowers_new', 'assets/flowers_new.png');
|
this.load.image('flowers_new', 'assets/flowers_new.png');
|
||||||
this.load.image('hill_sprite', 'assets/hill_sprite.png');
|
this.load.image('hill_sprite', 'assets/hill_sprite.png');
|
||||||
@@ -102,11 +109,18 @@ class PreloadScene extends Phaser.Scene {
|
|||||||
'tree_blue',
|
'tree_blue',
|
||||||
'tree_dead',
|
'tree_dead',
|
||||||
'rock_asset',
|
'rock_asset',
|
||||||
|
|
||||||
|
// FINAL TREES
|
||||||
|
'tree_green_final',
|
||||||
|
'tree_blue_final',
|
||||||
|
'tree_dead_final',
|
||||||
|
|
||||||
// NEW transparent assets
|
// NEW transparent assets
|
||||||
'tree_blue_new',
|
'tree_blue_new',
|
||||||
'tree_green_new',
|
'tree_green_new',
|
||||||
'rock_1',
|
'rock_1',
|
||||||
'rock_2',
|
'rock_2',
|
||||||
|
'rock_small',
|
||||||
'tree_dead_new',
|
'tree_dead_new',
|
||||||
'flowers_new',
|
'flowers_new',
|
||||||
'hill_sprite',
|
'hill_sprite',
|
||||||
@@ -151,9 +165,13 @@ class PreloadScene extends Phaser.Scene {
|
|||||||
const g = data[i + 1];
|
const g = data[i + 1];
|
||||||
const b = data[i + 2];
|
const b = data[i + 2];
|
||||||
|
|
||||||
// Remove white/light gray backgrounds (all sprites)
|
// Remove white/light gray backgrounds (Checkerboard & White)
|
||||||
if (r > 200 && g > 200 && b > 200) {
|
// Target grays: R,G,B should be similar and high value.
|
||||||
data[i + 3] = 0;
|
if (r > 150 && g > 150 && b > 150) {
|
||||||
|
// Check if it's grayscale (checkerboard is usually perfect gray)
|
||||||
|
if (Math.abs(r - g) < 30 && Math.abs(g - b) < 30) {
|
||||||
|
data[i + 3] = 0;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Special: Remove brown/tan backgrounds (merchant sprite)
|
// Special: Remove brown/tan backgrounds (merchant sprite)
|
||||||
|
|||||||
@@ -49,6 +49,17 @@ class UIScene extends Phaser.Scene {
|
|||||||
toggleCraftingMenu() {
|
toggleCraftingMenu() {
|
||||||
if (!this.craftingContainer) this.createCraftingMenu();
|
if (!this.craftingContainer) this.createCraftingMenu();
|
||||||
this.craftingContainer.setVisible(!this.craftingContainer.visible);
|
this.craftingContainer.setVisible(!this.craftingContainer.visible);
|
||||||
|
// Pause/Resume game?
|
||||||
|
// if (this.gameScene) this.gameScene.physics.world.isPaused = this.craftingContainer.visible;
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleCrafting() {
|
||||||
|
this.toggleCraftingMenu();
|
||||||
|
}
|
||||||
|
|
||||||
|
toggleInventory() {
|
||||||
|
// Za zdaj odpre crafting meni, ker nimamo ločenega "Big Inventory"
|
||||||
|
this.toggleCraftingMenu();
|
||||||
}
|
}
|
||||||
|
|
||||||
createCraftingMenu() {
|
createCraftingMenu() {
|
||||||
|
|||||||
@@ -125,6 +125,26 @@ class InteractionSystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 4. Try Planting Tree (Manual Planting)
|
||||||
|
if (!isAttack && (activeTool === 'tree_sapling' || activeTool === 'item_sapling')) {
|
||||||
|
const tile = this.scene.terrainSystem.getTile(gridX, gridY);
|
||||||
|
|
||||||
|
// Dovolimo sajenje samo na travo in dirt
|
||||||
|
if (tile && !tile.hasDecoration && !tile.hasCrop && (tile.type.includes('grass') || tile.type.includes('dirt'))) {
|
||||||
|
const saplingSprite = window.SPRITE_TREE_SAPLING || 'tree_sapling';
|
||||||
|
this.scene.terrainSystem.addDecoration(gridX, gridY, saplingSprite);
|
||||||
|
|
||||||
|
// Remove 1 sapling from hand
|
||||||
|
if (this.scene.inventorySystem) {
|
||||||
|
this.scene.inventorySystem.removeItem(activeTool, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sound
|
||||||
|
// this.scene.soundManager.playPlant();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// 4. Try Farming Action
|
// 4. Try Farming Action
|
||||||
if (this.scene.farmingSystem && !isAttack) {
|
if (this.scene.farmingSystem && !isAttack) {
|
||||||
const didFarm = this.scene.farmingSystem.interact(gridX, gridY, activeTool);
|
const didFarm = this.scene.farmingSystem.interact(gridX, gridY, activeTool);
|
||||||
@@ -136,38 +156,74 @@ class InteractionSystem {
|
|||||||
if (this.scene.terrainSystem.decorationsMap.has(id)) {
|
if (this.scene.terrainSystem.decorationsMap.has(id)) {
|
||||||
const decor = this.scene.terrainSystem.decorationsMap.get(id);
|
const decor = this.scene.terrainSystem.decorationsMap.get(id);
|
||||||
|
|
||||||
|
// handleTreeHit Logic (User Request)
|
||||||
|
// Preverimo tip in ustrezno orodje
|
||||||
let damage = 1;
|
let damage = 1;
|
||||||
|
|
||||||
if (decor.type === 'tree') {
|
// DREVESA (sapling, healthy, dead, blue)
|
||||||
damage = (activeTool === 'axe') ? 3 : 1;
|
if (decor.type.includes('tree') || decor.type.includes('sapling')) {
|
||||||
|
damage = (activeTool === 'axe') ? 5 : 1; // Povečal damage z sekiro
|
||||||
}
|
}
|
||||||
else if (decor.type === 'stone') {
|
// KAMNI (rock, stone)
|
||||||
damage = (activeTool === 'pickaxe') ? 3 : 1;
|
else if (decor.type.includes('rock') || decor.type.includes('stone')) {
|
||||||
|
damage = (activeTool === 'pickaxe') ? 5 : 1;
|
||||||
}
|
}
|
||||||
else if (decor.type === 'bush') damage = 2;
|
else if (decor.type.includes('bush')) damage = 5;
|
||||||
|
|
||||||
// Apply damage
|
// Apply damage
|
||||||
decor.hp -= damage;
|
decor.hp -= damage;
|
||||||
this.showFloatingText(`${-damage}`, gridX, gridY, '#ffaaaa');
|
this.showFloatingText(`-${damage}`, gridX, gridY, '#ffaaaa');
|
||||||
|
|
||||||
// Chop Sound
|
// Sound
|
||||||
if (this.scene.soundManager) {
|
if (this.scene.soundManager) {
|
||||||
this.scene.soundManager.playChop();
|
if (decor.type.includes('tree')) this.scene.soundManager.playChop();
|
||||||
|
else this.scene.soundManager.playHit(); // Generic hit for rocks
|
||||||
}
|
}
|
||||||
|
|
||||||
if (decor.hp <= 0) {
|
if (decor.hp <= 0) {
|
||||||
const type = this.scene.terrainSystem.removeDecoration(gridX, gridY);
|
const prevType = decor.type;
|
||||||
// Loot logic via LootSystem
|
|
||||||
let loot = 'wood';
|
|
||||||
if (type === 'stone') loot = 'stone';
|
|
||||||
if (type === 'bush') loot = 'seeds'; // Maybe berries?
|
|
||||||
|
|
||||||
if (this.scene.lootSystem) {
|
// Logic: If Tree (and not sapling), turn into Sapling immediately (Regrowth)
|
||||||
if (type === 'tree') {
|
if ((prevType.includes('tree') || prevType.includes('final')) && !prevType.includes('sapling')) {
|
||||||
this.scene.lootSystem.spawnLoot(gridX, gridY, 'wood', 3);
|
|
||||||
|
decor.type = window.SPRITE_TREE_SAPLING || 'tree_sapling';
|
||||||
|
decor.hp = 2; // Fragile sapling
|
||||||
|
decor.scale = 1.0;
|
||||||
|
|
||||||
|
// Update visual immediately
|
||||||
|
const sprite = this.scene.terrainSystem.visibleDecorations.get(id);
|
||||||
|
if (sprite) {
|
||||||
|
sprite.setTexture(decor.type);
|
||||||
|
sprite.setScale(decor.scale);
|
||||||
|
// Shrink effect to simulate falling/replacement
|
||||||
|
this.scene.tweens.add({
|
||||||
|
targets: sprite, scaleX: { from: 1.2, to: 1.0 }, scaleY: { from: 1.2, to: 1.0 }, duration: 200
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
this.scene.lootSystem.spawnLoot(gridX, gridY, loot, 1);
|
// Drop Wood Only
|
||||||
|
if (this.scene.lootSystem) {
|
||||||
|
this.scene.lootSystem.spawnLoot(gridX, gridY, 'item_wood', Math.floor(Math.random() * 3) + 2);
|
||||||
|
}
|
||||||
|
console.log('🌱 Tree replanted automatically.');
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const type = this.scene.terrainSystem.removeDecoration(gridX, gridY);
|
||||||
|
|
||||||
|
// Loot logic handled here via LootSystem
|
||||||
|
if (this.scene.lootSystem) {
|
||||||
|
if (type.includes('rock') || type.includes('stone')) {
|
||||||
|
this.scene.lootSystem.spawnLoot(gridX, gridY, 'item_stone', Math.floor(Math.random() * 3) + 1);
|
||||||
|
}
|
||||||
|
else if (type.includes('bush') || type.includes('sapling')) {
|
||||||
|
this.scene.lootSystem.spawnLoot(gridX, gridY, 'item_seeds', 1);
|
||||||
|
if (type.includes('sapling')) {
|
||||||
|
this.scene.lootSystem.spawnLoot(gridX, gridY, window.SPRITE_TREE_SAPLING || 'tree_sapling', 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type.includes('flowers')) {
|
||||||
|
this.scene.lootSystem.spawnLoot(gridX, gridY, 'item_seeds', 1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,18 @@ const CITY_SIZE = 15;
|
|||||||
const CITY_START_X = 65; // Desni del mape (npr. med 65 in 80)
|
const CITY_START_X = 65; // Desni del mape (npr. med 65 in 80)
|
||||||
const CITY_START_Y = 65;
|
const CITY_START_Y = 65;
|
||||||
|
|
||||||
|
// ========================================================
|
||||||
|
// NOVE KONSTANTE ZA RUDNIK IN RUDE
|
||||||
|
// ========================================================
|
||||||
|
const TILE_STONE_ORE = 82; // ID za navadni kamen (Ore Tile)
|
||||||
|
const TILE_IRON_ORE = 83; // ID za železovo rudo
|
||||||
|
const TILE_PAVEMENT = 16; // ID za prehodno ploščico (tla rudnika)
|
||||||
|
const TILE_MINE_WALL = 81; // ID za zid rudnika (Solid/Kolizija)
|
||||||
|
|
||||||
|
// ID-ji Virov
|
||||||
|
const ITEM_STONE = 20; // ID za kamen, ki ga igralec dobi
|
||||||
|
const ITEM_IRON = 21; // ID za železo
|
||||||
|
|
||||||
// Terrain Generator System
|
// Terrain Generator System
|
||||||
class TerrainSystem {
|
class TerrainSystem {
|
||||||
constructor(scene, width = 100, height = 100) {
|
constructor(scene, width = 100, height = 100) {
|
||||||
@@ -23,6 +35,7 @@ class TerrainSystem {
|
|||||||
this.decorations = [];
|
this.decorations = [];
|
||||||
this.decorationsMap = new Map();
|
this.decorationsMap = new Map();
|
||||||
this.cropsMap = new Map();
|
this.cropsMap = new Map();
|
||||||
|
this.tileHealthMap = new Map(); // Global register zdravja ploščic
|
||||||
|
|
||||||
this.visibleTiles = new Map();
|
this.visibleTiles = new Map();
|
||||||
this.visibleDecorations = new Map();
|
this.visibleDecorations = new Map();
|
||||||
@@ -92,7 +105,12 @@ class TerrainSystem {
|
|||||||
PAVEMENT: { name: 'pavement', height: 0.6, color: 0x777777 },
|
PAVEMENT: { name: 'pavement', height: 0.6, color: 0x777777 },
|
||||||
RUINS: { name: 'ruins', height: 0.6, color: 0x555555 },
|
RUINS: { name: 'ruins', height: 0.6, color: 0x555555 },
|
||||||
PATH: { name: 'path', height: -1, color: 0xc2b280 },
|
PATH: { name: 'path', height: -1, color: 0xc2b280 },
|
||||||
FARMLAND: { name: 'farmland', height: -1, color: 0x5c4033 }
|
FARMLAND: { name: 'farmland', height: -1, color: 0x5c4033 },
|
||||||
|
// MINE TYPES
|
||||||
|
MINE_FLOOR: { name: 'mine_floor', height: 0, color: 0x333333, id: TILE_PAVEMENT },
|
||||||
|
MINE_WALL: { name: 'mine_wall', height: 1, color: 0x1a1a1a, id: TILE_MINE_WALL },
|
||||||
|
ORE_STONE: { name: 'ore_stone', height: 0.5, color: 0x555555, id: TILE_STONE_ORE },
|
||||||
|
ORE_IRON: { name: 'ore_iron', height: 0.5, color: 0x884444, id: TILE_IRON_ORE }
|
||||||
};
|
};
|
||||||
|
|
||||||
this.offsetX = 0;
|
this.offsetX = 0;
|
||||||
@@ -218,6 +236,12 @@ class TerrainSystem {
|
|||||||
hasDecoration: false,
|
hasDecoration: false,
|
||||||
hasCrop: false
|
hasCrop: false
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Place Trees dynamically during generation
|
||||||
|
this.placeTree(x, y, terrainType.name);
|
||||||
|
|
||||||
|
// Place Rocks dynamically
|
||||||
|
this.placeRock(x, y, terrainType.name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -240,61 +264,12 @@ class TerrainSystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = validPositions.length - 1; i > 0; i--) {
|
// DECORATIONS REMOVED BY REQUEST
|
||||||
const j = Math.floor(Math.random() * (i + 1));
|
// Drevesa, kamni, rože in ruševine so odstranjeni.
|
||||||
[validPositions[i], validPositions[j]] = [validPositions[j], validPositions[i]];
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < Math.min(25, validPositions.length); i++) {
|
// Ostalo je samo generiranje ploščic (tiles) in fixnih con (farm, city floor).
|
||||||
const pos = validPositions[i];
|
|
||||||
let treeType = 'tree_green_new';
|
|
||||||
const rand = Math.random();
|
|
||||||
if (rand < 0.15) treeType = 'tree_blue_new';
|
|
||||||
else if (rand < 0.25) treeType = 'tree_dead_new';
|
|
||||||
|
|
||||||
this.addDecoration(pos.x, pos.y, treeType);
|
console.log(`✅ Teren generiran (CLEAN): ${treeCount} dreves, ${rockCount} kamnov.`);
|
||||||
treeCount++;
|
|
||||||
}
|
|
||||||
for (let i = 25; i < Math.min(50, validPositions.length); i++) {
|
|
||||||
const pos = validPositions[i];
|
|
||||||
// Uporabi uporabnikove kamne
|
|
||||||
const rockType = Math.random() > 0.5 ? 'rock_1' : 'rock_2';
|
|
||||||
this.addDecoration(pos.x, pos.y, rockType);
|
|
||||||
rockCount++;
|
|
||||||
}
|
|
||||||
|
|
||||||
const flowerNoise = new PerlinNoise(Date.now() + 3000);
|
|
||||||
for (let y = 5; y < this.height - 5; y++) {
|
|
||||||
for (let x = 5; x < this.width - 5; x++) {
|
|
||||||
if (isFarm(x, y) || isCity(x, y)) continue;
|
|
||||||
|
|
||||||
const tile = this.tiles[y][x];
|
|
||||||
const val = flowerNoise.noise(x * 0.12, y * 0.12);
|
|
||||||
if (val > 0.85 && tile.type.includes('grass')) {
|
|
||||||
this.addDecoration(x, y, 'flowers_new');
|
|
||||||
flowerCount++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const roomSize = 5;
|
|
||||||
const roomsAcross = Math.floor(CITY_SIZE / roomSize);
|
|
||||||
|
|
||||||
for (let ry = 0; ry < roomsAcross; ry++) {
|
|
||||||
for (let rx = 0; rx < roomsAcross; rx++) {
|
|
||||||
if (Math.random() < 0.75) {
|
|
||||||
const gx = CITY_START_X + rx * roomSize;
|
|
||||||
const gy = CITY_START_Y + ry * roomSize;
|
|
||||||
this.placeStructure(gx, gy, 'ruin_room');
|
|
||||||
} else {
|
|
||||||
const gx = CITY_START_X + rx * roomSize + 2;
|
|
||||||
const gy = CITY_START_Y + ry * roomSize + 2;
|
|
||||||
const rockType = Math.random() > 0.5 ? 'rock_1' : 'rock_2';
|
|
||||||
this.addDecoration(gx, gy, rockType);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
console.log(`✅ Teren generiran: ${treeCount} dreves, ${rockCount} kamnov.`);
|
console.log(`✅ Teren generiran: ${treeCount} dreves, ${rockCount} kamnov.`);
|
||||||
}
|
}
|
||||||
@@ -356,6 +331,80 @@ class TerrainSystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
placeTree(x, y, tileType) {
|
||||||
|
// 1. Safety Checks
|
||||||
|
if (!tileType || !tileType.includes('grass')) return;
|
||||||
|
|
||||||
|
const isFarm = Math.abs(x - FARM_CENTER_X) <= FARM_SIZE / 2 + 2;
|
||||||
|
const isCity = x >= CITY_START_X - 2 && x < CITY_START_X + CITY_SIZE + 2 && y >= CITY_START_Y - 2 && y < CITY_START_Y + CITY_SIZE + 2;
|
||||||
|
if (isFarm || isCity) return;
|
||||||
|
|
||||||
|
// 2. Noise for clustering (Forests)
|
||||||
|
// Offset inputs to decouple from terrain height noise
|
||||||
|
const noiseVal = this.noise.noise(x * 0.1 + 123.45, y * 0.1 + 678.90);
|
||||||
|
|
||||||
|
// 3. Selection Logic (Scattered & Saplings focus)
|
||||||
|
let shouldPlace = false;
|
||||||
|
let type = window.SPRITE_TREE_HEALTHY || 'tree_green_final';
|
||||||
|
|
||||||
|
// Bolj enakomerna porazdelitev (Scattered)
|
||||||
|
// Noise uporabimo le za rahlo variacijo, ne za stroge gruče
|
||||||
|
let chance = 0.015; // 1.5% base chance (zelo redko)
|
||||||
|
|
||||||
|
if (noiseVal > 0.30) chance = 0.03; // Malo večja gostota v "gozdu"
|
||||||
|
|
||||||
|
if (Math.random() < chance) {
|
||||||
|
shouldPlace = true;
|
||||||
|
|
||||||
|
// Variants Logic
|
||||||
|
const r = Math.random();
|
||||||
|
// 50% možnosti, da je drevo komaj začelo rasti (Sapling)
|
||||||
|
if (r < 0.50) type = window.SPRITE_TREE_SAPLING || 'tree_sapling';
|
||||||
|
else if (r < 0.60) type = window.SPRITE_TREE_DEAD || 'tree_dead_final';
|
||||||
|
else if (r < 0.65) type = window.SPRITE_TREE_BLUE || 'tree_blue_final';
|
||||||
|
// Ostalo (35%) je odraslo drevo
|
||||||
|
}
|
||||||
|
|
||||||
|
// 4. Placement
|
||||||
|
if (shouldPlace) {
|
||||||
|
this.addDecoration(x, y, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
placeRock(x, y, tileType) {
|
||||||
|
if (!tileType || !tileType.includes('grass') && !tileType.includes('dirt')) return;
|
||||||
|
|
||||||
|
const isFarm = Math.abs(x - FARM_CENTER_X) <= FARM_SIZE / 2 + 2;
|
||||||
|
const isCity = x >= CITY_START_X - 2 && x < CITY_START_X + CITY_SIZE + 2 && y >= CITY_START_Y - 2 && y < CITY_START_Y + CITY_SIZE + 2;
|
||||||
|
if (isFarm || isCity) return;
|
||||||
|
|
||||||
|
// Če je že dekoracija (drevo), ne dajaj kamna
|
||||||
|
if (this.tiles[y][x].hasDecoration) return;
|
||||||
|
|
||||||
|
// Noise for Rock Clusters
|
||||||
|
const noiseVal = this.noise.noise(x * 0.15 + 99.99, y * 0.15 + 88.88);
|
||||||
|
|
||||||
|
let shouldPlace = false;
|
||||||
|
let type = 'rock_1'; // Default
|
||||||
|
|
||||||
|
let chance = 0.01; // 1% Scattered chance
|
||||||
|
|
||||||
|
if (noiseVal > 0.45) { // Rock Cluster Area
|
||||||
|
chance = 0.30; // High density in cluster
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Math.random() < chance) {
|
||||||
|
shouldPlace = true;
|
||||||
|
// Variants - "Lepi kamni" (rock_asset)
|
||||||
|
// Odstranili smo nedokončane velike kamne
|
||||||
|
type = 'rock_asset';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldPlace) {
|
||||||
|
this.addDecoration(x, y, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
placeStructure(gridX, gridY, type) {
|
placeStructure(gridX, gridY, type) {
|
||||||
if (type === 'ruin') {
|
if (type === 'ruin') {
|
||||||
for (let y = 0; y < 6; y++) {
|
for (let y = 0; y < 6; y++) {
|
||||||
@@ -422,6 +471,7 @@ class TerrainSystem {
|
|||||||
else if (type === 'fence') scale = 0.025;
|
else if (type === 'fence') scale = 0.025;
|
||||||
else if (type === 'gravestone') scale = 0.03;
|
else if (type === 'gravestone') scale = 0.03;
|
||||||
else if (type === 'hill_sprite') scale = 0.025;
|
else if (type === 'hill_sprite') scale = 0.025;
|
||||||
|
else if (type.includes('_final')) scale = 1.0; // New Final Trees
|
||||||
else {
|
else {
|
||||||
// Old Assets (Low Res)
|
// Old Assets (Low Res)
|
||||||
if (type.includes('tree')) scale = 1.2 + Math.random() * 0.4;
|
if (type.includes('tree')) scale = 1.2 + Math.random() * 0.4;
|
||||||
@@ -429,6 +479,15 @@ class TerrainSystem {
|
|||||||
else scale = 1.0;
|
else scale = 1.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Calculate Plant Day for Saplings (Growth System)
|
||||||
|
let plantDay = -1;
|
||||||
|
if (type.includes('sapling')) {
|
||||||
|
const w = this.scene.weatherSystem;
|
||||||
|
plantDay = w ? w.getDayCount() : 1;
|
||||||
|
// Random init offset for initial generation
|
||||||
|
if (!w) plantDay = 1 - Math.floor(Math.random() * 2);
|
||||||
|
}
|
||||||
|
|
||||||
const decorData = {
|
const decorData = {
|
||||||
gridX: gridX,
|
gridX: gridX,
|
||||||
gridY: gridY,
|
gridY: gridY,
|
||||||
@@ -436,7 +495,8 @@ class TerrainSystem {
|
|||||||
id: key,
|
id: key,
|
||||||
maxHp: 10,
|
maxHp: 10,
|
||||||
hp: 10,
|
hp: 10,
|
||||||
scale: scale
|
scale: scale,
|
||||||
|
plantDay: plantDay // Added for Growth System
|
||||||
};
|
};
|
||||||
this.decorations.push(decorData);
|
this.decorations.push(decorData);
|
||||||
this.decorationsMap.set(key, decorData);
|
this.decorationsMap.set(key, decorData);
|
||||||
@@ -535,7 +595,7 @@ class TerrainSystem {
|
|||||||
sprite.setTexture(tile.type);
|
sprite.setTexture(tile.type);
|
||||||
const screenPos = this.iso.toScreen(x, y);
|
const screenPos = this.iso.toScreen(x, y);
|
||||||
sprite.setPosition(screenPos.x + this.offsetX, screenPos.y + this.offsetY);
|
sprite.setPosition(screenPos.x + this.offsetX, screenPos.y + this.offsetY);
|
||||||
sprite.setDepth(this.iso.getDepth(x, y));
|
sprite.setDepth(this.iso.getDepth(x, y, this.iso.LAYER_FLOOR)); // Tiles = Floor
|
||||||
this.visibleTiles.set(key, sprite);
|
this.visibleTiles.set(key, sprite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -552,6 +612,7 @@ class TerrainSystem {
|
|||||||
if (decor.type.includes('house') || decor.type.includes('market') || decor.type.includes('structure')) {
|
if (decor.type.includes('house') || decor.type.includes('market') || decor.type.includes('structure')) {
|
||||||
sprite.setOrigin(0.5, 0.8);
|
sprite.setOrigin(0.5, 0.8);
|
||||||
} else {
|
} else {
|
||||||
|
// DREVESA: Origin na dno, da Y-sort deluje
|
||||||
sprite.setOrigin(0.5, 1.0);
|
sprite.setOrigin(0.5, 1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,7 +623,8 @@ class TerrainSystem {
|
|||||||
sprite.setAlpha(decor.alpha);
|
sprite.setAlpha(decor.alpha);
|
||||||
}
|
}
|
||||||
|
|
||||||
sprite.setDepth(this.iso.getDepth(x, y) + 1);
|
// Layer Objects
|
||||||
|
sprite.setDepth(this.iso.getDepth(x, y, this.iso.LAYER_OBJECTS));
|
||||||
this.visibleDecorations.set(key, sprite);
|
this.visibleDecorations.set(key, sprite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -576,7 +638,8 @@ class TerrainSystem {
|
|||||||
sprite.setPosition(screenPos.x + this.offsetX, screenPos.y + this.offsetY - voxelOffset);
|
sprite.setPosition(screenPos.x + this.offsetX, screenPos.y + this.offsetY - voxelOffset);
|
||||||
sprite.setTexture(`crop_stage_${crop.stage}`);
|
sprite.setTexture(`crop_stage_${crop.stage}`);
|
||||||
sprite.setOrigin(0.5, 1);
|
sprite.setOrigin(0.5, 1);
|
||||||
sprite.setDepth(this.iso.getDepth(x, y) + 0.5);
|
// Layer Objects (da igralec hodi okoli njih)
|
||||||
|
sprite.setDepth(this.iso.getDepth(x, y, this.iso.LAYER_OBJECTS));
|
||||||
this.visibleCrops.set(key, sprite);
|
this.visibleCrops.set(key, sprite);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -605,4 +668,48 @@ class TerrainSystem {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getTile(x, y) {
|
||||||
|
if (x >= 0 && x < this.width && y >= 0 && y < this.height) {
|
||||||
|
return this.tiles[y][x];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
update(delta) {
|
||||||
|
this.growthTimer = (this.growthTimer || 0) + delta;
|
||||||
|
if (this.growthTimer < 5000) return;
|
||||||
|
this.growthTimer = 0;
|
||||||
|
|
||||||
|
const weather = this.scene.weatherSystem;
|
||||||
|
if (!weather) return;
|
||||||
|
const currentDay = weather.getDayCount();
|
||||||
|
|
||||||
|
const healthyType = window.SPRITE_TREE_HEALTHY || 'tree_green_final';
|
||||||
|
|
||||||
|
for (const decor of this.decorationsMap.values()) {
|
||||||
|
if (decor.type.includes('sapling')) {
|
||||||
|
if (decor.plantDay !== undefined && decor.plantDay > -100 && (currentDay - decor.plantDay >= 3)) {
|
||||||
|
decor.type = healthyType;
|
||||||
|
decor.scale = 1.0;
|
||||||
|
decor.hp = 10;
|
||||||
|
decor.plantDay = -1;
|
||||||
|
|
||||||
|
const key = decor.id;
|
||||||
|
if (this.visibleDecorations.has(key)) {
|
||||||
|
const sprite = this.visibleDecorations.get(key);
|
||||||
|
sprite.setTexture(decor.type);
|
||||||
|
sprite.setScale(decor.scale);
|
||||||
|
this.scene.tweens.add({
|
||||||
|
targets: sprite,
|
||||||
|
scaleY: { from: 0.1, to: decor.scale },
|
||||||
|
duration: 800,
|
||||||
|
ease: 'Bounce.out'
|
||||||
|
});
|
||||||
|
console.log(`🌳 Tree grew on Day ${currentDay}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,12 @@ class IsometricUtils {
|
|||||||
constructor(tileWidth = 48, tileHeight = 24) {
|
constructor(tileWidth = 48, tileHeight = 24) {
|
||||||
this.tileWidth = tileWidth;
|
this.tileWidth = tileWidth;
|
||||||
this.tileHeight = tileHeight;
|
this.tileHeight = tileHeight;
|
||||||
|
|
||||||
|
// Layer Constants
|
||||||
|
this.LAYER_FLOOR = 0;
|
||||||
|
this.LAYER_GRID_DECO = 100000; // Decorations on floor (shadows)
|
||||||
|
this.LAYER_OBJECTS = 200000; // Dynamic entities (Trees, Player, NPCs)
|
||||||
|
this.LAYER_UI = 300000;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Kartezične (grid) koordinate -> Isometrične (screen) koordinate
|
// Kartezične (grid) koordinate -> Isometrične (screen) koordinate
|
||||||
@@ -21,12 +27,10 @@ class IsometricUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Izračun depth (z-index) za pravilno sortiranje
|
// Izračun depth (z-index) za pravilno sortiranje
|
||||||
// Izračun depth (z-index)
|
getDepth(gridX, gridY, layerBase = 0) {
|
||||||
// V Phaserju je najbolje uporabiti kar Y koordinato spritha.
|
// Depth = LayerBase + ScreenY
|
||||||
// Tu vrnemo pričakovano Y pozicijo za grid celico.
|
// To zagotovi, da so objekti v layerju sortirani po Y
|
||||||
getDepth(gridX, gridY) {
|
return layerBase + ((gridX + gridY) * (this.tileHeight / 2));
|
||||||
// (gridX + gridY) * tileHeight/2 je točno screenY
|
|
||||||
return (gridX + gridY) * (this.tileHeight / 2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Izračun centerja tile-a
|
// Izračun centerja tile-a
|
||||||
|
|||||||
@@ -311,6 +311,26 @@ class TextureGenerator {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static createSaplingSprite(scene, key = 'tree_sapling') {
|
||||||
|
if (scene.textures.exists(key)) return;
|
||||||
|
const size = 32;
|
||||||
|
const canvas = scene.textures.createCanvas(key, size, size);
|
||||||
|
const ctx = canvas.getContext();
|
||||||
|
ctx.clearRect(0, 0, size, size);
|
||||||
|
|
||||||
|
// Majhno steblo
|
||||||
|
ctx.fillStyle = '#8B4513';
|
||||||
|
ctx.fillRect(14, 20, 4, 12);
|
||||||
|
|
||||||
|
// Parnosti listov
|
||||||
|
ctx.fillStyle = '#32CD32';
|
||||||
|
ctx.beginPath(); ctx.arc(12, 18, 4, 0, Math.PI * 2); ctx.fill();
|
||||||
|
ctx.beginPath(); ctx.arc(20, 18, 4, 0, Math.PI * 2); ctx.fill();
|
||||||
|
ctx.beginPath(); ctx.arc(16, 12, 5, 0, Math.PI * 2); ctx.fill();
|
||||||
|
|
||||||
|
canvas.refresh();
|
||||||
|
}
|
||||||
|
|
||||||
// Helper to generate ALL textures at once
|
// Helper to generate ALL textures at once
|
||||||
generateAll() {
|
generateAll() {
|
||||||
TextureGenerator.createPlayerSprite(this.scene);
|
TextureGenerator.createPlayerSprite(this.scene);
|
||||||
@@ -319,6 +339,7 @@ class TextureGenerator {
|
|||||||
|
|
||||||
TextureGenerator.createFlowerSprite(this.scene);
|
TextureGenerator.createFlowerSprite(this.scene);
|
||||||
TextureGenerator.createBushSprite(this.scene);
|
TextureGenerator.createBushSprite(this.scene);
|
||||||
|
TextureGenerator.createSaplingSprite(this.scene, 'tree_sapling'); // Dodano
|
||||||
TextureGenerator.createTreeSprite(this.scene); // Volumetric
|
TextureGenerator.createTreeSprite(this.scene); // Volumetric
|
||||||
TextureGenerator.createRockSprite(this.scene); // Volumetric
|
TextureGenerator.createRockSprite(this.scene); // Volumetric
|
||||||
TextureGenerator.createCloudSprite(this.scene);
|
TextureGenerator.createCloudSprite(this.scene);
|
||||||
|
|||||||
Reference in New Issue
Block a user