https://github.com/Axelderan/componentile
https://crates.io/crates/componentile
This is a structure of arrays optimized for discrete spaces, where instead of having entity IDs, components live directly in array indexes. It supports chunking for cache-locality. It has 2 types of storages at the moment: one is a bitset array for booleans, and the other an array for any other kind of Copy
type.
Some nice minor extras are an iterator with automatic bounds-checking, plus an extra, manual method for skipping 8 elements at a time.
The basic use is to define a world using a macro which chooses the appropriate storages and defines the World
impl
automatically.
define_world! {
foo: bool,
bar: (u8, u8),
baz: &str,
}
Now you have a World
.
let mut world = World::new();
let (x, y) = (0, 2);
world.foo.put(true, x, y);
assert_eq!(world.get(x, y), true);
Some trade-offs to be aware of: I've opted for allocation of an array the size of the world for each component. These may be very sparse arrays and consume a lot of memory. However, indexing is O(1) and spatially-local components are guaranteed to be cache-local. For a tile-based game, this seems like a sane trade-off, though I may support sparse component storages in the future.
Future plans include:
- a 3rd dimension, probably only 8 blocks high
- const generics to make it easier to define a
World
of size other than 1024x1024 cells, without having to modifyconst
declarations in the library file - perhaps a sparse storage
Future plans do not include:
- Inclusion of ancillary data structures, such as parent-child maps or maps for shared resources such as mesh data a la flyweight pattern. These should be usable with this structure, but this is a minimal structure without opinions of what other structures are used alongside it.
This is part of a game I've been working on and I'll be splitting at least one other piece out into a related, but separate library.