Files
g-world/scripts/game/climate.gd
T

66 lines
2.7 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
class_name Climate
extends RefCounted
## Климатическая норма: какой температуры и ветра ждать в это время года.
##
## Средняя полоса Европы — ориентир, а не точная модель. Только вычисления:
## погода (weather_system.gd) берёт отсюда цель и плавно к ней идёт.
## Среднемесячная температура, °C, с января по декабрь.
const MONTHLY_MEAN: Array[float] = [
0.5, 1.5, 5.0, 9.5, 14.0, 17.0, 19.0, 18.5, 14.5, 9.5, 4.5, 1.5,
]
## Суточный размах по месяцам: зимой день и ночь ближе друг к другу, чем летом.
const MONTHLY_SWING: Array[float] = [
4.0, 5.0, 7.0, 9.0, 10.0, 11.0, 11.0, 10.5, 9.0, 7.0, 4.5, 3.5,
]
## Самый тёплый час суток; самый холодный — через двенадцать часов от него.
const WARMEST_HOUR := 15.0
## Поправка к температуре по типу погоды, °C. Индекс — WeatherSystem.Kind;
## перечисление сюда не тянем, иначе получится циклическая ссылка между
## классами: погода уже зависит от климата.
const WEATHER_OFFSET: Array[float] = [1.5, 0.0, -1.0, -2.0, -3.0, -1.5, -3.0]
## Характерная скорость ветра по тем же типам, м/с.
const WEATHER_WIND: Array[float] = [2.5, 4.0, 5.5, 7.5, 15.0, 1.0, 5.0]
## Выше этого осадки идут дождём, ниже — снегом.
const SNOW_THRESHOLD := 0.5
## Ветер сильнее этого считаем предельным для визуализации.
const WIND_REFERENCE := 18.0
## Норма для месяца (1..12) и часа суток, без учёта погоды.
static func base_temperature(month: int, hour: float) -> float:
var index := clampi(month - 1, 0, 11)
var mean := MONTHLY_MEAN[index]
var swing := MONTHLY_SWING[index]
# Суточный ход — косинус с максимумом в WARMEST_HOUR.
var phase := (hour - WARMEST_HOUR) / 24.0 * TAU
return mean + swing * 0.5 * cos(phase)
static func weather_offset(kind: int) -> float:
if kind < 0 or kind >= WEATHER_OFFSET.size():
return 0.0
return WEATHER_OFFSET[kind]
static func base_wind(kind: int) -> float:
if kind < 0 or kind >= WEATHER_WIND.size():
return 3.0
return WEATHER_WIND[kind]
## «12°C» — для HUD.
static func temperature_text(celsius: float) -> String:
return "%d°C" % roundi(celsius)
## «4 м/с» — для HUD.
static func wind_text(speed: float) -> String:
return "%d м/с" % roundi(speed)