FAZA 17: 2.5D Minecraft-Style Terrain + Y-Layer Stacking + Custom Sprites

COMPLETED FEATURES:

 Custom Sprite Integration:
- Player, Zombie, Merchant sprites (0.2 scale)
- 11 custom sprites + 5 asset packs loaded
- Auto-transparency processing (white/brown removal)
- Gravestone system with atlas extraction

 2.5D Minecraft-Style Terrain:
- Volumetric blocks with 25px thickness
- Strong left/right side shading (30%/50% darker)
- Minecraft-style texture patterns (grass, dirt, stone)
- Crisp black outlines for definition

 Y-Layer Stacking System:
- GRASS_FULL: All green (elevation > 0.7)
- GRASS_TOP: Green top + brown sides (elevation 0.4-0.7)
- DIRT: All brown (elevation < 0.4)
- Dynamic terrain depth based on height

 Floating Island World Edge:
- Stone cliff walls at map borders
- 2-tile transition zone
- Elevation flattening for cliff drop-off effect
- 100x100 world with defined boundaries

 Performance & Polish:
- Canvas renderer for pixel-perfect sharpness
- CSS image-rendering: crisp-edges
- willReadFrequently optimization
- No Canvas2D warnings

 Technical:
- 3D volumetric trees and rocks
- Hybrid rendering (2.5D terrain + 2D characters)
- Procedural texture generation
- Y-layer aware terrain type selection
This commit is contained in:
2025-12-07 01:44:16 +01:00
parent 34a2d07538
commit 9eb57ed117
60 changed files with 5082 additions and 195 deletions

View File

@@ -0,0 +1,116 @@
class FarmingSystem {
constructor(scene) {
this.scene = scene;
this.growthTimer = 0;
this.growthTickRate = 5000; // Check growth every 5 seconds (real time)
// Or better: based on TimeSystem days?
// For fast testing: rapid growth.
}
// Called by InteractionSystem
interact(gridX, gridY, toolType) {
const terrain = this.scene.terrainSystem;
const tile = terrain.getTile(gridX, gridY);
if (!tile) return false;
// 1. HARVEST (Right click or just click ripe crop?)
// Let's say if it has crop and it is ripe, harvest it regardless of tool.
if (tile.hasCrop) {
const crop = terrain.cropsMap.get(`${gridX},${gridY}`);
if (crop && crop.stage === 4) {
this.harvest(gridX, gridY);
return true;
}
}
// 2. TILLING (Requires Hoe)
if (toolType === 'hoe') {
if (tile.type === 'grass' || tile.type === 'dirt') {
if (!tile.hasDecoration && !tile.hasCrop) {
console.log('🚜 Tilling soil...');
terrain.setTileType(gridX, gridY, 'farmland');
// Play sound
return true;
}
}
}
// 3. PLANTING (Requires Seeds)
if (toolType === 'seeds') {
if (tile.type === 'farmland' && !tile.hasCrop && !tile.hasDecoration) {
console.log('🌱 Planting seeds...');
this.plant(gridX, gridY);
return true; // Consume seed logic handled by caller?
}
}
return false;
}
plant(x, y) {
const terrain = this.scene.terrainSystem;
const cropData = {
gridX: x,
gridY: y,
stage: 1, // Seeds
type: 'wheat', // Default for now
timer: 0,
maxTime: 10 // Seconds per stage?
};
terrain.addCrop(x, y, cropData);
}
harvest(x, y) {
const terrain = this.scene.terrainSystem;
console.log('🌾 Harvesting!');
// Spawn loot
if (this.scene.interactionSystem) {
this.scene.interactionSystem.spawnLoot(x, y, 'wheat');
this.scene.interactionSystem.spawnLoot(x, y, 'seeds'); // Return seeds
// 50% chance for extra seeds
if (Math.random() > 0.5) this.scene.interactionSystem.spawnLoot(x, y, 'seeds');
}
// Remove crop
terrain.removeCrop(x, y);
// Revert to dirt? Or keep farmland? Usually keeps farmland.
}
update(delta) {
// Growth Logic
// Iterate all crops? Expensive?
// Better: Random tick like Minecraft or list iteration.
// Since we have cropsMap, iteration is easy.
// Only run every 1 second (1000ms) to save PERF
this.growthTimer += delta;
if (this.growthTimer < 1000) return;
const secondsPassed = this.growthTimer / 1000;
this.growthTimer = 0;
const terrain = this.scene.terrainSystem;
if (!terrain) return;
for (const [key, crop] of terrain.cropsMap) {
if (crop.stage < 4) {
crop.timer += secondsPassed;
// Growth thresholds (fast for testing)
// Stage 1 -> 2: 5s
// Stage 2 -> 3: 10s
// Stage 3 -> 4: 15s
const needed = 5;
if (crop.timer >= needed) {
crop.stage++;
crop.timer = 0;
terrain.updateCropVisual(crop.gridX, crop.gridY, crop.stage);
// Particle effect?
}
}
}
}
}