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:
135
src/systems/StatsSystem.js
Normal file
135
src/systems/StatsSystem.js
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user