Cauldron2D.Loop (Cauldron2D v0.1.3)

Copy Markdown View Source

A fixed timestep.

loop = Cauldron2D.Loop.new(60)

{steps, loop} = Cauldron2D.Loop.advance(loop, Cauldron2D.Loop.now())
world = Enum.reduce(1..steps//1, world, fn _, w -> World.step(w, Cauldron2D.Loop.dt(loop)) end)

advance/2 returns how many whole steps have come due since it was last called. dt/1 is constant, so a simulation driven by it runs at the same speed whatever the frame rate and replays identically given the same inputs.

Rules a caller must respect:

  • The first advance/2 call establishes the baseline and returns no steps.
  • At most :max_steps are returned from one call. Time beyond that is discarded rather than carried, so the simulation loses that time instead of owing a backlog.
  • Time below one step is carried in the accumulator and returned by a later call.
  • A now_ms earlier than the previous one contributes nothing; steps are never negative.

Summary

Functions

How many whole steps are due at now_ms, and the loop to carry forward.

The duration of one step, in seconds — the dt a simulation should use.

A loop running at hz steps per second. hz must be positive.

The current monotonic time in milliseconds, in the form advance/2 expects.

Types

t()

@type t() :: %Cauldron2D.Loop{
  accumulator: float(),
  last: integer() | nil,
  max_steps: pos_integer(),
  step_ms: float()
}

Functions

advance(loop, now_ms)

@spec advance(t(), integer()) :: {non_neg_integer(), t()}

How many whole steps are due at now_ms, and the loop to carry forward.

now_ms is a millisecond reading on a single monotonic scale, as now/0 returns. Returns {steps, loop}; pass the returned loop to the next call.

The first call on a fresh loop records now_ms as the baseline and returns 0 steps, whatever the interval since new/2.

dt(loop)

@spec dt(t()) :: float()

The duration of one step, in seconds — the dt a simulation should use.

new(hz, opts \\ [])

@spec new(number(), keyword()) :: t()

A loop running at hz steps per second. hz must be positive.

Options

  • :max_steps — the most steps one advance/2 call may return before the remaining time is discarded. Default 5

now()

@spec now() :: integer()

The current monotonic time in milliseconds, in the form advance/2 expects.