???
This commit is contained in:
parent
5587a7dc35
commit
022fac5966
8 changed files with 150 additions and 13 deletions
1
Cargo.lock
generated
1
Cargo.lock
generated
|
|
@ -791,6 +791,7 @@ version = "0.1.0"
|
|||
name = "moonhare_game"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"moonhare_ecs",
|
||||
"moonhare_graphics",
|
||||
"moonhare_log",
|
||||
"moonhare_window",
|
||||
|
|
|
|||
20
crates/moonhare_ecs/src/component.rs
Normal file
20
crates/moonhare_ecs/src/component.rs
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
use std::{collections::HashMap, marker::PhantomData};
|
||||
|
||||
use crate::generational_index::{self, GenerationalIndex};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Component<T: ComponentType> {
|
||||
id: usize,
|
||||
component_type: T,
|
||||
}
|
||||
|
||||
pub trait ComponentType{}
|
||||
|
||||
impl<T: ComponentType> Component<T> {
|
||||
pub fn new(id: usize, component_type: T) -> Self {
|
||||
Self {
|
||||
id,
|
||||
component_type
|
||||
}
|
||||
}
|
||||
}
|
||||
36
crates/moonhare_ecs/src/entity/mod.rs
Normal file
36
crates/moonhare_ecs/src/entity/mod.rs
Normal file
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
@ -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<AllocatorEntry>,
|
||||
free: Vec<usize>,
|
||||
}
|
||||
|
||||
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<T> {
|
||||
|
|
@ -74,7 +83,15 @@ struct ArrayEntry<T> {
|
|||
pub struct GenerationalIndexArray<T>(Vec<Option<ArrayEntry<T>>>);
|
||||
|
||||
impl <T> GenerationalIndexArray<T> {
|
||||
pub fn set(&mut self, index: GenerationalIndex, value: T) {
|
||||
pub fn new() -> GenerationalIndexArray<T> {
|
||||
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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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<T> = GenerationalIndexArray<T>;
|
||||
|
||||
// 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
|
||||
}
|
||||
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() {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
22
crates/moonhare_ecs/src/world.rs
Normal file
22
crates/moonhare_ecs/src/world.rs
Normal file
|
|
@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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" }
|
||||
|
|
|
|||
|
|
@ -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<moonhare_window::platforms::glfw_window::GLFWWindow>,
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue