Fix component pool entity removal

This commit is contained in:
Hugo Mårdbrink 2025-08-26 22:01:28 +02:00
parent 77c5c23cf5
commit 6d43f30c09
5 changed files with 48 additions and 18 deletions

View file

@ -5,6 +5,7 @@ import "core:log"
ComponentManager :: struct {
component_types: map[typeid]ComponentType,
component_pools: map[typeid]^ComponentPool(any),
destroy_procs: map[typeid]proc(pool: ^ComponentPool(any), entity_id: EntityID),
next_component_type: ComponentType,
}
@ -25,6 +26,15 @@ component_manager_register_component :: proc($T: typeid, component_manager: ^Com
component_pool := new(ComponentPool(T), context.allocator)
component_pool^ = component_pool_create(T)
component_manager.component_pools[T] = cast(^ComponentPool(any))component_pool
component_manager.destroy_procs[T] = proc(component_pool: ^ComponentPool(any), id: EntityID) {
typed_component_pool := cast(^ComponentPool(T))component_pool
if id in typed_component_pool.entity_to_index {
component_pool_remove_data(typed_component_pool, id)
}
}
component_manager.next_component_type += 1
}
@ -35,22 +45,22 @@ component_manager_get_component_type :: proc($T: typeid, component_manager: ^Com
component_manager_add_component :: proc($T: typeid, component_manager: ^ComponentManager, entity_id: EntityID, component: T) {
component_pool := cast(^ComponentPool(T))component_manager.component_pools[T]
component_pool_insert_data(T, component_pool, entity_id, component)
component_pool_insert_data(component_pool, entity_id, component)
}
component_manager_remove_component :: proc($T: typeid, component_manager: ^ComponentManager, entity_id: EntityID) {
component_pool := cast(^ComponentPool(T))component_manager.component_pools[T]
component_pool_remove_data(T, component_pool, entity_id)
component_pool_remove_data(component_pool, entity_id)
}
component_manager_get_component :: proc($T: typeid, component_manager: ^ComponentManager, entity_id: EntityID) -> ^T {
component_pool := cast(^ComponentPool(T))component_manager.component_pools[T]
return component_pool_get(T, component_pool, entity_id)
component_pool := cast(^ComponentPool(T)) component_manager.component_pools[T]
return component_pool_get(component_pool, entity_id)
}
component_manager_destroy_entity :: proc(component_manager: ^ComponentManager, entity_id: EntityID) {
for _, component_pool in component_manager.component_pools {
component_pool_destroy_entity(component_pool, entity_id)
for T, component_pool in component_manager.component_pools {
component_manager.destroy_procs[T](component_pool, entity_id)
}
}

View file

@ -2,7 +2,7 @@ package ecs
import "core:log"
ComponentPool :: struct($T: typeid) {
ComponentPool :: struct(T: typeid) {
data: []T,
entity_to_index: map[EntityID]uintptr,
index_to_entity: map[uintptr]EntityID,
@ -20,7 +20,7 @@ component_pool_create :: proc($T: typeid) -> ComponentPool(T) {
return component_pool
}
component_pool_insert_data :: proc($T: typeid, component_pool: ^ComponentPool(T), entity_id: EntityID, component: T) {
component_pool_insert_data :: proc(component_pool: ^ComponentPool($T), entity_id: EntityID, component: T) {
log.assertf(entity_id not_in component_pool.entity_to_index, "Component already added to entity")
new_idx := component_pool.size
@ -31,7 +31,7 @@ component_pool_insert_data :: proc($T: typeid, component_pool: ^ComponentPool(T)
component_pool.size += 1
}
component_pool_remove_data :: proc(component_pool: ^ComponentPool(any), entity_id: EntityID) {
component_pool_remove_data :: proc(component_pool: ^ComponentPool($T), entity_id: EntityID) {
log.assertf(entity_id in component_pool.entity_to_index, "Entity doesn't have component")
removed_entity_idx := component_pool.entity_to_index[entity_id]
@ -48,20 +48,20 @@ component_pool_remove_data :: proc(component_pool: ^ComponentPool(any), entity_i
component_pool.size -= 1
}
component_pool_get :: proc($T: typeid, component_pool: ^ComponentPool(T), entity_id: EntityID) -> ^T {
component_pool_get :: proc(component_pool: ^ComponentPool($T), entity_id: EntityID) -> ^T {
log.assertf(entity_id in component_pool.entity_to_index, "Entity doesn't have component")
idx := component_pool.entity_to_index[entity_id]
return &component_pool.data[idx]
}
component_pool_destroy_entity :: proc(component_pool: ^ComponentPool(any), entity_id: EntityID) {
component_pool_destroy_entity :: proc(component_pool: ^ComponentPool($T), entity_id: EntityID) {
if entity_id in component_pool.entity_to_index {
component_pool_remove_data(component_pool, entity_id)
}
}
component_pool_destroy :: proc(component_pool: ^ComponentPool(any)) {
component_pool_destroy :: proc(component_pool: ^ComponentPool($T)) {
delete(component_pool.entity_to_index)
delete(component_pool.index_to_entity)
delete(component_pool.data)

View file

@ -6,4 +6,4 @@ COMPONENT_MAX :: 32
ID :: u32
EntityID :: ID
ComponentType :: u8
ComponentType :: u16

View file

@ -1,10 +1,15 @@
package ecs
import "core:log"
PhysicsSystem :: struct {
using base: SystemBase,
}
physics_system_update :: proc(physics_system: ^PhysicsSystem, coordinator: ^Coordinator, dt: f32) {
entities_to_delete := make([dynamic]EntityID)
defer delete(entities_to_delete)
for entity in physics_system.entities {
rigid_body := coordinator_get_component(RigidBodyComponent, coordinator, entity)
transform := coordinator_get_component(TransformComponent, coordinator, entity)
@ -12,5 +17,13 @@ physics_system_update :: proc(physics_system: ^PhysicsSystem, coordinator: ^Coor
transform.position += rigid_body.velocity * dt
rigid_body.velocity += gravity.force * dt
if transform.position.y < -15 {
append(&entities_to_delete, entity)
}
}
for entity in entities_to_delete {
coordinator_destroy_entity(coordinator, entity)
}
}

View file

@ -218,7 +218,6 @@ render_system_update :: proc(render_system: ^RenderSystem, coordinator: ^Coordin
for entity in render_system.entities {
transform := coordinator_get_component(TransformComponent, coordinator, entity)
color := coordinator_get_component(ColorComponent, coordinator, entity)
mesh_id := coordinator_get_component(MeshComponent, coordinator, entity).mesh_id
mesh := render_system.meshes[mesh_id]
@ -226,9 +225,17 @@ render_system_update :: proc(render_system: ^RenderSystem, coordinator: ^Coordin
material_id := coordinator_get_component(MaterialComponent, coordinator, entity).material_id
material := render_system.materials[material_id]
color := coordinator_get_component(ColorComponent, coordinator, entity)
scale_mat := linalg.matrix4_scale_f32(transform.scale)
rot_mat := linalg.matrix4_from_yaw_pitch_roll_f32(
transform.rotation.y,
transform.rotation.x,
transform.rotation.z
)
pos_mat := linalg.matrix4_translate_f32(transform.position)
rot_mat := linalg.matrix4_from_yaw_pitch_roll_f32(transform.rotation.y, transform.rotation.x, transform.rotation.z)
model := pos_mat * rot_mat
model := pos_mat * rot_mat * scale_mat
mvp := proj * view * model
sg.apply_pipeline(material.pipeline)
sg.apply_bindings({
@ -240,8 +247,8 @@ render_system_update :: proc(render_system: ^RenderSystem, coordinator: ^Coordin
})
sg.apply_uniforms(shaders.UB_VsParams, sg_range(&shaders.Vsparams{
mvp = proj * view * model,
col = color.color
mvp = mvp,
col = color.color,
}))
sg.draw(0, 36, 1)