roll testing

This commit is contained in:
jacob 2026-02-18 18:07:48 -06:00
parent e9bad68135
commit 67171a9906
11 changed files with 178 additions and 102 deletions

View File

@ -444,18 +444,24 @@ f32 Vec2LenSq(Vec2 a)
Vec2 Vec2WithLen(Vec2 a, f32 len) Vec2 Vec2WithLen(Vec2 a, f32 len)
{ {
f32 l_sq = a.x * a.x + a.y * a.y; f32 l_sq = a.x * a.x + a.y * a.y;
if (l_sq != 0) if (l_sq > 0)
{ {
f32 denom = len / SqrtF32(l_sq); f32 denom = len / SqrtF32(l_sq);
a.x *= denom; a.x *= denom;
a.y *= denom; a.y *= denom;
} }
else
{
a = VEC2(len, 0);
}
return a; return a;
} }
Vec2 ClampVec2Len(Vec2 a, f32 min, f32 max) Vec2 ClampVec2Len(Vec2 a, f32 min, f32 max)
{ {
f32 l_sq = a.x * a.x + a.y * a.y; f32 l_sq = a.x * a.x + a.y * a.y;
if (l_sq > 0)
{
if (l_sq > max * max) if (l_sq > max * max)
{ {
f32 denom = max / SqrtF32(l_sq); f32 denom = max / SqrtF32(l_sq);
@ -468,6 +474,11 @@ Vec2 ClampVec2Len(Vec2 a, f32 min, f32 max)
a.x *= denom; a.x *= denom;
a.y *= denom; a.y *= denom;
} }
}
else
{
a = VEC2(min, 0);
}
return a; return a;
} }
@ -1146,14 +1157,7 @@ Xform NormXform(Xform xf)
Vec2 NormRot(Vec2 r) Vec2 NormRot(Vec2 r)
{ {
if (r.x == 0 && r.y == 0)
{
r.x = 1;
}
else
{
r = Vec2WithLen(r, 1); r = Vec2WithLen(r, 1);
}
return r; return r;
} }

View File

