From: Brendan Hansen Date: Tue, 1 Mar 2022 02:30:34 +0000 (-0600) Subject: player selection preview; patreon animations X-Git-Url: https://git.brendanfh.com/?a=commitdiff_plain;h=658678ffa7f631205b31ae518bdadb30ebd5a794;p=bar-game.git player selection preview; patreon animations --- diff --git a/run_tree/assets/images/spritesheet.png b/run_tree/assets/images/spritesheet.png new file mode 100644 index 0000000..9ed43d4 Binary files /dev/null and b/run_tree/assets/images/spritesheet.png differ diff --git a/run_tree/scenes/default.items b/run_tree/scenes/default.items index d0ee5ee..461847a 100644 --- a/run_tree/scenes/default.items +++ b/run_tree/scenes/default.items @@ -1,6 +1,6 @@ :beer name="Beer" -texture_path="./assets/images/beer-1.png" +texture_path="./assets/images/spritesheet.png" texture_pos = 0 0 texture_size = 16 16 diff --git a/run_tree/scenes/quick_save_new.scene b/run_tree/scenes/quick_save_new.scene index e67ba6b..1884503 100644 --- a/run_tree/scenes/quick_save_new.scene +++ b/run_tree/scenes/quick_save_new.scene @@ -29,7 +29,7 @@ color.a = 1.0000 [Player] id = 12 flags = 2 -pos.x = 379.7975 +pos.x = 379.7973 pos.y = 175.1558 size.x = 32.0000 size.y = 32.0000 @@ -122,8 +122,8 @@ max_timeout = 2.0000 [Patreon] id = 22 flags = 3 -pos.x = 385.0000 -pos.y = 248.0000 +pos.x = 388.6049 +pos.y = 284.5303 size.x = 32.0000 size.y = 32.0000 :RenderComponent @@ -134,7 +134,10 @@ color.b = 0.0000 color.a = 1.0000 :PatreonComponent state = 0 +seat_location.x = 400.0000 +seat_location.y = 400.0000 order_item = "beer" +order_show_animation = 0.0000 holding = 0 consume_timeout = 0.0000 @@ -211,19 +214,3 @@ color.a = 1.0000 item = "beer" max_timeout = 2.0000 -[Item_Entity] -id = 21 -flags = 4 -pos.x = 187.7317 -pos.y = 106.9191 -size.x = 16.0000 -size.y = 16.0000 -:RenderComponent -layer = 10 -color.r = 1.0000 -color.g = 1.0000 -color.b = 1.0000 -color.a = 1.0000 -:ItemComponent -item = "beer" - diff --git a/src/entity/components/dispenser.onyx b/src/entity/components/dispenser.onyx index 748f6d8..22c0e3c 100644 --- a/src/entity/components/dispenser.onyx +++ b/src/entity/components/dispenser.onyx @@ -45,6 +45,7 @@ DispenserComponent :: struct { } // This should dynamic... + item.pos = this.pos; item.size = .{16, 16}; (item->get(ItemComponent)).item = dispenser_comp.item; diff --git a/src/entity/components/patreon.onyx b/src/entity/components/patreon.onyx index bf20088..4f35f82 100644 --- a/src/entity/components/patreon.onyx +++ b/src/entity/components/patreon.onyx @@ -2,6 +2,7 @@ use package core #local Patreon_State :: enum { + Walking_To_Seat; Waiting_To_Place_Order; Waiting_For_Order; Consuming_Order; @@ -12,12 +13,15 @@ PatreonComponent :: struct { use component: Component; state := Patreon_State.Waiting_To_Place_Order; + seat_location: Vector2; order_item: str; + order_show_animation: f32; holding: Entity_ID; consume_timeout: f32; init :: (use this: ^PatreonComponent) { order_item = "beer"; + seat_location = .{ 400, 400 }; } added :: (use this: ^PatreonComponent, entity: ^Entity) { @@ -29,6 +33,16 @@ PatreonComponent :: struct { } update :: (use this: ^PatreonComponent, entity: ^Entity, dt: f32) { + if state == .Walking_To_Seat { + delta := Vector2.norm(seat_location - entity.pos) * 100; + entity.pos += delta * dt; + + if Vector2.square_mag(seat_location - entity.pos) < 16 { + entity.pos = seat_location; + state = .Waiting_To_Place_Order; + } + } + if consume_timeout > 0 && state == .Consuming_Order { consume_timeout -= dt; if consume_timeout < 0 { @@ -39,10 +53,17 @@ PatreonComponent :: struct { } } + if state == .Waiting_For_Order { + if order_show_animation > 0 { + order_show_animation *= 0.75; + } + } + if holding != Entity_Nothing { holding_object := scene->get(holding); r := Entity.get_rect(holding_object); - holding_object.pos = entity.pos + .{-10, 0}; + target_pos := entity.pos + .{-10, 0}; + holding_object.pos += (target_pos - holding_object.pos) * 0.25; } } @@ -53,6 +74,7 @@ PatreonComponent :: struct { case .Waiting_To_Place_Order { if interactor->has(PlayerComponent) { patreon.state = .Waiting_For_Order; + patreon.order_show_animation = 1.0f; } } @@ -74,10 +96,17 @@ PatreonComponent :: struct { } post_render :: (use this: ^PatreonComponent, entity: ^Entity) { - if state == .Waiting_For_Order { - r := entity->get_rect(); + r := entity->get_rect(); - r = Rect.{ r.x + (r.w - 24) / 2, r.y - r.h / 2 - 16, 24, 24 }; + r = Rect.{ r.x + (r.w - 24) / 2, r.y - r.h / 2 - 16, 24, 24 }; + r.y += 24 * order_show_animation; + + if state == .Waiting_To_Place_Order { + immediate_set_color(.{1, 1, 1}); + immediate_subimage(^Spritesheet, r.x + 4, r.y + 4, 16, 16, 1*16, 4*16, 16, 16); + } + + if state == .Waiting_For_Order { immediate_set_color(.{0, 0, 0}); immediate_rectangle(r.x, r.y, r.w, r.h); diff --git a/src/entity/components/player.onyx b/src/entity/components/player.onyx index ea08206..3b62e94 100644 --- a/src/entity/components/player.onyx +++ b/src/entity/components/player.onyx @@ -7,24 +7,55 @@ PlayerComponent :: struct { holding : Entity_ID; + #tag Editor_Hidden, Entity_Store.Skip + nearby_holding, nearby_interact : Entity_ID; + update :: (player: ^PlayerComponent, use this: ^Entity, dt: f32) { // Highlight the object that you are going to interact with + { + player.nearby_interact = Entity_Nothing; + area := Rect.{pos.x - size.x, pos.y - size.y, size.x * 2, size.y * 2}; + objects := scene->query_by_component(area, InteractableComponent); + defer memory.free_slice(^objects); - movement := this->get(MovementComponent); + dist := size.x * size.x + size.y * size.y; - // Try to interact with nearby objects - // - if is_key_just_up(movement.controls.interact) { + for objects { + d := Vector2.square_mag(pos - it.pos); + if d < dist { + player.nearby_interact = it.id; + dist = d; + } + } + } + + { + player.nearby_holding = Entity_Nothing; area := Rect.{pos.x - size.x, pos.y - size.y, size.x * 2, size.y * 2}; - objects := scene->query_by_component(area, InteractableComponent); + objects := scene->query_by_flags(area, .Carryable); defer memory.free_slice(^objects); + dist := size.x * size.x + size.y * size.y; + for objects { - interact_comp := it->get(InteractableComponent); - interact_comp.interact(it, this); + d := Vector2.square_mag(pos - it.pos); + if d < dist { + player.nearby_holding = it.id; + dist = d; + } } } + movement := this->get(MovementComponent); + + // Try to interact with nearby objects + // + if is_key_just_up(movement.controls.interact) && player.nearby_interact != Entity_Nothing { + it := scene->get(player.nearby_interact); + interact_comp := it->get(InteractableComponent); + interact_comp.interact(it, this); + } + // // Try to pick up nearby objects // @@ -38,23 +69,10 @@ PlayerComponent :: struct { holding_object.pos = pos + facing_to_direction_vector(movement.facing) * d; player.holding = Entity_Nothing; - } else { - area := Rect.{pos.x - size.x, pos.y - size.y, size.x * 2, size.y * 2}; - objects := scene->query_by_flags(area, .Carryable); - defer memory.free_slice(^objects); - - // This should first sort by the distance to the object - while i := 0; i < objects.count { - defer i += 1; - if objects[i] == this do continue; - - target_object := objects[i]; - target_object.flags ^= .Carryable; // This only works because we assume that it is Carryable, otherwise this would make it carryable. - player.holding = target_object.id; - break; - } - - // Should this fire an event on the target object? + } elseif player.nearby_holding != Entity_Nothing { + target_object := scene->get(player.nearby_holding); + target_object.flags ^= .Carryable; // This only works because we assume that it is Carryable, otherwise this would make it carryable. + player.holding = target_object.id; } } @@ -65,12 +83,29 @@ PlayerComponent :: struct { if player.holding != Entity_Nothing { holding_object := scene->get(player.holding); r := Entity.get_rect(holding_object); - holding_object.pos = pos - .{0, (size.y + r.h) / 2}; + target_pos := pos - .{0, (size.y + r.h) / 2}; + holding_object.pos += (target_pos - holding_object.pos) * 0.25; } } render :: (use this: ^Entity) { rect := Entity.get_rect(this); - immediate_image(^Player.assets.texture, rect.x, rect.y, rect.w, rect.h); + immediate_subimage(^Spritesheet, rect.x, rect.y, rect.w, rect.h, 0*16, 4*16, 16, 16); + } + + post_render :: (use this: ^PlayerComponent, entity: ^Entity) { + if nearby_interact != Entity_Nothing { + it := scene->get(nearby_interact); + r := it->get_rect(); + immediate_set_color(.{.2, .2, .8, .7}); + immediate_rectangle(r.x, r.y, r.w, r.h); + } + + if nearby_holding != Entity_Nothing && holding == Entity_Nothing { + it := scene->get(nearby_holding); + r := it->get_rect(); + immediate_set_color(.{.2, .8, .2, .7}); + immediate_rectangle(r.x, r.y, r.w, r.h); + } } } diff --git a/src/entity/editor.onyx b/src/entity/editor.onyx index ffe68cb..753bb8c 100644 --- a/src/entity/editor.onyx +++ b/src/entity/editor.onyx @@ -220,6 +220,8 @@ editor_draw :: () { if selected_entity_id != Entity_Nothing { selected_entity := scene->get(selected_entity_id); render_entity_fields(selected_entity, x, y, w, h); + } else { + render_entity_list(x, y, w, h); } } } @@ -255,6 +257,17 @@ editor_draw :: () { draw_checkbox(.{x, y + 150, w, 36.0f}, ^dumb, "Testing checkboxes"); } +#local render_entity_list :: (x, y, w, h: f32) { + buf: [256] u8; + for scene.entities { + msg := conv.format(buf, "{} ({})", it.schematic, cast(u32) it.id); + if draw_button(.{ x, y, w, 32 }, msg, increment=~~it) { + selected_entity_id = it.id; + } + y += 32; + } +} + #local render_entity_fields :: (entity: ^Entity, x, y, w, h: f32) { assert(entity != null, "entity is null"); @@ -277,12 +290,15 @@ editor_draw :: () { y += 32; for^ entry: entity.components.entries { + immediate_set_color(.{0, 0, 0}); + immediate_rectangle(x, y, w, 4); + y += 16; info = ~~ type_info.get_type_info(entry.key); - font_print(editor_font, x + 2, y + 24, info.name); + font_print(editor_font, x + 2, y + 20, info.name); y, i = render_struct_fields(any.{~~entry.value, entry.key}, i, x, y, w, h); - y += 16; + y += 32; } } @@ -327,7 +343,7 @@ editor_draw :: () { immediate_rectangle(x, y + 2, w, Field_Height + 2); } - font_print(editor_font, x + 2, y + Field_Height, it.name); + font_print(editor_font, x + 2, y + Field_Height - 2, it.name); #persist depth_colors := Color.[ Color.{0.4, 0.2, 0.2}, @@ -345,7 +361,7 @@ editor_draw :: () { } else { value_buf: [1024] u8; value_str := conv.format_va(value_buf, "{}", .[member_any]); - font_print(editor_font, x + w - font_get_width(editor_font, value_str) - 2, y + Field_Height, value_str); + font_print(editor_font, x + w - font_get_width(editor_font, value_str) - 2, y + Field_Height - 2, value_str); } } @@ -420,7 +436,7 @@ editor_draw :: () { } #local { - background_color :: Color.{0.5, 0.5, 0.5, 1}; + background_color :: Color.{0.15, 0.15, 0.15, 1}; editor_font: Font; editor_big_font: Font; diff --git a/src/entity/schematics/patreon.onyx b/src/entity/schematics/patreon.onyx index 6175952..b83056f 100644 --- a/src/entity/schematics/patreon.onyx +++ b/src/entity/schematics/patreon.onyx @@ -24,7 +24,7 @@ Patreon :: struct { render :: (use this: ^Entity) { r := this->get_rect(); - immediate_image(^Player.assets.texture, r.x, r.y, r.w, r.h); + immediate_subimage(^Spritesheet, r.x, r.y, r.w, r.h, 0*16, 4*16, 16, 16); } } diff --git a/src/entity/schematics/tap.onyx b/src/entity/schematics/tap.onyx index 9c5f965..4c00be0 100644 --- a/src/entity/schematics/tap.onyx +++ b/src/entity/schematics/tap.onyx @@ -25,12 +25,7 @@ Tap :: struct { render :: (use this: ^Entity) { rect := this->get_rect(); - immediate_image(^Tap.assets.texture, rect.x, rect.y, rect.w, rect.h); - } - - #persist assets: struct { - #tag "./assets/images/keg.png" - texture: Texture; + immediate_subimage(^Spritesheet, rect.x, rect.y, rect.w, rect.h, 0*16, 2*16, 32, 32); } } diff --git a/src/game.onyx b/src/game.onyx index 7eeeacf..242854d 100644 --- a/src/game.onyx +++ b/src/game.onyx @@ -13,13 +13,14 @@ item_store: Item_Store; scene_render_offset: Vector2; scene_canvas: Canvas; +Spritesheet: Texture; + game_init :: () { scene_canvas = canvas_make(800, 600); // This process of queueing the asset bucket should // be made automatic somehow... - queue_assets(^Player.assets); - queue_assets(^Tap.assets); + Spritesheet', _ := texture_lookup(#cstr "./assets/images/spritesheet.png"); load_assets(); diff --git a/src/utils/vecmath.onyx b/src/utils/vecmath.onyx index 3bda373..1ba7aa8 100644 --- a/src/utils/vecmath.onyx +++ b/src/utils/vecmath.onyx @@ -2,6 +2,15 @@ Vector2 :: struct { x, y: f32; mag :: macro (v: Vector2) => math.sqrt(v.x * v.x + v.y * v.y); + + square_mag :: macro (v: Vector2) => v.x * v.x + v.y * v.y; + + norm :: macro (v: Vector2) -> Vector2 { + l := math.sqrt(v.x * v.x + v.y * v.y); + return .{ v.x / l, v.y / l }; + } + + Zero :: Vector2.{0, 0} #struct_tag conv.Custom_Format.{format_vector2} @@ -50,7 +59,7 @@ Vector3 :: struct { #operator + macro (v1, v2: Vector2) => (typeof v1).{ v1.x + v2.x, v1.y + v2.y }; #operator - macro (v1, v2: Vector2) => (typeof v1).{ v1.x - v2.x, v1.y - v2.y }; -#operator * macro (v: Vector2, s: f32) => (typeof v1).{ v.x * s, v.y * s }; +#operator * macro (v: Vector2, s: f32) => (typeof v ).{ v.x * s, v.y * s }; #operator * macro (v1, v2: Vector2) => (typeof v1).{ v1.x * v2.x, v1.y * v2.y }; #operator == macro (v1, v2: Vector2) => v1.x == v2.x && v1.y == v2.y;