Skip to content

Calendar Time v2.1.2

Ageing — Two Time Models

Calendar Time supports two distinct ageing mechanics. Pick the one that matches your game design.

Status
Current
Version
v2.1.2
Source updated
2026-11-05
Generated on
2026-11-06

Calendar Time supports two distinct ageing mechanics. Pick the one that matches your game design.

Model 1: Clock-time ageing (continuous)

"This effect lasts N game-seconds."

AgeService tracks elapsed game time from GameClock.game_seconds_advanced. Ageing scales with clock speed — if you speed up the clock, ageing speeds up proportionally.

Use for:

  • Potion expiry ("expires in 5 game-minutes")
  • Buff/debuff durations
  • Cooldown timers
  • Real-time effects that should pause when the clock pauses
# One AgeService per clock; the demo assigns it where a clock lacks one.
var age_service:= AgeService.new()
age_service.clock= clock

# Scene usage: an AgeComponent node with `clock` and `age_preset` bound.
# In code:
var component:= AgeComponent.new(my_preset, clock)
add_child(component)

# Later: how much time has elapsed for this component?
var elapsed:= component.age_state.get_total_elapsed()
var current:= component.age_state.current

AddAfterGameSeconds is a convenience node: it adds a child node after N game-seconds have elapsed on the bound clock.

Model 2: Calendar-date ageing (discrete)

"This crop takes 3 game-days to mature."

Listen to clock.signal_bus.date_changed and advance growth stages discretely. Each calendar day that passes advances growth once, regardless of clock speed. One advance can cross several days at once, such as a sleep-to-morning jump, a large timescale step, or a loaded offline span. It still emits a single date_changed, and event.change carries the whole signed day span. Read that span instead of assuming one stage per signal.

This is the farming-game model (Stardew Valley, Rune Factory, Harvest Moon).

Use for:

  • Crop growth ("3 days to harvest")
  • Building construction ("7 days to complete")
  • Character aging ("1 year per game-year")
  • Seasonal changes
func _ready()-> void:
    clock.signal_bus.date_changed.connect(_on_date_changed)

var growth_stage:int = 0
const MAX_STAGE:int = 3

func _on_date_changed(event:DateChangeEvent)-> void:
    # `change` is the signed day span of this advance, not always 1.
    growth_stage= mini(MAX_STAGE, growth_stage+ maxi(event.change,0))
    _update_sprite(growth_stage)

DateChangeEvent also carries old_date, new_date, and the calendar that produced the change. To get one callback per crossed day, drive the clock with advance_through_microseconds(). It emits a date_changed per boundary with change of 1 or -1.

DateChangeEvent, DateChangeSpawner, DateChangeRandomizer, and DateChangeRandomToggler are ready-made nodes for common date-triggered behaviors.

Choosing between the models

Question Model
Should it pause when the clock pauses? Both do
Should it scale smoothly with clock speed? Model 1 (clock-time)
Should it advance in discrete day/month/year steps? Model 2 (calendar-date)
Is it a duration ("lasts N seconds")? Model 1
Is it a progression ("takes N days")? Model 2
Farming, construction, seasons? Model 2
Cooldowns, expiry, buffs? Model 1

Combining both models

Both models read from the same GameClock. Pausing the clock pauses both. Saving and loading preserve both: Model 1 through AgeComponent serialization, Model 2 through the calendar date in TimeSnapshot.

AgeService internals

AgeService is a per-clock Resource (not a singleton). Each clock can have its own AgeService with independent components. The service subscribes to game_seconds_advanced and advances the registry states that AgeComponent nodes read.

AgeStateRegistry tracks visual states per clock. AgeState defines what a component looks like at each threshold (sprite frame, material, scale). AgePreset bundles named presets for quick authoring.

AgeSceneReplacement swaps a node's scene at an age threshold — useful for "sapling → tree" or "ruins → rebuilt house" transitions.

Using this in a game?

Calendar Time v2.1.2 — full source, playable demos, commercial license

The guide above is the same setup the shipped demos use. Try the build in your browser before you buy it.