@ -1034,18 +1034,16 @@ String Base64FromString(Arena *arena, String str)
result.text = PushStructsNoZero(arena, u8, result.len); result.text = PushStructsNoZero(arena, u8, result.len);
u64 src_byte_pos = 0; u64 src_byte_pos = 0;
u64 out_byte_pos = 0; u64 out_byte_pos = 0;
while (src_byte_pos < str.len) while (src_byte_pos < str.len && out_byte_pos < result.len)
{ {
u32 chunk = 0; u32 chunk = 0;
chunk |= str.text[src_byte_pos] << 16; if (src_byte_pos < str.len) chunk |= (u32)str.text[src_byte_pos++] << 16;
if (src_byte_pos + 1 < str.len) chunk |= str.text[src_byte_pos + 1] << 8; if (src_byte_pos < str.len) chunk |= (u32)str.text[src_byte_pos++] << 8;
if (src_byte_pos + 2 < str.len) chunk |= str.text[src_byte_pos + 2] << 0; if (src_byte_pos < str.len) chunk |= (u32)str.text[src_byte_pos++] << 0;
result.text[out_byte_pos + 0] = to_base64[(chunk >> 18) & 0x3F]; if (out_byte_pos < result.len) result.text[out_byte_pos++] = to_base64[(chunk >> 18) & 0x3F];
result.text[out_byte_pos + 1] = to_base64[(chunk >> 12) & 0x3F]; if (out_byte_pos < result.len) result.text[out_byte_pos++] = to_base64[(chunk >> 12) & 0x3F];
result.text[out_byte_pos + 2] = to_base64[(chunk >> 6) & 0x3F]; if (out_byte_pos < result.len) result.text[out_byte_pos++] = to_base64[(chunk >> 6) & 0x3F];
result.text[out_byte_pos + 3] = to_base64[(chunk >> 0) & 0x3F]; if (out_byte_pos < result.len) result.text[out_byte_pos++] = to_base64[(chunk >> 0) & 0x3F];
src_byte_pos += 3;
out_byte_pos += 4;
} }
return result; return result;
} }
@ -1058,18 +1056,17 @@ String StringFromBase64(Arena *arena, String str)
PERSIST Readonly u8 from_base64[256] = {['A']=0,['B']=1,['C']=2,['D']=3,['E']=4,['F']=5,['G']=6,['H']=7,['I']=8,['J']=9,['K']=10,['L']=11,['M']=12,['N']=13,['O']=14,['P']=15,['Q']=16,['R']=17,['S']=18,['T']=19,['U']=20,['V']=21,['W']=22,['X']=23,['Y']=24,['Z']=25,['a']=26,['b']=27,['c']=28,['d']=29,['e']=30,['f']=31,['g']=32,['h']=33,['i']=34,['j']=35,['k']=36,['l']=37,['m']=38,['n']=39,['o']=40,['p']=41,['q']=42,['r']=43,['s']=44,['t']=45,['u']=46,['v']=47,['w']=48,['x']=49,['y']=50,['z']=51,['0']=52,['1']=53,['2']=54,['3']=55,['4']=56,['5']=57,['6']=58,['7']=59,['8']=60,['9']=61,['-']=62,['_']=63}; PERSIST Readonly u8 from_base64[256] = {['A']=0,['B']=1,['C']=2,['D']=3,['E']=4,['F']=5,['G']=6,['H']=7,['I']=8,['J']=9,['K']=10,['L']=11,['M']=12,['N']=13,['O']=14,['P']=15,['Q']=16,['R']=17,['S']=18,['T']=19,['U']=20,['V']=21,['W']=22,['X']=23,['Y']=24,['Z']=25,['a']=26,['b']=27,['c']=28,['d']=29,['e']=30,['f']=31,['g']=32,['h']=33,['i']=34,['j']=35,['k']=36,['l']=37,['m']=38,['n']=39,['o']=40,['p']=41,['q']=42,['r']=43,['s']=44,['t']=45,['u']=46,['v']=47,['w']=48,['x']=49,['y']=50,['z']=51,['0']=52,['1']=53,['2']=54,['3']=55,['4']=56,['5']=57,['6']=58,['7']=59,['8']=60,['9']=61,['-']=62,['_']=63};
u64 src_byte_pos = 0; u64 src_byte_pos = 0;
u64 out_byte_pos = 0; u64 out_byte_pos = 0;
while (src_byte_pos < str.len) while (src_byte_pos < str.len && out_byte_pos < result.len)
{ {
u32 chunk = 0; u32 chunk = 0;
chunk |= (from_base64[str.text[src_byte_pos + 0]]) << 18; b32 ok = 1;
chunk |= (from_base64[str.text[src_byte_pos + 1]]) << 12; if (src_byte_pos < str.len) chunk |= (u32)from_base64[str.text[src_byte_pos++]] << 18;
chunk |= (from_base64[str.text[src_byte_pos + 2]]) << 6; if (src_byte_pos < str.len) chunk |= (u32)from_base64[str.text[src_byte_pos++]] << 12;
chunk |= (from_base64[str.text[src_byte_pos + 3]]) << 0; if (src_byte_pos < str.len) chunk |= (u32)from_base64[str.text[src_byte_pos++]] << 6;
result.text[out_byte_pos + 0] = (chunk >> 16) & 0xFF; if (src_byte_pos < str.len) chunk |= (u32)from_base64[str.text[src_byte_pos++]] << 0;
result.text[out_byte_pos + 1] = (chunk >> 8) & 0xFF; if (out_byte_pos < result.len) result.text[out_byte_pos++] = (chunk >> 16) & 0xFF;
result.text[out_byte_pos + 2] = (chunk >> 0) & 0xFF; if (out_byte_pos < result.len) result.text[out_byte_pos++] = (chunk >> 8) & 0xFF;
src_byte_pos += 4; if (out_byte_pos < result.len) result.text[out_byte_pos++] = (chunk >> 0) & 0xFF;
out_byte_pos += 3;
} }
return result; return result;
} }

View File

@ -3566,7 +3566,7 @@ void G_D12_CollectionWorkerEntryPoint(WaveLaneCtx *lane)
at += 16; at += 16;
} break; } break;
} }
dst->p = 6; dst->p = 16;
} }
} }
} }

View File

@ -251,7 +251,7 @@ M_EmbedObj M_Embed(String store_name, String dir_path)
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ M //~ Build
void M_BuildEntryPoint(WaveLaneCtx *lane) void M_BuildEntryPoint(WaveLaneCtx *lane)
{ {
@ -528,6 +528,9 @@ void M_BuildEntryPoint(WaveLaneCtx *lane)
PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-incompatible-function-pointer-types")); PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-incompatible-function-pointer-types"));
PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-missing-braces")); PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-missing-braces"));
PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-unused-value")); PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-unused-value"));
PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-unused-variable"));
PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-unused-but-set-variable"));
PushStringToList(perm, &cp.warnings_clang, Lit("-Wno-switch"));
} }
//- Dxc //- Dxc

