use package core
use package glfw3
-Entity_Vtable :: struct {
+Entity_Handles :: struct {
update : (entity: ^Entity, dt: f32) -> void = null_proc;
draw : (entity: ^Entity) -> void = null_proc;
}
Entity :: struct {
- use vtable: ^Entity_Vtable;
-
id: u32;
type: type_expr;
}
IsEntity :: interface (e: $E) {
- { e } -> ^Entity;
+ { e } -> ^Entity;
+ { e.handles } -> Entity_Handles;
}
Entity_Manager :: struct {
// The allocator for these entity pointers is assumed to be the
// context allocator.
entities: [..] ^Entity;
+ entity_types: Map(type_expr, Entity_Handles);
next_entity_id: u32;
- update :: entity_manager_update;
register :: entity_manager_register;
+ add :: entity_manager_add;
+ update :: entity_manager_update;
draw :: entity_manager_draw;
}
em: Entity_Manager;
array.init(^em.entities, 4);
+ map.init(^em.entity_types);
// Entity ID 0 is reserved as a "empty / null" entity
em.next_entity_id = 1;
return em;
}
-entity_manager_register :: (use this: ^Entity_Manager, entity: ^$T) -> u32 where IsEntity(^T) {
+entity_manager_register :: (use this: ^Entity_Manager, $entity_type: type_expr) where IsEntity(^entity_type) {
+ if !entity_types->has(entity_type) {
+ entity_types[entity_type] = entity_type.handles;
+ }
+}
+
+entity_manager_add :: (use this: ^Entity_Manager, entity: ^$T) -> u32 where IsEntity(^T) {
+ this->register(T);
+
entity.type = T;
entity.id = next_entity_id;
next_entity_id += 1;
entity_manager_update :: (use this: ^Entity_Manager, dt: f32) {
for entities {
- if it.vtable == null do continue;
+ vtable := ^entity_types[it.type];
+ if vtable == null do continue;
- if it.update != null_proc {
- it->update(dt);
- }
+ vtable.update(it, dt);
}
}
entity_manager_draw :: (use this: ^Entity_Manager) {
// Entities should be sorted by z-order.
for entities {
- if it.vtable == null do continue;
+ vtable := ^entity_types[it.type];
+ if vtable == null do continue;
- if it.draw != null_proc {
- it->draw();
- }
+ vtable.draw(it);
}
}
use package glfw3
Player :: struct {
- use entity: Entity;
-}
+ handles :: Entity_Handles.{ update, draw }
-player_make :: () -> ^Player {
- player := new(Player);
- player.vtable = ^player_vtable;
-
- player.pos = .{0,0};
- return player;
-}
-
-player_update :: (use this: ^Player, dt: f32) {
- if is_key_down(GLFW_KEY_W) do pos.y -= 200 * dt;
- if is_key_down(GLFW_KEY_S) do pos.y += 200 * dt;
- if is_key_down(GLFW_KEY_A) do pos.x -= 200 * dt;
- if is_key_down(GLFW_KEY_D) do pos.x += 200 * dt;
-}
+ use entity: Entity;
-player_draw :: (use this: ^Player) {
- immediate_set_color(.{1,1,1});
- immediate_image(^player_texture, pos.x, pos.y, 64, 64);
+ make :: () -> ^Player {
+ player := new(Player);
+ player.pos = .{0,0};
+ return player;
+ }
+
+ update :: (use this: ^Player, dt: f32) {
+ if is_key_down(GLFW_KEY_W) do pos.y -= 200 * dt;
+ if is_key_down(GLFW_KEY_S) do pos.y += 200 * dt;
+ if is_key_down(GLFW_KEY_A) do pos.x -= 200 * dt;
+ if is_key_down(GLFW_KEY_D) do pos.x += 200 * dt;
+ }
+
+ draw :: (use this: ^Player) {
+ immediate_set_color(.{1,1,1});
+ immediate_image(^player_texture, pos.x, pos.y, 64, 64);
+ }
}
-#local player_vtable := Entity_Vtable.{ update=player_update, draw=player_draw };
player_texture: Texture;