I'm having a hard time doing this, and every attemps, I am getting issues I can't manage to resolve.
for context :
I'm building an entity component system, where the components are packed arrays in an anymap. What I call a packed array is a data structure that would look like an array with lots of empty slots, with index being entity id: for instance, the component at index 5 is the component attached to the entity of id 5.
Since not all entities have all components, there are lots of empty slots, so a packed array is a Vec of IndexedElem<T> to keep the data tight in memory:
pub struct PackedArray<T> {
data: Vec<IndexedElem<T>>,
}
pub struct IndexedElem<T> {
pub index: usize,
pub elem: T
}
Now, the component table itself is an AnyMap of these PackedArray:
pub struct ComponentTable {
components: anymap::Map,
}
So I have all the basics, like creating entities, adding / removing / getting components.
But now, I want to be able to iterate over components (that is the whole point of keeping components in a table of packed arrays).
It's easy to iterate over 1 component, I simply iterate over the Vec. Where I'm struggling, is to iterate over several components:
Let's say I want to iterate over all pairs of components C1 and C2 (meaning all entities that have both C1 and C2)
The idea is to get iterators of these two packed arrays, then I have a current_entity_id that starts at 0, I look if the IndexedElem of both iterator is the same as the id, returns the two elems if it's the case, go to the next one if not.
In theory, I will now how to build this, but I'm struggling a lot implementing it in rust, with lifetimes, ownerships, etc...
Here is my last attempt :
I have a ComponentIterator_2 struct, implementing the iterator trait with type being (C1, C2) :
pub struct ComponentIterator_2<'a, C1, C2> {
iterator_1: std::slice::IterMut<'a, IndexedElem<C1>>,
iterator_2: std::slice::IterMut<'a, IndexedElem<C2>>,
current_entity: usize,
}
But when I try to build it like so :
pub fn iterate_over_2_component<'a, C1: 'static, C2: 'static>(&'a mut self) -> Option<ComponentIterator_2<'a, C1, C2>> {
return Some(ComponentIterator_2::<C1, C2> {
iterator_1: match self.components.get_mut::<PackedArray<C1>>() {
None => return None,
Some(packed_array) => packed_array.iter_mut(),
},
iterator_2: match self.components.get_mut::<PackedArray<C2>>() {
None => return None,
Some(packed_array) => packed_array.iter_mut(),
},
current_entity: 0,
});
}
Here I can't borrow self.components twice, which I understand, but I can't get around it.
I've tried many other things, but I've struggled enough to ask for help here now !
So I would be really pleased if anyone could give me hints on ho to implement this properly, and if possible in an efficient way.
The whole project (The ecs, nothing more around it) is available on my GitHub.