slerp legs

This commit is contained in:
jacob 2026-04-04 18:06:34 -05:00
parent 92ed9a4c2d
commit be610d4055
7 changed files with 128 additions and 116 deletions

View File

@ -1992,20 +1992,7 @@ void P_SpawnEntsFromList(P_Frame *frame, P_EntList ents)
DllQueuePushNPZ(&P_NilEnt, frame->first_ent, frame->last_ent, dst, next, prev); DllQueuePushNPZ(&P_NilEnt, frame->first_ent, frame->last_ent, dst, next, prev);
DllQueuePushNP(bin->first, bin->last, dst, next_in_bin, prev_in_bin); DllQueuePushNP(bin->first, bin->last, dst, next_in_bin, prev_in_bin);
} }
{ dst->net_state = src->net_state;
P_Ent *old_next = dst->next;
P_Ent *old_prev = dst->prev;
P_Ent *old_next_in_bin = dst->next_in_bin;
P_Ent *old_prev_in_bin = dst->prev_in_bin;
{
*dst = *src;
dst->xf = NormXform(dst->xf);
}
dst->next = old_next;
dst->prev = old_prev;
dst->next_in_bin = old_next_in_bin;
dst->prev_in_bin = old_prev_in_bin;
}
dst->created_at_ns = frame->time_ns; dst->created_at_ns = frame->time_ns;
dst->created_at_tick = frame->tick; dst->created_at_tick = frame->tick;
dst->sim = !P_tl.is_client; dst->sim = !P_tl.is_client;
@ -3189,11 +3176,11 @@ void P_StepFrame(P_Frame *frame)
b32 is_bomb = 0; b32 is_bomb = 0;
if (button == P_Button_PrimaryFire && (firer->control.held[button] || firer->control.downs[button])) if (button == P_Button_PrimaryFire && (firer->control.held[button] || firer->control.downs[button]))
{ {
// fire_rate = 100; fire_rate = 25;
bullets_per_fire = 4; bullets_per_fire = 5;
// fire_rate = 50; // fire_rate = 50;
fire_rate = 50; // fire_rate = 50;
bullets_per_fire = 1; // bullets_per_fire = 1;
firing = (weapon->last_fire_ns + NsFromSeconds(1.0 / fire_rate)) <= frame->time_ns; firing = (weapon->last_fire_ns + NsFromSeconds(1.0 / fire_rate)) <= frame->time_ns;
if (firing) if (firing)
{ {
@ -3267,9 +3254,10 @@ void P_StepFrame(P_Frame *frame)
////////////////////////////// //////////////////////////////
//- Bullet properties //- Bullet properties
// f32 spread = Tau * 0.05; // f32 spread = Tau * 0.5;
f32 spread = Tau * 0.05;
// f32 spread = Tau * 0.2; // f32 spread = Tau * 0.2;
f32 spread = Tau * 0.01; // f32 spread = Tau * 0.01;
// f32 spread = 0; // f32 spread = 0;
b32 should_ricochet = 0; b32 should_ricochet = 0;
@ -3754,11 +3742,6 @@ void P_StepFrame(P_Frame *frame)
// } // }
// } // }
////////////////////////////// //////////////////////////////
//- Kill guys //- Kill guys
@ -3803,6 +3786,15 @@ void P_StepFrame(P_Frame *frame)
P_SpawnEntsFromList(frame, ents_to_spawn); P_SpawnEntsFromList(frame, ents_to_spawn);
} }
//////////////////////////////
//- Smooth values
for (P_Ent *ent = P_FirstEnt(frame); !P_IsEntNil(ent); ent = P_NextEnt(ent))
{
f32 lerp_rate = SaturateF32(25 * sim_dt);
ent->smoothed_move_dir = SlerpVec2(ent->smoothed_move_dir, NormVec2(ent->control.move), lerp_rate);
}
////////////////////////////// //////////////////////////////
//- Debug draw //- Debug draw

View File

@ -113,29 +113,13 @@ Struct(P_Control)
f32 downs[P_Button_COUNT]; f32 downs[P_Button_COUNT];
}; };
Struct(P_Ent) Struct(P_NetworkedEntState)
{ {
//- Internal world state
P_Ent *next;
P_Ent *prev;
P_Ent *next_in_bin;
P_Ent *prev_in_bin;
//- Persistent data //- Persistent data
P_EntKey key; P_EntKey key;
u64 rand_seq;
i64 created_at_ns; i64 created_at_ns;
i64 created_at_tick; i64 created_at_tick;
f64 lifetime_seconds;
//- Client data
i64 initial_observation_time_ns;
i64 last_observation_time_ns;
b32 is_first_observation;
//- Build data //- Build data
@ -150,12 +134,15 @@ Struct(P_Ent)
Xform xf; Xform xf;
f64 lifetime_seconds;
u64 rand_seq;
//- Bullet //- Bullet
b32 is_bullet; b32 is_bullet;
u32 bullet_hits_count; u32 bullet_hits_count;
//- Events //- Events
b32 is_trail; b32 is_trail;
@ -242,6 +229,35 @@ Struct(P_Ent)
Vec2 v; // Linear velocity Vec2 v; // Linear velocity
f32 w; // Angular velocity f32 w; // Angular velocity
//- Smoothed values
Vec2 smoothed_move_dir;
};
Struct(P_LocalEntState)
{
//- Observation info
i64 initial_observation_time_ns;
i64 last_observation_time_ns;
b32 is_first_observation;
// Vec2 smoothed_v;
// Vec2 smoothed_v_dir;
// Vec2 smoothed_move_dir;
// f32 smoothed_w;
};
Struct(P_Ent)
{
P_Ent *next;
P_Ent *prev;
P_Ent *next_in_bin;
P_Ent *prev_in_bin;
Embed(P_NetworkedEntState, net_state);
Embed(P_LocalEntState, local_state);
}; };
Struct(P_EntListNode) Struct(P_EntListNode)

