From bd0b22b88922080abbd5948c9111b4c0a4c91aab Mon Sep 17 00:00:00 2001 From: jacob Date: Sat, 31 Jan 2026 16:21:13 -0600 Subject: [PATCH] crosshair wip --- src/base/base_math.c | 13 +++- src/base/base_math.h | 11 +-- src/pp/pp.c | 34 +++++---- src/pp/pp_shared.cg | 2 +- src/pp/pp_shared.cgh | 4 +- src/pp/pp_sim/pp_sim_core.c | 3 - src/pp/pp_vis/pp_vis_core.c | 144 ++++++++++++++++++++++++++---------- src/pp/pp_vis/pp_vis_core.h | 6 +- src/sprite/sprite.c | 8 +- src/sprite/sprite.h | 8 +- src/ui/ui_core.h | 6 +- 11 files changed, 155 insertions(+), 84 deletions(-) diff --git a/src/base/base_math.c b/src/base/base_math.c index 55a835ec..ebb11a39 100644 --- a/src/base/base_math.c +++ b/src/base/base_math.c @@ -1045,11 +1045,20 @@ Vec2 ScaleFromAffine(Affine af) //////////////////////////////////////////////////////////// //~ Xform -Xform MakeXform(Vec2 t, Vec2 r) +Xform XformTR(Vec2 t, Vec2 r) { Xform xf; xf.t = t; - xf.r = NormRot(r); + xf.r = r; + return xf; +} + +Xform XformRT(Vec2 r, Vec2 t) +{ + Xform xf; + xf.t = VEC2(0, 0); + xf.r = r; + xf = TranslateXform(xf, t); return xf; } diff --git a/src/base/base_math.h b/src/base/base_math.h index eef0b641..764accb0 100644 --- a/src/base/base_math.h +++ b/src/base/base_math.h @@ -163,14 +163,6 @@ Struct(Affine) Vec2 og; // Origin }; -// (T)ranslation, (R)otation, (S)cale -Struct(Trs) -{ - Vec2 t; - Vec2 s; - f32 r; -}; - //////////////////////////////////////////////////////////// //~ Xform types @@ -508,7 +500,8 @@ Vec2 ScaleFromAffine(Affine af); #define XformIdentity ((Xform) { .r = { 1, 0 } }) #define CompXformIdentity { .r = { 1, 0 } } -Xform MakeXform(Vec2 t, Vec2 r); +Xform XformTR(Vec2 t, Vec2 r); +Xform XformRT(Vec2 r, Vec2 t); Xform MulXform(Xform a, Xform b); Xform TranslateXform(Xform xf, Vec2 t); diff --git a/src/pp/pp.c b/src/pp/pp.c index 0ff109e7..17bf1588 100644 --- a/src/pp/pp.c +++ b/src/pp/pp.c @@ -90,7 +90,7 @@ String P_NameFromTileKind(P_TileKind kind) // Tile names array #define X(name, ...) [P_TileKind_##name] = CompLit(#name), PERSIST Readonly String tile_names[] = { - P_TilesXMacro(X) + P_TilesXList(X) }; #undef X @@ -1673,23 +1673,31 @@ void P_StepFrame(P_Frame *frame) ////////////////////////////// //- Update guy controls from player controls - for (P_Ent *guy = P_FirstEnt(frame); !P_IsEntNil(guy); guy = P_NextEnt(guy)) { - if (guy->is_guy) + for (P_Ent *guy = P_FirstEnt(frame); !P_IsEntNil(guy); guy = P_NextEnt(guy)) { - ZeroStruct(&guy->control); - } - } - for (P_Ent *player = P_FirstEnt(frame); !P_IsEntNil(player); player = P_NextEnt(player)) - { - if (player->is_player) - { - P_Ent *guy = P_EntFromKey(frame, player->guy); - if (!P_IsEntNil(guy)) + if (guy->is_guy) { - guy->control = player->control; + ZeroStruct(&guy->control); } } + for (P_Ent *player = P_FirstEnt(frame); !P_IsEntNil(player); player = P_NextEnt(player)) + { + if (player->is_player) + { + P_Ent *guy = P_EntFromKey(frame, player->guy); + if (!P_IsEntNil(guy)) + { + guy->control = player->control; + } + } + } + + // Normalize controls + for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) + { + ent->control.move = ClampVec2Len(ent->control.move, 1); + } } ////////////////////////////// diff --git a/src/pp/pp_shared.cg b/src/pp/pp_shared.cg index 14471016..243dfebb 100644 --- a/src/pp/pp_shared.cg +++ b/src/pp/pp_shared.cg @@ -14,7 +14,7 @@ i32 P_TileIdxFromTilePos(Vec2 p) { PERSIST Readonly String tile_names[P_TileKind_COUNT] = { #define X(name, ...) [P_TileKind_##name] = CompLit(#name), - P_TilesXMacro(X) + P_TilesXList(X) #undef X }; String result = Zi; diff --git a/src/pp/pp_shared.cgh b/src/pp/pp_shared.cgh index f136e6e8..0cce5e79 100644 --- a/src/pp/pp_shared.cgh +++ b/src/pp/pp_shared.cgh @@ -12,7 +12,7 @@ #define P_TilesPitch (P_WorldPitch * P_TilesPerMeter) #define P_TilesCount (P_TilesPitch * P_TilesPitch) -#define P_TilesXMacro(X) \ +#define P_TilesXList(X) \ X(Empty) \ X(Tile) \ X(Carpet) \ @@ -23,7 +23,7 @@ Enum(P_TileKind) { #define X(name, ...) P_TileKind_##name, - P_TilesXMacro(X) + P_TilesXList(X) #undef X P_TileKind_COUNT }; diff --git a/src/pp/pp_sim/pp_sim_core.c b/src/pp/pp_sim/pp_sim_core.c index bb44aea7..1a6657e8 100644 --- a/src/pp/pp_sim/pp_sim_core.c +++ b/src/pp/pp_sim/pp_sim_core.c @@ -347,7 +347,6 @@ void S_TickForever(WaveLaneCtx *lane) P_Control *control = &client->controls[control_tick % client->controls_cap]; { *control = *raw_control; - control->move = ClampVec2Len(control->move, 1); } //- Propagate control @@ -462,8 +461,6 @@ void S_TickForever(WaveLaneCtx *lane) - - ////////////////////////////// //- Process connection messages diff --git a/src/pp/pp_vis/pp_vis_core.c b/src/pp/pp_vis/pp_vis_core.c index 5f9e3232..95bfe2f8 100644 --- a/src/pp/pp_vis/pp_vis_core.c +++ b/src/pp/pp_vis/pp_vis_core.c @@ -569,7 +569,7 @@ void V_TickForever(WaveLaneCtx *lane) frame->is_editing = prev_frame->is_editing; frame->ui_debug = prev_frame->ui_debug; frame->show_console = prev_frame->show_console; - frame->look = prev_frame->look; + frame->look = NormRot(prev_frame->look); frame->edit_mode = prev_frame->edit_mode; frame->equipped_tile = prev_frame->equipped_tile; frame->edit_camera_pos = prev_frame->edit_camera_pos; @@ -1309,6 +1309,7 @@ void V_TickForever(WaveLaneCtx *lane) frame->fire_held = fire_held; frame->fire_presses = fire_presses; } + frame->look = NormRot(frame->look); } ////////////////////////////// @@ -1368,7 +1369,7 @@ void V_TickForever(WaveLaneCtx *lane) control.tick = control_tick; control.orig_tick = control_tick; control.move = frame->move; - control.look = frame->look; + control.look = NormRot(frame->look); control.fire_held = frame->fire_held; // FIXME: Don't propagate fire presses over multiple sim frames control.fire_presses = frame->fire_presses; @@ -1832,51 +1833,52 @@ void V_TickForever(WaveLaneCtx *lane) ////////////////////////////// - //- Push guy quads - - - + //- Draw guy sprites for (P_Ent *ent = P_FirstEnt(local_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) { if (ent->is_guy) { P_Anim anim = P_AnimFromEnt(ent, local_frame->time_ns); + SPR_Sprite body = SPR_SpriteFromSheet(anim.sheet, anim.span, anim.frame_seq); + SPR_Sprite wep = SPR_SpriteFromSheet(anim.wep_sheet, anim.span, anim.frame_seq); - Vec2 pix_scale = VEC2(1.0 / P_CellsPerMeter, 1.0 / P_CellsPerMeter); - - // FIXME: Remove this - Xform ent_to_world_xf = ent->xf; - ent_to_world_xf = MakeXform(ent->xf.t, ent->control.look); - Affine ent_to_world_af = MulAffineXform(AffineIdentity, ent_to_world_xf); - - SPR_Slice body = SPR_SliceFromSheet(anim.sheet, anim.span, anim.frame_seq); - SPR_Slice wep = SPR_SliceFromSheet(anim.wep_sheet, anim.span, anim.frame_seq); - + //- Compute sprite transforms Affine body_pix_to_world_af = AffineIdentity; - { - body_pix_to_world_af = MulAffine(body_pix_to_world_af, ent_to_world_af); - body_pix_to_world_af = ScaleAffine(body_pix_to_world_af, pix_scale); - - SPR_Ray anchor_ray = body.rays[SPR_RayKind_Anchor]; - body_pix_to_world_af = RotateAffine(body_pix_to_world_af, InvertRot(anchor_ray.dir)); - body_pix_to_world_af = TranslateAffine(body_pix_to_world_af, NegVec2(anchor_ray.pos)); - } - Affine wep_pix_to_world_af = AffineIdentity; { - wep_pix_to_world_af = MulAffine(wep_pix_to_world_af, ent_to_world_af); - wep_pix_to_world_af = ScaleAffine(wep_pix_to_world_af, pix_scale); + Vec2 pix_scale = VEC2(1.0 / P_CellsPerMeter, 1.0 / P_CellsPerMeter); - SPR_Ray body_anchor_ray = body.rays[SPR_RayKind_Anchor]; - SPR_Ray body_ap_ray = body.rays[SPR_RayKind_Ap]; - wep_pix_to_world_af = RotateAffine(wep_pix_to_world_af, InvertRot(body_anchor_ray.dir)); - wep_pix_to_world_af = TranslateAffine(wep_pix_to_world_af, SubVec2(body_ap_ray.pos, body_anchor_ray.pos)); - wep_pix_to_world_af = RotateAffine(wep_pix_to_world_af, InvertRot(body_ap_ray.dir)); + // FIXME: Remove this, use ent rotation + Xform ent_to_world_xf = ent->xf; + ent_to_world_xf = XformTR(ent->xf.t, NormRot(ent->control.look)); + Affine ent_to_world_af = MulAffineXform(AffineIdentity, ent_to_world_xf); - SPR_Ray anchor_ray = wep.rays[SPR_RayKind_Anchor]; - wep_pix_to_world_af = RotateAffine(wep_pix_to_world_af, anchor_ray.dir); - wep_pix_to_world_af = TranslateAffine(wep_pix_to_world_af, NegVec2(anchor_ray.pos)); + //- Compute body transform + { + body_pix_to_world_af = MulAffine(body_pix_to_world_af, ent_to_world_af); + body_pix_to_world_af = ScaleAffine(body_pix_to_world_af, pix_scale); + + SPR_Ray anchor_ray = body.rays[SPR_RayKind_Anchor]; + body_pix_to_world_af = RotateAffine(body_pix_to_world_af, InvertRot(anchor_ray.dir)); + body_pix_to_world_af = TranslateAffine(body_pix_to_world_af, NegVec2(anchor_ray.pos)); + } + + //- Compute weapon transform + { + wep_pix_to_world_af = MulAffine(wep_pix_to_world_af, ent_to_world_af); + wep_pix_to_world_af = ScaleAffine(wep_pix_to_world_af, pix_scale); + + SPR_Ray body_anchor_ray = body.rays[SPR_RayKind_Anchor]; + SPR_Ray body_ap_ray = body.rays[SPR_RayKind_Ap]; + wep_pix_to_world_af = RotateAffine(wep_pix_to_world_af, InvertRot(body_anchor_ray.dir)); + wep_pix_to_world_af = TranslateAffine(wep_pix_to_world_af, SubVec2(body_ap_ray.pos, body_anchor_ray.pos)); + wep_pix_to_world_af = RotateAffine(wep_pix_to_world_af, InvertRot(body_ap_ray.dir)); + + SPR_Ray anchor_ray = wep.rays[SPR_RayKind_Anchor]; + wep_pix_to_world_af = RotateAffine(wep_pix_to_world_af, anchor_ray.dir); + wep_pix_to_world_af = TranslateAffine(wep_pix_to_world_af, NegVec2(anchor_ray.pos)); + } } //- Push weapon quad @@ -1903,6 +1905,69 @@ void V_TickForever(WaveLaneCtx *lane) } } + ////////////////////////////// + //- Draw crosshair + + // TODO: Alive / weapon check + if (!P_IsEntNil(local_guy)) + { + P_Ent *ent = local_guy; + + P_Anim anim = P_AnimFromEnt(ent, local_frame->time_ns); + SPR_Sprite body = SPR_SpriteFromSheet(anim.sheet, anim.span, anim.frame_seq); + SPR_Sprite wep = SPR_SpriteFromSheet(anim.wep_sheet, anim.span, anim.frame_seq); + + //- Compute sprite transforms + Affine body_pix_to_world_af = AffineIdentity; + Affine wep_pix_to_world_af = AffineIdentity; + { + Vec2 pix_scale = VEC2(1.0 / P_CellsPerMeter, 1.0 / P_CellsPerMeter); + + // FIXME: Remove this, use ent rotation + Xform ent_to_world_xf = ent->xf; + ent_to_world_xf = XformTR(ent->xf.t, NormRot(ent->control.look)); + Affine ent_to_world_af = MulAffineXform(AffineIdentity, ent_to_world_xf); + + //- Compute body transform + { + body_pix_to_world_af = MulAffine(body_pix_to_world_af, ent_to_world_af); + body_pix_to_world_af = ScaleAffine(body_pix_to_world_af, pix_scale); + + SPR_Ray anchor_ray = body.rays[SPR_RayKind_Anchor]; + body_pix_to_world_af = RotateAffine(body_pix_to_world_af, InvertRot(anchor_ray.dir)); + body_pix_to_world_af = TranslateAffine(body_pix_to_world_af, NegVec2(anchor_ray.pos)); + } + + //- Compute weapon transform + { + wep_pix_to_world_af = MulAffine(wep_pix_to_world_af, ent_to_world_af); + wep_pix_to_world_af = ScaleAffine(wep_pix_to_world_af, pix_scale); + + SPR_Ray body_anchor_ray = body.rays[SPR_RayKind_Anchor]; + SPR_Ray body_ap_ray = body.rays[SPR_RayKind_Ap]; + wep_pix_to_world_af = RotateAffine(wep_pix_to_world_af, InvertRot(body_anchor_ray.dir)); + wep_pix_to_world_af = TranslateAffine(wep_pix_to_world_af, SubVec2(body_ap_ray.pos, body_anchor_ray.pos)); + wep_pix_to_world_af = RotateAffine(wep_pix_to_world_af, InvertRot(body_ap_ray.dir)); + + SPR_Ray anchor_ray = wep.rays[SPR_RayKind_Anchor]; + wep_pix_to_world_af = RotateAffine(wep_pix_to_world_af, anchor_ray.dir); + wep_pix_to_world_af = TranslateAffine(wep_pix_to_world_af, NegVec2(anchor_ray.pos)); + } + } + + SPR_Ray fire_ray = wep.rays[SPR_RayKind_Ap]; + + Vec2 fire_pos = MulAffineVec2(wep_pix_to_world_af, fire_ray.pos); + Vec2 fire_dir = NormRot(MulAffineBasisVec2(wep_pix_to_world_af, fire_ray.dir)); + + Vec2 line_start = fire_pos; + Vec2 line_end = AddVec2(line_start, fire_dir); + P_DebugDrawLine(line_start, line_end, Color_Yellow); + + Vec2 cross = fire_pos; + P_DebugDrawPoint(cross, Color_Red); + } + ////////////////////////////// @@ -1917,7 +1982,6 @@ void V_TickForever(WaveLaneCtx *lane) { if (bullet->is_bullet) { - // FIXME: Truncate bullet trail at hit Vec2 start = bullet->bullet_start; Vec2 end = bullet->bullet_end; @@ -4277,18 +4341,18 @@ void V_TickForever(WaveLaneCtx *lane) { for (P_TileKind tile_kind = 0; tile_kind < P_TileKind_COUNT; ++tile_kind) { - SPR_Slice tile_slice = Zi; + SPR_Sprite tile_sprite = Zi; { String tile_name = P_TileNameFromKind(tile_kind); String sheet_name = StringF(frame->arena, "tile/%F.ase", FmtString(tile_name)); ResourceKey sheet_resource = ResourceKeyFromStore(&P_Resources, sheet_name); SPR_SheetKey sheet = SPR_SheetKeyFromResource(sheet_resource); - tile_slice = SPR_SliceFromSheet(sheet, SPR_NilSpanKey, 0); + tile_sprite = SPR_SpriteFromSheet(sheet, SPR_NilSpanKey, 0); } V_TileDesc tile_desc = Zi; { - tile_desc.tex = tile_slice.tex; - tile_desc.tex_slice_uv = DivRng2Vec2(tile_slice.tex_rect, tile_slice.tex_dims); + tile_desc.tex = tile_sprite.tex; + tile_desc.tex_slice_uv = DivRng2Vec2(tile_sprite.tex_rect, tile_sprite.tex_dims); } params.tile_descs[tile_kind] = tile_desc; } diff --git a/src/pp/pp_vis/pp_vis_core.h b/src/pp/pp_vis/pp_vis_core.h index 4a98741d..97a2c852 100644 --- a/src/pp/pp_vis/pp_vis_core.h +++ b/src/pp/pp_vis/pp_vis_core.h @@ -1,7 +1,7 @@ //////////////////////////////////////////////////////////// //~ Command table -#define V_CmdsTableXMacro(X) \ +#define V_CmdsTableXList(X) \ X(nop, NOP, V_CmdDescFlag_HideFromPalette, V_HOTKEY(0), ) \ X(exit_program, Exit Program, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_Escape ) ) \ X(toggle_palette, Toggle Command Palette, V_CmdDescFlag_HideFromPalette, V_HOTKEY( Button_E, .ctrl = 1 ), V_HOTKEY( Button_P, .ctrl = 1, .shift = 1 ), ) \ @@ -85,7 +85,7 @@ Struct(V_Hotkey) Enum(V_CmdKind) { #define X(name, ...) V_CmdKind_##name, - V_CmdsTableXMacro(X) + V_CmdsTableXList(X) #undef X V_CmdKind_COUNT, }; @@ -133,7 +133,7 @@ Struct(V_CmdNode) Global Readonly V_CmdDesc V_cmd_descs[V_CmdKind_COUNT] = { #define X(_name, _display_name, _flags, ...) { .name = CompLit(#_name), .display_name = CompLit(#_display_name), .flags = _flags, .default_hotkeys = { __VA_ARGS__ } }, - V_CmdsTableXMacro(X) + V_CmdsTableXList(X) #undef X }; diff --git a/src/sprite/sprite.c b/src/sprite/sprite.c index f3f87949..f8fbdd01 100644 --- a/src/sprite/sprite.c +++ b/src/sprite/sprite.c @@ -31,7 +31,7 @@ String SPR_NameFromRayKind(SPR_RayKind kind) { PERSIST Readonly String names[SPR_RayKind_COUNT] = { #define X(kind_name, layer_name, ...) [SPR_RayKind_##kind_name] = CompLit(#layer_name), - SPR_RayKindXMacro(X) + SPR_RayKindXList(X) #undef X }; String result = Zi; @@ -55,7 +55,7 @@ SPR_LayerKind SPR_LayerKindFromName(String name) //////////////////////////////////////////////////////////// //~ Lookup -SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 frame_seq) +SPR_Sprite SPR_SpriteFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 frame_seq) { ////////////////////////////// //- Fetch sheet @@ -195,7 +195,7 @@ SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 f f32 dir_x = (((f32)((ray_pix >> 0) & 0xFF) / 255.0) * 2.0) - 1; f32 dir_y = (((f32)((ray_pix >> 8) & 0xFF) / 255.0) * 2.0) - 1; Vec2 dir = NormVec2(VEC2(dir_x, dir_y)); - slice->rays[ray_kind].pos = SubVec2(ase_cel->bounds.p0, slice->canvas_rect.p0); + slice->rays[ray_kind].pos = AddVec2(SubVec2(ase_cel->bounds.p0, slice->canvas_rect.p0), VEC2(0.5, 0.5)); slice->rays[ray_kind].dir = dir; } } @@ -297,7 +297,7 @@ SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 f ////////////////////////////// //- Compute result - SPR_Slice result = Zi; + SPR_Sprite result = Zi; { b32 slice_ready = 0; if (sheet->ok) diff --git a/src/sprite/sprite.h b/src/sprite/sprite.h index eae80998..018d8733 100644 --- a/src/sprite/sprite.h +++ b/src/sprite/sprite.h @@ -24,7 +24,7 @@ Struct(SPR_Atlas) //////////////////////////////////////////////////////////// //~ Ray types -#define SPR_RayKindXMacro(X) \ +#define SPR_RayKindXList(X) \ X(Anchor, .anchor) \ X(Ap, .ap) \ /* ----------------------------- */ @@ -32,7 +32,7 @@ Struct(SPR_Atlas) Enum(SPR_RayKind) { #define X(kind_name, ...) SPR_RayKind_##kind_name, - SPR_RayKindXMacro(X) + SPR_RayKindXList(X) #undef X SPR_RayKind_COUNT }; @@ -55,7 +55,7 @@ Struct(SPR_Ray) Vec2 dir; }; -Struct(SPR_Slice) +Struct(SPR_Sprite) { SPR_Ray rays[SPR_RayKind_COUNT]; @@ -191,7 +191,7 @@ SPR_LayerKind SPR_LayerKindFromName(String name); //////////////////////////////////////////////////////////// //~ Lookup -SPR_Slice SPR_SliceFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 frame_seq); +SPR_Sprite SPR_SpriteFromSheet(SPR_SheetKey sheet_key, SPR_SpanKey span_key, i64 frame_seq); //////////////////////////////////////////////////////////// //~ Async diff --git a/src/ui/ui_core.h b/src/ui/ui_core.h index 3f8a35b0..41fe34b9 100644 --- a/src/ui/ui_core.h +++ b/src/ui/ui_core.h @@ -96,7 +96,7 @@ Enum(UI_BoxFlag) //////////////////////////////////////////////////////////// //~ Style types -#define UI_StyleKindsXMacro(X) \ +#define UI_StyleKindsXList(X) \ X(OmitFlags, UI_BoxFlag) \ X(OrFlags, UI_BoxFlag) \ X(Flags, UI_BoxFlag) \ @@ -136,7 +136,7 @@ Enum(UI_StyleKind) { #define X(name, type) UI_StyleKind_##name, UI_StyleKind_None, - UI_StyleKindsXMacro(X) + UI_StyleKindsXList(X) UI_StyleKind_COUNT, #undef X }; @@ -148,7 +148,7 @@ Struct(UI_Style) union { #define X(name, type) type name; - UI_StyleKindsXMacro(X) + UI_StyleKindsXList(X) #undef X }; };