diff --git a/src/ecs.odin b/src/ecs.odin index 888439b..a45fe1f 100644 --- a/src/ecs.odin +++ b/src/ecs.odin @@ -7,6 +7,13 @@ STARTUP :: 0 UPDATE :: 1 DRAW :: 2 +@(private) +sparse_entity_limit: int + +get_entity_limit :: proc() -> int { + return sparse_entity_limit +} + App :: struct { systems: map[int][dynamic]proc(), plugins: [dynamic]proc(app: ^App), @@ -27,13 +34,14 @@ add_plugin :: proc(app: ^App, plugin: proc(app: ^App)) { } // run the app -run :: proc(app: ^App) { +run :: proc(app: ^App, entity_limit: int = 1000) { + sparse_entity_limit = entity_limit for p in app.plugins { p(app) } for i in app.systems[STARTUP] {i()} - _, window := single(&Window) + window, _ := single(&Window) rl.InitWindow(window.width, window.height, strings.clone_to_cstring(window.title)) defer rl.CloseWindow() diff --git a/src/entities.odin b/src/entities.odin index 959f5cf..028a892 100644 --- a/src/entities.odin +++ b/src/entities.odin @@ -5,7 +5,9 @@ import "core:fmt" Entity :: distinct u32 Storage :: struct($T: typeid) { - data: map[Entity]T, + dense: [dynamic]T, + entities: [dynamic]Entity, + sparse: map[Entity]int, } // adds a new entity id to app and returns it @@ -24,33 +26,37 @@ add_component :: proc { // initializes new component of type and add to Storage add_fresh_component :: proc(entity: Entity, storage: ^Storage($T)) { - storage.data[entity] = T{} + append(&storage.dense, T{}) + append(&storage.entities, entity) + i := len(storage.dense) - 1 + defer storage.sparse[entity] = i } // creates a copy of component type with data and add to Storage add_component_with_data :: proc(entity: Entity, storage: ^Storage($T), component: T) { - storage.data[entity] = component + append(&storage.dense, component) + append(&storage.entities, entity) + i := len(storage.dense) - 1 + defer storage.sparse[entity] = i } // get components saved in Storage // returns storage.data -slice :: proc(storage: ^Storage($T)) -> map[Entity]T { - return storage.data +slice :: proc(storage: ^Storage($T)) -> [dynamic]T { + return storage.dense +} + +slice_entity :: proc(storage: ^Storage($T)) -> [dynamic]Entity { + return storage.entities } // get component saved in Storage // returns Entity and component of type -single :: proc(storage: ^Storage($T)) -> (Entity, ^T) { - for i, &v in slice(storage) { - return i, &v - } - return 0, nil +single :: proc(storage: ^Storage($T)) -> (^T, Entity) { + return &storage.dense[0], storage.entities[0] } // get component of type from entity get_component :: proc(entity: Entity, storage: ^Storage($T)) -> ^T { - if _, exists := storage.data[entity]; exists { - return &storage.data[entity] - } - return new(T) + return &storage.dense[storage.sparse[entity]] } diff --git a/src/systems.odin b/src/systems.odin index 599d092..4f175fe 100644 --- a/src/systems.odin +++ b/src/systems.odin @@ -17,8 +17,10 @@ DefaultPlugin :: proc(app: ^App) { @(private) draw_sprite :: proc() { - for i, &v in slice(&Sprite) { - sprite_transform := get_component(i, &Transform) + components := slice(&Sprite) + entities := slice_entity(&Sprite) + for &v, i in components { + sprite_transform := get_component(entities[i], &Transform) rl.DrawTexture( v.texture, i32(sprite_transform.translation.x),