}
}
-wall_create :: (scene: ^Entity_Manager, pos, size: Vector2) -> ^Entity {
+wall_create :: (scene: ^Scene, pos, size: Vector2) -> ^Entity {
this := scene->make();
this.pos = pos;
this.size = size;
}
}
-door_create :: (scene: ^Entity_Manager, pos, size: Vector2) -> ^Entity {
+door_create :: (scene: ^Scene, pos, size: Vector2) -> ^Entity {
this := scene->make();
this.pos = pos;
this.size = size;
+++ /dev/null
-
-use package core
-use package glfw3
-
-Entity_Nothing :: cast(Entity_ID) 0
-Entity_ID :: #distinct u32
-#match hash.to_u32 macro (e: Entity_ID) => (package core.hash).to_u32(cast(u32) e);
-#operator == (a, b: Entity_ID) => cast(u32) a == cast(u32) b;
-#operator != (a, b: Entity_ID) => cast(u32) a != cast(u32) b;
-
-#init #after conv.custom_formatters_initialized () {
- conv.register_custom_parser((e: ^Entity_ID, line: str, _: Allocator) => {
- *e = ~~ cast(u32) conv.str_to_i64(line);
- return true;
- });
-}
-
-#local Component_Vtable :: struct {
- //
- // 'init' is called when the component is first created, before it
- // has been added to any entity.
- init : (rawptr) -> void = null_proc;
-
- //
- // 'added' is called when the component is added to an entity.
- // In theory, it could be called multiple times, if the component
- // is shared between multiple entities.
- added : (rawptr, ^Entity) -> void = null_proc;
-
- //
- // 'update' is called every update cycle. Currently, there is no
- // specified as to the order in which components get updated.
- // I think by circumstance, it is the order that you add them
- // to the entity, but could break in the future.
- update : (rawptr, ^Entity, f32) -> void = null_proc;
-
- //
- // 'post_render' is called after the entity has been rendered
- // normally. Entities must have a 'RenderComponent' in order
- // to have 'post_render' called on their components. This
- // can be used to add overlays or popups to an entity.
- post_render: (rawptr, ^Entity) -> void = null_proc;
-}
-
-Component :: struct {
- #tag Editor_Hidden, Entity_Store.Skip
- use vtable: ^Component_Vtable;
-
- #tag Editor_Hidden, Entity_Store.Skip
- type: type_expr;
-}
-
-IsComponent :: interface (c: $C) {
- { c } -> ^Component;
-}
-
-RenderComponent :: struct {
- use base: Component;
-
- #tag Editor_Hidden, Entity_Store.Skip
- func : (e: ^Entity) -> void;
-
- layer := 0;
- color := Color.{1, 1, 1};
-}
-
-SizeComponent :: struct {
- use base: Component;
- func : (e: ^Entity) -> Rect;
-
- #struct_tag Entity_Store.Skip
-}
-
-InteractableComponent :: struct {
- use base: Component;
- interact: (e: ^Entity, interactor: ^Entity) -> void;
-
- #struct_tag Entity_Store.Skip
-}
-
-Entity :: struct {
- id: Entity_ID;
- flags: Entity_Flags;
-
- #tag Entity_Store.Skip
- schematic: type_expr;
-
- pos: Vector2;
-
- // Does every entity need to have a size?
- size: Vector2;
- get_rect :: (use e: ^Entity) => {
- if e->has(SizeComponent) do return (e->get(SizeComponent)).func(e);
-
- return Rect.{ pos.x - size.x / 2, pos.y - size.y / 2, size.x, size.y };
- };
-
- #tag Entity_Store.Skip, Editor_Hidden
- components: Map(type_expr, ^Component);
-
- has :: (use this: ^Entity, component_type: type_expr) => components->has(component_type);
- get :: (use this: ^Entity, $component_type: type_expr) => cast(^component_type) components[component_type];
- add :: (use this: ^Entity, component: ^Component) => {
- if components->has(component.type) do return;
- components[component.type] = component;
- if component.added != null_proc {
- component->added(this);
- }
- }
-}
-
-
-Entity_Flags :: enum #flags {
- // These have defined values for stable serialization.
- Interactable :: 0x01;
- Solid :: 0x02;
- Carryable :: 0x04;
- Dead :: 0x80000000;
-}
-
-Entity_Schematic :: struct {
- create: (^Entity_Manager) -> ^Entity;
- type := void; // This will be filled out at runtime.
-}
-
-Entity_Manager :: struct {
- entity_allocator: Allocator;
-
- // Hmmm... Do they need to be stored in both ways?
- entities: [..] ^Entity;
- entity_map: Map(Entity_ID, ^Entity);
-
- schematics: Map(str, ^Entity_Schematic);
- component_vtables: Map(type_expr, ^Component_Vtable);
-
- next_entity_id: Entity_ID;
-
- add :: entity_manager_add;
- make :: entity_manager_make;
- update :: entity_manager_update;
- draw :: entity_manager_draw;
- get :: entity_manager_get;
- delete :: entity_manager_delete;
- query :: entity_manager_query;
- query_by_flags :: entity_manager_query_by_flags;
-
- count_by_component :: entity_manager_count_by_component;
-
- query_by_component :: entity_manager_query_by_component;
- create_component :: entity_manager_create_component;
- create_and_add :: entity_manager_create_and_add;
-
- create_from_schematic :: entity_manager_create_from_schematic;
-
- load_from_file :: entity_manager_load_from_file;
- save_to_file :: entity_manager_save_to_file;
-}
-
-entity_manager_create :: () -> Entity_Manager {
- em: Entity_Manager;
- em.entity_allocator = context.allocator; @TODO // Replace the allocator here.
-
- array.init(^em.entities, 4);
-
- // Entity ID 0 is reserved as a "empty / null" entity
- em.next_entity_id = 1;
-
- entity_manager_load_schematics(^em);
- return em;
-}
-
-#local entity_manager_load_schematics :: (use this: ^Entity_Manager) {
- use type_info;
-
- index := 0;
- for type_table {
- defer index += 1;
- if it.kind != .Struct do continue;
-
- s_info := cast(^Type_Info_Struct) it;
- for^ s_info.tags {
- if it.type == Entity_Schematic {
- schematic := cast(^Entity_Schematic) it.data;
-
- // This is (mostly) safe to do as this data is in static memory
- // and is not shared with any other type info.
- schematic.type = cast(type_expr) index;
-
- // This is safe to use as the key, as a struct's name exists in static memory.
- schematics[s_info.name] = schematic;
-
- debug_log(.Debug, "Discovered schematic: '{}'", s_info.name);
- continue continue;
- }
- }
-
- if struct_inherits(~~ index, Component) {
- debug_log(.Debug, "Discovered component: '{}'", s_info.name);
-
- comp_type := cast(type_expr) index;
- if !component_vtables->has(comp_type) {
- vtable := new(Component_Vtable, allocator=entity_allocator);
- type_info.populate_struct_vtable(vtable, comp_type, safe=false);
- component_vtables[comp_type] = vtable;
- }
- }
- }
-}
-
-entity_manager_add :: (use this: ^Entity_Manager, entity: ^Entity) -> Entity_ID {
- // Automatically assign an id if the entity does not have one.
- // This will not be used when loading the entity from a file.
- if entity.id == 0 {
- entity.id = next_entity_id;
- next_entity_id = ~~(cast(u32) next_entity_id + 1);
- } else {
- next_entity_id = ~~(math.max(cast(u32) next_entity_id, cast(u32) entity.id) + 1);
- }
-
- entities << entity;
- entity_map[entity.id] = entity;
- return entity.id;
-}
-
-entity_manager_make :: (use this: ^Entity_Manager) -> ^Entity {
- entity := new(Entity, allocator=entity_allocator);
- map.init(^entity.components);
- return entity;
-}
-
-entity_manager_create_from_schematic :: (use this: ^Entity_Manager, schematic_name: str) -> ^Entity {
- schematic := schematics[schematic_name];
- if schematic == null do return null;
-
- entity := schematic.create(this);
- entity.schematic = schematic.type;
- return entity;
-}
-
-entity_manager_create_component :: (use this: ^Entity_Manager, component_type: type_expr) -> ^Component {
- comp := cast(^Component) new(component_type, allocator=entity_allocator);
- comp.type = component_type;
-
- if !component_vtables->has(comp.type) {
- vtable := new(Component_Vtable, allocator=entity_allocator);
- type_info.populate_struct_vtable(vtable, component_type, safe=false);
- component_vtables[comp.type] = vtable;
- }
-
- comp.vtable = component_vtables->get(comp.type);
- if comp.init != null_proc {
- comp->init();
- }
-
- return comp;
-}
-
-entity_manager_create_and_add :: macro (this: ^Entity_Manager, entity: ^Entity, $component_type: type_expr, init_block: Code) where IsComponent(^component_type) {
- use package core.intrinsics.onyx {__initialize}
-
- comp := cast(^component_type) this->create_component(component_type);
-
- // The 'create_component' function does not initailize the component, as it is not
- // a compile time known parameter and therefore cannot know how to initialize it.
- // This 'create_and_add' function is more often used by the programmer, so initializing
- // the component here before returning is a good idea.
- __initialize(comp);
-
- #insert init_block;
- entity->add(comp);
-}
-
-entity_manager_update :: (use this: ^Entity_Manager, dt: f32) {
- for entities {
- for^ entry: it.components.entries {
- comp := entry.value;
- if comp.update != null_proc {
- comp->update(it, dt);
- }
- }
- }
-
- while i := 0; i < entities.count {
- defer i += 1;
-
- if entities[i].flags & .Dead {
- this->delete(entities[i]);
- i -= 1;
- }
- }
-}
-
-entity_manager_draw :: (use this: ^Entity_Manager) {
-
- //
- // This is a rather expensive check.
- // It could probably be done solely when entities are added/removed.
- array.sort(entities, (e1, e2) => {
- e1_comp := e1->get(RenderComponent);
- e2_comp := e2->get(RenderComponent);
-
- e1_layer := e1_comp.layer if e1_comp != null else 0;
- e2_layer := e2_comp.layer if e2_comp != null else 0;
-
- return e1_layer - e2_layer;
- });
-
- for entities {
- render_comp := it->get(RenderComponent);
- if render_comp != null {
- immediate_set_color(render_comp.color);
- render_comp.func(it);
-
- for^ entry: it.components.entries {
- comp := entry.value;
- if comp.post_render != null_proc {
- comp->post_render(it);
- }
- }
- }
- }
-}
-
-entity_manager_get :: (use this: ^Entity_Manager, id: Entity_ID) => entity_map[id];
-
-entity_manager_delete :: (use this: ^Entity_Manager, ent: ^Entity, delete_from_array := true) {
- map.delete(^entity_map, ent.id);
-
- //
- // Not deleting the entity from the array, because this messes with the
- // order, and becaues of that, it breaks a for-loop.
- if delete_from_array do array.remove(^entities, ent); // This preserves the order of the entities, but does that matter?
-
- // This assuems that components cannot and will not be shared between entities.
- for^ ent.components.entries {
- if it.value != null {
- raw_free(entity_allocator, it.value);
- }
- }
-
- map.free(^ent.components);
- raw_free(entity_allocator, ent);
-}
-
-entity_manager_count_by_component :: (use this: ^Entity_Manager, comp_type: type_expr) -> u32 {
- count := 0;
- for entities {
- if it->has(comp_type) {
- count += 1;
- }
- }
-
- return count;
-}
-
-entity_manager_query :: (use this: ^Entity_Manager, area: Rect) -> [] ^Entity {
- ents: [..] ^Entity;
- for entities {
- if Rect.intersects(Entity.get_rect(it), area) {
- ents << it;
- }
- }
-
- return ents;
-}
-
-entity_manager_query_by_component :: (use this: ^Entity_Manager, area: Rect, comp_type: type_expr) -> [] ^Entity {
- ents: [..] ^Entity;
- for entities {
- if !it.components->has(comp_type) do continue;
-
- if Rect.intersects(Entity.get_rect(it), area) {
- ents << it;
- }
- }
-
- return ents;
-}
-
-entity_manager_query_by_flags :: (use this: ^Entity_Manager, area: Rect, flags: Entity_Flags) -> [] ^Entity {
- ents: [..] ^Entity;
-
- // Currently, enum #flags are not the greatest and & doesn't do what you want it to here.
- expected_flags := cast(u32) flags;
-
- for entities {
- if ~~ it.flags & expected_flags != expected_flags do continue;
-
- if Rect.intersects(Entity.get_rect(it), area) {
- ents << it;
- }
- }
-
- return ents;
-}
-
-
-
-
-
-@Relocate
-Sprite :: struct {
- sheet: str;
- pos: Vector2;
- size: Vector2;
- color: Color;
-
- render :: (use this: ^Sprite, r: Rect) {
- texture, valid := texture_lookup(sheet);
-
- immediate_set_color(color);
- if !valid {
- immediate_rectangle(r.x, r.y, r.w, r.h);
- } else {
- immediate_subimage(^texture, r.x, r.y, r.w, r.h, pos.x, pos.y, size.x, size.y);
- }
- }
-}
--- /dev/null
+
+use package core
+use package glfw3
+
+Entity_Nothing :: cast(Entity_ID) 0
+Entity_ID :: #distinct u32
+#match hash.to_u32 macro (e: Entity_ID) => (package core.hash).to_u32(cast(u32) e);
+#operator == (a, b: Entity_ID) => cast(u32) a == cast(u32) b;
+#operator != (a, b: Entity_ID) => cast(u32) a != cast(u32) b;
+
+#init #after conv.custom_formatters_initialized () {
+ conv.register_custom_parser((e: ^Entity_ID, line: str, _: Allocator) => {
+ *e = ~~ cast(u32) conv.str_to_i64(line);
+ return true;
+ });
+}
+
+#local Component_Vtable :: struct {
+ //
+ // 'init' is called when the component is first created, before it
+ // has been added to any entity.
+ init : (rawptr) -> void = null_proc;
+
+ //
+ // 'added' is called when the component is added to an entity.
+ // In theory, it could be called multiple times, if the component
+ // is shared between multiple entities.
+ added : (rawptr, ^Entity) -> void = null_proc;
+
+ //
+ // 'update' is called every update cycle. Currently, there is no
+ // specified as to the order in which components get updated.
+ // I think by circumstance, it is the order that you add them
+ // to the entity, but could break in the future.
+ update : (rawptr, ^Entity, f32) -> void = null_proc;
+
+ //
+ // 'post_render' is called after the entity has been rendered
+ // normally. Entities must have a 'RenderComponent' in order
+ // to have 'post_render' called on their components. This
+ // can be used to add overlays or popups to an entity.
+ post_render: (rawptr, ^Entity) -> void = null_proc;
+}
+
+Component :: struct {
+ #tag Editor_Hidden, Entity_Store.Skip
+ use vtable: ^Component_Vtable;
+
+ #tag Editor_Hidden, Entity_Store.Skip
+ type: type_expr;
+}
+
+IsComponent :: interface (c: $C) {
+ { c } -> ^Component;
+}
+
+RenderComponent :: struct {
+ use base: Component;
+
+ #tag Editor_Hidden, Entity_Store.Skip
+ func : (e: ^Entity) -> void;
+
+ layer := 0;
+ color := Color.{1, 1, 1};
+}
+
+SizeComponent :: struct {
+ use base: Component;
+ func : (e: ^Entity) -> Rect;
+
+ #struct_tag Entity_Store.Skip
+}
+
+InteractableComponent :: struct {
+ use base: Component;
+ interact: (e: ^Entity, interactor: ^Entity) -> void;
+
+ #struct_tag Entity_Store.Skip
+}
+
+Entity :: struct {
+ id: Entity_ID;
+ flags: Entity_Flags;
+
+ #tag Entity_Store.Skip
+ schematic: type_expr;
+
+ pos: Vector2;
+
+ // Does every entity need to have a size?
+ size: Vector2;
+ get_rect :: (use e: ^Entity) => {
+ if e->has(SizeComponent) do return (e->get(SizeComponent)).func(e);
+
+ return Rect.{ pos.x - size.x / 2, pos.y - size.y / 2, size.x, size.y };
+ };
+
+ #tag Entity_Store.Skip, Editor_Hidden
+ components: Map(type_expr, ^Component);
+
+ has :: (use this: ^Entity, component_type: type_expr) => components->has(component_type);
+ get :: (use this: ^Entity, $component_type: type_expr) => cast(^component_type) components[component_type];
+ add :: (use this: ^Entity, component: ^Component) => {
+ if components->has(component.type) do return;
+ components[component.type] = component;
+ if component.added != null_proc {
+ component->added(this);
+ }
+ }
+}
+
+
+Entity_Flags :: enum #flags {
+ // These have defined values for stable serialization.
+ Interactable :: 0x01;
+ Solid :: 0x02;
+ Carryable :: 0x04;
+ Dead :: 0x80000000;
+}
+
+Entity_Schematic :: struct {
+ create: (^Scene) -> ^Entity;
+ type := void; // This will be filled out at runtime.
+}
+
+Scene :: struct {
+ entity_allocator: Allocator;
+
+ // Hmmm... Do they need to be stored in both ways?
+ entities: [..] ^Entity;
+ entity_map: Map(Entity_ID, ^Entity);
+
+ schematics: Map(str, ^Entity_Schematic);
+ component_vtables: Map(type_expr, ^Component_Vtable);
+
+ next_entity_id: Entity_ID;
+
+ add :: scene_add;
+ make :: scene_make;
+ update :: scene_update;
+ draw :: scene_draw;
+ get :: scene_get;
+ delete :: scene_delete;
+ query :: scene_query;
+ query_by_flags :: scene_query_by_flags;
+
+ count_by_component :: scene_count_by_component;
+
+ query_by_component :: scene_query_by_component;
+ create_component :: scene_create_component;
+ create_and_add :: scene_create_and_add;
+
+ create_from_schematic :: scene_create_from_schematic;
+
+ load_from_file :: scene_load_from_file;
+ save_to_file :: scene_save_to_file;
+}
+
+scene_create :: () -> Scene {
+ em: Scene;
+ em.entity_allocator = context.allocator; @TODO // Replace the allocator here.
+
+ array.init(^em.entities, 4);
+
+ // Entity ID 0 is reserved as a "empty / null" entity
+ em.next_entity_id = 1;
+
+ scene_load_schematics(^em);
+ return em;
+}
+
+#local scene_load_schematics :: (use this: ^Scene) {
+ use type_info;
+
+ index := 0;
+ for type_table {
+ defer index += 1;
+ if it.kind != .Struct do continue;
+
+ s_info := cast(^Type_Info_Struct) it;
+ for^ s_info.tags {
+ if it.type == Entity_Schematic {
+ schematic := cast(^Entity_Schematic) it.data;
+
+ // This is (mostly) safe to do as this data is in static memory
+ // and is not shared with any other type info.
+ schematic.type = cast(type_expr) index;
+
+ // This is safe to use as the key, as a struct's name exists in static memory.
+ schematics[s_info.name] = schematic;
+
+ debug_log(.Debug, "Discovered schematic: '{}'", s_info.name);
+ continue continue;
+ }
+ }
+
+ if struct_inherits(~~ index, Component) {
+ debug_log(.Debug, "Discovered component: '{}'", s_info.name);
+
+ comp_type := cast(type_expr) index;
+ if !component_vtables->has(comp_type) {
+ vtable := new(Component_Vtable, allocator=entity_allocator);
+ type_info.populate_struct_vtable(vtable, comp_type, safe=false);
+ component_vtables[comp_type] = vtable;
+ }
+ }
+ }
+}
+
+scene_add :: (use this: ^Scene, entity: ^Entity) -> Entity_ID {
+ // Automatically assign an id if the entity does not have one.
+ // This will not be used when loading the entity from a file.
+ if entity.id == 0 {
+ entity.id = next_entity_id;
+ next_entity_id = ~~(cast(u32) next_entity_id + 1);
+ } else {
+ next_entity_id = ~~(math.max(cast(u32) next_entity_id, cast(u32) entity.id) + 1);
+ }
+
+ entities << entity;
+ entity_map[entity.id] = entity;
+ return entity.id;
+}
+
+scene_make :: (use this: ^Scene) -> ^Entity {
+ entity := new(Entity, allocator=entity_allocator);
+ map.init(^entity.components);
+ return entity;
+}
+
+scene_create_from_schematic :: (use this: ^Scene, schematic_name: str) -> ^Entity {
+ schematic := schematics[schematic_name];
+ if schematic == null do return null;
+
+ entity := schematic.create(this);
+ entity.schematic = schematic.type;
+ return entity;
+}
+
+scene_create_component :: (use this: ^Scene, component_type: type_expr) -> ^Component {
+ comp := cast(^Component) new(component_type, allocator=entity_allocator);
+ comp.type = component_type;
+
+ if !component_vtables->has(comp.type) {
+ vtable := new(Component_Vtable, allocator=entity_allocator);
+ type_info.populate_struct_vtable(vtable, component_type, safe=false);
+ component_vtables[comp.type] = vtable;
+ }
+
+ comp.vtable = component_vtables->get(comp.type);
+ if comp.init != null_proc {
+ comp->init();
+ }
+
+ return comp;
+}
+
+scene_create_and_add :: macro (this: ^Scene, entity: ^Entity, $component_type: type_expr, init_block: Code) where IsComponent(^component_type) {
+ use package core.intrinsics.onyx {__initialize}
+
+ comp := cast(^component_type) this->create_component(component_type);
+
+ // The 'create_component' function does not initailize the component, as it is not
+ // a compile time known parameter and therefore cannot know how to initialize it.
+ // This 'create_and_add' function is more often used by the programmer, so initializing
+ // the component here before returning is a good idea.
+ __initialize(comp);
+
+ #insert init_block;
+ entity->add(comp);
+}
+
+scene_update :: (use this: ^Scene, dt: f32) {
+ for entities {
+ for^ entry: it.components.entries {
+ comp := entry.value;
+ if comp.update != null_proc {
+ comp->update(it, dt);
+ }
+ }
+ }
+
+ while i := 0; i < entities.count {
+ defer i += 1;
+
+ if entities[i].flags & .Dead {
+ this->delete(entities[i]);
+ i -= 1;
+ }
+ }
+}
+
+scene_draw :: (use this: ^Scene) {
+
+ //
+ // This is a rather expensive check.
+ // It could probably be done solely when entities are added/removed.
+ array.sort(entities, (e1, e2) => {
+ e1_comp := e1->get(RenderComponent);
+ e2_comp := e2->get(RenderComponent);
+
+ e1_layer := e1_comp.layer if e1_comp != null else 0;
+ e2_layer := e2_comp.layer if e2_comp != null else 0;
+
+ return e1_layer - e2_layer;
+ });
+
+ for entities {
+ render_comp := it->get(RenderComponent);
+ if render_comp != null {
+ immediate_set_color(render_comp.color);
+ render_comp.func(it);
+
+ for^ entry: it.components.entries {
+ comp := entry.value;
+ if comp.post_render != null_proc {
+ comp->post_render(it);
+ }
+ }
+ }
+ }
+}
+
+scene_get :: (use this: ^Scene, id: Entity_ID) => entity_map[id];
+
+scene_delete :: (use this: ^Scene, ent: ^Entity, delete_from_array := true) {
+ map.delete(^entity_map, ent.id);
+
+ //
+ // Not deleting the entity from the array, because this messes with the
+ // order, and becaues of that, it breaks a for-loop.
+ if delete_from_array do array.remove(^entities, ent); // This preserves the order of the entities, but does that matter?
+
+ // This assuems that components cannot and will not be shared between entities.
+ for^ ent.components.entries {
+ if it.value != null {
+ raw_free(entity_allocator, it.value);
+ }
+ }
+
+ map.free(^ent.components);
+ raw_free(entity_allocator, ent);
+}
+
+scene_count_by_component :: (use this: ^Scene, comp_type: type_expr) -> u32 {
+ count := 0;
+ for entities {
+ if it->has(comp_type) {
+ count += 1;
+ }
+ }
+
+ return count;
+}
+
+scene_query :: (use this: ^Scene, area: Rect) -> [] ^Entity {
+ ents: [..] ^Entity;
+ for entities {
+ if Rect.intersects(Entity.get_rect(it), area) {
+ ents << it;
+ }
+ }
+
+ return ents;
+}
+
+scene_query_by_component :: (use this: ^Scene, area: Rect, comp_type: type_expr) -> [] ^Entity {
+ ents: [..] ^Entity;
+ for entities {
+ if !it.components->has(comp_type) do continue;
+
+ if Rect.intersects(Entity.get_rect(it), area) {
+ ents << it;
+ }
+ }
+
+ return ents;
+}
+
+scene_query_by_flags :: (use this: ^Scene, area: Rect, flags: Entity_Flags) -> [] ^Entity {
+ ents: [..] ^Entity;
+
+ // Currently, enum #flags are not the greatest and & doesn't do what you want it to here.
+ expected_flags := cast(u32) flags;
+
+ for entities {
+ if ~~ it.flags & expected_flags != expected_flags do continue;
+
+ if Rect.intersects(Entity.get_rect(it), area) {
+ ents << it;
+ }
+ }
+
+ return ents;
+}
+
+
+
+
+
+@Relocate
+Sprite :: struct {
+ sheet: str;
+ pos: Vector2;
+ size: Vector2;
+ color: Color;
+
+ render :: (use this: ^Sprite, r: Rect) {
+ texture, valid := texture_lookup(sheet);
+
+ immediate_set_color(color);
+ if !valid {
+ immediate_rectangle(r.x, r.y, r.w, r.h);
+ } else {
+ immediate_subimage(^texture, r.x, r.y, r.w, r.h, pos.x, pos.y, size.x, size.y);
+ }
+ }
+}
(scene) => Furniture.create(scene, .{0, 0})
}
- create :: (scene: ^Entity_Manager, pos: Vector2) -> ^Entity {
+ create :: (scene: ^Scene, pos: Vector2) -> ^Entity {
this := scene->make();
this.pos = pos;
this.size = .{16, 16};
(scene) => Patron.create(scene, .{0,0})
}
- create :: (scene: ^Entity_Manager, pos: Vector2) -> ^Entity {
+ create :: (scene: ^Scene, pos: Vector2) -> ^Entity {
this := scene->make();
this.pos = pos;
this.size = .{32, 32};
Player :: struct {
#struct_tag Entity_Schematic.{
- (scene: ^Entity_Manager) => Player.create(scene, .{0,0})
+ (scene: ^Scene) => Player.create(scene, .{0,0})
}
- create :: (scene: ^Entity_Manager, pos: Vector2, controls := player_1_controls) -> ^Entity {
+ create :: (scene: ^Scene, pos: Vector2, controls := player_1_controls) -> ^Entity {
this := scene->make();
this.pos = pos;
this.size = .{32, 32};
(scene) => Tap.create(scene, .{0,0}, .{0,0})
}
- create :: (scene: ^Entity_Manager, pos: Vector2, size: Vector2) -> ^Entity {
+ create :: (scene: ^Scene, pos: Vector2, size: Vector2) -> ^Entity {
this := scene->make();
this.pos = pos;
this.size = size;
Skip;
}
-entity_manager_save_to_file :: (use this: ^Entity_Manager, filename: str) {
+scene_save_to_file :: (use this: ^Scene, filename: str) {
err, output_file := os.open(filename, .Write);
defer os.close(^output_file);
writer_ := io.writer_make(^output_file);
}
}
-entity_manager_load_from_file :: (use this: ^Entity_Manager, filename: str) {
+scene_load_from_file :: (use this: ^Scene, filename: str) {
err, input_file := os.open(filename, .Read);
if err != .None {
debug_log(.Error, "Failed to open file: {}", filename);
// Game Global Variables
//
-scene: Entity_Manager;
+scene: Scene;
item_store: Item_Store;
scene_render_offset: Vector2;
load_assets();
- scene = entity_manager_create();
+ scene = scene_create();
scene->load_from_file(quick_save_file);
item_store = item_store_make();