Add synchronized time and weather systems
This commit is contained in:
parent
30ad9215ca
commit
58fb3d6605
37 changed files with 1900 additions and 17 deletions
126
world/world_time_service.gd
Normal file
126
world/world_time_service.gd
Normal file
|
|
@ -0,0 +1,126 @@
|
|||
class_name WorldTimeService
|
||||
extends Node
|
||||
|
||||
signal time_changed(time_hours: float, phase: Phase)
|
||||
signal phase_changed(phase: Phase)
|
||||
|
||||
enum Phase {
|
||||
DAWN,
|
||||
DAY,
|
||||
DUSK,
|
||||
NIGHT,
|
||||
}
|
||||
|
||||
const HOURS_PER_DAY: float = 24.0
|
||||
const REAL_SECONDS_PER_CYCLE: float = 60.0 * 60.0
|
||||
const HOURS_PER_REAL_SECOND: float = HOURS_PER_DAY / REAL_SECONDS_PER_CYCLE
|
||||
const DAY_START_HOUR: float = 8.0
|
||||
const NIGHT_START_HOUR: float = 20.0
|
||||
const TRANSITION_HALF_HOURS: float = 0.5
|
||||
const DAWN_START_HOUR: float = DAY_START_HOUR - TRANSITION_HALF_HOURS
|
||||
const DAWN_END_HOUR: float = DAY_START_HOUR + TRANSITION_HALF_HOURS
|
||||
const DUSK_START_HOUR: float = NIGHT_START_HOUR - TRANSITION_HALF_HOURS
|
||||
const DUSK_END_HOUR: float = NIGHT_START_HOUR + TRANSITION_HALF_HOURS
|
||||
const DEFAULT_START_HOUR: float = DAY_START_HOUR
|
||||
|
||||
var _time_hours: float = DEFAULT_START_HOUR
|
||||
var _running: bool = false
|
||||
var _phase: Phase = Phase.DAWN
|
||||
|
||||
|
||||
func _ready() -> void:
|
||||
set_process(false)
|
||||
|
||||
|
||||
func _process(delta: float) -> void:
|
||||
advance_time(delta)
|
||||
|
||||
|
||||
func begin_session(start_hour: float = DEFAULT_START_HOUR) -> void:
|
||||
_running = true
|
||||
set_process(true)
|
||||
_set_time_hours(start_hour, true)
|
||||
|
||||
|
||||
func end_session() -> void:
|
||||
_running = false
|
||||
set_process(false)
|
||||
_set_time_hours(DEFAULT_START_HOUR, true)
|
||||
|
||||
|
||||
func advance_time(real_seconds: float) -> void:
|
||||
if not _running or real_seconds <= 0.0:
|
||||
return
|
||||
_set_time_hours(
|
||||
_time_hours + real_seconds * HOURS_PER_REAL_SECOND,
|
||||
false,
|
||||
)
|
||||
|
||||
|
||||
func synchronize_time(authoritative_time_hours: float) -> void:
|
||||
if not is_finite(authoritative_time_hours):
|
||||
return
|
||||
_set_time_hours(authoritative_time_hours, true)
|
||||
|
||||
|
||||
func get_time_hours() -> float:
|
||||
return _time_hours
|
||||
|
||||
|
||||
func get_phase() -> Phase:
|
||||
return _phase
|
||||
|
||||
|
||||
func is_night_period() -> bool:
|
||||
return _time_hours < DAY_START_HOUR or _time_hours >= NIGHT_START_HOUR
|
||||
|
||||
|
||||
func is_transition() -> bool:
|
||||
return _phase in [Phase.DAWN, Phase.DUSK]
|
||||
|
||||
|
||||
func get_clock_text() -> String:
|
||||
return format_clock_time(_time_hours)
|
||||
|
||||
|
||||
static func phase_for_hour(time_hours: float) -> Phase:
|
||||
var hour: float = _normalized_hour(time_hours)
|
||||
if hour >= DAWN_START_HOUR and hour < DAWN_END_HOUR:
|
||||
return Phase.DAWN
|
||||
if hour >= DAWN_END_HOUR and hour < DUSK_START_HOUR:
|
||||
return Phase.DAY
|
||||
if hour >= DUSK_START_HOUR and hour < DUSK_END_HOUR:
|
||||
return Phase.DUSK
|
||||
return Phase.NIGHT
|
||||
|
||||
|
||||
static func format_clock_time(time_hours: float) -> String:
|
||||
var hour: float = _normalized_hour(time_hours)
|
||||
var total_minutes: int = floori(hour * 60.0)
|
||||
var hour_24: int = floori(float(total_minutes) / 60.0)
|
||||
var minute: int = total_minutes % 60
|
||||
var hour_12: int = hour_24 % 12
|
||||
if hour_12 == 0:
|
||||
hour_12 = 12
|
||||
return "%d:%02d %s" % [
|
||||
hour_12,
|
||||
minute,
|
||||
"am" if hour_24 < 12 else "pm",
|
||||
]
|
||||
|
||||
|
||||
func _set_time_hours(time_hours: float, force_emit: bool) -> void:
|
||||
var normalized: float = _normalized_hour(time_hours)
|
||||
var next_phase: Phase = phase_for_hour(normalized)
|
||||
var phase_was_changed: bool = next_phase != _phase
|
||||
var time_was_changed: bool = not is_equal_approx(normalized, _time_hours)
|
||||
_time_hours = normalized
|
||||
_phase = next_phase
|
||||
if phase_was_changed:
|
||||
phase_changed.emit(_phase)
|
||||
if force_emit or time_was_changed or phase_was_changed:
|
||||
time_changed.emit(_time_hours, _phase)
|
||||
|
||||
|
||||
static func _normalized_hour(time_hours: float) -> float:
|
||||
return fposmod(time_hours, HOURS_PER_DAY)
|
||||
Loading…
Add table
Add a link
Reference in a new issue