This commit is contained in:
2025-12-12 00:13:55 +01:00
parent 158beec572
commit e15b429e75
17 changed files with 482 additions and 202 deletions

View File

@@ -0,0 +1,134 @@
# 🌲 Sesija: Optimizacija Gozda - 12. December 2025
## 📋 Povzetek Sesije
### 🎯 Cilj
Generirati 100x100 mapo z **Stardew Valley stilom gozda** z vijolčnimi in sadnimi drevesi ter zapuščenimi hišami.
### ✅ Dosežki
#### 1. **Velikost Mape**
- ✅ Spremenjena na **100x100** tiles
- ✅ Celoten teren: `GRASS_FULL`
- ✅ Farm: 8x8 na (50,50) z `DIRT` ploščicami
#### 2. **Drevesni Sistem**
-**Gostota:** 1% (zelo nizka, optimizirana)
-**Preverjanje razdalje:** Min 2 tiles med drevesi
-**Vrste dreves:**
- 💜 30% Vijolčna drevesa (`tree_purple`)
- 🍎 20% Sadna drevesa (`tree_apple`, `tree_pear`, `tree_cherry`)
- 🌳 50% Zelena/modra drevesa (`tree_green_final`, `tree_blue_final`)
#### 3. **Sprite-i**
- ✅ Generirani novi sprite-i za drevesa
- ✅ Ultra agresivno odstranjevanje ozadij (brightness > 100)
- ✅ Čisti, transparentni sprite-i
#### 4. **Optimizacije**
- ✅ Odstranjena vsa ozadja iz sprite-ov
- ✅ Pomanjšana drevesa (scale 0.6-0.7)
- ✅ Sistem preverjanja razdalje med drevesi
- ✅ Čista mapa brez nepotrebnih dekoracij
### 🔧 Ključne Spremembe
#### **TerrainSystem.js**
```javascript
// Konstante
const TREE_DENSITY = 0.01; // 1% gostota
const PURPLE_TREE_CHANCE = 0.30;
const FRUIT_TREE_CHANCE = 0.20;
const MIN_TREE_DISTANCE_SQUARED = 2 * 2;
// Tracking dreves
this.placedTrees = [];
// Funkcija za preverjanje razdalje
isTreeLocationFarEnough(newX, newY) {
// Preveri razdaljo do vseh dreves
// Vrne true če je OK, false če preblizu
}
```
#### **GameScene.js**
```javascript
// Farm ploščice - DIRT namesto GRASS
this.terrainSystem.tiles[y][x].type = 'dirt';
this.terrainSystem.tiles[y][x].sprite.setTexture('dirt');
```
#### **PreloadScene.js**
```javascript
// Novi sprite-i
this.load.image('tree_purple', 'assets/tree_purple.png');
this.load.image('tree_apple', 'assets/tree_apple.png');
this.load.image('tree_pear', 'assets/tree_pear.png');
this.load.image('tree_cherry', 'assets/tree_cherry.png');
// Ultra agresivno odstranjevanje ozadij
processSpriteTransparency(spriteKey) {
// Odstrani VSE svetle barve (brightness > 100)
// Odstrani VSE sive barve
// Odstrani VSE pastelne barve
}
```
### 🐛 Odpravljene Napake
1.**TypeError: Cannot read properties of null (reading 'addDecoration')**
- Dodano preverjanje `if (this.terrainSystem)` pred klici
2.**ReferenceError: TILE_PAVEMENT is not defined**
- Dodane manjkajoče konstante za rudnik
3.**Cannot read properties of null (reading 'getTile')**
- Dodano preverjanje v OceanSystem
4.**Stari save file nalaga hiše**
- Onemogočen loadGame() za testiranje
- Odstranjena koda za generiranje hiš
5.**Ozadja še vedno vidna**
- Ultra agresivno odstranjevanje (brightness > 100)
- Python skripta za procesiranje
### 📊 Končna Konfiguracija
**Mapa:**
- Velikost: 100x100
- Teren: Zelena trava (`grass_full`)
- Farm: 8x8 dirt ploščice na (50,50)
**Drevesa:**
- Gostota: 1%
- Min. razdalja: 2 tiles
- Vijolčna: 30%
- Sadna: 20%
- Zelena/modra: 50%
**Dekoracije:**
- Grmički: 0%
- Rože: 0%
- Skale: 0%
- Hiše: 0%
### 🎯 Naslednji Koraki
1. **Testiranje v igri** - Vizualno preverjanje gozda
2. **Dodatne izboljšave** - Po potrebi prilagoditev gostote
3. **Interakcije** - Sekanje dreves, nabiranje sadja
4. **Zapuščene hiše** - Ponovno dodati če želeno
### 📝 Opombe
- Save sistem je ponovno omogočen
- Vsi sprite-i imajo transparentna ozadja
- Sistem preverjanja razdalje preprečuje prekrivanje
- Optimizirana gostota za boljšo vidnost
---
**Datum:** 12. December 2025
**Trajanje:** ~1.5 ure
**Status:** ✅ Uspešno zaključeno

