122 lines
4.0 KiB
JavaScript
122 lines
4.0 KiB
JavaScript
export class Weather {
|
||
constructor(game) {
|
||
this.game = game;
|
||
this.current = 'clear'; // clear | rain | snow | fog
|
||
this.temperature = 15; // °C
|
||
this.changeTimer = 0;
|
||
this.changeCooldown = 180; // секунд реальных между сменами погоды
|
||
this.windStrength = 0;
|
||
}
|
||
|
||
init() {
|
||
this.current = 'clear';
|
||
this.temperature = 15;
|
||
this.changeTimer = 60 + Math.random() * 120;
|
||
}
|
||
|
||
update(dt) {
|
||
this.changeTimer -= dt;
|
||
|
||
if (this.changeTimer <= 0) {
|
||
this.changeWeather();
|
||
this.changeTimer = this.changeCooldown + Math.random() * 120;
|
||
}
|
||
|
||
// Температура зависит от времени суток, погоды и сезона
|
||
const hour = this.game.gameTime / 60;
|
||
let baseTemp;
|
||
if (hour >= 10 && hour < 16) {
|
||
baseTemp = 18;
|
||
} else if (hour >= 6 && hour < 10) {
|
||
baseTemp = 10;
|
||
} else if (hour >= 16 && hour < 21) {
|
||
baseTemp = 12;
|
||
} else {
|
||
baseTemp = 3;
|
||
}
|
||
|
||
// Сезонный модификатор температуры
|
||
baseTemp += this.game.seasons.getTemperatureModifier();
|
||
|
||
if (this.current === 'rain') baseTemp -= 5;
|
||
if (this.current === 'snow') baseTemp -= 15;
|
||
if (this.current === 'fog') baseTemp -= 2;
|
||
|
||
this.temperature += (baseTemp - this.temperature) * dt * 0.1;
|
||
|
||
// Влияние на тепло игрока
|
||
this.applyEffects(dt);
|
||
|
||
// Ветер
|
||
this.windStrength = (this.current === 'rain' || this.current === 'snow') ?
|
||
0.3 + Math.sin(Date.now() * 0.001) * 0.2 : 0.05;
|
||
}
|
||
|
||
changeWeather() {
|
||
// Веса погоды зависят от сезона
|
||
const weights = this.game.seasons.getWeatherWeights();
|
||
const hour = this.game.gameTime / 60;
|
||
|
||
// Ночью больше тумана и снега
|
||
if (hour < 6 || hour > 21) {
|
||
weights.fog += 2;
|
||
weights.snow += 1;
|
||
}
|
||
|
||
// Строим массив с весами
|
||
const pool = [];
|
||
for (const [type, w] of Object.entries(weights)) {
|
||
for (let i = 0; i < w; i++) pool.push(type);
|
||
}
|
||
|
||
let newWeather;
|
||
do {
|
||
newWeather = pool[Math.floor(Math.random() * pool.length)];
|
||
} while (newWeather === this.current && pool.length > 1);
|
||
|
||
this.current = newWeather;
|
||
this.game.particles.setWeather(newWeather);
|
||
|
||
// Визуальные эффекты тумана
|
||
if (newWeather === 'fog') {
|
||
this.game.scene.fog.near = 10;
|
||
this.game.scene.fog.far = 50;
|
||
} else {
|
||
this.game.scene.fog.near = 80;
|
||
this.game.scene.fog.far = 200;
|
||
}
|
||
|
||
const names = { clear: 'Ясно', rain: 'Дождь', snow: 'Снег', fog: 'Туман' };
|
||
this.game.notify(`Погода: ${names[newWeather]} (${Math.round(this.temperature)}°C)`);
|
||
}
|
||
|
||
applyEffects(dt) {
|
||
const player = this.game.player;
|
||
const seasonDrain = this.game.seasons.getWarmthDrain();
|
||
|
||
if (this.current === 'rain') {
|
||
player.stats.warmth = Math.max(0, player.stats.warmth - 0.08 * seasonDrain * dt);
|
||
player.stats.mood = Math.max(0, player.stats.mood - 0.03 * dt);
|
||
}
|
||
|
||
if (this.current === 'snow') {
|
||
player.stats.warmth = Math.max(0, player.stats.warmth - 0.15 * seasonDrain * dt);
|
||
player.stats.mood = Math.max(0, player.stats.mood - 0.05 * dt);
|
||
}
|
||
|
||
// Холодная температура
|
||
if (this.temperature < 5) {
|
||
player.stats.warmth = Math.max(0, player.stats.warmth - 0.1 * seasonDrain * dt);
|
||
}
|
||
}
|
||
|
||
getIcon() {
|
||
const icons = { clear: '☀️', rain: '🌧️', snow: '❄️', fog: '🌫️' };
|
||
return icons[this.current] || '☀️';
|
||
}
|
||
|
||
reset() {
|
||
this.init();
|
||
}
|
||
}
|