all-is-cubes 0.5.0

Recursive voxel game engine. Can be used for voxel raytracing.
Documentation
//! Time passing “in game”, i.e. in a [`Universe`] and its contents.
//!
//! [`Universe`]: crate::universe::Universe

// TODO: This module exists because I am intending to add complications to Tick
// like having multiple subdivisions of time (to allow efficient slower-running
// yet synchronized game systems). If that doesn't happen, it should be merged
// into universe.rs or something like that.

pub use instant::{Duration, Instant};

/// Specifies an amount of time passing in a [`Universe`](crate::universe::Universe)
/// and its contents.
///
/// [`Universe`]: crate::universe::Universe
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Tick {
    // TODO: Replace this with a rational-number-based system so that we can
    // (1) step in exact 60ths or other frame rate fractions
    // (2) have a standard subdivision for slower-than-every-frame events
    pub(crate) delta_t: Duration,

    /// Whether game time is paused, and `delta_t` should not be considered
    /// as an amount of game time passing. See [`Self::paused()`] for details.
    paused: bool,
}

impl Tick {
    /// A tick of arbitrary length, for testing purposes. Do not use this for actual gameplay.
    pub const fn arbitrary() -> Self {
        Self {
            delta_t: Duration::from_secs(1),
            paused: false,
        }
    }

    /// Construct a [`Tick`] of the specified length.
    pub const fn from_duration(delta_t: Duration) -> Self {
        Self {
            delta_t,
            paused: false,
        }
    }

    pub fn from_seconds(dt: f64) -> Self {
        Self {
            delta_t: Duration::from_micros((dt * 1e6) as u64),
            paused: false,
        }
    }

    /// Return the amount of time passed as a [`Duration`].
    pub fn delta_t(self) -> Duration {
        self.delta_t
    }

    /// Set the paused flag. See [`Tick::paused`] for more information.
    #[must_use]
    pub fn pause(self) -> Self {
        Self {
            paused: true,
            ..self
        }
    }

    /// Returns the "paused" state of this Tick. If true, then step operations should
    /// not perform any changes that reflect "in-game" time passing. They should still
    /// take care of the side effects of other mutations/transactions, particularly where
    /// not doing so might lead to a stale or inconsistent view.
    ///
    /// Note that functions which propagate ticks to subordinate game objects are free to
    /// not propagate paused ticks. TODO: The exact policies are not yet settled.
    pub fn paused(&self) -> bool {
        self.paused
    }
}