From 4632dd8e9e95a377993ef677a157202fda8072f9 Mon Sep 17 00:00:00 2001 From: Dominik Kaiser Date: Tue, 2 Jun 2026 23:23:57 +0200 Subject: Implement ECS --- src/sparse_set.rs | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 100 insertions(+) create mode 100644 src/sparse_set.rs (limited to 'src/sparse_set.rs') diff --git a/src/sparse_set.rs b/src/sparse_set.rs new file mode 100644 index 0000000..d7a69eb --- /dev/null +++ b/src/sparse_set.rs @@ -0,0 +1,100 @@ +use super::Entity; + +pub struct SparseSet { + pub dense: Vec, + pub entities: Vec, + pub sparse: Vec>, +} + +impl SparseSet { + pub fn new() -> Self { + Self { + dense: Vec::new(), + entities: Vec::new(), + sparse: Vec::new(), + } + } + + pub fn insert(&mut self, entity: Entity, component: T) { + if self.sparse.len() <= entity { + self.sparse.resize(entity + 1, None); + } + + self.dense.push(component); + self.entities.push(entity); + + let id = self.dense.len() - 1; + self.sparse[entity] = Some(id); + } + + pub fn remove(&mut self, entity: Entity) { + let Some(id) = self.sparse.get(entity).copied().flatten() else { + return; + }; + let Some(last) = self.entities.last().copied() else { + return; + }; + self.dense.swap_remove(id); + self.entities.swap_remove(id); + self.sparse[last] = Some(id); + self.sparse[entity] = None; + } + + pub fn iter(&self) -> impl Iterator { + self.entities.iter().copied().zip(self.dense.iter()) + } + + pub fn iter_mut(&mut self) -> impl Iterator { + self.entities.iter().copied().zip(self.dense.iter_mut()) + } + + pub fn get(&self, entity: Entity) -> Option<&T> { + if let Some(id) = self.sparse.get(entity) { + match id { + Some(id) => self.dense.get(*id), + None => None, + } + } else { + None + } + } + + pub fn get_mut(&mut self, entity: Entity) -> Option<&mut T> { + if let Some(id) = self.sparse.get(entity) { + match id { + Some(id) => self.dense.get_mut(*id), + None => None, + } + } else { + None + } + } +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn test_remove() { + let mut set = SparseSet::::new(); + set.insert(3, 300); + set.insert(2, 200); + set.insert(4, 400); + set.insert(7, 700); + + set.remove(4); + + assert!(set.get(7).copied() == Some(700)); + assert!(set.get(3).copied() == Some(300)); + assert!(set.get(2).copied() == Some(200)); + assert!(set.get(4).copied().is_none()); + + set.remove(7); + assert!(set.get(7).copied().is_none()); + assert!(set.get(3).copied() == Some(300)); + assert!(set.get(2).copied() == Some(200)); + assert!(set.get(4).copied().is_none()); + } +} -- cgit v1.2.3