From c25afa72b9cc3586c59438087a9ef4db0bb29683 Mon Sep 17 00:00:00 2001 From: jacob Date: Thu, 1 Aug 2024 14:47:37 -0500 Subject: [PATCH] implement partially broken slice based aiming --- src/game.c | 191 +++++++++++++++++++++++++++++------------------------ src/math.h | 8 +-- 2 files changed, 110 insertions(+), 89 deletions(-) diff --git a/src/game.c b/src/game.c index 5a526536..f7c24692 100644 --- a/src/game.c +++ b/src/game.c @@ -132,7 +132,7 @@ INTERNAL void recalculate_world_xforms_recurse(struct entity *parent) struct xform xform_world = xform_mul(node.parent_xform_world, child->xform); child->xform_world = xform_world; - /* Calculate sprite xform */ + /* Calculate sprite world xform */ struct xform sprite_xform_world = xform_mul(xform_world, child->sprite_xform); child->sprite_xform_world = sprite_xform_world; @@ -178,8 +178,8 @@ INTERNAL void game_update(void) e->xform = XFORM_TRS(.t = pos, .r = r, .s = size); e->sprite = sprite_tag_from_path(STR("res/graphics/tim.ase")); - e->sprite_span_name = STR("idle.unarmed"); - //e->sprite_span_name = STR("idle.two_handed"); + //e->sprite_span_name = STR("idle.unarmed"); + e->sprite_span_name = STR("idle.two_handed"); entity_enable_prop(e, ENTITY_PROP_PLAYER_CONTROLLED); e->player_max_speed = 4.f; @@ -256,10 +256,76 @@ INTERNAL void game_update(void) /* ---------------------------------------------------------------------- */ /* ---------------------------------------------------------------------- */ + /* ========================== * + * Update sprite + * ========================== */ + + /* Recalculate world xforms */ + for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) { + struct entity *ent = &entities_array.entities[entity_index]; + if (ent->valid && !ent->parent.gen) { + recalculate_world_xforms_recurse(ent); + } + } + + for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) { + struct entity *ent = &entities_array.entities[entity_index]; + if (!ent->valid) continue; + if (sprite_tag_is_nil(ent->sprite)) continue; + + /* ========================== * + * Update animation + * ========================== */ + + if (entity_has_prop(ent, ENTITY_PROP_ANIMATING)) { + struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, ent->sprite); + struct sprite_sheet_span span = sprite_sheet_get_span(sheet, ent->sprite_span_name); + + f64 time_in_frame = ent->animation_time_in_frame + G.world.dt; + u64 frame_index = ent->animation_frame; + if (frame_index < span.start || frame_index > span.end) { + frame_index = span.start; + } + + struct sprite_sheet_frame frame = sprite_sheet_get_frame(sheet, frame_index); + while (time_in_frame > frame.duration) { + time_in_frame -= frame.duration; + ++frame_index; + if (frame_index > span.end) { + /* Loop animation */ + frame_index = span.start; + } + frame = sprite_sheet_get_frame(sheet, frame_index); + } + + ent->animation_time_in_frame = time_in_frame; + ent->animation_frame = frame_index; + } + + /* ========================== * + * Update sprite xform + * ========================== */ + + struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite); + struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("pivot"), ent->animation_frame); + struct v2 sprite_size = v2_div(sheet->frame_size, (f32)PIXELS_PER_UNIT); + struct v2 pivot_pos = v2_mul_v2(slice.center_norm, sprite_size); + ent->sprite_xform = xform_with_scale(XFORM_POS(v2_neg(pivot_pos)), sprite_size); + } + + /* ========================== * * Update entities pre-physics * ========================== */ + /* Recalculate world xforms */ + for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) { + struct entity *ent = &entities_array.entities[entity_index]; + if (ent->valid && !ent->parent.gen) { + recalculate_world_xforms_recurse(ent); + } + } + for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) { struct entity *ent = &entities_array.entities[entity_index]; if (!ent->valid) continue; @@ -276,43 +342,28 @@ INTERNAL void game_update(void) } /* ========================== * - * Update animation + * Calculate player aim angle * ========================== */ - if (entity_has_prop(ent, ENTITY_PROP_ANIMATING)) { - f64 time_in_frame = ent->animation_time_in_frame + G.world.dt; - u64 span_frame_offset = ent->animation_frame; + if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) { + /* Update focus */ + ent->focus = G.world.player_aim; - struct sprite_sheet *sheet = sprite_sheet_from_tag_async(sprite_frame_scope, ent->sprite); - struct sprite_sheet_span span = sprite_sheet_get_span(sheet, ent->sprite_span_name); - u64 frame_index = span.start + span_frame_offset; - - struct sprite_sheet_frame frame = sprite_sheet_get_frame(sheet, frame_index); - while (time_in_frame > frame.duration) { - time_in_frame -= frame.duration; - ++frame_index; - if (frame_index > span.end) { - /* Loop animation */ - frame_index = span.start; - } - frame = sprite_sheet_get_frame(sheet, frame_index); - } - span_frame_offset = frame_index - span.start; - - ent->animation_time_in_frame = time_in_frame; - ent->animation_frame = span_frame_offset; - } - - /* ========================== * - * Update sprite xform - * ========================== */ - - if (!sprite_tag_is_nil(ent->sprite)) { struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_frame_scope, ent->sprite); - struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("pivot"), ent->animation_frame); - struct v2 sprite_size = v2_div(sheet->frame_size, (f32)PIXELS_PER_UNIT); - struct v2 pivot_pos = v2_mul_v2(slice.center_norm, sprite_size); - ent->sprite_xform = xform_with_scale(XFORM_POS(v2_neg(pivot_pos)), sprite_size); + struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("hold"), ent->animation_frame); + + struct v2 hold_pos = xform_mul_v2(ent->xform_world, xform_mul_v2(ent->sprite_xform, slice.center_norm)); + struct v2 hold_dir = xform_basis_mul_v2(ent->xform_world, xform_basis_mul_v2(ent->sprite_xform, slice.dir_norm)); + + struct v2 focus_pos = v2_add(ent->xform_world.og, ent->focus); + struct v2 hold_focus_dir = v2_sub(focus_pos, hold_pos); + + /* Only rotate if rotation to focus around origin is possible */ + f32 ent_hold_len = v2_len(v2_sub(hold_pos, ent->xform_world.og)); + f32 ent_focus_len = v2_len(v2_sub(focus_pos, ent->xform_world.og)); + if (ent_focus_len > ent_hold_len) { + ent->xform = xform_rotate(ent->xform, v2_angle_from_dirs(hold_dir, hold_focus_dir)); + } } /* ========================== * @@ -323,7 +374,7 @@ INTERNAL void game_update(void) if (entity_has_prop(ent, ENTITY_PROP_TEST)) { f32 t = ((f32)G.world.time); struct v2 og = v2_mul(V2(math_cos(t), math_sin(t)), 3); - f32 r = t + PI / 2; + f32 r = t * 3; struct v2 s = V2(1 + (math_fabs(math_sin(t * 5)) * 3), 1); (UNUSED)og; (UNUSED)r; @@ -338,43 +389,13 @@ INTERNAL void game_update(void) ent->xform = xform_with_rotation(ent->xform, r); ent->xform = xform_with_scale(ent->xform, s); } - - /* ========================== * - * Calculate player aim angle - * ========================== */ - - if (entity_has_prop(ent, ENTITY_PROP_PLAYER_CONTROLLED)) { -#if 0 - /* Update focus */ - ent->focus = G.world.player_aim; - - /* Update view angle */ - struct v2 ent_pos = ent->xform.og; - struct v2 look_pos = v2_add(ent_pos, ent->focus); - - float r; - { - struct sprite_sheet *sheet = sprite_sheet_from_tag_await(sprite_scope, ent->sprite); - struct sprite_sheet_slice slice = sprite_sheet_get_slice(sheet, STR("hold"), ent->animation_frame); - - struct v2 dir = slice.dir_norm; - } - - ent->xform = xform_with_rotation(ent->xform, r); -#else - /* Update focus */ - ent->focus = G.world.player_aim; - - /* Update view angle */ - struct v2 ent_pos = ent->xform.og; - struct v2 look_pos = v2_add(ent_pos, ent->focus); - f32 r = v2_angle_to_point(ent_pos, look_pos) + PI / 2; - ent->xform = xform_with_rotation(ent->xform, r); -#endif - } } - /* Recalculate xforms */ + /* ========================== * + * Update entity physics + * ========================== */ + + /* Recalculate world xforms */ for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) { struct entity *ent = &entities_array.entities[entity_index]; if (ent->valid && !ent->parent.gen) { @@ -382,10 +403,6 @@ INTERNAL void game_update(void) } } - /* ========================== * - * Update entity physics - * ========================== */ - for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) { struct entity *ent = &entities_array.entities[entity_index]; if (!ent->valid) continue; @@ -419,7 +436,11 @@ INTERNAL void game_update(void) } } - /* Recalculate xforms */ + /* ========================== * + * Update entities post-physics + * ========================== */ + + /* Recalculate world xforms */ for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) { struct entity *ent = &entities_array.entities[entity_index]; if (ent->valid && !ent->parent.gen) { @@ -427,10 +448,6 @@ INTERNAL void game_update(void) } } - /* ========================== * - * Update entities post-physics - * ========================== */ - for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) { struct entity *ent = &entities_array.entities[entity_index]; if (!ent->valid) continue; @@ -492,7 +509,14 @@ INTERNAL void game_update(void) } } - /* Recalculate xforms */ + /* ---------------------------------------------------------------------- */ + /* ---------------------------------------------------------------------- */ + + /* ========================== * + * Publish tick + * ========================== */ + + /* Recalculate world xforms */ for (u64 entity_index = 0; entity_index < entities_array.count; ++entity_index) { struct entity *ent = &entities_array.entities[entity_index]; if (ent->valid && !ent->parent.gen) { @@ -500,9 +524,6 @@ INTERNAL void game_update(void) } } - /* ---------------------------------------------------------------------- */ - /* ---------------------------------------------------------------------- */ - /* Publish tick */ publish_game_tick(); __profframe("Game"); diff --git a/src/math.h b/src/math.h index 8301ef64..77d3b1b3 100644 --- a/src/math.h +++ b/src/math.h @@ -631,14 +631,14 @@ INLINE f32 v2_angle(struct v2 v) return math_atan2(v.y, v.x); } -INLINE f32 v2_angle_to_dir(struct v2 a, struct v2 b) +INLINE f32 v2_angle_from_dirs(struct v2 dir1, struct v2 dir2) { - return math_atan2(v2_wedge(a, b), v2_dot(a, b)); + return math_atan2(v2_wedge(dir1, dir2), v2_dot(dir1, dir2)); } -INLINE f32 v2_angle_to_point(struct v2 a, struct v2 b) +INLINE f32 v2_angle_from_points(struct v2 pt1, struct v2 pt2) { - return v2_angle(v2_sub(b, a)); + return v2_angle(v2_sub(pt2, pt1)); } /* ========================== *