summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraura <nw@moneybot.cc>2026-03-01 18:04:13 +0100
committeraura <nw@moneybot.cc>2026-03-01 18:04:13 +0100
commitda27ee18bef82c2152e348e8ff805cb64c80643e (patch)
tree795e8161b4451bec2ef20b62e197aa1df727bc75
parent78db9dd151f7c7719787a7e092f0c34ae6b85179 (diff)
fix ramps make movement s m o o t h
-rw-r--r--assets/maps/test.hmap29
-rw-r--r--src/game/physics/movement.cpp111
-rw-r--r--src/game/world/trace.cpp2
-rw-r--r--src/game/world/trace.h2
-rw-r--r--src/util/vector.h1
5 files changed, 107 insertions, 38 deletions
diff --git a/assets/maps/test.hmap b/assets/maps/test.hmap
index 16b1394..df52de5 100644
--- a/assets/maps/test.hmap
+++ b/assets/maps/test.hmap
@@ -1,6 +1,6 @@
DEF map {
I32 wallcount = 7;
- I32 polycount = 1;
+ I32 polycount = 2;
I32 propcount = 5;
I32 spritecount = 1;
VEC3 startpos = { 84, 109, -39.75 };
@@ -90,6 +90,33 @@ DEF map {
}
}
}
+ DEF 1 {
+ I32 vertcount = 4;
+ I32 propid = 0;
+ I32 type = 0;
+ DEF vertices {
+ DEF 0 {
+ VEC3 pos = { 188, 187, -7.5 };
+ VEC2 uv = { 1, 0 };
+ CLR clr = { 1, 1, 1, 1 };
+ }
+ DEF 1 {
+ VEC3 pos = { 6, 187, -7.5 };
+ VEC2 uv = { 0, 0 };
+ CLR clr = { 1, 1, 1, 1 };
+ }
+ DEF 2 {
+ VEC3 pos = { 6.79887, 133.711, -40 };
+ VEC2 uv = { 0, 1 };
+ CLR clr = { 1, 1, 1, 1 };
+ }
+ DEF 3 {
+ VEC3 pos = { 188.102, 133.711, -40 };
+ VEC2 uv = { 1, 1 };
+ CLR clr = { 1, 1, 1, 1 };
+ }
+ }
+ }
}
DEF sprites {
DEF 0 {
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;
}
diff --git a/src/game/world/trace.cpp b/src/game/world/trace.cpp
index 1c28d78..3548fa8 100644
--- a/src/game/world/trace.cpp
+++ b/src/game/world/trace.cpp
@@ -243,7 +243,7 @@ U8 bsp_trace_sweep_aabb_to_face(
}
}
- if( fabsf( ndir ) < BSP_TRACE_EPSILON )
+ if( ndir > BSP_TRACE_EPSILON )
return 0;
F32 t_enter = (-radius - s0) / ndir;
diff --git a/src/game/world/trace.h b/src/game/world/trace.h
index 644515d..d04ed6b 100644
--- a/src/game/world/trace.h
+++ b/src/game/world/trace.h
@@ -5,7 +5,7 @@
// quake uses 1 / 32
const F32 BSP_TRACE_EPSILON = 1.f / 64.f;
-const F32 BSP_EDGE_TOLERANCE = 1.f / 64.f;
+const F32 BSP_EDGE_TOLERANCE = 1.f / 16.f;
struct BSP_TRACE {
VEC3 in_start;
diff --git a/src/util/vector.h b/src/util/vector.h
index d492e8d..6065343 100644
--- a/src/util/vector.h
+++ b/src/util/vector.h
@@ -54,6 +54,7 @@ struct VEC3 {
VEC3( const VEC2& v ) { x = v.x; y = v.y; z = 0.f; }
+ bool operator==( const VEC3& v ) const { return ( x == v.x && y == v.y && z == v.z ); }
VEC3& operator=( const VEC3& v ) { x = v.x; y = v.y; z = v.z; return *this; }
F32& operator[]( I32 i ) { return ( (F32*)this )[i]; }
F32 operator[]( I32 i ) const { return ( (F32*)this )[i]; }