8 releases (4 breaking)
0.13.1 | Oct 5, 2024 |
---|---|
0.12.1 | Jun 29, 2024 |
0.12.0 | Jan 27, 2024 |
0.11.1 | Sep 27, 2023 |
0.5.0 |
|
#77 in Game dev
1,071 downloads per month
145KB
4K
SLoC
Sparsey
Sparsey is a sparse set-based Entity Component System (ECS).
Design Goals
- Be flexible: Any
Send + Sync + 'static
type can be used as a component. - Be concise: The most commonly used functionalities should require the least amount of typing.
- Make use of sparse sets: Provide features exclusive to sparse set-based ECS.
Example
use sparsey::World;
struct Position(i32, i32);
struct Velocity(i32, i32);
fn main() {
let mut world = World::builder()
.register::<Position>()
.register::<Velocity>()
.build();
world.create((Position(0, 0), Velocity(1, 2)));
world.create((Position(0, 0), Velocity(2, 3)));
world.for_each::<(&mut Position, &Velocity)>(|(position, velocity)| {
position.0 += velocity.0;
position.1 += velocity.1;
});
}
Features
Powerful Queries
Get, include and exclude components using Sparsey's query API.
// Iter components A and B from entities with A and B.
world
.query_all::<(&A, &B)>()
.for_each(|_| ());
// Iter components A from entities with A and B.
world
.query_all::<&A>()
.include::<&B>()
.for_each(|_| ());
// Iter components A from entities with A and without B.
world
.query_all::<&A>()
.exclude::<&B>()
.for_each(|_| ());
// Iter components A from entities with A and B, without C.
world
.query_all::<&A>()
.include::<&B>()
.exclude::<&C>()
.for_each(|_| ());
Great Performance with Grouped Storages
Sparsey allows the user to "group" components to greatly optimize iteration
performance. When a component group is formed, the World
ensures that all
components that belong to that group are stored in order at the beginning of
their storages, making the iteration process a traversal of densely-packed
arrays.
let mut world = World::builder()
.add_group::<(A, B)>()
.add_group::<(A, B, C, D>)>()
.build();
Additionally, grouped components can be accessed as slices.
/// Get all entities with A and B as a slice.
world
.query_all::<Entity>()
.include::<(&A, &B)>
.slice()
.map(|_| ());
/// Get all A and B components of entities with A and B as a tuple of slices.
world
.query_all::<(&A, &B)>()
.slice()
.map(|_| ());
/// Get all entities and A and B components of entities with A and B as a tuple
/// of slices.
world
.query_all::<(Entity, &A, &B)>()
.slice()
.map(|_| ());
/// Get all A and B components of entities with A and B, and without C and D as
/// a tuple.
world
.query_all::<(&A, &B)>()
.exclude::<(&C, &D)>()
.slice()
.map(|_| ());
Thanks
Sparsey takes inspiration and borrows features from other free and open source ECS projects, namely Bevy, EnTT, Legion, Shipyard and Specs. Make sure you check them out!
License
Sparsey is dual-licensed under either
-
MIT License (LICENSE-MIT or https://opensource.org/license/mit/)
-
Apache License, Version 2.0 (LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0)
at your option.
Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above without any additional terms or conditions.
Dependencies
~0.5–1MB
~15K SLoC