View File

@ -794,7 +794,7 @@ void S_TickForever(WaveLaneCtx *lane)
{ {
// TODO: Delta compress // TODO: Delta compress
should_transmit = 1; should_transmit = 1;
BB_WriteBytes(&packer_bbw, StringFromStruct(ent)); BB_WriteBytes(&packer_bbw, StringFromStruct(&ent->net_state));
} }
u64 delta_end = BB_GetNumBytesWritten(&packer_bbw); u64 delta_end = BB_GetNumBytesWritten(&packer_bbw);
if (should_transmit) if (should_transmit)

View File

@ -52,30 +52,30 @@ PERSIST Readonly String P_PresetHumanNames[] = {
// Taken from a random GMOD server // Taken from a random GMOD server
PERSIST Readonly String P_PresetPlayerNames[] = { PERSIST Readonly String P_PresetPlayerNames[] = {
CompLit("lionberg"),
CompLit("charlie main"),
CompLit("frezh"),
CompLit("KARMA"),
CompLit("Kirep"), CompLit("Kirep"),
CompLit("Cyan Crayon"),
CompLit("THE WIFE"),
CompLit("Panda"),
CompLit("adoti"), CompLit("adoti"),
CompLit("yoyota"),
CompLit("Mr. Bones"),
CompLit("TaurusJ3"), CompLit("TaurusJ3"),
CompLit("dub"), CompLit("dub"),
CompLit("Tidunbly"), CompLit("Tidunbly"),
CompLit("Siepter"), CompLit("Siepter"),
CompLit("frezh"),
CompLit("lowayo"), CompLit("lowayo"),
CompLit("Zunix"), CompLit("Zunix"),
CompLit("_Runne_"), CompLit("_Runne_"),
CompLit("Fr0stie"), CompLit("Fr0stie"),
CompLit("Mr. Bones"),
CompLit("Lumby"), CompLit("Lumby"),
CompLit("Legs"), CompLit("Legs"),
CompLit("Talids"), CompLit("Talids"),
CompLit("yoyota"),
CompLit("Train"), CompLit("Train"),
CompLit("lionberg"),
CompLit("Cyan Crayon"),
CompLit("Poy"), CompLit("Poy"),
CompLit("Kaitsedd"), CompLit("Kaitsedd"),
CompLit("Panda"),
CompLit("THE WIFE"),
CompLit("KARMA"),
CompLit("jiyu"), CompLit("jiyu"),
CompLit("charlie main"),
}; };

View File

@ -1822,11 +1822,11 @@ void V_TickForever(WaveLaneCtx *lane)
while (!done && BB_NumBitsRemaining(&bbr) > 0) while (!done && BB_NumBitsRemaining(&bbr) > 0)
{ {
// TODO: Delta compress // TODO: Delta compress
P_Ent *raw_ent = (P_Ent *)BB_ReadBytesRaw(&bbr, sizeof(P_Ent)); P_NetworkedEntState *raw_net_state = (P_NetworkedEntState *)BB_ReadBytesRaw(&bbr, sizeof(P_NetworkedEntState));
if (raw_ent) if (raw_net_state)
{ {
P_EntListNode tmp_ent_node = Zi; P_EntListNode tmp_ent_node = Zi;
CopyStruct(&tmp_ent_node.ent, raw_ent); CopyStruct(&tmp_ent_node.ent.net_state, raw_net_state);
P_EntList ent_list = Zi; P_EntList ent_list = Zi;
ent_list.first = &tmp_ent_node; ent_list.first = &tmp_ent_node;
ent_list.last = &tmp_ent_node; ent_list.last = &tmp_ent_node;
@ -2429,8 +2429,10 @@ void V_TickForever(WaveLaneCtx *lane)
ent->xf.t = LerpVec2(left->xf.t, right->xf.t, blend_t); ent->xf.t = LerpVec2(left->xf.t, right->xf.t, blend_t);
ent->xf.r = SlerpVec2(left->xf.r, right->xf.r, blend_t); ent->xf.r = SlerpVec2(left->xf.r, right->xf.r, blend_t);
ent->walk_time_accum_ns = LerpI64(left->walk_time_accum_ns, right->walk_time_accum_ns, blend_t); ent->walk_time_accum_ns = LerpI64(left->walk_time_accum_ns, right->walk_time_accum_ns, blend_t);
ent->fire_time_accum_ns = LerpI64(left->fire_time_accum_ns, right->fire_time_accum_ns, blend_t);
ent->v = LerpVec2(left->v, right->v, blend_t); ent->v = LerpVec2(left->v, right->v, blend_t);
ent->w = LerpF32(left->w, right->w, blend_t); ent->w = LerpF32(left->w, right->w, blend_t);
ent->smoothed_move_dir = SlerpVec2(left->smoothed_move_dir, right->smoothed_move_dir, blend_t);
} }
} }
} }
@ -2456,6 +2458,8 @@ void V_TickForever(WaveLaneCtx *lane)
{ {
P_EntKey key = ent->key; P_EntKey key = ent->key;
i64 expiration_ns = NsFromSeconds(P_ObservationDurationSeconds); i64 expiration_ns = NsFromSeconds(P_ObservationDurationSeconds);
//- Fetch observation
V_Observation *obs = 0; V_Observation *obs = 0;
{ {
V_ObservationBin *bin = &V.observation_bins[key.v % countof(V.observation_bins)]; V_ObservationBin *bin = &V.observation_bins[key.v % countof(V.observation_bins)];
@ -2499,6 +2503,8 @@ void V_TickForever(WaveLaneCtx *lane)
} }
obs->last_observation_time_ns = frame->time_ns; obs->last_observation_time_ns = frame->time_ns;
} }
//- Observe
ent->last_observation_time_ns = frame->time_ns; ent->last_observation_time_ns = frame->time_ns;
ent->is_first_observation = obs->initial_observation_time_ns == frame->time_ns; ent->is_first_observation = obs->initial_observation_time_ns == frame->time_ns;
} }
@ -2897,7 +2903,8 @@ void V_TickForever(WaveLaneCtx *lane)
SPR_Sprite legs = Zi; SPR_Sprite legs = Zi;
Affine legs_pix_to_world_af = AffineIdentity; Affine legs_pix_to_world_af = AffineIdentity;
{ {
Vec2 legs_dir = NormVec2(ent->control.move); // Vec2 legs_dir = NormVec2(ent->control.move);
Vec2 legs_dir = ent->smoothed_move_dir;
if (P_IsEntRolling(local_frame, ent)) if (P_IsEntRolling(local_frame, ent))
{ {
legs_dir = ent->xf.r; legs_dir = ent->xf.r;
@ -3441,10 +3448,10 @@ void V_TickForever(WaveLaneCtx *lane)
//- Wall impact particles //- Wall impact particles
if (material != P_MaterialKind_Flesh) if (material != P_MaterialKind_Flesh)
{ {
// Hot debris //- Debris
{ {
V_Emitter emitter = Zi; V_Emitter emitter = Zi;
emitter.kind = V_ParticleKind_HotDebris; emitter.kind = V_ParticleKind_Debris;
emitter.count = 32; emitter.count = 32;
f32 angle = AngleFromVec2(impact_dir); f32 angle = AngleFromVec2(impact_dir);
@ -3466,13 +3473,13 @@ void V_TickForever(WaveLaneCtx *lane)
//- Wall spark //- Hot debris
{ {
V_Emitter emitter = Zi; V_Emitter emitter = Zi;
emitter.kind = V_ParticleKind_Spark; emitter.kind = V_ParticleKind_HotDebris;
// emitter.count = MaxF32(1000 * frame->dt, 1); // emitter.count = MaxF32(1000 * frame->dt, 1);
// emitter.count = 128; // emitter.count = 128;
emitter.count = 1; emitter.count = 32;
f32 angle = AngleFromVec2(impact_dir); f32 angle = AngleFromVec2(impact_dir);
@ -3668,12 +3675,16 @@ void V_TickForever(WaveLaneCtx *lane)
// f32 speed = 100; // f32 speed = 100;
f32 speed_spread = speed * 2; f32 speed_spread = speed * 2;
emitter.pos.p0 = emitter.pos.p1 = frame->world_cursor; f32 particles_per_meter_per_second = Kibi(128);
emitter.pos.p0 = prev_frame->world_cursor;
emitter.pos.p1 = frame->world_cursor;
f32 len_meters = MaxF32(Vec2Len(SubVec2(emitter.pos.p1, emitter.pos.p0)), 1);
emitter.count = particles_per_meter_per_second * len_meters * frame->dt;
emitter.speed.min = speed - speed_spread * 0.5; emitter.speed.min = speed - speed_spread * 0.5;
emitter.speed.max = speed + speed_spread * 0.5; emitter.speed.max = speed + speed_spread * 0.5;
emitter.angle.min = angle - angle_spread * 0.5; emitter.angle.min = angle - angle_spread * 0.5;
emitter.angle.max = angle + angle_spread * 0.5; emitter.angle.max = angle + angle_spread * 0.5;
emitter.count = Kibi(32) * frame->dt;
V_PushParticles(emitter); V_PushParticles(emitter);
} }
@ -3733,26 +3744,18 @@ void V_TickForever(WaveLaneCtx *lane)
f32 speed = 100; f32 speed = 100;
f32 speed_spread = speed * 2; f32 speed_spread = speed * 2;
emitter.pos.p0 = emitter.pos.p1 = frame->world_cursor; f32 particles_per_meter_per_second = Kibi(128);
emitter.pos.p0 = prev_frame->world_cursor;
emitter.pos.p1 = frame->world_cursor;
f32 len_meters = MaxF32(Vec2Len(SubVec2(emitter.pos.p1, emitter.pos.p0)), 1);
emitter.count = particles_per_meter_per_second * len_meters * frame->dt;
emitter.speed.min = speed - speed_spread * 0.5; emitter.speed.min = speed - speed_spread * 0.5;
emitter.speed.max = speed + speed_spread * 0.5; emitter.speed.max = speed + speed_spread * 0.5;
emitter.angle.min = angle - angle_spread * 0.5; emitter.angle.min = angle - angle_spread * 0.5;
emitter.angle.max = angle + angle_spread * 0.5; emitter.angle.max = angle + angle_spread * 0.5;
// emitter.falloff.min = emitter.falloff.max = 0;
// emitter.count = CeilF32(Kibi(64) * frame->dt);
// emitter.count = CeilF32(Mebi(32) * frame->dt);
// emitter.count = CeilF32(Mebi(8) * frame->dt);
// emitter.count = Mebi(16);
// emitter.count = Mebi(2);
// emitter.count = Kibi(32);
emitter.count = Kibi(8);
// emitter.count = 128;
// emitter.count = 128;
// emitter.count = 32;
// emitter.count = 1;
V_PushParticles(emitter); V_PushParticles(emitter);
} }
@ -5619,10 +5622,10 @@ void V_TickForever(WaveLaneCtx *lane)
// TODO: Remove this // TODO: Remove this
if (frame->tick == 1) // if (frame->tick == 1)
{ // {
frame->show_consoles = 1; // frame->show_consoles = 1;
} // }

View File

@ -378,6 +378,7 @@ Struct(V_Observation)
V_Observation *prev; V_Observation *prev;
V_Observation *next_in_bin; V_Observation *next_in_bin;
V_Observation *prev_in_bin; V_Observation *prev_in_bin;
u64 key; u64 key;
i64 initial_observation_time_ns; i64 initial_observation_time_ns;
i64 last_observation_time_ns; i64 last_observation_time_ns;

View File

@ -79,10 +79,10 @@ Enum(V_ParticleLayer)
/* Layer */ V_ParticleLayer_Mid, \ /* Layer */ V_ParticleLayer_Mid, \
/* Stain rate, pen chance */ 0, 0, \ /* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ Inf, Inf, \ /* Lifetime */ Inf, Inf, \
/* Falloff */ 10, 20, \ /* Falloff */ 20, 30, \
/* Prune speed threshold */ 0.01, \ /* Prune speed threshold */ 0.1, \
/* Base color */ VEC4(0.4, 0.3, 0.2, 1), \ /* Base color */ VEC4(0.4, 0.3, 0.2, 1), \
/* Dry color factor */ VEC4(1, 1, 1, 1) \ /* Dry color factor */ VEC4(0.2, 0.1, 0.1, 1) \
) \ ) \
X( \ X( \
/* Name */ Fire, \ /* Name */ Fire, \
@ -103,12 +103,12 @@ Enum(V_ParticleLayer)
/* Lifetime */ Inf, Inf, \ /* Lifetime */ Inf, Inf, \
/* Falloff */ 20, 30, \ /* Falloff */ 20, 30, \
/* Prune speed threshold */ 0.1, \ /* Prune speed threshold */ 0.1, \
/* Base color */ VEC4(0.4, 0.3, 0.2, 1), \ /* Base color */ VEC4(2, 0.5, 0, 1), \
/* Dry color factor */ VEC4(0.2, 0.1, 0.1, 1) \ /* Dry color factor */ VEC4(0.2, 0.1, 0.1, 1) \
) \ ) \
X( \ X( \
/* Name */ Spark, \ /* Name */ Spark, \
/* Flags */ V_ParticleFlag_StainWhenPruned, \ /* Flags */ V_ParticleFlag_None, \
/* Layer */ V_ParticleLayer_Mid, \ /* Layer */ V_ParticleLayer_Mid, \
/* Stain rate, pen chance */ 0, 0, \ /* Stain rate, pen chance */ 0, 0, \
/* Lifetime */ 0.2, 0.3, \ /* Lifetime */ 0.2, 0.3, \