diff options
| author | aura <nw@moneybot.cc> | 2026-02-25 14:45:28 +0100 |
|---|---|---|
| committer | aura <nw@moneybot.cc> | 2026-02-25 14:45:28 +0100 |
| commit | b384930de5044934207d1b2ceb4fa55705094f8b (patch) | |
| tree | 7937d3382e83ead2db1851b4a02b8378d02ac150 /src/game/physics/movement.cpp | |
| parent | cabe4471c309b2bba3be78b8346c9007485b1d57 (diff) | |
movement stuff + fix map zoom when dragging
Diffstat (limited to 'src/game/physics/movement.cpp')
| -rw-r--r-- | src/game/physics/movement.cpp | 204 |
1 files changed, 181 insertions, 23 deletions
diff --git a/src/game/physics/movement.cpp b/src/game/physics/movement.cpp index e9e0132..c9b7688 100644 --- a/src/game/physics/movement.cpp +++ b/src/game/physics/movement.cpp @@ -5,6 +5,12 @@ #include "../../game.h" GAME_MOVEMENT* gmove; +CVAR* mv_gravity = var_new( "mv_gravity", 5.5f ); +CVAR* mv_friction = var_new( "mv_friction", 5.f ); +CVAR* mv_accelerate = var_new( "mv_accelerate", 5.5f ); +CVAR* mv_airaccelerate = var_new( "mv_airaccelerate", 12.f ); +CVAR* mv_wallboost = var_new( "mv_wallboost", 0 ); +CVAR* mv_maxspeed = var_new( "mv_maxspeed", 3500.f ); void gmove_init( GAME_DATA* game ) { gmove = new GAME_MOVEMENT; @@ -45,6 +51,24 @@ void gmove_set_player( PLAYER* player ) { gmove->input = &player->input; } +void gmove_start_tick() { + PLAYER* p = gmove->pl; + gmove->velocity = p->velocity; + gmove->pos = p->pos; + gmove->angle = p->rot; + gmove->maxspeed = p->maxspeed; + gmove->walkspeed = p->walkspeed; + gmove->aabb.min = p->mins; + gmove->aabb.max = p->maxs; + gmove->bsp = gmove->game->state.map->bsp; +} + +void gmove_end_tick() { + PLAYER* p = gmove->pl; + p->velocity = gmove->velocity; + p->pos = gmove->pos; +} + VEC3 gmove_clip_velocity( VEC3 in, VEC3 norm, F32 overbounce ) { F32 blocked = vec_dot( in, norm ); F32 backoff = blocked * overbounce; @@ -54,14 +78,83 @@ VEC3 gmove_clip_velocity( VEC3 in, VEC3 norm, F32 overbounce ) { if( adjust < 0.f ) out -= (norm * adjust); - // uncomment to enable quake/hl1-like wallboosting - // F32 len = vec_len( out ); - // if( len > 0.f ) - // out *= ( -1.f * blocked + len ) / len; + 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 ); + + for( U32 i = 0; i < 3; ++i ) { + F32* v = &gmove->pl->velocity[i]; + if( isnan( *v ) ) *v = 0.f; continue; + if( *v > maxspeed ) *v = maxspeed; + if( *v < -maxspeed ) *v = -maxspeed; + } +} + +void gmove_start_gravity() { + F32 gravity = gmove->pl->gravity * var_getf( mv_gravity ); + + gmove->velocity.z -= gravity * 0.5f * TICK_INTERVAL; + gmove_check_velocity(); +} + +void gmove_end_gravity() { + +} + +void gmove_accelerate( VEC3& wishdir, F32 wishspeed, F32 accel ) { + F32 addspeed, accelspeed, currentspeed; + F32 surf_friction = 1.f; + + currentspeed = vec_dot( gmove->pl->velocity, wishdir ); + addspeed = wishspeed - currentspeed; + if( addspeed <= 0 ) + return; + + accelspeed = accel * TICK_INTERVAL * wishspeed * surf_friction; + if( accelspeed > addspeed ) + accelspeed = addspeed; + + gmove->velocity += wishdir * accelspeed; +} + +// todo: player hull extends at center instead of at feet +// should extend at feet +void gmove_stay_on_ground() { + BSP_TRACE tr{}; + VEC3 start = gmove->pos; + VEC3 end = gmove->pos; + + start.z += 2.f; + end.z -= gmove->pl->stepsize; + + bsp_trace( &tr, gmove->bsp, gmove->aabb, start, end ); + 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 > 0.5f * BSP_TRACE_EPSILON ) + gmove->pos = tr.point; + } +} + +void gmove_airaccelerate() { + +} + +void gmove_categorize_pos() { + +} + VEC3 gmove_clip_planes( VEC3 vel, LIST<VEC3>* planes, F32 overbounce ) { if( planes->size > 2 ) vel = {}; @@ -90,12 +183,13 @@ VEC3 gmove_clip_planes( VEC3 vel, LIST<VEC3>* planes, F32 overbounce ) { return vel; } -F32 gmove_try_move( BSP_TRACE* t, AABB aabb, VEC3* pos, VEC3 vel ) { - F32 dt = TICK_INTERVAL; +F32 gmove_try_move( BSP_TRACE* t, VEC3* pos, VEC3* vel ) { + F32 dt = TICK_INTERVAL; + AABB aabb = gmove->aabb; LIST<VEC3> planes; for( U32 bump = 0; bump < 4; ++bump ) { - VEC3 wishmove = vel * dt; + VEC3 wishmove = *vel * dt; bsp_trace( t, gmove->game->state.map->bsp, aabb, *pos, *pos + wishmove ); if( !t->hit ) { *pos = t->point; @@ -112,38 +206,100 @@ F32 gmove_try_move( BSP_TRACE* t, AABB aabb, VEC3* pos, VEC3 vel ) { if( dt <= 0.0001f ) break; - vel = gmove_clip_planes( vel, &planes, 1.f /* surface friction */ ); + *vel = gmove_clip_planes( *vel, &planes, 1.f /* todo : surface friction */ ); } return dt < 0 ? 0 : dt; } +void gmove_step_move( VEC3 dest, BSP_TRACE* tr ) { + VEC3 endpos = dest; + VEC3 pos = gmove->pos; + VEC3 vel = gmove->velocity; + + VEC3 up = pos, down = pos; + VEC3 upvel = vel, downvel = vel; + + gmove_try_move( tr, &down, &downvel ); + + 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 ) { + up = tr->point; + } + + gmove_try_move( tr, &up, &upvel ); + endpos = up; + endpos.z -= (gmove->pl->stepsize + BSP_DIST_EPSILON); + + bsp_trace( tr, gmove->bsp, gmove->aabb, up, endpos ); + if( tr->normal.z < 0.7 ) { // not ground, slope + gmove->pos = down; + gmove->velocity = downvel; + F32 step_dist = gmove->pos.z - pos.z; + gmove->out_step = step_dist; + return; + } + + if( !tr->startsolid && tr->frac > BSP_TRACE_EPSILON ) { + up = tr->point; + } + + F32 updist = vec_dist( pos, up ); + F32 downdist = vec_dist( pos, down ); + + gmove->out_step = gmove->pos.z - pos.z; + if( downdist > updist ) { + gmove->pos = down; + gmove->velocity = downvel; + } + else { + gmove->pos = up; + gmove->velocity = upvel; + return; + } +} + void gmove_walk_move() { - PLAYER* p = gmove->pl; - VEC2 move = gmove->input->move; - F32 yawrad = m_deg2rad( p->rot.y ); - VEC3 wishdir = { + VEC2 move = gmove->input->move; + F32 yawrad = m_deg2rad( gmove->angle.y ); + VEC3 wishdir = { move.x * cosf( yawrad ) - move.y * sinf( yawrad ), move.y * cosf( yawrad ) + move.x * sinf( yawrad ), 0 }; - VEC3 vel = wishdir * p->maxspeed; - VEC3 wishmove = vel * TICK_INTERVAL; - p->velocity = vel; + VEC3 vel = wishdir * gmove->walkspeed; + F32 speed = vec_len( vel ); + if( speed > gmove->maxspeed ) { + vel *= gmove->maxspeed / speed; + speed = gmove->maxspeed; + } - if( vec_len( wishmove ) < BSP_TRACE_EPSILON ) + gmove_accelerate( wishdir, speed, var_getf( mv_accelerate ) ); + speed = vec_len( vel ); + + if( speed < 1.f ) { + gmove->velocity = {}; return; + } + VEC3 dest = gmove->pos + vel * TICK_INTERVAL; BSP_TRACE tr{}; - AABB aabb{}; - aabb.min = p->mins; - aabb.max = p->maxs; - VEC3 npos = p->pos; + bsp_trace( &tr, gmove->bsp, gmove->aabb, gmove->pos, dest ); + + if( !tr.hit ) { + gmove->pos = dest; + gmove_stay_on_ground(); + return; + } + + gmove_step_move( dest, &tr ); + gmove_stay_on_ground(); +} - F32 frac = gmove_try_move( &tr, aabb, &npos, vel ); - p->velocity *= frac / TICK_INTERVAL; - p->pos = npos; +void gmove_full_walk_move() { + } void gmove_process_move() { @@ -153,5 +309,7 @@ void gmove_process_move() { void gmove_tick() { if( !gmove_check_valid( "gmove_tick()" ) ) return; + gmove_start_tick(); gmove_process_move(); + gmove_end_tick(); } |
