Chapter 24
The ride instant
A moment carries four things: the rider, the truck, the clock, and the plan for when the cat or the bird ahead starts to move. A step makes the next moment from this one. This chapter explains that step, then groups the ride's moving parts by how they change.
One step §
Here's the step, whole:
## The instant a step after `instant`. The world and the rider change each
## other within one step, in this order. First the rider reads the world as it
## stands at the old clock: the stage of the encounter on the rider's segment.
## Then the rider steps, and the clock ticks. Then the world answers the rider
## that has just moved. The truck aims at how far along the route this step's
## rider is, and the encounter plan is kept, forgotten at a new segment, or made
## from this step's rider at the new clock. The rider never reads the truck.
next : Route, RideInstant -> RideInstant
next = |route, instant| {
stage_before = RideInstant.encounter_stage(route, instant)
rider = instant.rider.rider_at_next_step({ route, encounter_stage: stage_before })
clock = instant.clock.next()
rider_place = rider.motorcycle.route_place
truck = TruckJourney.truck_progress_at_next_step(
instant.truck,
{ rider_distance: rider_place.distance_along(route), route },
)
segment_change =
if rider_place.segment_index == RideInstant.rider_segment_index(instant) {
SameSegment
} else {
NewSegment
}
encounter_plan = instant.encounter_plan.plan_at_next_step({
segment_change,
approach: encounter_approach(rider_place.segment_on(route).encounter, rider.motorcycle),
now: clock,
})
{ rider, truck, clock, encounter_plan }
}
next_or_restart, from the “Immutable values: a flip book” chapter, calls this step until the rider reaches the end of the road. The doc comment on next gives the order, and the order matters. The rider moves first, reading where the encounter ahead has got to. Then the clock ticks. Then the world answers the rider who has just moved: the truck aims at how far along the route the rider now is, and plan_at_next_step keeps the encounter plan, drops it at a new segment, or makes one from this step's rider. The last line puts the four together into the next moment, and the old moment stays as it was.
The rider reads the encounter as a stage, where its animation has got to:
## Where an animation has got to: not begun, playing and this many steps in,
## which is the frame it shows, or over this many steps ago.
Stage : [Waiting, Playing(Steps), Past(Steps)]
Waiting comes before the animation starts, Playing counts the steps in, and Past counts the steps since it ended. The “The cat” chapter shows how the plan and the clock make one.
Carried and derived §
Those four fields are all the ride carries from one step to the next. The ride derives everything else in a frame from them and the road, afresh for each frame. So the ride's moving parts come in three kinds:
| Kind | Things | How it changes |
|---|---|---|
| Clock-driven | The sun's height, the sky, the beacons | Derived from the clock, and for a beacon its tower |
| Stepped | The rider, the truck | Carried in the moment, and moved on once a step by its step function |
| Rider-driven | The cat, the bird | Derived from the clock and the carried plan, which the rider's approach sets |
The trees and the cows stay put.
Clock.next, Rider.rider_at_next_step and TruckJourney.truck_progress_at_next_step all have the same shape: a value goes in, and the next value comes out. Call that a step function. Set beside the clock-driven kind, stepping has a cost:
- A function of the clock returns the sun at any step, straight away. To find the truck at step 4,000, the ride has to play that far.
- A wrong sky spoils only the frames it touches. A wrong step moves the rider for the rest of the ride.
- The lines of
RideInstant.nextrun in order. Once the moments exist, the platform can paint their frames in any order.
So the stepped parts need the most care.
The clock-driven things come next, and the beacons are the simplest of them: they follow the clock and their towers.