sparse set

This commit is contained in:
wooshings
2026-10-17 11:15:41 -07:00
parent a4791bcb57
commit 32ec90f67e
3 changed files with 34 additions and 18 deletions
+10 -2
View File
@@ -7,6 +7,13 @@ STARTUP :: 0
UPDATE :: 1 UPDATE :: 1
DRAW :: 2 DRAW :: 2
@(private)
sparse_entity_limit: int
get_entity_limit :: proc() -> int {
return sparse_entity_limit
}
App :: struct { App :: struct {
systems: map[int][dynamic]proc(), systems: map[int][dynamic]proc(),
plugins: [dynamic]proc(app: ^App), plugins: [dynamic]proc(app: ^App),
@@ -27,13 +34,14 @@ add_plugin :: proc(app: ^App, plugin: proc(app: ^App)) {
} }
// run the 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 { for p in app.plugins {
p(app) p(app)
} }
for i in app.systems[STARTUP] {i()} 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)) rl.InitWindow(window.width, window.height, strings.clone_to_cstring(window.title))
defer rl.CloseWindow() defer rl.CloseWindow()
+20 -14
View File
@@ -5,7 +5,9 @@ import "core:fmt"
Entity :: distinct u32 Entity :: distinct u32
Storage :: struct($T: typeid) { 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 // 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 // initializes new component of type and add to Storage
add_fresh_component :: proc(entity: Entity, storage: ^Storage($T)) { 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 // creates a copy of component type with data and add to Storage
add_component_with_data :: proc(entity: Entity, storage: ^Storage($T), component: T) { 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 // get components saved in Storage
// returns storage.data // returns storage.data
slice :: proc(storage: ^Storage($T)) -> map[Entity]T { slice :: proc(storage: ^Storage($T)) -> [dynamic]T {
return storage.data return storage.dense
}
slice_entity :: proc(storage: ^Storage($T)) -> [dynamic]Entity {
return storage.entities
} }
// get component saved in Storage // get component saved in Storage
// returns Entity and component of type // returns Entity and component of type
single :: proc(storage: ^Storage($T)) -> (Entity, ^T) { single :: proc(storage: ^Storage($T)) -> (^T, Entity) {
for i, &v in slice(storage) { return &storage.dense[0], storage.entities[0]
return i, &v
}
return 0, nil
} }
// get component of type from entity // get component of type from entity
get_component :: proc(entity: Entity, storage: ^Storage($T)) -> ^T { get_component :: proc(entity: Entity, storage: ^Storage($T)) -> ^T {
if _, exists := storage.data[entity]; exists { return &storage.dense[storage.sparse[entity]]
return &storage.data[entity]
}
return new(T)
} }
+4 -2
View File
@@ -17,8 +17,10 @@ DefaultPlugin :: proc(app: ^App) {
@(private) @(private)
draw_sprite :: proc() { draw_sprite :: proc() {
for i, &v in slice(&Sprite) { components := slice(&Sprite)
sprite_transform := get_component(i, &Transform) entities := slice_entity(&Sprite)
for &v, i in components {
sprite_transform := get_component(entities[i], &Transform)
rl.DrawTexture( rl.DrawTexture(
v.texture, v.texture,
i32(sprite_transform.translation.x), i32(sprite_transform.translation.x),