View File

@ -242,7 +242,7 @@ P_Shape P_WorldShapeFromEnt(P_Ent *ent)
} }
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Animation helpers //~ Status helpers
P_Anim P_AnimFromEnt(P_Frame *frame, P_Ent *ent) P_Anim P_AnimFromEnt(P_Frame *frame, P_Ent *ent)
{ {
@ -255,8 +255,16 @@ P_Anim P_AnimFromEnt(P_Frame *frame, P_Ent *ent)
i64 walk_duration_ns = frame->time_ns; i64 walk_duration_ns = frame->time_ns;
result.frame_seq = walk_duration_ns / animation_rate_ns; result.frame_seq = walk_duration_ns / animation_rate_ns;
// result.span = SPR_SpanKeyFromName(Lit("test")); // result.span = SPR_SpanKeyFromName(Lit("test"));
if (P_IsEntRolling(frame, ent))
{
result.span = SPR_SpanKeyFromName(Lit("roll"));
}
else
{
result.span = SPR_SpanKeyFromName(Lit("walk")); result.span = SPR_SpanKeyFromName(Lit("walk"));
} }
}
// TODO: Use prefab lookup // TODO: Use prefab lookup
@ -264,8 +272,7 @@ P_Anim P_AnimFromEnt(P_Frame *frame, P_Ent *ent)
{ {
result.sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("guy/guy.ase"))); result.sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("guy/guy.ase")));
} }
else if (ent->is_guy_spawn)
if (ent->is_guy_spawn)
{ {
result.sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("prefab/GuySpawn.ase"))); result.sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("prefab/GuySpawn.ase")));
} }
@ -273,9 +280,7 @@ P_Anim P_AnimFromEnt(P_Frame *frame, P_Ent *ent)
if (wep->is_uzi) if (wep->is_uzi)
{ {
result.wep_sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("wep/uzi.ase"))); result.wep_sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("wep/uzi.ase")));
} } else if (wep->is_launcher)
if (wep->is_launcher)
{ {
result.wep_sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("wep/launcher.ase"))); result.wep_sheet = SPR_SheetKeyFromResource(ResourceKeyFromStore(&P_Resources, Lit("wep/launcher.ase")));
} }
@ -283,6 +288,16 @@ P_Anim P_AnimFromEnt(P_Frame *frame, P_Ent *ent)
return result; return result;
} }
b32 P_IsEntRolling(P_Frame *frame, P_Ent *ent)
{
b32 result = (
ent->last_roll_time_ns > 0 &&
(frame->time_ns - ent->last_roll_time_ns) > 0 &&
(frame->time_ns - ent->last_roll_time_ns) < P_RollTimeNs
);
return result;
}
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Collision //~ Collision
@ -2223,6 +2238,7 @@ void P_StepFrame(P_Frame *frame)
ZeroStruct(&guy->control); ZeroStruct(&guy->control);
} }
} }
for (P_Ent *player = P_FirstEnt(frame); !P_IsEntNil(player); player = P_NextEnt(player)) for (P_Ent *player = P_FirstEnt(frame); !P_IsEntNil(player); player = P_NextEnt(player))
{ {
if (player->is_player) if (player->is_player)
@ -2242,6 +2258,29 @@ void P_StepFrame(P_Frame *frame)
} }
} }
//////////////////////////////
//- Roll guys
for (P_Ent *guy = P_FirstEnt(frame); !P_IsEntNil(guy); guy = P_NextEnt(guy))
{
if (guy->is_guy)
{
if (guy->control.roll_presses && !IsVec2Zero(guy->control.move))
{
// TODO: Not like this
i64 roll_timeout_ns = P_RollTimeoutNs;
i64 roll_time_ns = P_RollTimeNs;
if (frame->time_ns - roll_timeout_ns + roll_time_ns > guy->last_roll_time_ns || guy->last_roll_time_ns == 0)
{
guy->last_roll_time_ns = frame->time_ns;
guy->last_roll_dir = NormRot(guy->control.move);
}
}
}
}
////////////////////////////// //////////////////////////////
//- Integrate guy control forces //- Integrate guy control forces
@ -2265,24 +2304,43 @@ void P_StepFrame(P_Frame *frame)
} }
} }
// Integrate linear movement f32 turn_rate = TweakFloat("Guy turn rate", 1, 0, 1);
{
f32 move_force = TweakFloat("Guy move force", 400, 0, 400); f32 move_force = TweakFloat("Guy move force", 400, 0, 400);
f32 max_speed = TweakFloat("Guy max speed", 10, 0, 20); f32 max_speed = TweakFloat("Guy max speed", 10, 0, 20);
Vec2 look = control.look;
Vec2 move = control.move;
// FIXME: Roll timeout
b32 is_rolling = P_IsEntRolling(frame, guy);
if (is_rolling)
{
Vec2 roll_dir = NormRot(guy->last_roll_dir);
move = roll_dir;
look = roll_dir;
f32 roll_factor = 1.3;
move_force *= roll_factor;
max_speed *= roll_factor;
}
// Integrate linear movement
{
Vec2 new_velocity = guy->solved_v; Vec2 new_velocity = guy->solved_v;
new_velocity = AddVec2(new_velocity, MulVec2(control.move, move_force * sim_dt)); new_velocity = AddVec2(new_velocity, MulVec2(move, move_force * sim_dt));
if (Vec2Len(new_velocity) > max_speed) if (Vec2Len(new_velocity) > max_speed)
{ {
new_velocity = Vec2WithLen(new_velocity, max_speed); new_velocity = Vec2WithLen(new_velocity, max_speed);
} }
guy->solved_v = new_velocity; guy->solved_v = new_velocity;
} }
// Integrate look // Integrate look
{ {
f32 turn_rate = TweakFloat("Guy turn rate", 1, 0, 1);
f32 cur_angle = AngleFromVec2(guy->xf.r); f32 cur_angle = AngleFromVec2(guy->xf.r);
f32 desired_angle = AngleFromVec2(control.look); f32 desired_angle = AngleFromVec2(look);
f32 diff = UnwindAngleF32(desired_angle - cur_angle); f32 diff = UnwindAngleF32(desired_angle - cur_angle);
f32 look_force = 1.0 / (sim_dt * sim_dt) * turn_rate; f32 look_force = 1.0 / (sim_dt * sim_dt) * turn_rate;
guy->solved_w = diff * sim_dt * look_force; guy->solved_w = diff * sim_dt * look_force;
@ -2290,21 +2348,6 @@ void P_StepFrame(P_Frame *frame)
} }
} }
//////////////////////////////
//- Setup constraints store
i32 solver_steps_count = SIM_PHYSICS_SUBSTEPS;
f32 solver_dt = sim_dt / solver_steps_count;
// Solid params
// SoftSpring solid_spring = MakeSpring(TweakFloat("Contact spring hz", 25, 5, 200), TweakFloat("Contact spring damp", 10, 5, 100), solver_dt);
SoftSpring solid_spring = MakeSpring(TweakFloat("Contact spring hz", 100, 5, 200), TweakFloat("Contact spring damp", 10, 5, 100), solver_dt);
f32 solid_pushout_velocity = TweakFloat("Contact spring pushout", 3, 0, 50);
// Gentle params
// f32 gentle_pushout_factor = TweakFloat("Gentle pushout factor", 10, 0, 50);
f32 gentle_pushout_factor = TweakFloat("Gentle pushout factor", 0.5, 0, 50);
////////////////////////////// //////////////////////////////
//- Bake world //- Bake world
@ -2324,6 +2367,21 @@ void P_StepFrame(P_Frame *frame)
P_Space pre_solve_ents_space = P_SpaceFromEnts(scratch.arena, frame); P_Space pre_solve_ents_space = P_SpaceFromEnts(scratch.arena, frame);
//////////////////////////////
//- Setup constraint constants
i32 solver_steps_count = SIM_PHYSICS_SUBSTEPS;
f32 solver_dt = sim_dt / solver_steps_count;
// Solid params
// SoftSpring solid_spring = MakeSpring(TweakFloat("Contact spring hz", 25, 5, 200), TweakFloat("Contact spring damp", 10, 5, 100), solver_dt);
SoftSpring solid_spring = MakeSpring(TweakFloat("Contact spring hz", 100, 5, 200), TweakFloat("Contact spring damp", 10, 5, 100), solver_dt);
f32 solid_pushout_velocity = TweakFloat("Contact spring pushout", 3, 0, 50);
// Gentle params
// f32 gentle_pushout_factor = TweakFloat("Gentle pushout factor", 10, 0, 50);
f32 gentle_pushout_factor = TweakFloat("Gentle pushout factor", 0.5, 0, 50);
////////////////////////////// //////////////////////////////
//- Generate guy constraints //- Generate guy constraints
@ -2842,8 +2900,8 @@ void P_StepFrame(P_Frame *frame)
for (P_Ent *firer = P_FirstEnt(frame); !P_IsEntNil(firer); firer = P_NextEnt(firer)) for (P_Ent *firer = P_FirstEnt(frame); !P_IsEntNil(firer); firer = P_NextEnt(firer))
{ {
P_Ent *weapon = P_EntFromKey(frame, firer->weapon); P_Ent *weapon = P_EntFromKey(frame, firer->weapon);
if (weapon->is_weapon && firer->control.fire_held) // if (weapon->is_weapon && firer->control.fire_held)
// if (weapon->is_weapon && firer->control.fire_presses) if (weapon->is_weapon && firer->control.fire_presses)
{ {
// i64 fire_delta_ns = frame->time_ns - firer->last_fire_ns; // i64 fire_delta_ns = frame->time_ns - firer->last_fire_ns;

View File

@ -80,6 +80,8 @@ Struct(P_DebugDrawNode)
#define P_MinPlayerNameLen 1 #define P_MinPlayerNameLen 1
#define P_MaxPlayerNameLen 24 #define P_MaxPlayerNameLen 24
#define P_RollTimeNs NsFromSeconds(0.5)
#define P_RollTimeoutNs NsFromSeconds(1)
Struct(P_Control) Struct(P_Control)
{ {
@ -93,6 +95,7 @@ Struct(P_Control)
Vec2 look; Vec2 look;
f32 fire_held; f32 fire_held;
f32 fire_presses; f32 fire_presses;
f32 roll_presses;
}; };
Struct(P_Ent) Struct(P_Ent)
@ -164,6 +167,8 @@ Struct(P_Ent)
//- Guy //- Guy
P_EntKey weapon; P_EntKey weapon;
i64 last_roll_time_ns;
Vec2 last_roll_dir;
//- Weapon //- Weapon
@ -613,9 +618,10 @@ P_Shape P_LocalShapeFromEnt(P_Ent *ent);
P_Shape P_WorldShapeFromEnt(P_Ent *ent); P_Shape P_WorldShapeFromEnt(P_Ent *ent);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Animation helpers //~ Status helpers
P_Anim P_AnimFromEnt(P_Frame *frame, P_Ent *ent); P_Anim P_AnimFromEnt(P_Frame *frame, P_Ent *ent);
b32 P_IsEntRolling(P_Frame *frame, P_Ent *ent);
//////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////
//~ Collision //~ Collision

BIN
src/pp/pp_res/guy/guy.ase (Stored with Git LFS)

Binary file not shown.

View File

@ -21,13 +21,13 @@ String P_PackWorld(Arena *arena, P_World *src_world)
result.len += PushString(arena, Lit("{\n")).len; result.len += PushString(arena, Lit("{\n")).len;
for (P_Ent *ent = P_FirstEnt(src_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent)) for (P_Ent *ent = P_FirstEnt(src_frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
{ {
// TODO: Pack bullets // TODO: Pack ignored ents
b32 should_pack = 1; b32 ignore = 0;
if (ent->is_bullet) if (ent->is_bullet || ent->is_weapon)
{ {
should_pack = 0; ignore = 1;
} }
if (should_pack) if (!ignore)
{ {
result.len += StringF(arena, " 0x%F:\n", FmtHex(ent->key.v)).len; result.len += StringF(arena, " 0x%F:\n", FmtHex(ent->key.v)).len;
result.len += PushString(arena, Lit(" {\n")).len; result.len += PushString(arena, Lit(" {\n")).len;
@ -67,9 +67,9 @@ String P_PackWorld(Arena *arena, P_World *src_world)
result.len += StringF(arena, " angle: \"%F\"\n", FmtFloat(AngleFromVec2(ent->xf.r))).len; result.len += StringF(arena, " angle: \"%F\"\n", FmtFloat(AngleFromVec2(ent->xf.r))).len;
result.len += StringF(arena, " look: \"%F\"\n", FmtFloat2(ent->control.look)).len; result.len += StringF(arena, " look: \"%F\"\n", FmtFloat2(ent->control.look)).len;
result.len += StringF(arena, " exists: \"%F\"\n", FmtFloat(ent->exists)).len; result.len += StringF(arena, " exists: \"%F\"\n", FmtFloat(ent->exists)).len;
result.len += StringF(arena, " look: \"%F\"\n", FmtFloat2(ent->control.look)).len;
result.len += StringF(arena, " health: \"%F\"\n", FmtFloat(ent->health)).len; result.len += StringF(arena, " health: \"%F\"\n", FmtFloat(ent->health)).len;
result.len += StringF(arena, " guy: \"0x%F\"\n", FmtHex(ent->guy.v)).len; result.len += StringF(arena, " guy: \"0x%F\"\n", FmtHex(ent->guy.v)).len;
result.len += StringF(arena, " weapon: \"0x%F\"\n", FmtHex(ent->weapon.v)).len;
result.len += StringF(arena, " source: \"0x%F\"\n", FmtHex(ent->source.v)).len; result.len += StringF(arena, " source: \"0x%F\"\n", FmtHex(ent->source.v)).len;
result.len += StringF(arena, " kills: \"%F\"\n", FmtFloat(ent->kills)).len; result.len += StringF(arena, " kills: \"%F\"\n", FmtFloat(ent->kills)).len;
result.len += StringF(arena, " deaths: \"%F\"\n", FmtFloat(ent->deaths)).len; result.len += StringF(arena, " deaths: \"%F\"\n", FmtFloat(ent->deaths)).len;
@ -202,10 +202,6 @@ P_UnpackedWorld P_UnpackWorld(Arena *arena, String packed)
{ {
ent->exists = CR_FloatFromString(attr->value); ent->exists = CR_FloatFromString(attr->value);
} }
if (MatchString(attr->name, Lit("look")))
{
ent->control.look = CR_Vec2FromString(attr->value);
}
if (MatchString(attr->name, Lit("health"))) if (MatchString(attr->name, Lit("health")))
{ {
ent->health = CR_FloatFromString(attr->value); ent->health = CR_FloatFromString(attr->value);
@ -214,6 +210,10 @@ P_UnpackedWorld P_UnpackWorld(Arena *arena, String packed)
{ {
ent->guy.v = CR_IntFromString(attr->value); ent->guy.v = CR_IntFromString(attr->value);
} }
if (MatchString(attr->name, Lit("weapon")))
{
ent->weapon.v = CR_IntFromString(attr->value);
}
if (MatchString(attr->name, Lit("source"))) if (MatchString(attr->name, Lit("source")))
{ {
ent->source.v = CR_IntFromString(attr->value); ent->source.v = CR_IntFromString(attr->value);

View File

@ -598,6 +598,8 @@ void V_TickForever(WaveLaneCtx *lane)
frame->ui_debug = prev_frame->ui_debug; frame->ui_debug = prev_frame->ui_debug;
frame->show_console = prev_frame->show_console; frame->show_console = prev_frame->show_console;
frame->look = prev_frame->look; frame->look = prev_frame->look;
frame->fire_presses = prev_frame->fire_presses;
frame->roll_presses = prev_frame->roll_presses;
frame->edit_mode = prev_frame->edit_mode; frame->edit_mode = prev_frame->edit_mode;
frame->equipped_tile = prev_frame->equipped_tile; frame->equipped_tile = prev_frame->equipped_tile;
frame->equipped_prefab = prev_frame->equipped_prefab ; frame->equipped_prefab = prev_frame->equipped_prefab ;
@ -903,9 +905,8 @@ void V_TickForever(WaveLaneCtx *lane)
if (frame->held_buttons[Button_S]) move.y += 1; if (frame->held_buttons[Button_S]) move.y += 1;
} }
move = ClampVec2Len(move, 0, 1); move = ClampVec2Len(move, 0, 1);
f32 fire_held = frame->held_buttons[Button_M1];
Vec2 look = Zi; Vec2 look = Zi;
f32 fire_presses = fire_held && !prev_frame->held_buttons[Button_M1];
{ {
f32 mouse_sensitivity = TweakFloat("Mouse sensitivity", 1.0, 0.1, 5.0); f32 mouse_sensitivity = TweakFloat("Mouse sensitivity", 1.0, 0.1, 5.0);
f32 mouse_scale_factor = 0.007; f32 mouse_scale_factor = 0.007;
@ -924,11 +925,18 @@ void V_TickForever(WaveLaneCtx *lane)
look = ClampVec2Len(look, min_look_radius, max_look_radius); look = ClampVec2Len(look, min_look_radius, max_look_radius);
} }
f32 fire_held = frame->held_buttons[Button_M1];
f32 roll_held = frame->held_buttons[Button_Space];
f32 fire_presses = fire_held && !prev_frame->held_buttons[Button_M1];
f32 roll_presses = roll_held && !prev_frame->held_buttons[Button_Space];
if (frame->is_looking) if (frame->is_looking)
{ {
frame->look = look; frame->look = look;
frame->fire_held = fire_held; frame->fire_held = fire_held;
frame->fire_presses = fire_presses; frame->fire_presses += fire_presses;
frame->roll_presses += roll_presses;
} }
if (frame->is_moving) if (frame->is_moving)
@ -944,7 +952,8 @@ void V_TickForever(WaveLaneCtx *lane)
frame->edit_camera_pos = AddVec2(frame->edit_camera_pos, MulVec2(move, edit_move_speed * frame->dt)); frame->edit_camera_pos = AddVec2(frame->edit_camera_pos, MulVec2(move, edit_move_speed * frame->dt));
} }
} }
frame->look = frame->look;
DEBUGBREAKABLE;
} }
////////////////////////////// //////////////////////////////
@ -1075,6 +1084,7 @@ void V_TickForever(WaveLaneCtx *lane)
frame->af.screen_to_shade = AffineIdentity; frame->af.screen_to_shade = AffineIdentity;
{ {
frame->af.shade_to_screen = MulAffine(frame->af.world_to_screen, frame->af.shade_to_world); frame->af.shade_to_screen = MulAffine(frame->af.world_to_screen, frame->af.shade_to_world);
frame->af.shade_to_screen.og = RoundVec2(frame->af.shade_to_screen.og);
frame->af.screen_to_shade = InvertAffine(frame->af.shade_to_screen); frame->af.screen_to_shade = InvertAffine(frame->af.shade_to_screen);
} }
@ -1085,6 +1095,7 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
frame->af.world_to_cell = ScaleAffine(frame->af.world_to_cell, VEC2(P_CellsPerMeter, P_CellsPerMeter)); frame->af.world_to_cell = ScaleAffine(frame->af.world_to_cell, VEC2(P_CellsPerMeter, P_CellsPerMeter));
frame->af.world_to_cell = TranslateAffine(frame->af.world_to_cell, VEC2((P_WorldPitch / 2.0), (P_WorldPitch / 2.0))); frame->af.world_to_cell = TranslateAffine(frame->af.world_to_cell, VEC2((P_WorldPitch / 2.0), (P_WorldPitch / 2.0)));
frame->af.world_to_cell.og = RoundVec2(frame->af.world_to_cell.og);
frame->af.cell_to_world = InvertAffine(frame->af.world_to_cell); frame->af.cell_to_world = InvertAffine(frame->af.world_to_cell);
} }
@ -1095,6 +1106,7 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
frame->af.world_to_tile = ScaleAffine(frame->af.world_to_tile, VEC2(P_TilesPerMeter, P_TilesPerMeter)); frame->af.world_to_tile = ScaleAffine(frame->af.world_to_tile, VEC2(P_TilesPerMeter, P_TilesPerMeter));
frame->af.world_to_tile = TranslateAffine(frame->af.world_to_tile, VEC2((P_WorldPitch / 2.0), (P_WorldPitch / 2.0))); frame->af.world_to_tile = TranslateAffine(frame->af.world_to_tile, VEC2((P_WorldPitch / 2.0), (P_WorldPitch / 2.0)));
// frame->af.world_to_tile.og = RoundVec2(frame->af.world_to_tile.og);
frame->af.tile_to_world = InvertAffine(frame->af.world_to_tile); frame->af.tile_to_world = InvertAffine(frame->af.world_to_tile);
} }
@ -1394,8 +1406,11 @@ void V_TickForever(WaveLaneCtx *lane)
control.move = frame->move; control.move = frame->move;
control.look = frame->look; control.look = frame->look;
control.fire_held = frame->fire_held; control.fire_held = frame->fire_held;
// FIXME: Don't propagate fire presses over multiple sim frames
control.fire_presses = frame->fire_presses; control.fire_presses = frame->fire_presses;
control.roll_presses = frame->roll_presses;
frame->fire_presses = 0;
frame->roll_presses = 0;
//- Fill controls buffer backwards //- Fill controls buffer backwards
i64 max_fill_count = SIM_TICKS_PER_SECOND / 4; i64 max_fill_count = SIM_TICKS_PER_SECOND / 4;
@ -2641,7 +2656,7 @@ void V_TickForever(WaveLaneCtx *lane)
// } // }
// // for (P_QueryResult query = P_FirstRaycast(wrold, ray_start, ray_dir); query. // // for (P_QueryResult query = P_FirstRaycast(world, ray_start, ray_dir); query.
// // P_RaycastWorldResult hits = P_RaycastWorld(local_frame, ray_start, ray_dir) // // P_RaycastWorldResult hits = P_RaycastWorld(local_frame, ray_start, ray_dir)
// // { // // {
// // } // // }

View File

@ -595,9 +595,9 @@ ComputeShader2D(V_CompositeCS, 8, 8)
Vec2 screen_pos = SV_DispatchThreadID.xy + 0.5; Vec2 screen_pos = SV_DispatchThreadID.xy + 0.5;
Vec2 world_pos = mul(frame.af.screen_to_world, Vec3(screen_pos, 1)); Vec2 world_pos = mul(frame.af.screen_to_world, Vec3(screen_pos, 1));
Vec2 tile_pos = mul(frame.af.world_to_tile, Vec3(world_pos, 1));
Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(world_pos, 1)); Vec2 cell_pos = mul(frame.af.world_to_cell, Vec3(world_pos, 1));
Vec2 shade_pos = mul(frame.af.screen_to_shade, Vec3(screen_pos.xy, 1)); Vec2 shade_pos = mul(frame.af.screen_to_shade, Vec3(screen_pos.xy, 1));
Vec2 tile_pos = mul(frame.af.world_to_tile, Vec3(world_pos, 1));
Vec2 half_world_dims = Vec2(P_WorldPitch, P_WorldPitch) * 0.5; Vec2 half_world_dims = Vec2(P_WorldPitch, P_WorldPitch) * 0.5;
Vec2 world_bounds_screen_p0 = mul(frame.af.world_to_screen, Vec3(-half_world_dims.xy, 1)); Vec2 world_bounds_screen_p0 = mul(frame.af.world_to_screen, Vec3(-half_world_dims.xy, 1));
@ -663,32 +663,24 @@ ComputeShader2D(V_CompositeCS, 8, 8)
{ {
V_TileDesc tile_desc = frame.tile_descs[tile]; V_TileDesc tile_desc = frame.tile_descs[tile];
Texture2D<Vec4> tile_tex = G_Dereference<Vec4>(tile_desc.tex); Texture2D<Vec4> tile_tex = G_Dereference<Vec4>(tile_desc.tex);
Vec2 tile_samp_uv = lerp(tile_desc.tex_slice_uv.p0, tile_desc.tex_slice_uv.p1, frac(world_pos)); Vec2 samp_t = clamp(frac(world_pos), 0.00001, 1.0 - 0.00001);
Vec2 tile_samp_uv = lerp(tile_desc.tex_slice_uv.p0, tile_desc.tex_slice_uv.p1, samp_t);
tile_color = tile_tex.SampleLevel(sampler, tile_samp_uv, 0); tile_color = tile_tex.SampleLevel(sampler, tile_samp_uv, 0);
} }
// Checkered grid
else if (tile == P_TileKind_Empty) else if (tile == P_TileKind_Empty)
{ {
// Checkered grid
i32 color_idx = 0; i32 color_idx = 0;
Vec4 colors[2] = { Vec4 colors[2] = {
LinearFromSrgb(Vec4(0.30, 0.30, 0.30, 1)), LinearFromSrgb(Vec4(0.30, 0.30, 0.30, 1)),
LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1)) LinearFromSrgb(Vec4(0.15, 0.15, 0.15, 1))
}; };
const f32 checker_size = 0.5; Vec2 tile_pos_mod = fmod(abs(tile_pos), Vec2(2, 2));
Vec2 world_pos_modded = fmod(abs(world_pos), Vec2(checker_size * 2, checker_size * 2)); if (tile_pos_mod.x < 1)
if (world_pos_modded.x < checker_size)
{ {
color_idx = !color_idx; color_idx = !color_idx;
} }
if (world_pos_modded.y < checker_size) if (tile_pos_mod.y < 1)
{
color_idx = !color_idx;
}
if (world_pos.x < 0)
{
color_idx = !color_idx;
}
if (world_pos.y < 0)
{ {
color_idx = !color_idx; color_idx = !color_idx;
} }

View File

@ -335,6 +335,7 @@ Struct(V_SharedFrame)
Vec2 look; Vec2 look;
f32 fire_held; f32 fire_held;
f32 fire_presses; f32 fire_presses;
f32 roll_presses;
//- Gpu data //- Gpu data