summaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/game')
-rw-r--r--src/game/physics/movement.cpp204
-rw-r--r--src/game/physics/movement.h21
-rw-r--r--src/game/player.cpp3
-rw-r--r--src/game/player.h5
-rw-r--r--src/game/vars.cpp71
-rw-r--r--src/game/vars.h5
-rw-r--r--src/game/world/trace.cpp3
-rw-r--r--src/game/world/trace.h1
8 files changed, 268 insertions, 45 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 );
diff --git a/src/game/player.cpp b/src/game/player.cpp
index 65daa9b..74ecea2 100644
--- a/src/game/player.cpp
+++ b/src/game/player.cpp
@@ -6,7 +6,8 @@
#include <cmath>
#include "player.h"
-F32 PLAYER_HULL_HEIGHT = 50.f;
+// todo : temporary
+F32 PLAYER_HULL_HEIGHT = 1.f;
F32 PLAYER_HULL_WIDTH = 32.f;
PLAYER* player_create( VEC3 origin, F32 yaw ) {
diff --git a/src/game/player.h b/src/game/player.h
index c0e126d..7dfd009 100644
--- a/src/game/player.h
+++ b/src/game/player.h
@@ -2,7 +2,6 @@
#include "object.h"
#include "camera.h"
-
struct PLAYER_INPUT {
PLAYER_CAMERA cam;
struct PLAYER* pobj;
@@ -23,7 +22,11 @@ struct PLAYER : OBJECT {
VEC3 mins;
VEC3 maxs;
+ F32 gravity{1.f};
F32 maxspeed{70.f};
+ F32 walkspeed{70.f};
+ F32 stepsize{16.f};
+
VEC3 velocity;
};
diff --git a/src/game/vars.cpp b/src/game/vars.cpp
index d7b1f9b..3d1eaf4 100644
--- a/src/game/vars.cpp
+++ b/src/game/vars.cpp
@@ -4,16 +4,18 @@
VAR_LIST* varl;
+void vars_check_global_list() {
+ if( !varl )
+ varl = vars_init();
+}
+
VAR_LIST* vars_init() {
VAR_LIST* ret = new VAR_LIST;
return ret;
}
CVAR* var_new( const char* name, F32 v ) {
- if( !varl ) {
- dlog( "var_new() : error: varl null\n" );
- return 0;
- }
+ vars_check_global_list();
CVAR* ret = new CVAR;
memset( ret, 0 , sizeof( CVAR ) );
@@ -26,10 +28,7 @@ CVAR* var_new( const char* name, F32 v ) {
}
CVAR* var_new( const char* name, I32 i ) {
- if( !varl ) {
- dlog( "var_new() : error: varl null\n" );
- return 0;
- }
+ vars_check_global_list();
CVAR* ret = new CVAR;
memset( ret, 0 , sizeof( CVAR ) );
@@ -42,10 +41,7 @@ CVAR* var_new( const char* name, I32 i ) {
}
CVAR* var_new( const char* name, CLR c ) {
- if( !varl ) {
- dlog( "var_new() : error: varl null\n" );
- return 0;
- }
+ vars_check_global_list();
CVAR* ret = new CVAR;
memset( ret, 0 , sizeof( CVAR ) );
@@ -58,10 +54,7 @@ CVAR* var_new( const char* name, CLR c ) {
}
CVAR* var_new( const char* name, CVAR_FUNC func ) {
- if( !varl ) {
- dlog( "var_new() : error: varl null\n" );
- return 0;
- }
+ vars_check_global_list();
CVAR* ret = new CVAR;
memset( ret, 0 , sizeof( CVAR ) );
@@ -74,10 +67,7 @@ CVAR* var_new( const char* name, CVAR_FUNC func ) {
}
CVAR* var_new( const char* name, const char* v ) {
- if( !varl ) {
- dlog( "var_new() : error: varl null\n" );
- return 0;
- }
+ vars_check_global_list();
CVAR* ret = new CVAR;
memset( ret, 0, sizeof( CVAR ) );
@@ -113,3 +103,44 @@ I32 var_call( CVAR *cmdvar, const char *cmdline ) {
return cmdvar->fn_v( cmdvar, cmdline );
}
+
+F32 var_getf( CVAR *var ) {
+ switch( var->type ) {
+ case CVAR_TYPE_FLOAT: return var->fl_v;
+ case CVAR_TYPE_INT: return (F32)var->fl_v;
+ default: return 0.f;
+ }
+}
+
+I32 var_geti( CVAR *var ) {
+ switch( var->type ) {
+ case CVAR_TYPE_INT: return var->fl_v;
+ case CVAR_TYPE_FLOAT: return (I32)var->fl_v;
+ default: return 0;
+ }
+}
+
+CLR var_getclr( CVAR *var ) {
+ switch( var->type ) {
+ case CVAR_TYPE_COLOR: return var->clr_v;
+ case CVAR_TYPE_FLOAT: return (CLR){ var->fl_v, var->fl_v, var->fl_v, 1.f };
+ default: return {};
+ }
+}
+
+const char* var_gets( CVAR *var ) {
+ switch( var->type ) {
+ case CVAR_TYPE_STRING: return var->str_v;
+ case CVAR_TYPE_FLOAT:
+ sprintf( var->str_v + sizeof(F32), "%f", var->fl_v );
+ return var->str_v + sizeof(F32);
+ case CVAR_TYPE_INT:
+ sprintf( var->str_v + sizeof(I32), "%d", var->i_v );
+ return var->str_v + sizeof(I32);
+ case CVAR_TYPE_COLOR:
+ sprintf( var->str_v + sizeof(CLR), "%f %f %f %f", var->clr_v.r, var->clr_v.g, var->clr_v.b, var->clr_v.a );
+ return var->str_v + sizeof(CLR);
+ default:
+ return "";
+ }
+}
diff --git a/src/game/vars.h b/src/game/vars.h
index 395c470..8abe2fa 100644
--- a/src/game/vars.h
+++ b/src/game/vars.h
@@ -44,7 +44,12 @@ extern CVAR* var_new( const char* name, CLR v );
extern CVAR* var_new( const char* name, const char* v );
extern CVAR* var_new( const char* name, CVAR_FUNC fn );
+
extern CVAR* var_find( const char* name );
extern I32 var_call( CVAR* cmdvar, const char* cmdline );
+extern F32 var_getf( CVAR* var );
+extern I32 var_geti( CVAR* var );
+extern CLR var_getclr( CVAR* var );
+extern const char* var_gets( CVAR* var );
extern VAR_LIST* varl;
diff --git a/src/game/world/trace.cpp b/src/game/world/trace.cpp
index 43f5f68..fd6a03b 100644
--- a/src/game/world/trace.cpp
+++ b/src/game/world/trace.cpp
@@ -165,6 +165,7 @@ U8 bsp_trace( BSP_TRACE* trace, BSP* bsp ) {
}
trace->hit = 0;
+ trace->startsolid = 0;
bsp_trace_nudge( trace );
VEC3 start = trace->in_start;
@@ -237,6 +238,7 @@ U8 bsp_trace_sweep_aabb_to_face(
if( point_in_inflated_poly( start, face, hull, norm ) ) {
trace->hit = 1;
trace->frac = 0.f;
+ trace->startsolid = 1;
trace->point = start;
trace->normal = norm;
trace->propid = face->propid;
@@ -375,6 +377,7 @@ U8 bsp_trace( BSP_TRACE* trace, BSP* bsp, AABB hull ) {
if( !trace || !bsp )
return 0;
+ trace->startsolid = 0;
trace->hit = 0;
bsp_trace_nudge( trace );
VEC3 start = trace->in_start;
diff --git a/src/game/world/trace.h b/src/game/world/trace.h
index 8a0f4eb..717fc8f 100644
--- a/src/game/world/trace.h
+++ b/src/game/world/trace.h
@@ -17,6 +17,7 @@ struct BSP_TRACE {
U32 propid;
I32 leafid;
U32 faceid;
+ U8 startsolid;
};
extern U8 bsp_trace( BSP_TRACE* trace, BSP* bsp );