36 lines
1.0 KiB
GDScript
36 lines
1.0 KiB
GDScript
class_name SimulationClock
|
|
extends RefCounted
|
|
|
|
var tick_interval: float
|
|
var accumulator := 0.0
|
|
var elapsed_ticks := 0
|
|
var cycle_duration_seconds := 240.0
|
|
|
|
|
|
func _init(interval: float = 1.0) -> void:
|
|
tick_interval = maxf(interval, 0.0001)
|
|
|
|
|
|
func advance(delta: float, max_ticks: int = 0) -> int:
|
|
accumulator += maxf(delta, 0.0)
|
|
var ticks_due := 0
|
|
while accumulator >= tick_interval and (max_ticks <= 0 or ticks_due < max_ticks):
|
|
accumulator -= tick_interval
|
|
elapsed_ticks += 1
|
|
ticks_due += 1
|
|
return ticks_due
|
|
|
|
|
|
func reset() -> void:
|
|
accumulator = 0.0
|
|
elapsed_ticks = 0
|
|
|
|
|
|
func time_of_day() -> float:
|
|
# A capped frame can leave several whole ticks in the accumulator. Those ticks
|
|
# are backlog, not simulated time yet; only retain the sub-tick fraction for
|
|
# smooth presentation until the manager consumes the remaining work.
|
|
var fractional_progress := fmod(accumulator, tick_interval)
|
|
var total_seconds := elapsed_ticks * tick_interval + fractional_progress
|
|
return fmod(total_seconds / maxf(cycle_duration_seconds, 1.0), 1.0)
|