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

135
src/systems/StatsSystem.js Normal file
View File

@@ -0,0 +1,135 @@
class StatsSystem {
constructor(scene) {
this.scene = scene;
// Stats
this.health = 100;
this.maxHealth = 100;
this.hunger = 100; // 100 = full
this.maxHunger = 100;
this.thirst = 100; // 100 = not thirsty
this.maxThirst = 100;
// Decay rates (per second)
this.hungerDecay = 0.5; // Pade na 0 v 200s (cca 3 min)
this.thirstDecay = 0.8; // Pade na 0 v 125s (cca 2 min)
this.damageTickTimer = 0;
// Friendship System (Hearts ❤️)
this.friendship = {
merchant: 0,
zombie: 0,
villager: 0
};
}
update(delta) {
const seconds = delta / 1000;
// Decay
if (this.hunger > 0) {
this.hunger -= this.hungerDecay * seconds;
}
if (this.thirst > 0) {
this.thirst -= this.thirstDecay * seconds;
}
// Clamp values
this.hunger = Math.max(0, this.hunger);
this.thirst = Math.max(0, this.thirst);
// Starvation / Dehydration logic
if (this.hunger <= 0 || this.thirst <= 0) {
this.damageTickTimer += delta;
if (this.damageTickTimer >= 1000) { // Vsako sekundo damage
this.damageTickTimer = 0;
this.takeDamage(5); // 5 DMG na sekundo če si lačen/žejen
// Shake camera effect za opozorilo
this.scene.cameras.main.shake(100, 0.005);
}
} else {
this.damageTickTimer = 0;
// Natural regeneration if full
if (this.hunger > 80 && this.thirst > 80 && this.health < this.maxHealth) {
this.health += 1 * seconds;
}
}
this.health = Math.min(this.health, this.maxHealth);
this.updateUI();
}
takeDamage(amount) {
this.health -= amount;
if (this.health <= 0) {
this.health = 0;
this.die();
}
}
eat(amount) {
this.hunger += amount;
this.hunger = Math.min(this.hunger, this.maxHunger);
}
drink(amount) {
this.thirst += amount;
this.thirst = Math.min(this.thirst, this.maxThirst);
}
die() {
console.log('💀 Player died!');
// Zaenkrat samo respawn / reset
this.health = 100;
this.hunger = 100;
this.thirst = 100;
// Teleport to spawn
const spawnX = this.scene.terrainOffsetX + 500; // Dummy
const spawnY = this.scene.terrainOffsetY + 100; // Dummy
// Reset player pos...
// V pravi implementaciji bi klicali GameScene.respawnPlayer()
// Show notification
const uiScene = this.scene.scene.get('UIScene');
if (uiScene) {
const txt = uiScene.add.text(uiScene.width / 2, uiScene.height / 2, 'YOU DIED', {
fontSize: '64px', color: '#ff0000', fontStyle: 'bold'
}).setOrigin(0.5);
uiScene.time.delayedCall(2000, () => txt.destroy());
}
}
updateUI() {
const uiScene = this.scene.scene.get('UIScene');
if (uiScene) {
if (uiScene.healthBar) uiScene.setBarValue(uiScene.healthBar, this.health);
if (uiScene.hungerBar) uiScene.setBarValue(uiScene.hungerBar, this.hunger);
if (uiScene.thirstBar) uiScene.setBarValue(uiScene.thirstBar, this.thirst);
}
}
// Friendship System
addFriendship(npcType, amount) {
if (this.friendship[npcType] !== undefined) {
this.friendship[npcType] += amount;
console.log(`❤️ +${amount} Friendship with ${npcType} (Total: ${this.friendship[npcType]})`);
}
}
getFriendship(npcType) {
return this.friendship[npcType] || 0;
}
setFriendship(npcType, amount) {
if (this.friendship[npcType] !== undefined) {
this.friendship[npcType] = amount;
}
}
}