Struct Scene

Source
pub struct Scene<'a> { /* private fields */ }
Expand description

Container for GameObjects.

A scene is initialized with Scene::builder, which is used to register the GameObject types which can be spawned into the scene. The memory for the game objects is allocated at the end in SceneBuilder::build.

Game objects are spawned with Scene::spawn, after which they can be accessed by running systems (in the Entity-Component-System sense) with Scene::run_system. To skip the boilerplate, the define_system macro is recommended for defining system functions.

§Example

use engine::{game_objects::Scene, define_system, impl_game_object};

// Define some component types:

// NOTE: Zeroable and Pod are manually implemented here to avoid
// the engine depending on proc macros. They should generally be
// derived, if compile times allow, as Pod has a lot of
// requirements that are easy to forget.

#[derive(Debug, Clone, Copy)]
#[repr(C)]
struct Position { pub x: i32, pub y: i32 }
unsafe impl bytemuck::Zeroable for Position {}
unsafe impl bytemuck::Pod for Position {}

#[derive(Debug, Clone, Copy)]
#[repr(C)]
struct Velocity { pub x: i32, pub y: i32 }
unsafe impl bytemuck::Zeroable for Velocity {}
unsafe impl bytemuck::Pod for Velocity {}

// Define the "Foo" game object:

#[derive(Debug)]
struct Foo {
    pub position: Position,
    pub velocity: Velocity,
}

impl_game_object! {
    impl GameObject for Foo using components {
        position: Position,
        velocity: Velocity,
    }
}

// Create a Scene that five game objects of type Foo can be spawned in:
let mut scene = Scene::builder()
    .with_game_object_type::<Foo>(5)
    .build(arena, temp_arena)
    .unwrap();

// Spawn a game object of type Foo:
scene.spawn(Foo {
    position: Position { x: 100, y: 100 },
    velocity: Velocity { x: 20,  y: -10 },
}).unwrap();

// Run a "physics simulation" system for all game objects which
// have a Position and Velocity component:
scene.run_system(define_system!(|_, pos: &mut [Position], vel: &[Velocity]| {
    // This closure gets called once for each game object type with a Position
    // and a Velocity, passing in that type's components, which can be zipped
    // and iterated through to operate on a single game object's data at a
    // time. In this case, the closure only gets called for Foo as it's our
    // only game object type, and these slices are 1 long, as we only spawned
    // one game object.
    for (pos, vel) in pos.iter_mut().zip(vel) {
        pos.x += vel.x;
        pos.y += vel.y;
    }
}));

// Just assert that we ended up where we intended to end up.
let mut positions_in_scene = 0;
scene.run_system(define_system!(|_, pos: &[Position]| {
    for pos in pos {
        assert_eq!(120, pos.x);
        assert_eq!(90, pos.y);
        positions_in_scene += 1;
    }
}));
assert_eq!(1, positions_in_scene);

// Game objects can be deleted by collecting and deleting them in batches:
use engine::collections::FixedVec;
let mut handles_to_delete = FixedVec::new(temp_arena, 1).unwrap();
scene.run_system(define_system!(|handles, pos: &[Position]| {
    for (handle, pos) in handles.zip(pos) {
        if pos.x == 120 {
            handles_to_delete.push(handle).unwrap();
        }
    }
}));

// NOTE: After deletion, all handles get invalidated, so
// handles_to_delete would need to be re-acquired from a run_system call.
scene.delete(&mut handles_to_delete).unwrap();

Implementations§

Source§

impl Scene<'_>

Source

pub fn builder<'a>() -> SceneBuilder<'a>

Creates a SceneBuilder which is used to create a Scene.

Source§

impl Scene<'_>

Source

pub fn spawn<G: GameObject>(&mut self, object: G) -> Result<(), SpawnError>

Spawns the game object into this scene if there’s space for it.

See the Scene documentation for example usage.

Source

pub fn run_system<F>(&mut self, system_func: F) -> bool

Runs system_func for each game object type in this Scene, passing in the components for each.

Returns false if all system_func invocations return false. When using define_system, this happens when the scene doesn’t contain any game object types with the set of components requested.

The GameObjectHandleIterator returns handles to the game objects associated with the components in a particular iteration, if iterated through at the same pace as the component columns.

Each ComponentColumn contains tightly packed data for a specific component type, and the columns can be zipped together to iterate through sets of components belonging to a single game object, as component A at index N belongs to the same game object as component B at index N.

This is intended to be used with define_system, which can extract the relevant components from the component columns. See the Scene documentation for example usage.

Source

pub fn delete(&mut self, handles: &mut [GameObjectHandle]) -> Result<(), usize>

Deletes the game objects referred to by the given handles.

If any handles are invalid (e.g. have been invalidated by a previous call to Scene::delete), the amount of invalid handles is returned in an Err.

The slice of handles is mutable to allow sorting the slice, which is needed for a performant implementation of this function.

Source

pub fn reset(&mut self)

Deletes all game objects in this scene.

Auto Trait Implementations§

§

impl<'a> Freeze for Scene<'a>

§

impl<'a> RefUnwindSafe for Scene<'a>

§

impl<'a> Send for Scene<'a>

§

impl<'a> Sync for Scene<'a>

§

impl<'a> Unpin for Scene<'a>

§

impl<'a> !UnwindSafe for Scene<'a>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.