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.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;
|
||||
|
||||
// Update attached elements depth
|
||||
|
||||
@@ -133,6 +133,51 @@ class Player {
|
||||
left: Phaser.Input.Keyboard.KeyCodes.A,
|
||||
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() {
|
||||
@@ -224,6 +269,24 @@ class Player {
|
||||
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
|
||||
let dx = 0;
|
||||
let dy = 0;
|
||||
@@ -354,8 +417,12 @@ class Player {
|
||||
|
||||
// Optimization: Create dirty check
|
||||
if (this.lastDepthY === undefined || Math.abs(this.sprite.y - this.lastDepthY) > 0.1) {
|
||||
this.sprite.setDepth(this.sprite.y);
|
||||
if (this.handSprite) this.handSprite.setDepth(this.sprite.y + 1);
|
||||
// Uporabi LAYER_OBJECTS da se pravilno sortira z drevesi/kamni
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,6 +40,12 @@ class BootScene extends Phaser.Scene {
|
||||
console.log('✅ BootScene: Complete!');
|
||||
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
|
||||
this.time.delayedCall(100, () => {
|
||||
this.scene.start('PreloadScene');
|
||||
|
||||
@@ -265,9 +265,10 @@ class GameScene extends Phaser.Scene {
|
||||
);
|
||||
}
|
||||
|
||||
// Terrain Culling
|
||||
// Terrain Culling & Update
|
||||
if (this.terrainSystem) {
|
||||
this.terrainSystem.updateCulling(this.cameras.main);
|
||||
this.terrainSystem.update(delta);
|
||||
}
|
||||
|
||||
// Clouds
|
||||
|
||||
@@ -36,11 +36,18 @@ class PreloadScene extends Phaser.Scene {
|
||||
this.load.image('tree_dead', 'assets/tree_dead.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
|
||||
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('rock_1', 'assets/rock_1.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('flowers_new', 'assets/flowers_new.png');
|
||||
this.load.image('hill_sprite', 'assets/hill_sprite.png');
|
||||
@@ -102,11 +109,18 @@ class PreloadScene extends Phaser.Scene {
|
||||
'tree_blue',
|
||||
'tree_dead',
|
||||
'rock_asset',
|
||||
|
||||
// FINAL TREES
|
||||
'tree_green_final',
|
||||
'tree_blue_final',
|
||||
'tree_dead_final',
|
||||
|
||||
// NEW transparent assets
|
||||
'tree_blue_new',
|
||||
'tree_green_new',
|
||||
'rock_1',
|
||||
'rock_2',
|
||||
'rock_small',
|
||||
'tree_dead_new',
|
||||
'flowers_new',
|
||||
'hill_sprite',
|
||||
@@ -151,9 +165,13 @@ class PreloadScene extends Phaser.Scene {
|
||||
const g = data[i + 1];
|
||||
const b = data[i + 2];
|
||||
|
||||
// Remove white/light gray backgrounds (all sprites)
|
||||
if (r > 200 && g > 200 && b > 200) {
|
||||
data[i + 3] = 0;
|
||||
// Remove white/light gray backgrounds (Checkerboard & White)
|
||||
// Target grays: R,G,B should be similar and high value.
|
||||
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)
|
||||
|
||||
@@ -49,6 +49,17 @@ class UIScene extends Phaser.Scene {
|
||||
toggleCraftingMenu() {
|
||||
if (!this.craftingContainer) this.createCraftingMenu();
|
||||
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() {
|
||||
|
||||
@@ -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
|
||||
if (this.scene.farmingSystem && !isAttack) {
|
||||
const didFarm = this.scene.farmingSystem.interact(gridX, gridY, activeTool);
|
||||
@@ -136,38 +156,74 @@ class InteractionSystem {
|
||||
if (this.scene.terrainSystem.decorationsMap.has(id)) {
|
||||
const decor = this.scene.terrainSystem.decorationsMap.get(id);
|
||||
|
||||
// handleTreeHit Logic (User Request)
|
||||
// Preverimo tip in ustrezno orodje
|
||||
let damage = 1;
|
||||
|
||||
if (decor.type === 'tree') {
|
||||
damage = (activeTool === 'axe') ? 3 : 1;
|
||||
// DREVESA (sapling, healthy, dead, blue)
|
||||
if (decor.type.includes('tree') || decor.type.includes('sapling')) {
|
||||
damage = (activeTool === 'axe') ? 5 : 1; // Povečal damage z sekiro
|
||||
}
|
||||
else if (decor.type === 'stone') {
|
||||
damage = (activeTool === 'pickaxe') ? 3 : 1;
|
||||
// KAMNI (rock, stone)
|
||||
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
|
||||
decor.hp -= damage;
|
||||
this.showFloatingText(`${-damage}`, gridX, gridY, '#ffaaaa');
|
||||
this.showFloatingText(`-${damage}`, gridX, gridY, '#ffaaaa');
|
||||
|
||||
// Chop Sound
|
||||
// Sound
|
||||
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) {
|
||||
const type = this.scene.terrainSystem.removeDecoration(gridX, gridY);
|
||||
// Loot logic via LootSystem
|
||||
let loot = 'wood';
|
||||
if (type === 'stone') loot = 'stone';
|
||||
if (type === 'bush') loot = 'seeds'; // Maybe berries?
|
||||
const prevType = decor.type;
|
||||
|
||||
if (this.scene.lootSystem) {
|
||||
if (type === 'tree') {
|
||||
this.scene.lootSystem.spawnLoot(gridX, gridY, 'wood', 3);
|
||||
// Logic: If Tree (and not sapling), turn into Sapling immediately (Regrowth)
|
||||
if ((prevType.includes('tree') || prevType.includes('final')) && !prevType.includes('sapling')) {
|
||||
|
||||
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_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
|
||||
class TerrainSystem {
|
||||
constructor(scene, width = 100, height = 100) {
|
||||
@@ -23,6 +35,7 @@ class TerrainSystem {
|
||||
this.decorations = [];
|
||||
this.decorationsMap = new Map();
|
||||
this.cropsMap = new Map();
|
||||
this.tileHealthMap = new Map(); // Global register zdravja ploščic
|
||||
|
||||
this.visibleTiles = new Map();
|
||||
this.visibleDecorations = new Map();
|
||||
@@ -92,7 +105,12 @@ class TerrainSystem {
|
||||
PAVEMENT: { name: 'pavement', height: 0.6, color: 0x777777 },
|
||||
RUINS: { name: 'ruins', height: 0.6, color: 0x555555 },
|
||||
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;
|
||||
@@ -218,6 +236,12 @@ class TerrainSystem {
|
||||
hasDecoration: 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--) {
|
||||
const j = Math.floor(Math.random() * (i + 1));
|
||||
[validPositions[i], validPositions[j]] = [validPositions[j], validPositions[i]];
|
||||
}
|
||||
// DECORATIONS REMOVED BY REQUEST
|
||||
// Drevesa, kamni, rože in ruševine so odstranjeni.
|
||||
|
||||
for (let i = 0; i < Math.min(25, validPositions.length); i++) {
|
||||
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';
|
||||
// Ostalo je samo generiranje ploščic (tiles) in fixnih con (farm, city floor).
|
||||
|
||||
this.addDecoration(pos.x, pos.y, treeType);
|
||||
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 (CLEAN): ${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) {
|
||||
if (type === 'ruin') {
|
||||
for (let y = 0; y < 6; y++) {
|
||||
@@ -422,6 +471,7 @@ class TerrainSystem {
|
||||
else if (type === 'fence') scale = 0.025;
|
||||
else if (type === 'gravestone') scale = 0.03;
|
||||
else if (type === 'hill_sprite') scale = 0.025;
|
||||
else if (type.includes('_final')) scale = 1.0; // New Final Trees
|
||||
else {
|
||||
// Old Assets (Low Res)
|
||||
if (type.includes('tree')) scale = 1.2 + Math.random() * 0.4;
|
||||
@@ -429,6 +479,15 @@ class TerrainSystem {
|
||||
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 = {
|
||||
gridX: gridX,
|
||||
gridY: gridY,
|
||||
@@ -436,7 +495,8 @@ class TerrainSystem {
|
||||
id: key,
|
||||
maxHp: 10,
|
||||
hp: 10,
|
||||
scale: scale
|
||||
scale: scale,
|
||||
plantDay: plantDay // Added for Growth System
|
||||
};
|
||||
this.decorations.push(decorData);
|
||||
this.decorationsMap.set(key, decorData);
|
||||
@@ -535,7 +595,7 @@ class TerrainSystem {
|
||||
sprite.setTexture(tile.type);
|
||||
const screenPos = this.iso.toScreen(x, y);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -552,6 +612,7 @@ class TerrainSystem {
|
||||
if (decor.type.includes('house') || decor.type.includes('market') || decor.type.includes('structure')) {
|
||||
sprite.setOrigin(0.5, 0.8);
|
||||
} else {
|
||||
// DREVESA: Origin na dno, da Y-sort deluje
|
||||
sprite.setOrigin(0.5, 1.0);
|
||||
}
|
||||
|
||||
@@ -562,7 +623,8 @@ class TerrainSystem {
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -576,7 +638,8 @@ class TerrainSystem {
|
||||
sprite.setPosition(screenPos.x + this.offsetX, screenPos.y + this.offsetY - voxelOffset);
|
||||
sprite.setTexture(`crop_stage_${crop.stage}`);
|
||||
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);
|
||||
}
|
||||
}
|
||||
@@ -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) {
|
||||
this.tileWidth = tileWidth;
|
||||
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
|
||||
@@ -21,12 +27,10 @@ class IsometricUtils {
|
||||
}
|
||||
|
||||
// Izračun depth (z-index) za pravilno sortiranje
|
||||
// Izračun depth (z-index)
|
||||
// V Phaserju je najbolje uporabiti kar Y koordinato spritha.
|
||||
// Tu vrnemo pričakovano Y pozicijo za grid celico.
|
||||
getDepth(gridX, gridY) {
|
||||
// (gridX + gridY) * tileHeight/2 je točno screenY
|
||||
return (gridX + gridY) * (this.tileHeight / 2);
|
||||
getDepth(gridX, gridY, layerBase = 0) {
|
||||
// Depth = LayerBase + ScreenY
|
||||
// To zagotovi, da so objekti v layerju sortirani po Y
|
||||
return layerBase + ((gridX + gridY) * (this.tileHeight / 2));
|
||||
}
|
||||
|
||||
// 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
|
||||
generateAll() {
|
||||
TextureGenerator.createPlayerSprite(this.scene);
|
||||
@@ -319,6 +339,7 @@ class TextureGenerator {
|
||||
|
||||
TextureGenerator.createFlowerSprite(this.scene);
|
||||
TextureGenerator.createBushSprite(this.scene);
|
||||
TextureGenerator.createSaplingSprite(this.scene, 'tree_sapling'); // Dodano
|
||||
TextureGenerator.createTreeSprite(this.scene); // Volumetric
|
||||
TextureGenerator.createRockSprite(this.scene); // Volumetric
|
||||
TextureGenerator.createCloudSprite(this.scene);
|
||||
|
||||
Reference in New Issue
Block a user