From: Brendan Hansen Date: Sat, 26 Feb 2022 21:54:20 +0000 (-0600) Subject: quick save returned; dynamically loading component methods X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=2eaf5ed784d250f1223ab9a6ad48d4126506bbda;p=bar-game.git quick save returned; dynamically loading component methods --- diff --git a/run_tree/scenes/quick_save.scene b/run_tree/scenes/quick_save.scene index 8d0cfb4..ff33349 100644 --- a/run_tree/scenes/quick_save.scene +++ b/run_tree/scenes/quick_save.scene @@ -1,57 +1,60 @@ [Wall] -id = 10 -flags = 2 -pos.x = 168.0000 -pos.y = 320.0000 -size.x = 336.0000 -size.y = 32.0000 + id = 10 + flags = 2 + pos.x = 168.0000 + pos.y = 320.0000 + size.x = 336.0000 + size.y = 32.0000 [Wall] -id = 11 -flags = 2 -pos.x = 448.0000 -pos.y = 168.0000 -size.x = 32.0000 -size.y = 336.0000 + id = 11 + flags = 2 + pos.x = 448.0000 + pos.y = 168.0000 + size.x = 32.0000 + size.y = 336.0000 [Player] -id = 12 -flags = 2 -pos.x = 200.0000 -pos.y = 152.0000 -size.x = 48.0000 -size.y = 48.0000 -:PlayerComponent -holding = 0 -controls.up = 87 -controls.down = 83 -controls.left = 65 -controls.right = 68 -controls.interact = 70 -controls.pick_up = 71 -color.r = 1.0000 -color.g = 1.0000 -color.b = 1.0000 -color.a = 1.0000 -facing = 4 + id = 12 + flags = 2 + pos.x = 200.0000 + pos.y = 152.0000 + size.x = 48.0000 + size.y = 48.0000 + + :PlayerComponent + holding = 0 + controls.up = 87 + controls.down = 83 + controls.left = 65 + controls.right = 68 + controls.interact = 70 + controls.pick_up = 71 + color.r = 1.0000 + color.g = 1.0000 + color.b = 1.0000 + color.a = 1.0000 + facing = 4 [Door] -id = 13 -flags = 3 -pos.x = 352.0000 -pos.y = 320.0000 -size.x = 160.0000 -size.y = 32.0000 -:DoorComponent -target_openness = 0.0000 + id = 13 + flags = 3 + pos.x = 352.0000 + pos.y = 320.0000 + size.x = 160.0000 + size.y = 32.0000 + + :DoorComponent + target_openness = 0.0000 [Item_Entity] -id = 14 -flags = 4 -pos.x = 272.0000 -pos.y = 144.0000 -size.x = 32.0000 -size.y = 32.0000 -:ItemComponent -item = "beer" + id = 14 + flags = 4 + pos.x = 272.0000 + pos.y = 144.0000 + size.x = 32.0000 + size.y = 32.0000 + + :ItemComponent + item = "beer" diff --git a/run_tree/scenes/quick_save_new.scene b/run_tree/scenes/quick_save_new.scene new file mode 100644 index 0000000..bc595c2 --- /dev/null +++ b/run_tree/scenes/quick_save_new.scene @@ -0,0 +1,59 @@ +[Wall] +id = 10 +flags = 2 +pos.x = 168.0000 +pos.y = 320.0000 +size.x = 336.0000 +size.y = 32.0000 + +[Wall] +id = 11 +flags = 2 +pos.x = 448.0000 +pos.y = 168.0000 +size.x = 32.0000 +size.y = 336.0000 + +[Player] +id = 12 +flags = 2 +pos.x = 342.9302 +pos.y = 205.3930 +size.x = 48.0000 +size.y = 48.0000 +:PlayerComponent +color.r = 1.0000 +color.g = 1.0000 +color.b = 1.0000 +color.a = 1.0000 +holding = 0 +controls.up = 87 +controls.down = 83 +controls.left = 65 +controls.right = 68 +controls.interact = 70 +controls.pick_up = 71 +facing = 4 + +[Door] +id = 13 +flags = 3 +pos.x = 352.0000 +pos.y = 320.0000 +size.x = 160.0000 +size.y = 32.0000 +:DoorComponent +max_openness = 0.8000 +target_openness = 0.0000 +openness = 0.0000 + +[Item_Entity] +id = 14 +flags = 4 +pos.x = 386.9302 +pos.y = 205.3930 +size.x = 32.0000 +size.y = 32.0000 +:ItemComponent +item = "beer" + diff --git a/src/entity/manager.onyx b/src/entity/manager.onyx index 4448519..1f0dd33 100644 --- a/src/entity/manager.onyx +++ b/src/entity/manager.onyx @@ -15,30 +15,31 @@ Entity_ID :: #distinct u32 }); } +#local Component_Vtable :: struct { + init : (^Component) -> void = null_proc; + update: (^Component, ^Entity, f32) -> void = null_proc; +} + Component :: struct { - type: type_expr; + [Entity_Store.Skip] use vtable: ^Component_Vtable; + [Entity_Store.Skip] type: type_expr; } IsComponent :: interface (c: $C) { { c } -> ^Component; } -UpdateComponent :: struct { - use base: Component; - func : (e: ^Entity, dt: f32) -> void; -} - RenderComponent :: struct { use base: Component; func : (e: ^Entity) -> void; } -SizeComponent :: struct { +SizeComponent :: struct [Entity_Store.Skip] { use base: Component; func : (e: ^Entity) -> Rect; } -InteractableComponent :: struct { +InteractableComponent :: struct [Entity_Store.Skip] { use base: Component; interact: (e: ^Entity, interactor: ^Entity) -> void; } @@ -46,7 +47,8 @@ InteractableComponent :: struct { Entity :: struct { id: Entity_ID; flags: Entity_Flags; - schematic: type_expr; + + [Entity_Store.Skip] schematic: type_expr; pos: Vector2; @@ -56,8 +58,9 @@ Entity :: struct { 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 }; - } + }; + [Entity_Store.Skip] 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]; @@ -87,6 +90,7 @@ Entity_Manager :: struct { entity_map: Map(Entity_ID, ^Entity); schematics: Map(str, ^Entity_Schematic); + component_vtables: Map(type_expr, ^Component_Vtable); next_entity_id: Entity_ID; @@ -181,12 +185,20 @@ entity_manager_create_from_schematic :: (use this: ^Entity_Manager, schematic_na entity_manager_create_component :: (use this: ^Entity_Manager, $component_type: type_expr) -> ^component_type where IsComponent(^component_type) { comp := 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); + return comp; } entity_manager_create_and_add :: macro (this: ^Entity_Manager, entity: ^Entity, $component_type: type_expr, init_block: Code) where IsComponent(^component_type) { - comp := new(component_type, allocator=this.entity_allocator); - comp.type = component_type; + comp := this->create_component(component_type); #insert init_block; entity->add(comp); @@ -194,9 +206,13 @@ entity_manager_create_and_add :: macro (this: ^Entity_Manager, entity: ^Entity, entity_manager_update :: (use this: ^Entity_Manager, dt: f32) { for entities { - update_comp := it->get(UpdateComponent); - if update_comp != null { - update_comp.func(it, dt); + for^ entry: it.components.entries { + comp := entry.value; + + @CompilerBug // comp->update(it, dt); should be legal here, but it says 'update' is not a member of '^Component'. + if comp.vtable.update != null_proc { + comp.vtable.update(comp, it, dt); + } } } } diff --git a/src/entity/player.onyx b/src/entity/player.onyx index 64f74f2..873bb4e 100644 --- a/src/entity/player.onyx +++ b/src/entity/player.onyx @@ -61,10 +61,6 @@ player_create :: (scene: ^Entity_Manager, pos: Vector2, controls := player_1_con comp.color = .{1,1,1}; } - scene->create_and_add(this, UpdateComponent) { - comp.func = PlayerComponent.update; - } - scene->create_and_add(this, RenderComponent) { comp.func = PlayerComponent.render; } @@ -80,11 +76,9 @@ PlayerComponent :: struct { controls : Player_Controls; facing := Facing.Up; - update :: (use this: ^Entity, dt: f32) { + update :: (player: ^PlayerComponent, use this: ^Entity, dt: f32) { speed :: 128.0f; - player := this->get(PlayerComponent); - delta: Vector2; if is_key_down(player.controls.left) { delta.x -= speed * dt; player.facing = .Left; } if is_key_down(player.controls.right) { delta.x += speed * dt; player.facing = .Right; } @@ -219,11 +213,6 @@ player_assets: struct { #local Door :: struct [Entity_Schematic.{create}] { create :: (scene) => door_create(scene, .{0, 0}, .{0, 0}); - update :: (use this: ^Entity, dt: f32) { - door := this->get(DoorComponent); - door->update(dt); - } - render :: (use this: ^Entity) { immediate_set_color(.{0.7, 0.7, 0.1}); @@ -253,7 +242,7 @@ DoorComponent :: struct { target_openness := 0.0f; openness := 0.0f; - update :: (use this: ^DoorComponent, dt: f32) { + update :: (use this: ^DoorComponent, door: ^Entity, dt: f32) { if openness != target_openness { move_towards(^openness, target_openness, dt * 2); } @@ -273,7 +262,6 @@ door_create :: (scene: ^Entity_Manager, pos, size: Vector2) -> ^Entity { this.flags |= .Solid; scene->create_and_add(this, DoorComponent) {} - scene->create_and_add(this, UpdateComponent) { comp.func = Door.update; } scene->create_and_add(this, RenderComponent) { comp.func = Door.render; } scene->create_and_add(this, SizeComponent) { comp.func = Door.get_rect; } scene->create_and_add(this, InteractableComponent) { comp.interact = Door.interact; } diff --git a/src/entity/store.onyx b/src/entity/store.onyx index 5c05cee..10a9c81 100644 --- a/src/entity/store.onyx +++ b/src/entity/store.onyx @@ -8,7 +8,6 @@ Entity_Store :: enum { } entity_manager_save_to_file :: (use this: ^Entity_Manager, filename: str) { - /* err, output_file := os.open(filename, .Write); defer os.close(^output_file); writer_ := io.writer_make(^output_file); @@ -19,9 +18,20 @@ entity_manager_save_to_file :: (use this: ^Entity_Manager, filename: str) { use type_info; for entities { - info := cast(^Type_Info_Struct) get_type_info(it.type); - io.write_format(writer, ":{}\n", info.name); - emit_struct_fields(any.{~~ it, it.type}, writer, ""); + info := cast(^Type_Info_Struct) get_type_info(it.schematic); + io.write_format(writer, "[{}]\n", info.name); + emit_struct_fields(any.{~~ it, Entity}, writer, ""); + + for^ it.components.entries { + info := cast(^Type_Info_Struct) get_type_info(it.key); + for info.tags { + if it.type != Entity_Store do continue; + if *(cast(^Entity_Store) it.data) == .Skip do continue continue; + } + + io.write_format(writer, ":{}\n", info.name); + emit_struct_fields(any.{~~ it.value, it.key}, writer, ""); + } io.write(writer, "\n"); } @@ -71,7 +81,6 @@ entity_manager_save_to_file :: (use this: ^Entity_Manager, filename: str) { } } } - */ } entity_manager_load_from_file :: (use this: ^Entity_Manager, filename: str) { diff --git a/src/game.onyx b/src/game.onyx index aeab713..d2ca9f5 100644 --- a/src/game.onyx +++ b/src/game.onyx @@ -17,39 +17,13 @@ game_init :: () { load_assets(); scene = entity_manager_create(); - scene->load_from_file("scenes/quick_save.scene"); - /* - // player := player_create(^scene); - - player := scene.schematics["Player"](^scene); - scene->add(player); - - // wall := wall_create(^scene, .{0, 100}, .{300, 40}); - wall := scene.schematics["Wall"](^scene); - wall.pos = .{0, 100}; - wall.size = .{300, 40}; - scene->add(wall); - - door := scene.schematics["Door"](^scene); - door.pos = .{500, 300}; - door.size = .{100, 20}; - scene->add(door); - - item := scene.schematics["Item_Entity"](^scene); - item.pos = .{100, 200}; - item.size = .{32, 32}; - with (item->get(ItemComponent)) { - it.item = "beer"; - } - - scene->add(item); - */ + scene->load_from_file(quick_save_file); item_store = item_store_make(); item_store->load_items_from_file("scenes/default.items"); } -#local quick_save_file := "scenes/quick_save.scene"; +#local quick_save_file := "scenes/quick_save_new.scene"; game_update :: (dt: f32) { if is_key_just_up(GLFW_KEY_F8) {