pub struct Sim {
pub world: World,
pub step: Duration,
pub max_steps: u32,
/* private fields */
}Expand description
Fixed-timestep simulation state.
The game owns a Sim, registers plain systems on its schedule, feeds it
wall-clock time every frame with Sim::step, and pulls a snapshot out
for the viewport. There is no window, no renderer, and no app object.
Fields§
§world: WorldEntity/component store. Game crates add their own components here.
step: DurationFixed step size. Defaults to 60 Hz (see Sim::with_default_step).
Each Sim::tick advances SimTime by exactly this amount, so
gameplay stays deterministic regardless of frame rate. Change it
before the first Sim::step call; changing it mid-run rescales
future ticks but leaves already-simulated time untouched.
max_steps: u32Maximum fixed steps per Sim::step call. Defaults to 8.
Guards against the spiral of death: after a long hitch (app resume, debugger pause, slow device), the sim runs at most this many catch-up ticks and drops the excess wall time instead of scheduling dozens of ticks that make the next frame even longer. The dropped time is gone, not carried over. The sim slows down instead of freezing.
Note: clamped to a minimum of 1 per call, so the sim always
makes progress while wall time keeps arriving.
Implementations§
Source§impl Sim
impl Sim
pub fn new(step: Duration) -> Self
Sourcepub fn with_default_step() -> Self
pub fn with_default_step() -> Self
60 Hz fixed-step sim.
Sourcepub fn add_system<M>(&mut self, system: impl IntoSystem<(), (), M>) -> &mut Self
pub fn add_system<M>(&mut self, system: impl IntoSystem<(), (), M>) -> &mut Self
Register a system into the per-step schedule.
Sourcepub fn add_chained_systems<M>(
&mut self,
systems: impl IntoScheduleConfigs<ScheduleSystem, M>,
) -> &mut Self
pub fn add_chained_systems<M>( &mut self, systems: impl IntoScheduleConfigs<ScheduleSystem, M>, ) -> &mut Self
Register systems with a guaranteed execution order.
A bare Schedule does not preserve add_system insertion order for
systems with conflicting accesses, so multi-step pipelines (economy,
combat) must register as one (a, b, c).chain() tuple through here
instead of separate add_system calls.
Sourcepub fn step(&mut self, dt: Duration) -> u32
pub fn step(&mut self, dt: Duration) -> u32
Advance the sim by dt wall time, running zero or more fixed steps.
Returns the number of steps run.
Wall time accumulates across calls: a dt smaller than Sim::step
banks its fraction for later, and a large dt runs several ticks at
once. At most Sim::max_steps ticks run per call; any time still
banked beyond that is dropped (see Sim::max_steps).
Typical frame pump:
let steps = sim.step(frame_dt);
// `steps` ticks ran; build the viewport snapshot from `sim.world`.Sourcepub fn leftover(&self) -> Duration
pub fn leftover(&self) -> Duration
Unconsumed fractional time carried to the next frame.
Always less than one Sim::step (a full step would have ticked).
Returns Duration::ZERO right after a step boundary and after a
hitch that hit the Sim::max_steps cap (the excess is dropped,
not reported here).
Sourcepub fn alpha(&self) -> f32
pub fn alpha(&self) -> f32
Blend factor between the last ticked state and the next one, from
0.0 (just ticked) to 1.0 (a full step banked, tick imminent).
Computed as accumulator / step, clamped to 0..1; returns 0.0
for a degenerate (zero) step size. The sim itself never interpolates.
Snapshots read the last ticked state, but games that keep the
previous snapshot can blend toward the current one with this factor
for smooth rendering.
Note: after a capped hitch (see Sim::max_steps) the
accumulator is cleared, so alpha reads 0.0 on the next frame.
Auto Trait Implementations§
impl !Freeze for Sim
impl !RefUnwindSafe for Sim
impl !UnwindSafe for Sim
impl Send for Sim
impl Sync for Sim
impl Unpin for Sim
impl UnsafeUnpin for Sim
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
impl<T> ConditionalSend for Twhere
T: Send,
Source§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
Source§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>, which can then be
downcast into Box<dyn ConcreteType> where ConcreteType implements Trait.Source§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>, which can then be further
downcast into Rc<ConcreteType> where ConcreteType implements Trait.Source§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.Source§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.