diff options
| author | aura <nw@moneybot.cc> | 2026-02-25 08:58:39 +0100 |
|---|---|---|
| committer | aura <nw@moneybot.cc> | 2026-02-25 08:58:39 +0100 |
| commit | 3e5e15a4923c752be703d7afb1214d5e5a767fad (patch) | |
| tree | d76049a556bd0fff581a018408faa6bed23b74eb /src/game/physics | |
| parent | 25da8e01a0499c273357cb2feb2825b53e86795b (diff) | |
finish wall collisions (clipvelocity), some utils
Diffstat (limited to 'src/game/physics')
| -rw-r--r-- | src/game/physics/movement.cpp | 157 | ||||
| -rw-r--r-- | src/game/physics/movement.h | 16 |
2 files changed, 173 insertions, 0 deletions
diff --git a/src/game/physics/movement.cpp b/src/game/physics/movement.cpp new file mode 100644 index 0000000..e9e0132 --- /dev/null +++ b/src/game/physics/movement.cpp @@ -0,0 +1,157 @@ +#include "movement.h" +#include "../world/trace.h" +#include "../../util/math.h" +#include "../../util/string.h" +#include "../../game.h" + +GAME_MOVEMENT* gmove; + +void gmove_init( GAME_DATA* game ) { + gmove = new GAME_MOVEMENT; + gmove->game = game; +} + +U8 gmove_check_valid( STR<256> from ) { + if( !gmove->game ) { + dlog( "%s : game not init\n", from.data ); + return 0; + } + + if( !gmove->pl ) { + dlog( "%s : player null\n", from.data ); + return 0; + } + + if( !gmove->input ) { + dlog( "%s : input null\n", from.data ); + return 0; + } + + if( !gmove->game->state.map ) { + dlog( "%s : no map loaded\n", from.data ); + return 0; + } + + if( !gmove->game->state.map->bsp ) { + dlog( "%s : no bsp loaded\n", from.data ); + return 0; + } + + return 1; +} + +void gmove_set_player( PLAYER* player ) { + gmove->pl = player; + gmove->input = &player->input; +} + +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); + + // uncomment to enable quake/hl1-like wallboosting + // F32 len = vec_len( out ); + // if( len > 0.f ) + // out *= ( -1.f * blocked + len ) / len; + + return out; +} + +VEC3 gmove_clip_planes( VEC3 vel, LIST<VEC3>* planes, F32 overbounce ) { + if( planes->size > 2 ) + vel = {}; + + planes->each( fn( VEC3* p ) { + vel = gmove_clip_velocity( vel, *p, overbounce ); + } ); + + if( planes->size > 1 ) { + for( U32 i = 0; i < planes->size; ++i ) { + if( vec_dot( vel, planes->data[i] ) < 0.f ) { + VEC3 dir = vec_cross( planes->data[0], planes->data[1] ); + F32 len = vec_len( dir ); + if( len > 0.00001f ) { + dir *= 1.0f / len; + vel = dir * vec_dot( vel, dir ); + } else { + vel = {}; + } + + break; + } + } + } + + return vel; +} + +F32 gmove_try_move( BSP_TRACE* t, AABB aabb, VEC3* pos, VEC3 vel ) { + F32 dt = TICK_INTERVAL; + LIST<VEC3> planes; + + for( U32 bump = 0; bump < 4; ++bump ) { + VEC3 wishmove = vel * dt; + bsp_trace( t, gmove->game->state.map->bsp, aabb, *pos, *pos + wishmove ); + if( !t->hit ) { + *pos = t->point; + break; + } + + *pos += wishmove * t->frac; + // nudge player away from wall + *pos += t->normal * (BSP_TRACE_EPSILON * 2.f); + + planes.push( t->normal ); + + dt *= (1.f - t->frac); + if( dt <= 0.0001f ) + break; + + vel = gmove_clip_planes( vel, &planes, 1.f /* surface friction */ ); + } + + return dt < 0 ? 0 : dt; +} + +void gmove_walk_move() { + PLAYER* p = gmove->pl; + VEC2 move = gmove->input->move; + F32 yawrad = m_deg2rad( p->rot.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; + + if( vec_len( wishmove ) < BSP_TRACE_EPSILON ) + return; + + BSP_TRACE tr{}; + AABB aabb{}; + aabb.min = p->mins; + aabb.max = p->maxs; + VEC3 npos = p->pos; + + F32 frac = gmove_try_move( &tr, aabb, &npos, vel ); + p->velocity *= frac / TICK_INTERVAL; + p->pos = npos; +} + +void gmove_process_move() { + gmove_walk_move(); +} + +void gmove_tick() { + if( !gmove_check_valid( "gmove_tick()" ) ) + return; + gmove_process_move(); +} diff --git a/src/game/physics/movement.h b/src/game/physics/movement.h index e69de29..7c78d79 100644 --- a/src/game/physics/movement.h +++ b/src/game/physics/movement.h @@ -0,0 +1,16 @@ +#pragma once + +#include "../player.h" + +struct GAME_MOVEMENT { + PLAYER* pl; + PLAYER_INPUT* input; + GAME_DATA* game; +}; + +extern void gmove_init( GAME_DATA* game ); +extern void gmove_set_player( PLAYER* player ); +extern void gmove_tick(); +extern void gmove_process_move(); + +extern GAME_MOVEMENT* gmove; |
