[−][src]Crate tiny_ecs
Tiny ECS
The intention of this crate is that a basic ECS is provided, where you will be required to exercise a little additional control.
Where most other ECS crates provide a mechanism for inserting "systems" in to the ECS to run against entities, this one leaves it out - you can think of it as a "system for entity/components". You will need to create external systems; these can be a function, a loop, or anything else.
Internally this ECS is the use of bitmasks
. Each entity ID is in
practice an internal index number in to an array which contains bitmasks.
The bitmasks themselves keep track of what components the entity has.
Note: borrows of VecMap
are checked at runtime.
Examples
Init with a capacity
This is good to do if you know the size required as it will prevent many reallocs/moves as data is added. This affects both the entity and component map allocs (they will be equal in length).
use tiny_ecs::Entities; let mut entities = Entities::new(Some(1000), Some(24));
Demonstrating use
use tiny_ecs::Entities; use tiny_ecs::ECSError; // These are the "components" we will use struct Vector1 { x: i32, } struct Vector2 { x: i32, y: i32, } struct Vector3 { x: i32, y: i32, z: i32, } // Initialize the Entity collection let mut entities = Entities::new(Some(3), Some(3)); // Creating an entity uses the builder pattern. // Be sure to return the ID if you need to track it let entity_1 = entities.new_entity() .with(Vector1 { x: 42 })? .with(Vector3 { x: 3, y: 10, z: -12 })? .finalise()?; // The entity ID will increment up from 0 assert_eq!(entity_1, 0); // Do note however, that you can keep adding parts to this entity // via the builder pattern until you choose to create another entity // To add another entity you need to create one entities.new_entity() .with(Vector2 { x: 66, y: 6 })? .with(Vector1 { x: 6 })? .finalise()?;
Access an entities part of type <T>
struct Vector3 {x: i32, y: i32, z: i32 } // To get access to a part belonging to an entity you need // first to get the component map created for the part type // You need to 'anchor' this with a let or the ref is // dropped before you can use it let mut components = entities .borrow_mut::<Vector3>()?; // You can then use the part by getting a reference let mut part = components.get_mut(entity_1).unwrap(); assert_eq!(part.z, -12);
Check if Entity
contains a part type + remove part
struct Vector1 {x: i32 } let entity_1 = entities.new_entity() .with(Vector1 { x: 3 })? .finalise()?; // You can check if an entity contains a part with the type signature if entities.entity_contains::<Vector1>(entity_1) { assert!(entities.rm_component::<Vector1>(entity_1).is_ok()); } assert_eq!(entities.entity_contains::<Vector1>(entity_1), false);
A system that uses an get_mut()
struct Vector1 {x: i32 } // Make a system of some form that takes a `VecMap<T>` arg fn some_system(mut components: &mut VecMap<Vector1>) { // You can then iterate over the components directly for (k, v) in components.iter_mut() { v.x += 1; assert!(v.x > k as i32); } } some_system(&mut components);
Get components for an entity ID list
struct Vector1 {x: i32 } // A system that fetches the components for only the entities you are require fn second_system(active: &[usize], mut v1_map: &mut VecMap<Vector1>) { for id in active { if let Some(part) = v1_map.get_mut(*id) { part.x = 42; } } } second_system(&[0, 1, 2], &mut components);
A more complex system using VecMaps directly
// Or a system handles the `Entities` container directly fn other_system(active_ents: &[usize], entities: &mut Entities) -> Result<(), ECSError> { // You can mutably borrow multiple component maps at once let mut v1_components = entities .borrow_mut::<Vector1>()?; let mut v2_components = entities .borrow_mut::<Vector2>()?; // But not have a mutable borrow and immutable borrow to the same map // Fails at runtime! // let v2_components = entities.borrow::<Vector2>().unwrap(); for id in active_ents { if entities.entity_contains::<Vector1>(*id) && entities.entity_contains::<Vector2>(*id) { let v1_part = v1_components.get_mut(*id).unwrap(); let v2_part = v2_components.get_mut(*id).unwrap(); v1_part.x = 42; assert_ne!(v1_part.x, 43); assert_eq!(v1_part.x, 42); } } Ok(()) } other_system(&[0, 1, 2], &mut entities);
Structs
Entities | This is the root of the ECS implementation |
MapRef | Immutable reference container for |
MapRefMut | Mutable reference container for |
VecMap | A map optimized for small integer keys. |
Enums
ECSError |