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,159 @@
class WeatherSystem {
constructor(scene) {
this.scene = scene;
this.currentWeather = 'clear'; // clear, rain, storm, fog
this.weatherDuration = 0;
this.maxWeatherDuration = 30000; // 30s per weather cycle
// Weather effects containers
this.rainParticles = [];
this.overlay = null;
this.init();
}
init() {
// Create weather overlay
this.overlay = this.scene.add.graphics();
this.overlay.setDepth(5000); // Above everything but UI
this.overlay.setScrollFactor(0); // Fixed to camera
// Start with random weather
this.changeWeather();
}
changeWeather() {
// Clean up old weather
this.clearWeather();
// Random new weather
const weathers = ['clear', 'clear', 'rain', 'fog']; // Clear more common
this.currentWeather = weathers[Math.floor(Math.random() * weathers.length)];
this.weatherDuration = 0;
console.log(`🌦️ Weather changed to: ${this.currentWeather}`);
// Apply new weather effects
this.applyWeather();
}
applyWeather() {
if (this.currentWeather === 'rain') {
this.startRain();
// Play rain sound
if (this.scene.soundManager) {
this.scene.soundManager.playRainSound();
}
} else if (this.currentWeather === 'fog') {
this.applyFog();
} else if (this.currentWeather === 'storm') {
this.startRain(true);
// Play rain sound (louder?)
if (this.scene.soundManager) {
this.scene.soundManager.playRainSound();
}
} else {
// Clear weather - stop ambient sounds
if (this.scene.soundManager) {
this.scene.soundManager.stopRainSound();
}
}
}
startRain(heavy = false) {
const width = this.scene.cameras.main.width;
const height = this.scene.cameras.main.height;
// Create rain drops
const dropCount = heavy ? 150 : 100;
for (let i = 0; i < dropCount; i++) {
const drop = {
x: Math.random() * width,
y: Math.random() * height,
speed: heavy ? Phaser.Math.Between(400, 600) : Phaser.Math.Between(200, 400),
length: heavy ? Phaser.Math.Between(10, 15) : Phaser.Math.Between(5, 10)
};
this.rainParticles.push(drop);
}
// Darken screen slightly
this.overlay.clear();
this.overlay.fillStyle(0x000033, heavy ? 0.3 : 0.2);
this.overlay.fillRect(0, 0, width, height);
}
applyFog() {
const width = this.scene.cameras.main.width;
const height = this.scene.cameras.main.height;
this.overlay.clear();
this.overlay.fillStyle(0xcccccc, 0.4);
this.overlay.fillRect(0, 0, width, height);
}
clearWeather() {
// Remove all weather effects
this.rainParticles = [];
if (this.overlay) {
this.overlay.clear();
}
}
update(delta) {
this.weatherDuration += delta;
// Change weather periodically
if (this.weatherDuration > this.maxWeatherDuration) {
this.changeWeather();
}
// Update rain
if (this.currentWeather === 'rain' || this.currentWeather === 'storm') {
this.updateRain(delta);
}
}
updateRain(delta) {
const height = this.scene.cameras.main.height;
const width = this.scene.cameras.main.width;
// Update drop positions
for (const drop of this.rainParticles) {
drop.y += (drop.speed * delta) / 1000;
// Reset if off screen
if (drop.y > height) {
drop.y = -10;
drop.x = Math.random() * width;
}
}
// Render rain
this.overlay.clear();
// Background darkening
const isDark = this.currentWeather === 'storm' ? 0.3 : 0.2;
this.overlay.fillStyle(0x000033, isDark);
this.overlay.fillRect(0, 0, width, height);
// Draw drops
this.overlay.lineStyle(1, 0x88aaff, 0.5);
for (const drop of this.rainParticles) {
this.overlay.beginPath();
this.overlay.moveTo(drop.x, drop.y);
this.overlay.lineTo(drop.x - 2, drop.y + drop.length);
this.overlay.strokePath();
}
}
getCurrentWeather() {
return this.currentWeather;
}
setWeather(weather) {
this.currentWeather = weather;
this.weatherDuration = 0;
this.applyWeather();
}
}