BIN
assets/tree_apple.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 916 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 129 KiB

BIN
assets/tree_cherry.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 988 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 209 KiB

After

Width:  |  Height:  |  Size: 177 KiB

BIN
assets/tree_pear.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 986 KiB

BIN
assets/tree_purple.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 898 KiB

18
clear_all_saves.js Normal file
View File

@@ -0,0 +1,18 @@
// CLEAR ALL SAVE FILES
console.log('🗑️ Clearing ALL save files...');
// Clear main save
localStorage.removeItem('novafarma_savefile');
// Clear all slots
for (let i = 1; i <= 3; i++) {
localStorage.removeItem(`novafarma_save_slot${i}`);
localStorage.removeItem(`novafarma_slot${i}_meta`);
}
// Clear other saves
localStorage.removeItem('novafarma_save');
localStorage.removeItem('novafarma_achievement_progress');
console.log('✅ All saves cleared! Reload page (F4) for fresh start.');
console.log('📝 Remaining keys:', Object.keys(localStorage).filter(k => k.includes('novafarma')));

3
clear_save.js Normal file
View File

@@ -0,0 +1,3 @@
// Clear localStorage save file
localStorage.removeItem('novafarma_savefile');
console.log('✅ Save file cleared! Reload page (F4) for fresh start.');

View File

