diff --git a/Cargo.lock b/Cargo.lock index 6cacabe..7471a01 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -791,6 +791,7 @@ version = "0.1.0" name = "moonhare_game" version = "0.1.0" dependencies = [ + "moonhare_ecs", "moonhare_graphics", "moonhare_log", "moonhare_window", diff --git a/crates/moonhare_ecs/src/component.rs b/crates/moonhare_ecs/src/component.rs new file mode 100644 index 0000000..7a0ab09 --- /dev/null +++ b/crates/moonhare_ecs/src/component.rs @@ -0,0 +1,20 @@ +use std::{collections::HashMap, marker::PhantomData}; + +use crate::generational_index::{self, GenerationalIndex}; + +#[derive(Debug)] +pub struct Component { + id: usize, + component_type: T, +} + +pub trait ComponentType{} + +impl Component { + pub fn new(id: usize, component_type: T) -> Self { + Self { + id, + component_type + } + } +} \ No newline at end of file diff --git a/crates/moonhare_ecs/src/entity/mod.rs b/crates/moonhare_ecs/src/entity/mod.rs new file mode 100644 index 0000000..964313e --- /dev/null +++ b/crates/moonhare_ecs/src/entity/mod.rs @@ -0,0 +1,36 @@ +use crate::{entity, generational_index::{GenerationalIndex, GenerationalIndexAllocator}}; + +#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Copy, Hash)] +pub struct Entity(GenerationalIndex); + +impl Entity { + pub fn index(&self) -> usize { + self.0.index() + } + + pub fn generation(&self) -> u64 { + self.0.generation() + } +} + + +#[derive(Debug, Clone)] +pub struct EntityAllocator(GenerationalIndexAllocator); + +impl EntityAllocator { + pub fn new() -> Self { + EntityAllocator(GenerationalIndexAllocator::new()) + } + + pub fn allocate(&mut self) -> Entity { + Entity(self.0.allocate()) + } + + pub fn deallocate(&mut self, entity: Entity) -> bool { + self.0.deallocate(entity.0) + } + + pub fn is_live(&self, entity: Entity) -> bool { + self.0.is_live(entity.0) + } +} \ No newline at end of file diff --git a/crates/moonhare_ecs/src/generational_index.rs b/crates/moonhare_ecs/src/generational_index.rs index 2def46f..e68a0b6 100644 --- a/crates/moonhare_ecs/src/generational_index.rs +++ b/crates/moonhare_ecs/src/generational_index.rs @@ -1,4 +1,4 @@ -#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy)] +#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Hash)] pub struct GenerationalIndex { index: usize, generation: u64, @@ -14,17 +14,22 @@ impl GenerationalIndex { } } +#[derive(Debug, Clone)] struct AllocatorEntry { is_live: bool, generation: u64, } +#[derive(Debug, Clone, Default)] pub struct GenerationalIndexAllocator { entries: Vec, free: Vec, } impl GenerationalIndexAllocator { + pub fn new() -> Self { + Default::default() + } pub fn allocate(&mut self) -> GenerationalIndex { match self.free.pop() { Some(index) =>{ @@ -64,6 +69,10 @@ impl GenerationalIndexAllocator { pub fn is_live(&self, index: GenerationalIndex) -> bool { index.index() < self.entries.len() && self.entries[index.index()].generation == index.generation && self.entries[index.index()].is_live } + + pub fn max_allocated_index(&self) -> usize { + self.entries.len() + } } struct ArrayEntry { @@ -74,7 +83,15 @@ struct ArrayEntry { pub struct GenerationalIndexArray(Vec>>); impl GenerationalIndexArray { - pub fn set(&mut self, index: GenerationalIndex, value: T) { + pub fn new() -> GenerationalIndexArray { + GenerationalIndexArray(Vec::new()) + } + + pub fn clear(&mut self) { + self.0.clear(); + } + + pub fn insert(&mut self, index: GenerationalIndex, value: T) { while self.0.len() <= index.index() { self.0.push(None); } diff --git a/crates/moonhare_ecs/src/lib.rs b/crates/moonhare_ecs/src/lib.rs index 6a9fc59..da147cf 100644 --- a/crates/moonhare_ecs/src/lib.rs +++ b/crates/moonhare_ecs/src/lib.rs @@ -1,15 +1,55 @@ +use std::{collections::HashMap, path::{Component, Components}}; + use anymap::AnyMap; -use crate::generational_index::{GenerationalIndex, GenerationalIndexAllocator, GenerationalIndexArray}; +use crate::{entity::{Entity, EntityAllocator}, generational_index::{GenerationalIndex, GenerationalIndexAllocator, GenerationalIndexArray}}; pub mod generational_index; +pub mod world; +pub mod entity; +pub mod component; -pub type Entity = GenerationalIndex; -pub type EntityMap = GenerationalIndexArray; // based on: https://kyren.github.io/2018/09/14/rustconf-talk.html + +/* Moonhare ECS Design +-------------------------------------- + Game + 🠟 + Systems +(RenderSystem, PhysicsSystem, EnemyAISystem, EnemyCollisionSystem,...) + 🠟 + Entity + 🠟 + Components +-------------------------------------- +*/ + +#[derive(Debug)] pub struct ECS { - pub entity_allocator: GenerationalIndexAllocator, - pub entity_components: AnyMap, - pub resources: AnyMap -} \ No newline at end of file + entities: EntityAllocator, + components: AnyMap +} + +impl ECS { + pub fn new() -> ECS { + ECS { + entities: EntityAllocator::new(), + components: AnyMap::new(), + } + } + + pub fn add_entity(&mut self) -> Entity { + self.entities.allocate() + } + + pub fn entity_is_live(&self, entity: Entity) -> bool { + self.entities.is_live(entity) + } + + pub fn register_component() { + + } + +} + diff --git a/crates/moonhare_ecs/src/world.rs b/crates/moonhare_ecs/src/world.rs new file mode 100644 index 0000000..bd3bac7 --- /dev/null +++ b/crates/moonhare_ecs/src/world.rs @@ -0,0 +1,22 @@ +use std::fmt::Error; + +use anymap::AnyMap; + +use crate::{Entity, ECS}; + +/// stores Entitys, Components and resources +/// provides methods to search for specific Entitys +#[derive(Debug)] +pub struct World { + ecs: ECS, + resources: AnyMap +} + +impl World { + pub fn new() -> Self { + Self { + ecs: ECS::new(), + resources: AnyMap::new(), + } + } +} \ No newline at end of file diff --git a/crates/moonhare_game/Cargo.toml b/crates/moonhare_game/Cargo.toml index 2800e98..97d9f14 100644 --- a/crates/moonhare_game/Cargo.toml +++ b/crates/moonhare_game/Cargo.toml @@ -5,6 +5,7 @@ version.workspace = true authors.workspace = true [dependencies] +moonhare_ecs = { path = "../moonhare_ecs" } moonhare_graphics = { path = "../moonhare_graphics" } moonhare_log = { path = "../moonhare_log" } moonhare_window = { path = "../moonhare_window" } diff --git a/crates/moonhare_game/src/lib.rs b/crates/moonhare_game/src/lib.rs index 5ff365c..add2b6e 100644 --- a/crates/moonhare_game/src/lib.rs +++ b/crates/moonhare_game/src/lib.rs @@ -2,6 +2,8 @@ use std::rc::Rc; + +use moonhare_ecs::world::World; use moonhare_graphics::{color::Color, glium::{backend::Context, glutin::api::egl::context}}; use moonhare_log::*; use moonhare_window::{platforms::glfw_window::GLFWWindow}; @@ -10,19 +12,17 @@ pub mod basic; /// Only one Game may exist per project #[derive(Debug)] pub struct Game { + pub world: World, pub is_running: bool, pub name: String, - pub context: moonhare_window::WindowRenderContext, - pub glfw_window: Option, } impl Default for Game { fn default() -> Self { Self { + world: World::new(), is_running: true, name: default_game_name(), - context: moonhare_window::WindowRenderContext::OPENGLGLFW, - glfw_window: None, } } }