diff options
| author | aura <nw@moneybot.cc> | 2026-03-01 18:04:13 +0100 |
|---|---|---|
| committer | aura <nw@moneybot.cc> | 2026-03-01 18:04:13 +0100 |
| commit | da27ee18bef82c2152e348e8ff805cb64c80643e (patch) | |
| tree | 795e8161b4451bec2ef20b62e197aa1df727bc75 /src/game/physics | |
| parent | 78db9dd151f7c7719787a7e092f0c34ae6b85179 (diff) | |
fix ramps make movement s m o o t h
Diffstat (limited to 'src/game/physics')
| -rw-r--r-- | src/game/physics/movement.cpp | 111 |
1 files changed, 76 insertions, 35 deletions
diff --git a/src/game/physics/movement.cpp b/src/game/physics/movement.cpp index 73c5202..1e2e973 100644 --- a/src/game/physics/movement.cpp +++ b/src/game/physics/movement.cpp @@ -80,23 +80,6 @@ void gmove_end_tick() { p->flags &= ~PFL_ONGROUND; } -VEC3 gmove_clip_velocity( VEC3 in, VEC3 norm, F32 overbounce ) { - F32 blocked = vec_dot( in, norm ); - F32 backoff = blocked * overbounce; - VEC3 out = in - norm * backoff; - - F32 adjust = vec_dot( out, norm ); - if( adjust < 0.f ) - out -= (norm * adjust); - - if( var_geti( mv_wallboost ) ) { - F32 len = vec_len( out ); - if( len > 0.f ) - out *= ( -1.f * blocked + len ) / len; - } - - return out; -} void gmove_check_velocity() { F32 maxspeed = var_getf( mv_maxspeed ); @@ -203,6 +186,27 @@ void gmove_categorize_pos() { gmove->ground = objl->world; } } + + if( gmove->ground ) + gmove->velocity.z = 0.f; +} + +VEC3 gmove_clip_velocity( VEC3 in, VEC3 norm, F32 overbounce ) { + F32 blocked = vec_dot( in, norm ); + F32 backoff = blocked * overbounce; + VEC3 out = in - norm * backoff; + + F32 adjust = vec_dot( out, norm ); + if( adjust < 0.f ) + out -= (norm * adjust); + + if( var_geti( mv_wallboost ) ) { + F32 len = vec_len( out ); + if( len > 0.f ) + out *= ( -1.f * blocked + len ) / len; + } + + return out; } VEC3 gmove_clip_planes( VEC3 vel, VEC3* pos, LIST<VEC3>* planes, F32 overbounce ) { @@ -236,9 +240,11 @@ VEC3 gmove_clip_planes( VEC3 vel, VEC3* pos, LIST<VEC3>* planes, F32 overbounce } F32 gmove_try_move( BSP_TRACE* t, VEC3* pos, VEC3* vel ) { + VEC3 origin = *pos; F32 dt = TICK_INTERVAL; AABB aabb = gmove->aabb; LIST<VEC3> planes; + I32 nudges = 0; for( U32 bump = 0; bump < 4; ++bump ) { VEC3 wishmove = *vel * dt; @@ -248,12 +254,24 @@ F32 gmove_try_move( BSP_TRACE* t, VEC3* pos, VEC3* vel ) { break; } + F32 dot = vec_dot( *vel, t->normal ); *pos += wishmove * t->frac; // nudge player away from wall - if( vec_dot( *vel, t->normal ) < 0.f ) - *pos += t->normal * (BSP_TRACE_EPSILON * 2.f); - - planes.push( t->normal ); + *pos += t->normal * BSP_TRACE_EPSILON * 4.f; + + // avoid clipping planes twice + // in a rare edge case its possible to get stuck in the plane again after pushing away from it + if( fabsf( dot ) > 0.0001f || planes.idx_of( t->normal ) == -1 ) + planes.push( t->normal ); + else { + --bump; + if( nudges++ > 3 ) { + *vel = {}; + *pos = origin; + break; + } + continue; + } dt *= (1.f - t->frac); if( dt <= 0.0001f ) @@ -396,19 +414,20 @@ void gmove_stay_on_ground() { start.z += 2.f; end.z -= gmove->pl->stepsize; - bsp_trace( &tr, gmove->bsp, gmove->aabb, start, end ); - start = tr.point + BSP_TRACE_EPSILON; + bsp_trace( &tr, gmove->bsp, gmove->aabb, gmove->pos, start ); + start = tr.point; bsp_trace( &tr, gmove->bsp, gmove->aabb, start, end ); if( tr.frac > 0.f && tr.frac < 1.f && !tr.startsolid && tr.normal.z >= 0.7f ) { F32 delta = fabs( gmove->pos.z - tr.point.z ); - if( delta > BSP_TRACE_EPSILON ) - gmove->pos = tr.point + tr.normal * BSP_EDGE_TOLERANCE; + if( delta > BSP_TRACE_EPSILON ) { + gmove->pos = tr.point + tr.normal * BSP_TRACE_EPSILON * 2.f; + gmove_check_stuck( &gmove->pos ); + } } } - void gmove_step_move( VEC3 dest, BSP_TRACE* tr ) { VEC3 endpos = dest; VEC3 pos = gmove->pos; @@ -416,17 +435,32 @@ void gmove_step_move( VEC3 dest, BSP_TRACE* tr ) { VEC3 up = pos, down = pos; VEC3 upvel = vel, downvel = vel; + F32 groundn = 0.f; + if( gmove->ground ) { + VEC3 ground = pos; + ground.z += 2.f; + bsp_trace( tr, gmove->bsp, gmove->aabb, pos, ground ); + if( tr->hit ) + groundn = tr->normal.z; + } + + // try moving forward first gmove_try_move( tr, &down, &downvel ); VEC3 downn = tr->normal; - endpos.z += gmove->pl->stepsize + BSP_DIST_EPSILON; + // move up a step + endpos = pos; + endpos.z += (gmove->pl->stepsize + BSP_DIST_EPSILON); + bsp_trace( tr, gmove->bsp, gmove->aabb, pos, endpos ); - if( !tr->startsolid && tr->frac > BSP_TRACE_EPSILON ) { + if( !tr->startsolid ) up = tr->point; - } gmove_try_move( tr, &up, &upvel ); + VEC3 upnorm = tr->normal; + + // move back down onto the ground endpos = up; endpos.z -= (gmove->pl->stepsize + BSP_DIST_EPSILON); @@ -443,9 +477,8 @@ void gmove_step_move( VEC3 dest, BSP_TRACE* tr ) { return; } - if( !tr->startsolid && tr->frac > BSP_TRACE_EPSILON ) { + if( !tr->startsolid ) up = tr->point; - } F32 updist = vec_dist( pos, up ); F32 downdist = vec_dist( pos, down ); @@ -454,13 +487,15 @@ void gmove_step_move( VEC3 dest, BSP_TRACE* tr ) { if( downdist > updist ) { gmove->pos = down; if( downn.z < 0.99f ) - gmove->pos += downn * BSP_TRACE_EPSILON * 2.f; + gmove->pos += downn * BSP_TRACE_EPSILON; gmove->velocity = downvel; } else { + // likely unnecessary but a sanity check + // avoid moving more than velocity per tick horizontally VEC3 delta = up - pos; - F32 dist = vec_len( delta ); - F32 speed = vec_len( gmove->velocity ) * TICK_INTERVAL; + F32 dist = vec_len2d( delta ); + F32 speed = vec_len2d( gmove->velocity ) * TICK_INTERVAL; if( dist > speed ) { for( U32 i = 0; i < 2; ++i ) delta[i] *= speed / dist; @@ -469,7 +504,11 @@ void gmove_step_move( VEC3 dest, BSP_TRACE* tr ) { gmove->pos += delta; if( tr->normal.z < 0.99f ) gmove->pos += tr->normal * BSP_TRACE_EPSILON * 2.f; + // hack : moving to a steeper slope, move up a bit to avoid getting stuck in the edge + if( gmove->ground && tr->normal.z < groundn ) + gmove->pos.z += BSP_TRACE_EPSILON; gmove->velocity = upvel; + gmove->velocity.z = downvel.z; } } @@ -496,12 +535,13 @@ void gmove_walk_move() { gmove->velocity[2] = 0; speed = vec_len( gmove->velocity ); - defer( gmove_check_stuck( &gmove->pos ) ); if( speed < 1.f ) { gmove->velocity = {}; + gmove_check_stuck( &gmove->pos ); return; } + VEC3 dest = gmove->pos + gmove->velocity * TICK_INTERVAL; BSP_TRACE tr{}; bsp_trace( &tr, gmove->bsp, gmove->aabb, gmove->pos, dest ); @@ -509,6 +549,7 @@ void gmove_walk_move() { defer( gmove_stay_on_ground() ); if( !tr.hit ) { gmove->pos = dest; + gmove_check_stuck( &gmove->pos ); return; } |