@@ -23,7 +23,9 @@
"type": "commonjs",
"dependencies": {
"canvas": "^3.2.0",
"phaser": "^3.80.1"
"express": "^5.2.1",
"phaser": "^3.80.1",
"socket.io": "^4.8.1"
},
"devDependencies": {
"electron": "^33.2.1"

78
remove_backgrounds.py Normal file
View File

@@ -0,0 +1,78 @@
from PIL import Image
import os
# Lista slik za procesiranje
images_to_process = [
'assets/tree_purple.png',
'assets/tree_apple.png',
'assets/tree_pear.png',
'assets/tree_cherry.png'
]
def remove_background(image_path):
"""Odstrani ozadje iz slike - naredi transparentno"""
try:
# Naloži sliko
img = Image.open(image_path).convert('RGBA')
data = img.getdata()
new_data = []
for item in data:
r, g, b, a = item
# Izračunaj brightness in grayscale
brightness = (r + g + b) / 3
is_grayscale = abs(r - g) < 20 and abs(g - b) < 20 and abs(r - b) < 20
# Odstrani:
# 1. Vse sive barve (šahovsko ozadje)
# 2. Vse svetle barve (brightness > 150)
# 3. Bele barve
# 4. Pastelne barve (nizka saturacija)
should_remove = False
# Sive barve
if is_grayscale and brightness > 80:
should_remove = True
# Svetle barve
if brightness > 150:
should_remove = True
# Bele
if r > 240 and g > 240 and b > 240:
should_remove = True
# Pastelne (nizka saturacija)
max_rgb = max(r, g, b)
min_rgb = min(r, g, b)
saturation = 0 if max_rgb == 0 else (max_rgb - min_rgb) / max_rgb
if saturation < 0.3 and brightness > 120:
should_remove = True
if should_remove:
new_data.append((r, g, b, 0)) # Transparentno
else:
new_data.append(item) # Ohrani original
# Posodobi sliko
img.putdata(new_data)
# Shrani
img.save(image_path)
print(f'✅ Processed: {image_path}')
except Exception as e:
print(f'❌ Error processing {image_path}: {e}')
# Procesiraj vse slike
print('🎨 Removing backgrounds from tree sprites...')
for img_path in images_to_process:
if os.path.exists(img_path):
remove_background(img_path)
else:
print(f'⚠️ File not found: {img_path}')
print('✅ Done! All backgrounds removed.')

View File

@@ -208,14 +208,19 @@ class GameScene extends Phaser.Scene {
this.signposts = [];
// Path markers (using fence sprites as signposts)
const pathMarkers = [
{ x: 35, y: 35, label: '→ City' },
{ x: 50, y: 50, label: '← Farm' },
];
// ONLY if terrainSystem was successfully initialized
if (this.terrainSystem) {
const pathMarkers = [
{ x: 35, y: 35, label: '→ City' },
{ x: 50, y: 50, label: '← Farm' },
];
for (const marker of pathMarkers) {
this.terrainSystem.addDecoration(marker.x, marker.y, 'fence');
this.signposts.push({ gridX: marker.x, gridY: marker.y, label: marker.label });
for (const marker of pathMarkers) {
this.terrainSystem.addDecoration(marker.x, marker.y, 'fence');
this.signposts.push({ gridX: marker.x, gridY: marker.y, label: marker.label });
}
} else {
console.warn('⚠️ TerrainSystem not initialized - skipping signposts');
}
// Kamera sledi igralcu z gladko interpolacijo (lerp 0.1)
@@ -280,8 +285,8 @@ class GameScene extends Phaser.Scene {
// Initialize Save System
this.saveSystem = new SaveSystem(this);
// Auto-load if available
this.saveSystem.loadGame();
// Auto-load if available (DISABLED in SaveSystem!)
this.saveSystem.loadGame(); // Vrne false - ne naloži save-a!
// Debug Text
this.add.text(10, 10, 'NovaFarma Alpha v0.6', { font: '16px monospace', fill: '#ffffff' })
@@ -738,11 +743,11 @@ class GameScene extends Phaser.Scene {
if (this.terrainSystem.decorationsMap.has(key)) {
this.terrainSystem.removeDecoration(x, y);
}
// Make it grass or dirt - USE CORRECT TERRAIN TYPE OBJECT
// Make it DIRT for farming
if (this.terrainSystem.tiles[y] && this.terrainSystem.tiles[y][x]) {
this.terrainSystem.tiles[y][x].type = this.terrainSystem.terrainTypes.GRASS_FULL;
this.terrainSystem.tiles[y][x].type = 'dirt';
if (this.terrainSystem.tiles[y][x].sprite) {
this.terrainSystem.tiles[y][x].sprite.setTexture('grass');
this.terrainSystem.tiles[y][x].sprite.setTexture('dirt');
this.terrainSystem.tiles[y][x].sprite.setTint(0xffffff); // Clear tint
}
}

View File

@@ -41,6 +41,13 @@ class PreloadScene extends Phaser.Scene {
this.load.image('tree_blue_final', 'assets/tree_blue_final.png');
this.load.image('tree_dead_final', 'assets/tree_dead_final.png');
// STARDEW VALLEY FOREST TREES (NEW!)
this.load.image('tree_purple', 'assets/tree_purple.png');
this.load.image('tree_apple', 'assets/tree_apple.png');
this.load.image('tree_pear', 'assets/tree_pear.png');
this.load.image('tree_cherry', 'assets/tree_cherry.png');
this.load.image('tree_sapling', 'assets/tree_green_final.png'); // Reuse green as sapling
// NEW transparent tree/rock assets
this.load.image('tree_blue_new', 'assets/tree_blue_new.png'); // Keep for backup
@@ -53,6 +60,9 @@ class PreloadScene extends Phaser.Scene {
this.load.image('merchant_new', 'assets/merchant_new.png');
this.load.image('elite_zombie', 'assets/elite_zombie.png');
// Fence old for abandoned houses
this.load.image('fence_old', 'assets/fence_isometric.png'); // Reuse fence for old houses
// AI-Generated NPC Sprites (with cache-busting)
const cacheBust = Date.now();
this.load.image('cow', `assets/cow.png?v=${cacheBust}`);
@@ -191,6 +201,13 @@ class PreloadScene extends Phaser.Scene {
'tree_blue_final',
'tree_dead_final',
// STARDEW VALLEY FOREST TREES
'tree_purple',
'tree_apple',
'tree_pear',
'tree_cherry',
'tree_sapling',
// NEW transparent assets
'tree_blue_new',
'tree_green_new',
@@ -203,6 +220,7 @@ class PreloadScene extends Phaser.Scene {
'flowers_new',
'hill_sprite',
'fence',
'fence_old',
'gravestone',
// City content
'chest',
@@ -288,43 +306,51 @@ class PreloadScene extends Phaser.Scene {
const imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
const data = imageData.data;
// Remove backgrounds - IMPROVED CHECKBOARD DETECTION
// Remove backgrounds - ULTRA AGGRESSIVE MODE!
for (let i = 0; i < data.length; i += 4) {
const r = data[i];
const g = data[i + 1];
const b = data[i + 2];
const a = data[i + 3];
// Remove ALL grayscale colors (checkboard pattern)
// Checkboard has both light (204,204,204) and dark (153,153,153) squares
const isGrayscale = Math.abs(r - g) < 15 && Math.abs(g - b) < 15 && Math.abs(r - b) < 15;
// Skip if already transparent
if (a === 0) continue;
if (isGrayscale) {
// ULTRA-AGGRESSIVE: Remove ALL grays from 100-240
const isAnyGray = r >= 100 && r <= 240;
if (isAnyGray) {
data[i + 3] = 0; // Make transparent
}
}
// AGGRESSIVE: Remove ALL light backgrounds (AI-generated sprites)
const brightness = (r + g + b) / 3;
const isVeryLight = brightness > 170 && Math.abs(r - g) < 50 && Math.abs(g - b) < 50;
if (isVeryLight) {
// 1. Remove ALL grayscale colors (ANY shade of gray)
const isGrayscale = Math.abs(r - g) < 20 && Math.abs(g - b) < 20 && Math.abs(r - b) < 20;
if (isGrayscale && brightness > 80) {
data[i + 3] = 0; // Make transparent
continue;
}
// ULTRA AGGRESSIVE: Remove PURE WHITE backgrounds
const isWhite = r > 240 && g > 240 && b > 240;
if (isWhite) {
// 2. Remove ALL light/bright backgrounds (AI-generated sprites)
if (brightness > 150) {
data[i + 3] = 0; // Make transparent
continue;
}
// ULTRA AGGRESSIVE: Remove OFF-WHITE backgrounds (cream, beige)
const isOffWhite = brightness > 230 && Math.abs(r - g) < 20 && Math.abs(g - b) < 20;
if (isOffWhite) {
data[i + 3] = 0; // Make transparent
// 3. Remove PURE WHITE
if (r > 240 && g > 240 && b > 240) {
data[i + 3] = 0;
continue;
}
// 4. Remove OFF-WHITE / CREAM / BEIGE
if (brightness > 200 && Math.abs(r - g) < 30 && Math.abs(g - b) < 30) {
data[i + 3] = 0;
continue;
}
// 5. Remove PASTEL colors (low saturation, high brightness)
const maxRGB = Math.max(r, g, b);
const minRGB = Math.min(r, g, b);
const saturation = maxRGB === 0 ? 0 : (maxRGB - minRGB) / maxRGB;
if (saturation < 0.3 && brightness > 120) {
data[i + 3] = 0; // Remove low-saturation backgrounds
continue;
}
// Special: Remove brown/tan backgrounds (merchant sprite)

View File

@@ -26,7 +26,7 @@ class OceanSystem {
}
update(time, delta) {
if (!this.scene.player) return;
if (!this.scene.player || !this.scene.terrainSystem) return;
const playerPos = this.scene.player.getPosition();
const tile = this.scene.terrainSystem.getTile(playerPos.x, playerPos.y);
@@ -83,6 +83,8 @@ class OceanSystem {
return;
}
if (!this.scene.terrainSystem) return;
// Check if on water or near water?
// Actually, let's allow "deploying" boat anywhere, but only moving fast on water?
// OR: Only allow deploying on water tile.

View File

@@ -1,29 +1,34 @@
// ========================================================
// NOVE GLOBALNE KONSTANTE ZA LOKACIJE
// STARDEW VALLEY STYLE FOREST MAP - 100x100
// ========================================================
const MAP_SIZE = 100; // 100x100 velika mapa!
const FARM_SIZE = 8; // 8x8 MICRO FARM - Začetek igre!
const FARM_CENTER_X = 50; // Center mape (50,50)
const FARM_CENTER_Y = 50; // Center mape (50,50)
const CITY_SIZE = 15;
const CITY_START_X = 65; // Desni del mape (npr. med 65 in 80)
const CITY_START_Y = 65;
// Zapuščene hiše lokacije - ODSTRANJENO ZA TESTIRANJE!
const ABANDONED_HOUSES = [
// { x: 25, y: 25, size: 5 },
// { x: 75, y: 30, size: 6 },
// { x: 40, y: 75, size: 4 }
]; // PRAZNO - brez hiš!
// ========================================================
// NOVE KONSTANTE ZA RUDNIK IN RUDE
// GOZD KONSTANTE - STARDEW VALLEY STYLE (OPTIMIZIRANO)
// ========================================================
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
const TREE_DENSITY_THRESHOLD = 0.45; // Višja vrednost = manj gosto (manj gozda)
const TREE_DENSITY = 0.01; // 1% chance za drevo (zelo nizka gostota)
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
// ========================================================
// RUDNIK KONSTANTE (za terrainTypes)
// ========================================================
const TILE_PAVEMENT = 16; // ID za prehodno ploščico
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
// Terrain Generator System
class TerrainSystem {
constructor(scene, width = 100, height = 100) {
@@ -127,10 +132,35 @@ class TerrainSystem {
this.generatedChunks = new Set();
this.chunkSize = 10;
// FOREST GENERATION: Tracking postavljenih dreves za preverjanje razdalje
this.placedTrees = []; // Seznam vseh postavljenih dreves { x, y }
this.MIN_TREE_DISTANCE_SQUARED = 2 * 2; // Minimalna razdalja med drevesi (2 tiles)
// Init tiles array with NULLs
this.tiles = Array.from({ length: this.height }, () => Array(this.width).fill(null));
}
/**
* Preveri, ali je nova lokacija (newX, newY) dovolj oddaljena od vseh
* že postavljenih dreves. Uporablja kvadrat razdalje za hitrejšo optimizacijo.
*/
isTreeLocationFarEnough(newX, newY) {
for (let i = 0; i < this.placedTrees.length; i++) {
const existingTree = this.placedTrees[i];
// Izračunaj kvadrat razdalje
const dx = newX - existingTree.x;
const dy = newY - existingTree.y;
const distanceSq = (dx * dx) + (dy * dy);
// Če je razdalja manjša od zahtevane minimalne razdalje, zavrni lokacijo
if (distanceSq < this.MIN_TREE_DISTANCE_SQUARED) {
return false;
}
}
return true; // Lokacija je dovolj oddaljena
}
createTileTextures() {
const tileWidth = 48;
const tileHeight = 60;
@@ -373,186 +403,87 @@ class TerrainSystem {
for (let y = startY; y < endY; y++) {
for (let x = startX; x < endX; x++) {
// --- PER TILE GENERATION LOGIC (Moved from old loop) ---
const nx = x * 0.1;
const ny = y * 0.1;
const elevation = this.noise.noise(nx, ny);
// SIMPLE TERRAIN - samo grass (brez elevation/stone/hills)
let terrainType = this.terrainTypes.GRASS_FULL;
// Edges of WORLD -也 grass
// (removed elevation-based terrain - user wants clean platform)
// --- STARDEW VALLEY FOREST GENERATION ---
let terrainType = this.terrainTypes.GRASS_FULL; // Vsa mapa je trava!
// Farm Override - ZELENA PLATFORMA!
if (Math.abs(x - FARM_CENTER_X) <= FARM_SIZE / 2 && Math.abs(y - FARM_CENTER_Y) <= FARM_SIZE / 2) {
terrainType = this.terrainTypes.GRASS_FULL; // ZELENA TRAVA!
terrainType = this.terrainTypes.GRASS_FULL;
}
// RIVER Override - VIJUGAST POTOK!
// River gre diagonalno skozi mapo z sinusnim vijuganjem
const riverCenterY = 50; // Center Y pozicija za river
const riverWidth = 3; // Širina potoka (3 tiles)
const waveAmplitude = 8; // Amplituda vijuganja
const waveFrequency = 0.1; // Frekvenca vijuganja
// Izračun vijugaste poti
const riverOffset = Math.sin(x * waveFrequency) * waveAmplitude;
const riverY = riverCenterY + riverOffset;
// Če je tile znotraj river area
if (Math.abs(y - riverY) <= riverWidth / 2) {
terrainType = this.terrainTypes.WATER; // VODA!
}
// City Override - DISABLED (User request: no walls)
// if (x >= CITY_START_X && x < CITY_START_X + CITY_SIZE &&
// y >= CITY_START_Y && y < CITY_START_Y + CITY_SIZE) {
// const isEdge = (x === CITY_START_X ||
// x === CITY_START_X + CITY_SIZE - 1 ||
// y === CITY_START_Y ||
// y === CITY_START_Y + CITY_SIZE - 1);
// if (isEdge) {
// terrainType = { name: 'WALL_EDGE', color: 0x505050, solid: true };
// } else {
// terrainType = this.terrainTypes.PAVEMENT;
// if (Math.random() < 0.15) {
// terrainType = this.terrainTypes.RUINS;
// }
// }
// }
// Zapuščene hiše - DIRT tiles
let isHouse = false;
ABANDONED_HOUSES.forEach(house => {
if (x >= house.x && x < house.x + house.size &&
y >= house.y && y < house.y + house.size) {
terrainType = this.terrainTypes.DIRT; // Hiša na DIRT
isHouse = true;
}
});
// Create Tile Data
this.tiles[y][x] = {
type: terrainType.name,
texture: terrainType.name === 'water' ? 'water_frame_0' : terrainType.name, // Water tiles get animated frame!
texture: terrainType.name,
hasDecoration: false,
hasCrop: false,
solid: terrainType.solid || false
solid: terrainType.solid || false,
isHouse: isHouse
};
// Track water tiles za animacijo
if (terrainType.name === 'water') {
this.waterTiles.push(this.tiles[y][x]);
}
// Track valid positions for decorations
if (terrainType.name !== 'water' && terrainType.name !== 'sand' && terrainType.name !== 'stone' && !terrainType.solid) {
// Exclude Farm/City from random decor logic
// Track valid positions for decorations (TREES!)
if (terrainType.name === 'grass_full' && !isHouse) {
const isFarm = Math.abs(x - FARM_CENTER_X) <= (FARM_SIZE / 2 + 2) && Math.abs(y - FARM_CENTER_Y) <= (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) {
if (!isFarm) {
validPositions.push({ x, y });
}
}
// Direct Placement Calls (Trees/Rocks) - legacy method support
// this.placeTree(x, y, terrainType.name); // Optional: keep this if preferred over random batch
}
}
// --- CHUNK DECORATION PASS ---
// DISABLED - User wants clean platform (no trees, rocks, flowers)
// 1. Random Decorations - DISABLED
// validPositions.forEach(pos => {
// // Trees
// if (Math.random() < 0.05) {
// this.placeTree(pos.x, pos.y, 'grass');
// }
// // Rocks
// if (Math.random() < 0.02) {
// this.placeRock(pos.x, pos.y, 'grass');
// }
// // Flowers
// if (Math.random() < 0.05) {
// const flowers = ['flower_red', 'flower_yellow', 'flower_blue'];
// const flowerType = flowers[Math.floor(Math.random() * flowers.length)];
// this.addDecoration(pos.x, pos.y, flowerType);
// }
// // Path Stones
// if (Math.random() < 0.02) {
// this.addDecoration(pos.x, pos.y, 'path_stone');
// }
// });
// MICRO FARM FENCE (8x8 starting area) - DISABLED FOR NOW
// Will be added properly later
// --- STARDEW VALLEY FOREST DECORATION PASS ---
const farmMinX = FARM_CENTER_X - FARM_SIZE / 2;
const farmMaxX = FARM_CENTER_X + FARM_SIZE / 2;
const farmMinY = FARM_CENTER_Y - FARM_SIZE / 2;
const farmMaxY = FARM_CENTER_Y + FARM_SIZE / 2;
// DECORATIONS: Flowers & Bushes on grass tiles (random)
for (let y = startY; y < endY; y++) {
for (let x = startX; x < endX; x++) {
const tile = this.tiles[y][x]; // Corrected access to this.tiles
// DREVESA - 3% gostota z preverjanjem razdalje!
validPositions.forEach(pos => {
const rand = Math.random();
// Only on grass tiles, outside farm area
if (tile && tile.type === 'GRASS_FULL' && // Changed 'grass' to 'GRASS_FULL' to match terrainType.name
(x < farmMinX || x > farmMaxX || y < farmMinY || y > farmMaxY)) {
const rand = Math.random();
// 10% chance for flowers
if (rand < 0.10) {
const flowerTypes = ['flowers_new', 'flowers_pink_isometric'];
const randomType = flowerTypes[Math.floor(Math.random() * flowerTypes.length)];
this.addDecoration(x, y, randomType);
}
// 8% chance for grass patches (visual variety)
else if (rand >= 0.10 && rand < 0.18) {
this.addDecoration(x, y, 'grass_sprite');
}
// 5% chance for bushes
else if (rand >= 0.18 && rand < 0.23) {
this.addDecoration(x, y, 'bush_small');
}
// 3% chance for small rocks
else if (rand >= 0.23 && rand < 0.26) {
const rockTypes = ['rock_small', 'rock_2'];
const randomRock = rockTypes[Math.floor(Math.random() * rockTypes.length)];
this.addDecoration(x, y, randomRock);
}
// 3% chance za drevo
if (rand < TREE_DENSITY) {
// PREVERJANJE RAZDALJE: Ali je ta lokacija dovolj oddaljena?
if (!this.isTreeLocationFarEnough(pos.x, pos.y)) {
return; // Preskoči to lokacijo - preblizu drugim drevesom!
}
}
}
// Check if this chunk contains farm border
if (cx * this.chunkSize <= farmMaxX && (cx + 1) * this.chunkSize >= farmMinX &&
cy * this.chunkSize <= farmMaxY && (cy + 1) * this.chunkSize >= farmMinY) {
const treeRand = Math.random();
let treeType;
// Top border (y = farmMinY)
if (startY <= farmMinY && endY > farmMinY) {
for (let x = Math.max(startX, farmMinX); x <= Math.min(endX - 1, farmMaxX); x++) {
this.addDecoration(x, farmMinY, 'fence_isometric');
// 30% VIJOLČNA DREVESA
if (treeRand < PURPLE_TREE_CHANCE) {
treeType = 'tree_purple';
}
}
// Bottom border (y = farmMaxY)
if (startY <= farmMaxY && endY > farmMaxY) {
for (let x = Math.max(startX, farmMinX); x <= Math.min(endX - 1, farmMaxX); x++) {
this.addDecoration(x, farmMaxY, 'fence_isometric');
// 20% SADNA DREVESA
else if (treeRand < PURPLE_TREE_CHANCE + FRUIT_TREE_CHANCE) {
const fruitTypes = ['tree_apple', 'tree_pear', 'tree_cherry'];
treeType = fruitTypes[Math.floor(Math.random() * fruitTypes.length)];
}
}
// Left border (x = farmMinX)
if (startX <= farmMinX && endX > farmMinX) {
for (let y = Math.max(startY, farmMinY); y <= Math.min(endY - 1, farmMaxY); y++) {
this.addDecoration(farmMinX, y, 'fence_isometric');
// 50% NAVADNA DREVESA
else {
const normalTrees = ['tree_green_final', 'tree_blue_final', 'tree_sapling'];
treeType = normalTrees[Math.floor(Math.random() * normalTrees.length)];
}
}
// Right border (x = farmMaxX)
if (startX <= farmMaxX && endX > farmMaxX) {
for (let y = Math.max(startY, farmMinY); y <= Math.min(endY - 1, farmMaxY); y++) {
this.addDecoration(farmMaxX, y, 'fence_isometric');
}
// DODAJ DREVO
this.addDecoration(pos.x, pos.y, treeType);
this.placedTrees.push({ x: pos.x, y: pos.y });
}
}
});
// KONEC generateChunk
}
updateChunks(camera) {
@@ -777,18 +708,22 @@ class TerrainSystem {
let scale = 1.0;
if (type === 'rock_1' || type === 'rock_2') scale = 1.5; // Povečano (bilo 0.5)
// POMANJŠANA DREVESA - Stardew Valley stil
if (type === 'rock_1' || type === 'rock_2') scale = 1.0; // Zmanjšano
else if (type === 'tree_green_new' || type === 'tree_blue_new' || type === 'tree_dead_new') scale = 0.04;
else if (type === 'flowers_new') scale = 0.02;
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 if (type.includes('_final')) scale = 0.7; // POMANJŠANO - final trees
else if (type.includes('purple') || type.includes('apple') || type.includes('pear') || type.includes('cherry')) {
scale = 0.6; // POMANJŠANO - novi sadni in vijolčni
}
else {
// Old Assets (Low Res)
if (type.includes('tree')) scale = 1.2 + Math.random() * 0.4;
else if (type.includes('rock')) scale = 0.8;
else scale = 1.0;
if (type.includes('tree')) scale = 0.7 + Math.random() * 0.2; // POMANJŠANO (bilo 1.2-1.6)
else if (type.includes('rock')) scale = 0.6; // POMANJŠANO
else scale = 0.8; // POMANJŠANO
}
// Calculate Plant Day for Saplings (Growth System)

77
ultra_remove_bg.py Normal file
View File

@@ -0,0 +1,77 @@
from PIL import Image
import os
# Lista slik za procesiranje
images_to_process = [
'assets/tree_purple.png',
'assets/tree_apple.png',
'assets/tree_pear.png',
'assets/tree_cherry.png',
'assets/tree_green_final.png',
'assets/tree_blue_final.png',
'assets/tree_dead_final.png'
]
def ultra_remove_background(image_path):
"""ULTRA AGRESIVNO odstranjevanje ozadja"""
try:
# Naloži sliko
img = Image.open(image_path).convert('RGBA')
data = img.getdata()
new_data = []
for item in data:
r, g, b, a = item
# Če je že transparentno, ohrani
if a == 0:
new_data.append(item)
continue
# Izračunaj brightness
brightness = (r + g + b) / 3
# ULTRA AGRESIVNO: Odstrani VSE kar je svetlejše od 100
# To bo odstranilo VSE šahovske kvadratke
if brightness > 100:
new_data.append((r, g, b, 0)) # Transparentno
continue
# Odstrani VSE sive barve (ne glede na brightness)
is_grayscale = abs(r - g) < 25 and abs(g - b) < 25 and abs(r - b) < 25
if is_grayscale:
new_data.append((r, g, b, 0)) # Transparentno
continue
# Ohrani samo temne, nasičene barve (drevesa)
max_rgb = max(r, g, b)
min_rgb = min(r, g, b)
saturation = 0 if max_rgb == 0 else (max_rgb - min_rgb) / max_rgb
# Če je nizka saturacija (pastelno) -> odstrani
if saturation < 0.2:
new_data.append((r, g, b, 0))
continue
# Ohrani pixel
new_data.append(item)
# Posodobi sliko
img.putdata(new_data)
# Shrani
img.save(image_path)
print(f'✅ ULTRA Processed: {image_path}')
except Exception as e:
print(f'❌ Error processing {image_path}: {e}')
# Procesiraj vse slike
print('🔥 ULTRA AGGRESSIVE background removal...')
for img_path in images_to_process:
if os.path.exists(img_path):
ultra_remove_background(img_path)
else:
print(f'⚠️ File not found: {img_path}')
print('✅ Done! All backgrounds ULTRA removed.')