Time
“Time is an illusion.” – Albert Einstein
This is even more true in turn-based strategy games where turns usually abstract away the passage of a certain amount of time.
The time system should help accomplish a few things:
- Give players a sense of the passage of time in the game world.
- Enable scripted events that happen at a specific time.
- Enable scripted events that happen at a certain frequency (e.g. every day or every week).
A good example of a time system in a turn-based strategy game is Heroes of Might and Magic:
- Every day:
- Towns, castles and gold mines produces gold.
- Mines produce resources.
- Heroes have their movement points replenished.
- Every week:
- Dwellings produce creatures.
- Encounter buildings refill their rewards (e.g. Windmill)
- Random chance of spawning mobs of monster all over the map.
ECS Design
Components
Clock
- ticks: Integer
In this case ticks is an abstract measure of how much time has passed. You define how long a tick is in your game design. For example, Heroes of Might and Magic would have a tick equal to one day.
This component should be a Singleton as it is the global clock for the whole game.
TimedEvent
- frequency: Integer
- ticks: Integer
The ticks indicate how much time has passed.
When ticks is equal to frequency trigger the event by adding EventTrigger.
EventTrigger
A marker interface indicating that this TimedEvent has been triggered and should do whatever it does when it triggers.
Player
From the turn system. Use it to let your clock have a turn at the end of the round so that it can update the amount of time that has passed.
Active
From the turn system. Use it to let your clock have a turn at the end of the round so that it can update the amount of time that has passed.
EndTurn
From the turn system. Use it to let end your clock turn.
Entities
One clock entity with Clock and Player. When it gets Active as well, the turn is over.
So we increase the number of ticks on the Clock and update the ticks in each TimedEvent - if that event should trigger we reset the number of ticks and add EventTrigger to let it do whatever happens when it triggers.
Finally we add EndTurn to our clock to end its turn and let the next round start.
Systems
TimeSystem
The SystemName should be implemented aprroximately as follows (Python pseudo-code):
ticks_per_turn = 1
clocks = world.get_entities_with_component(Clock, Player, Active)
for clock in clocks:
clock.clock.ticks += ticks_per_turn
events = world.get_entities_with_component(TimedEvent)
for event in events:
event.timed_event.ticks += ticks_per_turn
if event.timed_event.frequency == event.timed_event.ticks:
event.timed_event.ticks = 0
world.add_component(event, EventTrigger)
world.add_component(clock, EndTurn)
EventSystem
This will actually be multiple systems - one for each type of TimedEvent you have.
events = world.get_entities_with_component(EventTrigger, TriggeredComponent)
for event in events:
# Do whatever event.triggered_component does when it is triggered
world.remove_component(event, EventTrigger)