popravki
This commit is contained in:
@@ -368,28 +368,10 @@ class Player {
|
||||
const key = `${targetX},${targetY}`;
|
||||
if (terrainSystem.decorationsMap.has(key)) {
|
||||
const decor = terrainSystem.decorationsMap.get(key);
|
||||
// Vsi trdni objekti - igralec ne more hoditi skozi njih
|
||||
const solidTypes = [
|
||||
'tree', 'stone', 'bush', 'wall', 'ruin', 'fence', 'house', 'gravestone',
|
||||
'rock_asset', 'rock_1', 'rock_2', 'rock_small', // Kamni
|
||||
'tree_green_final', 'tree_blue_final', 'tree_dead_final', // Drevesa
|
||||
'chest', 'spawner', // City struktury
|
||||
'signpost_city', 'signpost_farm', 'signpost_both', // Signposti
|
||||
'arena' // Arena
|
||||
];
|
||||
|
||||
// Check ali je tip solid - case-insensitive
|
||||
const typeLower = (decor.type || '').toLowerCase();
|
||||
const isSolid = solidTypes.includes(decor.type) ||
|
||||
typeLower.includes('tree') ||
|
||||
typeLower.includes('sapling') ||
|
||||
typeLower.includes('rock') ||
|
||||
typeLower.includes('stone') ||
|
||||
typeLower.includes('signpost') ||
|
||||
typeLower.includes('hill');
|
||||
|
||||
if (isSolid) {
|
||||
console.log('⛔ BLOCKED:', decor.type);
|
||||
// Preverimo decor.solid property (set by TerrainSystem.addDecoration)
|
||||
if (decor.solid === true) {
|
||||
console.log('⛔ BLOCKED by solid decoration:', decor.type);
|
||||
isPassable = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@ const config = {
|
||||
clearBeforeRender: true,
|
||||
powerPreference: 'high-performance',
|
||||
// Eksplicitna NEAREST_NEIGHBOR filtracija
|
||||
mipmapFilter: 'LINEAR_MIPMAP_LINEAR',
|
||||
mipmapFilter: 'NEAREST',
|
||||
batchSize: 4096
|
||||
},
|
||||
physics: {
|
||||
|
||||
@@ -102,6 +102,21 @@ class GameScene extends Phaser.Scene {
|
||||
this.terrainSystem.placeStructure(65, 64, 'signpost_farm'); // Pri mestu "← Farm"
|
||||
this.terrainSystem.placeStructure(45, 40, 'signpost_both'); // Na križišču
|
||||
|
||||
// DAMAGED CITY WALLS - vizualni markerji mesta (porušeni zidovi)
|
||||
console.log('🏚️ Placing Damaged City Walls...');
|
||||
// Delno porušeni zidovi okoli city perimetra
|
||||
const wallPositions = [
|
||||
[65, 65], [70, 65], [75, 65], // Top wall
|
||||
[65, 79], [70, 79], [75, 79], // Bottom wall
|
||||
[65, 70], [65, 75], // Left wall
|
||||
[79, 70], [79, 75] // Right wall
|
||||
];
|
||||
wallPositions.forEach(([wx, wy]) => {
|
||||
if (Math.random() < 0.7) { // 70% chance per segment (gaps for realism)
|
||||
this.terrainSystem.placeStructure(wx, wy, 'wall_damaged');
|
||||
}
|
||||
});
|
||||
|
||||
// Initialize Pathfinding (Worker)
|
||||
console.log('🗺️ Initializing Pathfinding...');
|
||||
this.pathfinding = new PathfindingSystem(this);
|
||||
@@ -358,6 +373,9 @@ class GameScene extends Phaser.Scene {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Run Antigravity Engine Update
|
||||
this.Antigravity_Update(delta);
|
||||
}
|
||||
|
||||
spawnNightZombie() {
|
||||
@@ -464,19 +482,40 @@ class GameScene extends Phaser.Scene {
|
||||
// 2. Place starter resources (chest s semeni)
|
||||
this.terrainSystem.placeStructure(farmX + 3, farmY + 3, 'chest');
|
||||
|
||||
// 3. Place fence around farm (optional)
|
||||
const fencePositions = [
|
||||
[farmX - farmRadius, farmY - farmRadius],
|
||||
[farmX + farmRadius, farmY - farmRadius],
|
||||
[farmX - farmRadius, farmY + farmRadius],
|
||||
[farmX + farmRadius, farmY + farmRadius]
|
||||
];
|
||||
fencePositions.forEach(([fx, fy]) => {
|
||||
if (fx >= 0 && fx < 100 && fy >= 0 && fy < 100) {
|
||||
this.terrainSystem.placeStructure(fx, fy, 'fence');
|
||||
// 3. Place FULL FENCE around farm
|
||||
console.log('🚧 Building Farm Fence...');
|
||||
const minX = farmX - farmRadius;
|
||||
const maxX = farmX + farmRadius;
|
||||
const minY = farmY - farmRadius;
|
||||
const maxY = farmY + farmRadius;
|
||||
|
||||
// Top and bottom horizontal fences
|
||||
for (let x = minX; x <= maxX; x++) {
|
||||
if (x >= 0 && x < 100) {
|
||||
this.terrainSystem.placeStructure(x, minY, 'fence_full'); // Top
|
||||
this.terrainSystem.placeStructure(x, maxY, 'fence_full'); // Bottom
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Left and right vertical fences
|
||||
for (let y = minY; y <= maxY; y++) {
|
||||
if (y >= 0 && y < 100) {
|
||||
this.terrainSystem.placeStructure(minX, y, 'fence_full'); // Left
|
||||
this.terrainSystem.placeStructure(maxX, y, 'fence_full'); // Right
|
||||
}
|
||||
}
|
||||
|
||||
console.log('✅ Farm Area Initialized at (20,20)');
|
||||
}
|
||||
|
||||
// ========================================================
|
||||
// ANTIGRAVITY ENGINE UPDATE
|
||||
// ========================================================
|
||||
|
||||
Antigravity_Update(delta) {
|
||||
// Globalni update klic
|
||||
if (window.Antigravity) {
|
||||
window.Antigravity.Update(this, delta);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,6 +56,18 @@ class PreloadScene extends Phaser.Scene {
|
||||
this.load.image('fence', 'assets/fence.png');
|
||||
this.load.image('gravestone', 'assets/gravestone.png');
|
||||
|
||||
// City content assets
|
||||
this.load.image('chest', 'assets/chest.png');
|
||||
this.load.image('spawner', 'assets/spawner.png');
|
||||
this.load.image('signpost_city', 'assets/signpost_city.png');
|
||||
this.load.image('signpost_farm', 'assets/signpost_farm.png');
|
||||
this.load.image('signpost_both', 'assets/signpost_both.png');
|
||||
this.load.image('city_wall', 'assets/city_wall.png');
|
||||
this.load.image('road_tile', 'assets/road_tile.png');
|
||||
this.load.image('farm_zone', 'assets/farm_zone.png');
|
||||
this.load.image('fence_full', 'assets/fence_full.png');
|
||||
this.load.image('wall_damaged', 'assets/wall_damaged.png');
|
||||
|
||||
// Voxel stil asset-i (2.5D)
|
||||
this.load.image('tree_voxel_green', 'assets/tree_voxel_green.png');
|
||||
this.load.image('tree_voxel_blue', 'assets/tree_voxel_blue.png');
|
||||
@@ -130,6 +142,12 @@ class PreloadScene extends Phaser.Scene {
|
||||
'hill_sprite',
|
||||
'fence',
|
||||
'gravestone',
|
||||
// City content
|
||||
'chest',
|
||||
'spawner',
|
||||
'signpost_city',
|
||||
'signpost_farm',
|
||||
'signpost_both',
|
||||
// Voxel stil
|
||||
'tree_voxel_green',
|
||||
'tree_voxel_blue',
|
||||
|
||||
56
src/systems/Antigravity.js
Normal file
56
src/systems/Antigravity.js
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
* ANTIGRAVITY ENGINE
|
||||
* Core system for NovaFarma
|
||||
*/
|
||||
|
||||
window.Antigravity = {
|
||||
Config: {
|
||||
Tileset: {
|
||||
Spacing: 0,
|
||||
Margin: 0,
|
||||
TextureFilter: 'NEAREST'
|
||||
}
|
||||
},
|
||||
|
||||
Rendering: {
|
||||
/**
|
||||
* Zagotavlja pravilno globinsko razvrščanje (Depth Sorting) vseh spritov
|
||||
* @param {Phaser.Scene} scene
|
||||
*/
|
||||
depthSortSprites: function (scene) {
|
||||
// 1. Player Depth
|
||||
if (scene.player && scene.player.sprite) {
|
||||
scene.player.updateDepth();
|
||||
}
|
||||
|
||||
// 2. NPC Depth
|
||||
if (scene.npcs) {
|
||||
scene.npcs.forEach(npc => {
|
||||
if (npc && npc.sprite && npc.sprite.visible) {
|
||||
npc.updateDepth(); // Vsak NPC ima svojo metodo
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// 3. Projectiles / Particles (če bi jih imeli ločene)
|
||||
// ...
|
||||
}
|
||||
},
|
||||
|
||||
Physics: {
|
||||
checkCollisions: function (scene) {
|
||||
// Placeholder za centraliziran collision logic
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Glavni update loop za Engine
|
||||
* @param {Phaser.Scene} scene
|
||||
* @param {number} delta
|
||||
*/
|
||||
Update: function (scene, delta) {
|
||||
this.Rendering.depthSortSprites(scene);
|
||||
}
|
||||
};
|
||||
|
||||
console.log('🌌 Antigravity Engine Initialized', window.Antigravity.Config);
|
||||
@@ -21,6 +21,9 @@ const TILE_MINE_WALL = 81; // ID za zid rudnika (Solid/Kolizija)
|
||||
const ITEM_STONE = 20; // ID za kamen, ki ga igralec dobi
|
||||
const ITEM_IRON = 21; // ID za železo
|
||||
|
||||
const TREE_DENSITY_THRESHOLD = 0.65; // Višja vrednost = manj gosto (manj gozda)
|
||||
const ROCK_DENSITY_THRESHOLD = 0.60; // Prag za skupine skal
|
||||
|
||||
// Terrain Generator System
|
||||
class TerrainSystem {
|
||||
constructor(scene, width = 100, height = 100) {
|
||||
@@ -121,65 +124,86 @@ class TerrainSystem {
|
||||
createTileTextures() {
|
||||
const tileWidth = 48;
|
||||
const tileHeight = 60;
|
||||
const P = 2; // PADDING (Margin) za preprečevanje črt
|
||||
|
||||
const types = Object.values(this.terrainTypes);
|
||||
|
||||
types.forEach((type) => {
|
||||
if (this.scene.textures.exists(type.name)) return;
|
||||
|
||||
const graphics = this.scene.make.graphics({ x: 0, y: 0, add: false });
|
||||
const x = 0;
|
||||
const midX = 24;
|
||||
const midY = 12;
|
||||
const bottomY = 24;
|
||||
|
||||
// Koordinate z upoštevanjem paddinga
|
||||
const xs = P;
|
||||
const xe = 48 + P;
|
||||
const midX = 24 + P;
|
||||
|
||||
const topY = P;
|
||||
const midY = 12 + P;
|
||||
const bottomY = 24 + P;
|
||||
const depth = 20;
|
||||
|
||||
graphics.fillStyle(0x8B4513);
|
||||
// 1. STRANICE (Faces)
|
||||
// Left Face
|
||||
const cLeft = 0x8B4513;
|
||||
graphics.fillStyle(cLeft);
|
||||
graphics.beginPath();
|
||||
graphics.moveTo(midX, bottomY);
|
||||
graphics.lineTo(midX, bottomY + depth);
|
||||
graphics.lineTo(x, midY + depth);
|
||||
graphics.lineTo(x, midY);
|
||||
graphics.lineTo(xs, midY + depth);
|
||||
graphics.lineTo(xs, midY);
|
||||
graphics.closePath();
|
||||
graphics.fill();
|
||||
graphics.lineStyle(2, cLeft); // Overdraw
|
||||
graphics.strokePath();
|
||||
|
||||
graphics.fillStyle(0x6B3410);
|
||||
// Right Face
|
||||
const cRight = 0x6B3410;
|
||||
graphics.fillStyle(cRight);
|
||||
graphics.beginPath();
|
||||
graphics.moveTo(x + 48, midY);
|
||||
graphics.lineTo(x + 48, midY + depth);
|
||||
graphics.moveTo(xe, midY);
|
||||
graphics.lineTo(xe, midY + depth);
|
||||
graphics.lineTo(midX, bottomY + depth);
|
||||
graphics.lineTo(midX, bottomY);
|
||||
graphics.closePath();
|
||||
graphics.fill();
|
||||
|
||||
graphics.fillStyle(type.color);
|
||||
graphics.beginPath();
|
||||
graphics.moveTo(midX, 0);
|
||||
graphics.lineTo(x + 48, midY);
|
||||
graphics.lineTo(midX, bottomY);
|
||||
graphics.lineTo(x, midY);
|
||||
graphics.closePath();
|
||||
graphics.fill();
|
||||
|
||||
graphics.lineStyle(1, 0xffffff, 0.15);
|
||||
graphics.beginPath();
|
||||
graphics.moveTo(x, midY);
|
||||
graphics.lineTo(midX, 0);
|
||||
graphics.lineTo(x + 48, midY);
|
||||
graphics.lineStyle(2, cRight);
|
||||
graphics.strokePath();
|
||||
|
||||
// 2. ZGORNJA PLOSKEV (Top Face)
|
||||
graphics.fillStyle(type.color);
|
||||
graphics.beginPath();
|
||||
graphics.moveTo(xs, midY);
|
||||
graphics.lineTo(midX, topY);
|
||||
graphics.lineTo(xe, midY);
|
||||
graphics.lineTo(midX, bottomY);
|
||||
graphics.closePath();
|
||||
graphics.fill();
|
||||
graphics.lineStyle(2, type.color); // Overdraw
|
||||
graphics.strokePath();
|
||||
|
||||
// Highlight
|
||||
graphics.lineStyle(1, 0xffffff, 0.15);
|
||||
graphics.beginPath();
|
||||
graphics.moveTo(xs, midY);
|
||||
graphics.lineTo(midX, topY);
|
||||
graphics.lineTo(xe, midY);
|
||||
graphics.strokePath();
|
||||
|
||||
// 3. DETAJLI
|
||||
if (type.name.includes('grass')) {
|
||||
graphics.fillStyle(Phaser.Display.Color.IntegerToColor(type.color).lighten(10).color);
|
||||
for (let i = 0; i < 8; i++) {
|
||||
const rx = x + 10 + Math.random() * 28;
|
||||
const ry = 4 + Math.random() * 16;
|
||||
const rx = xs + 10 + Math.random() * 28;
|
||||
const ry = topY + 4 + Math.random() * 16;
|
||||
graphics.fillRect(rx, ry, 2, 2);
|
||||
}
|
||||
}
|
||||
if (type.name.includes('stone') || type.name.includes('ruins')) {
|
||||
graphics.fillStyle(0x444444);
|
||||
for (let i = 0; i < 6; i++) {
|
||||
const rx = x + 8 + Math.random() * 30;
|
||||
const ry = 4 + Math.random() * 16;
|
||||
const rx = xs + 8 + Math.random() * 30;
|
||||
const ry = topY + 4 + Math.random() * 16;
|
||||
graphics.fillRect(rx, ry, 3, 3);
|
||||
}
|
||||
}
|
||||
@@ -187,12 +211,12 @@ class TerrainSystem {
|
||||
if (type.name.includes('pavement')) {
|
||||
graphics.lineStyle(1, 0x555555, 0.5);
|
||||
graphics.beginPath();
|
||||
graphics.moveTo(x + 12, midY + 6);
|
||||
graphics.lineTo(x + 36, midY - 6);
|
||||
graphics.moveTo(xs + 12, midY + 6);
|
||||
graphics.lineTo(xs + 36, midY - 6);
|
||||
graphics.strokePath();
|
||||
}
|
||||
|
||||
graphics.generateTexture(type.name, tileWidth, tileHeight);
|
||||
graphics.generateTexture(type.name, tileWidth + P * 2, tileHeight + P * 2);
|
||||
graphics.destroy();
|
||||
});
|
||||
}
|
||||
@@ -357,22 +381,27 @@ class TerrainSystem {
|
||||
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)
|
||||
// KLJUČNO PREVERJANJE: Ali tu že stoji drug Sprite?
|
||||
const key = `${x},${y}`;
|
||||
if (this.decorationsMap.has(key)) return;
|
||||
if (this.tiles[y][x].hasDecoration) return;
|
||||
|
||||
// 3. Selection Logic
|
||||
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) {
|
||||
// USER LOGIC: Gostota 40% če smo nad pragom (Gozd)
|
||||
if (noiseVal > TREE_DENSITY_THRESHOLD && Math.random() < 0.4) {
|
||||
shouldPlace = true;
|
||||
}
|
||||
// Fallback: Redka posamična drevesa (1.5%)
|
||||
else if (Math.random() < 0.015) {
|
||||
shouldPlace = true;
|
||||
}
|
||||
|
||||
if (shouldPlace) {
|
||||
// Variants Logic
|
||||
const r = Math.random();
|
||||
// 50% možnosti, da je drevo komaj začelo rasti (Sapling)
|
||||
@@ -395,26 +424,24 @@ class TerrainSystem {
|
||||
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
|
||||
// KLJUČNO PREVERJANJE: Ali tu že stoji drug Sprite?
|
||||
const key = `${x},${y}`;
|
||||
if (this.decorationsMap.has(key)) return;
|
||||
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 type = 'rock_asset'; // Default lep kamen
|
||||
|
||||
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) {
|
||||
// USER LOGIC: Gostota 40% če smo nad pragom (Skalovje)
|
||||
if (noiseVal > ROCK_DENSITY_THRESHOLD && Math.random() < 0.4) {
|
||||
shouldPlace = true;
|
||||
}
|
||||
// Fallback: Redke posamične skale (1%)
|
||||
else if (Math.random() < 0.01) {
|
||||
shouldPlace = true;
|
||||
// Variants - "Lepi kamni" (rock_asset)
|
||||
// Odstranili smo nedokončane velike kamne
|
||||
type = 'rock_asset';
|
||||
}
|
||||
|
||||
if (shouldPlace) {
|
||||
@@ -505,6 +532,24 @@ class TerrainSystem {
|
||||
if (!w) plantDay = 1 - Math.floor(Math.random() * 2);
|
||||
}
|
||||
|
||||
// Determine if decoration is SOLID (blocking movement)
|
||||
const typeLower = type.toLowerCase();
|
||||
const isSolid = typeLower.includes('tree') ||
|
||||
typeLower.includes('sapling') ||
|
||||
typeLower.includes('rock') ||
|
||||
typeLower.includes('stone') ||
|
||||
typeLower.includes('fence') ||
|
||||
typeLower.includes('wall') ||
|
||||
typeLower.includes('signpost') ||
|
||||
typeLower.includes('hill') ||
|
||||
typeLower.includes('chest') ||
|
||||
typeLower.includes('spawner') ||
|
||||
typeLower.includes('ruin') ||
|
||||
typeLower.includes('arena') ||
|
||||
typeLower.includes('house') ||
|
||||
typeLower.includes('gravestone') ||
|
||||
typeLower.includes('bush');
|
||||
|
||||
const decorData = {
|
||||
gridX: gridX,
|
||||
gridY: gridY,
|
||||
@@ -513,7 +558,8 @@ class TerrainSystem {
|
||||
maxHp: 10,
|
||||
hp: 10,
|
||||
scale: scale,
|
||||
plantDay: plantDay // Added for Growth System
|
||||
plantDay: plantDay, // Added for Growth System
|
||||
solid: isSolid // TRDNOST (collision blocking)
|
||||
};
|
||||
this.decorations.push(decorData);
|
||||
this.decorationsMap.set(key, decorData);
|
||||
@@ -611,7 +657,7 @@ class TerrainSystem {
|
||||
const sprite = this.tilePool.get();
|
||||
sprite.setTexture(tile.type);
|
||||
const screenPos = this.iso.toScreen(x, y);
|
||||
sprite.setPosition(screenPos.x + this.offsetX, screenPos.y + this.offsetY);
|
||||
sprite.setPosition(Math.round(screenPos.x + this.offsetX), Math.round(screenPos.y + this.offsetY));
|
||||
sprite.setDepth(this.iso.getDepth(x, y, this.iso.LAYER_FLOOR)); // Tiles = Floor
|
||||
this.visibleTiles.set(key, sprite);
|
||||
}
|
||||
@@ -624,7 +670,7 @@ class TerrainSystem {
|
||||
const sprite = this.decorationPool.get();
|
||||
const screenPos = this.iso.toScreen(x, y);
|
||||
|
||||
sprite.setPosition(screenPos.x + this.offsetX, screenPos.y + this.offsetY - voxelOffset);
|
||||
sprite.setPosition(Math.round(screenPos.x + this.offsetX), Math.round(screenPos.y + this.offsetY - voxelOffset));
|
||||
|
||||
if (decor.type.includes('house') || decor.type.includes('market') || decor.type.includes('structure')) {
|
||||
sprite.setOrigin(0.5, 0.8);
|
||||
@@ -652,7 +698,7 @@ class TerrainSystem {
|
||||
if (!this.visibleCrops.has(key)) {
|
||||
const sprite = this.cropPool.get();
|
||||
const screenPos = this.iso.toScreen(x, y);
|
||||
sprite.setPosition(screenPos.x + this.offsetX, screenPos.y + this.offsetY - voxelOffset);
|
||||
sprite.setPosition(Math.round(screenPos.x + this.offsetX), Math.round(screenPos.y + this.offsetY - voxelOffset));
|
||||
sprite.setTexture(`crop_stage_${crop.stage}`);
|
||||
sprite.setOrigin(0.5, 1);
|
||||
// Layer Objects (da igralec hodi okoli njih)
|
||||
|
||||
Reference in New Issue
Block a user