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