crosshair wip

This commit is contained in:
jacob 2026-01-31 16:21:13 -06:00
parent a99ae88d22
commit bd0b22b889
11 changed files with 155 additions and 84 deletions

View File

@ -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;
}

View File

@ -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);

View File

@ -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);
}
}
//////////////////////////////

View File

@ -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;

View File

@ -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
};

View File

@ -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

View File

@ -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;
}

View File

@ -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
};

View File

@ -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)

View File

@ -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

View File

@ -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
};
};