From: Brendan Hansen Date: Sat, 29 Jan 2022 19:48:03 +0000 (-0600) Subject: testing what it feels like use the entity system X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=fbd2400843e1f99c49e5133cd4a95cee66a16c69;p=bar-game.git testing what it feels like use the entity system --- diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..1bb4614 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +*.code-workspace \ No newline at end of file diff --git a/src/entity/manager.onyx b/src/entity/manager.onyx index 8d43f9c..29da0c0 100644 --- a/src/entity/manager.onyx +++ b/src/entity/manager.onyx @@ -2,8 +2,11 @@ use package core use package glfw3 +Entity_ID :: u32 +Entity_Nothing :: cast(Entity_ID) 0 + Entity :: struct { - id: u32; + id: Entity_ID; type: type_expr; flags: Entity_Flags; @@ -13,6 +16,7 @@ Entity :: struct { Entity_Flags :: enum #flags { Interactable; Solid; + Carryable; } IsEntity :: interface (e: $E) { @@ -30,16 +34,21 @@ Entity_Handles :: struct { Entity_Manager :: struct { entity_allocator: Allocator; + + // Hmmm... Do they need to be stored in both ways? entities: [..] ^Entity; + entity_map: Map(Entity_ID, ^Entity); + entity_types: Map(type_expr, Entity_Handles); - next_entity_id: u32; + next_entity_id: Entity_ID; register :: entity_manager_register; add :: entity_manager_add; make :: entity_manager_make; update :: entity_manager_update; draw :: entity_manager_draw; + get :: entity_manager_get; query :: entity_manager_query; query_by_type :: entity_manager_query_by_type; query_by_flags :: entity_manager_query_by_flags; @@ -82,6 +91,7 @@ entity_manager_add :: (use this: ^Entity_Manager, entity: ^$T) -> u32 where IsEn next_entity_id += 1; entities << entity; + entity_map[entity.id] = entity; return entity.id; } @@ -111,6 +121,8 @@ entity_manager_draw :: (use this: ^Entity_Manager) { } } +entity_manager_get :: (use this: ^Entity_Manager, id: Entity_ID) => entity_map[id]; + entity_manager_query :: (use this: ^Entity_Manager, area: Rect) -> [] ^Entity { ents: [..] ^Entity; for entities { @@ -154,7 +166,7 @@ entity_manager_query_by_flags :: (use this: ^Entity_Manager, area: Rect, flags: expected_flags := cast(u32) flags; for entities { - if (~~ it.flags & expected_flags) != expected_flags do continue; + if ~~ it.flags & expected_flags != expected_flags do continue; get_rect := entity_types[it.type].get_rect; if get_rect == null_proc do continue; @@ -167,9 +179,20 @@ entity_manager_query_by_flags :: (use this: ^Entity_Manager, area: Rect, flags: return ents; } -entity_is :: macro (entity: ^Entity, type: type_expr, body: Code) { +if_entity_is :: macro (entity: ^Entity, type: type_expr, body: Code) { if entity.type == type { it := cast(^type) entity; #insert body; } } + +switch_entity :: macro (entity: ^Entity, body: Code) { + switch entity.type do #insert body; +} + +entity_case :: macro (type: type_expr, body: Code) { + case type { + object := cast(^type) it; + #insert body; + } +} diff --git a/src/entity/player.onyx b/src/entity/player.onyx index e3c119a..b42f0c5 100644 --- a/src/entity/player.onyx +++ b/src/entity/player.onyx @@ -2,19 +2,34 @@ use package core use package glfw3 +Player_Controls :: struct { + up := GLFW_KEY_W; + down := GLFW_KEY_S; + left := GLFW_KEY_A; + right := GLFW_KEY_D; + interact := GLFW_KEY_F; + pick_up := GLFW_KEY_G; +} + Player :: struct { use entity: Entity; - health := 69.0f; + holding: Entity_ID; + + controls: Player_Controls; Size :: 16.0f init_data :: struct { pos := Vector2.{400, 200}; + controls := Player_Controls.{}; } init :: (use this: ^Player, data: init_data) { this.pos = data.pos; + this.holding = Entity_Nothing; + + this.controls = data.controls; } get_rect :: (use this: ^Player) => Rect.{ pos.x - Size, pos.y - Size, Size * 2, Size * 2 }; @@ -23,10 +38,10 @@ Player :: struct { speed :: Size * 8; delta: Vector2; - if is_key_down(GLFW_KEY_W) do delta.y -= speed * dt; - if is_key_down(GLFW_KEY_S) do delta.y += speed * dt; - if is_key_down(GLFW_KEY_A) do delta.x -= speed * dt; - if is_key_down(GLFW_KEY_D) do delta.x += speed * dt; + if is_key_down(controls.up) do delta.y -= speed * dt; + if is_key_down(controls.down) do delta.y += speed * dt; + if is_key_down(controls.left) do delta.x -= speed * dt; + if is_key_down(controls.right) do delta.x += speed * dt; walls := entity_manager->query_by_flags(.{pos.x - 100, pos.y - 100, 200, 200}, .Solid); defer memory.free_slice(^walls); @@ -34,9 +49,34 @@ Player :: struct { try_move(this, .{delta.x, 0}, walls); try_move(this, .{0, delta.y}, walls); - if is_key_just_up(GLFW_KEY_SPACE) { + // + // Try to pick up nearby objects + // + if is_key_just_up(controls.pick_up) { + if holding != Entity_Nothing { + holding_object := entity_manager->get(holding); + holding_object.pos = pos + .{20, 0}; + holding = Entity_Nothing; + + } else { + area := Rect.{pos.x - Size * 2, pos.y - Size * 2, Size * 4, Size * 4}; + objects := entity_manager->query_by_flags(area, .Carryable); + defer memory.free_slice(^objects); + + // This should first sort by the distance to the object + target_object := objects[0]; + this.holding = target_object.id; + + // Should this fire an event on the target object? + } + } + + // + // Try to interact with nearby objects + // + if is_key_just_up(controls.interact) { area := Rect.{pos.x - Size * 2, pos.y - Size * 2, Size * 4, Size * 4}; - objects := entity_manager->query_by_flags(area, Entity_Flags.Solid | .Interactable); + objects := entity_manager->query_by_flags(area, .Interactable); defer memory.free_slice(^objects); for objects { @@ -45,6 +85,19 @@ Player :: struct { vtable.interact(it, this); } } + + // + // Adjust the position of the entity you are carrying + // to be above the players head. + // + if holding != Entity_Nothing { + holding_object := entity_manager->get(holding); + vtable := ^entity_manager.entity_types[holding_object.type]; + if vtable.get_rect != null_proc { + r := vtable.get_rect(holding_object); + holding_object.pos = pos - .{0, Size + r.h}; + } + } } try_move :: (use this: ^Player, delta: Vector2, obsticles: [] ^Entity) { @@ -52,6 +105,9 @@ Player :: struct { ent_rect := get_rect(this); for obsticles { + // Don't check collision on the object that you are carrying because it probably won't make sense. + if it.id == this.holding do continue; + vtable := ^entity_manager.entity_types[it.type]; if Rect.intersects(ent_rect, vtable.get_rect(~~ it)) { pos -= delta; @@ -114,6 +170,7 @@ Door :: struct { this.flags |= .Interactable; this.flags |= .Solid; + this.flags |= .Carryable; } get_rect :: (use this: ^Door) => Rect.{ pos.x, pos.y, size.x * (1 - openness), size.y }; @@ -128,12 +185,8 @@ Door :: struct { printf("The door at {} was interacted with by a {}!\n", pos, interactor.type); // Doors only open if interacted with by a player - entity_is(interactor, Player) { - if target_openness > 0 do target_openness = 0; - else do target_openness = 0.8f; - - dist := Vector2.mag(this.pos - interactor.pos); - printf("The player is {} units away and has {.2} health.\n", dist, it.health); + if_entity_is(interactor, Player) { + target_openness = 0.8f - target_openness; } } @@ -145,6 +198,37 @@ Door :: struct { } } + +Item :: struct { + use entity: Entity; + + Size :: 8.0f; + + color: Color; + + init_data :: struct { + pos := Vector2.{0, 0}; + color := Color.{1, 0, 1, 1}; + } + + init :: (use this: ^Item, data: init_data) { + this.pos = data.pos; + this.color = data.color; + this.flags |= .Carryable; + } + + get_rect :: (use this: ^Item) => Rect.{ pos.x - Size, pos.y - Size, Size * 2, Size * 2 }; + + draw :: (use this: ^Item) { + immediate_set_color(this.color); + + r := this->get_rect(); + immediate_rectangle(r.x, r.y, r.w, r.h); + } +} + + + @Relocate move_towards :: (v: ^$T, target: T, diff: T) { if math.abs(target - *v) <= diff { diff --git a/src/main.onyx b/src/main.onyx index a96a1e5..37efd8e 100644 --- a/src/main.onyx +++ b/src/main.onyx @@ -54,6 +54,8 @@ init :: () { entity_manager->make(Door, .{ .{400, 150}, .{50, 50} }); entity_manager->make(Door, .{ .{400, 400}, .{50, 50} }); entity_manager->make(Door, .{ .{150, 400}, .{50, 50} }); + + entity_manager->make(Item, .{ pos=.{ 250, 250 } }); } update :: (dt: f32) {