summaryrefslogtreecommitdiff
path: root/src/game/physics
diff options
context:
space:
mode:
authoraura <nw@moneybot.cc>2026-02-25 14:45:28 +0100
committeraura <nw@moneybot.cc>2026-02-25 14:45:28 +0100
commitb384930de5044934207d1b2ceb4fa55705094f8b (patch)
tree7937d3382e83ead2db1851b4a02b8378d02ac150 /src/game/physics
parentcabe4471c309b2bba3be78b8346c9007485b1d57 (diff)
movement stuff + fix map zoom when dragging
Diffstat (limited to 'src/game/physics')
-rw-r--r--src/game/physics/movement.cpp204
-rw-r--r--src/game/physics/movement.h21
2 files changed, 202 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();
}
diff --git a/src/game/physics/movement.h b/src/game/physics/movement.h
index 7c78d79..47aa97d 100644
--- a/src/game/physics/movement.h
+++ b/src/game/physics/movement.h
@@ -1,11 +1,32 @@
#pragma once
+#include "../../util/aabb.h"
+#include "../world/bsp.h"
#include "../player.h"
+#include "../vars.h"
+
+extern CVAR* mv_gravity;
+extern CVAR* mv_friction;
+extern CVAR* mv_accelerate;
+extern CVAR* mv_airaccelerate;
+extern CVAR* mv_wallboost;
+extern CVAR* mv_maxspeed;
+
struct GAME_MOVEMENT {
PLAYER* pl;
PLAYER_INPUT* input;
GAME_DATA* game;
+
+ VEC3 velocity;
+ VEC3 pos;
+ VEC3 angle;
+ F32 maxspeed;
+ F32 walkspeed;
+ AABB aabb;
+ BSP* bsp;
+
+ F32 out_step;
};
extern void gmove_init( GAME_DATA* game );