summaryrefslogtreecommitdiff
path: root/src/game
diff options
context:
space:
mode:
Diffstat (limited to 'src/game')
-rw-r--r--src/game/physics/movement.cpp157
-rw-r--r--src/game/physics/movement.h16
-rw-r--r--src/game/player.cpp95
-rw-r--r--src/game/player.h2
-rw-r--r--src/game/world/bsp.cpp1
-rw-r--r--src/game/world/map.cpp4
-rw-r--r--src/game/world/trace.cpp7
7 files changed, 208 insertions, 74 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;
diff --git a/src/game/player.cpp b/src/game/player.cpp
index 51d1cf8..65daa9b 100644
--- a/src/game/player.cpp
+++ b/src/game/player.cpp
@@ -1,6 +1,7 @@
#include "../game.h"
#include "SDL_scancode.h"
#include "objlist.h"
+#include "physics/movement.h"
#include "world/trace.h"
#include <cmath>
#include "player.h"
@@ -34,8 +35,9 @@ PLAYER* player_create( VEC3 origin, F32 yaw ) {
void capture_mouse( PLAYER* p ) {
F32* yaw = &p->input.cam.pos.y;
F32* pitch = &p->input.cam.pos.x;
+
if( input.keys[SDL_SCANCODE_F1] ) {
- input_capture_mouse( false );
+ input_capture_mouse( 0 );
}
if( input.mouselock ) {
@@ -56,59 +58,47 @@ void capture_mouse( PLAYER* p ) {
void capture_move_keys( PLAYER* p ) {
VEC2* move = &p->input.move;
if( input.keys[input.binds.fwd] ) {
- if( !p->input.fwd_held )
- move->x = 1.f;
- p->input.fwd_held = true;
+ if( !p->input.fwd_held ) move->x = 1.f;
+ p->input.fwd_held = 1;
} else {
if( p->input.fwd_held ) {
- if( p->input.bk_held )
- move->x = -1.f;
- else
- move->x = 0.f;
+ if( p->input.bk_held ) move->x = -1.f;
+ else move->x = 0.f;
}
- p->input.fwd_held = false;
+ p->input.fwd_held = 0;
}
if( input.keys[input.binds.back] ) {
- if( !p->input.bk_held )
- move->x = -1.f;
- p->input.bk_held = true;
+ if( !p->input.bk_held ) move->x = -1.f;
+ p->input.bk_held = 1;
} else {
if( p->input.bk_held ) {
- if( p->input.fwd_held )
- move->x = 1.f;
- else
- move->x = 0.f;
+ if( p->input.fwd_held ) move->x = 1.f;
+ else move->x = 0.f;
}
- p->input.bk_held = false;
+ p->input.bk_held = 0;
}
if( input.keys[input.binds.left] ) {
- if( !p->input.left_held )
- move->y = -1.f;
- p->input.left_held = true;
+ if( !p->input.left_held ) move->y = -1.f;
+ p->input.left_held = 1;
} else {
if( p->input.left_held ) {
- if( p->input.right_held )
- move->y = 1.f;
- else
- move->y = 0.f;
+ if( p->input.right_held ) move->y = 1.f;
+ else move->y = 0.f;
}
- p->input.left_held = false;
+ p->input.left_held = 0;
}
if( input.keys[input.binds.right] ) {
- if( !p->input.right_held )
- move->y = 1.f;
- p->input.right_held = true;
+ if( !p->input.right_held ) move->y = 1.f;
+ p->input.right_held = 1;
} else {
if( p->input.right_held ) {
- if( p->input.left_held )
- move->y = -1.f;
- else
- move->y = 0.f;
+ if( p->input.left_held ) move->y = -1.f;
+ else move->y = 0.f;
}
- p->input.right_held = false;
+ p->input.right_held = 0;
}
}
@@ -121,43 +111,8 @@ void player_input( GAME_DATA* game, PLAYER* p ) {
}
void player_move( GAME_DATA* game, PLAYER* p ) {
- VEC2 move = p->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 * 70.f;
- p->velocity = vel;
- VEC3 wishmove = vel * TICK_INTERVAL;
- // todo : should never be false
- if( vec_len( wishmove ) > BSP_TRACE_EPSILON && game->state.map->bsp ) {
- BSP_TRACE tr{};
- AABB aabb{};
- tr.in_start = p->pos;
- tr.in_end = tr.in_start + wishmove;
- aabb.min = p->mins;
- aabb.max = p->maxs;
-
- bsp_trace( &tr, game->state.map->bsp, aabb );
- if( !tr.hit )
- p->pos += wishmove;
- else {
- p->pos += wishmove * tr.frac;
-
-
- // TODO: clipvelocity fixes this, clips velocity to 1 wall (should do 4)
- VEC3 left = wishmove * (1.f - tr.frac);
- F32 into = vec_dot( left, tr.normal );
- if( into < 0.f )
- left -= tr.normal * into;
-
- p->pos += left;
- }
- }
+ gmove_set_player( p );
+ gmove_tick();
}
VEC3 player_get_view_pos( PLAYER* p ) {
diff --git a/src/game/player.h b/src/game/player.h
index 6617f01..c0e126d 100644
--- a/src/game/player.h
+++ b/src/game/player.h
@@ -20,10 +20,10 @@ struct PLAYER : OBJECT {
F32 eyeoffset{40.f};
PLAYER_INPUT input;
-
VEC3 mins;
VEC3 maxs;
+ F32 maxspeed{70.f};
VEC3 velocity;
};
diff --git a/src/game/world/bsp.cpp b/src/game/world/bsp.cpp
index a95a693..c6c9726 100644
--- a/src/game/world/bsp.cpp
+++ b/src/game/world/bsp.cpp
@@ -736,6 +736,7 @@ BSP* bsp_build_map( WORLD_MAP* m ) {
bsp_build_portals( bsp );
bsp_build_pvs( bsp );
+ m->bsp = bsp;
return bsp;
}
diff --git a/src/game/world/map.cpp b/src/game/world/map.cpp
index aba283d..53cfe22 100644
--- a/src/game/world/map.cpp
+++ b/src/game/world/map.cpp
@@ -518,13 +518,13 @@ WORLD_MAP* map_from_file( GAME_DATA* game, const char* path ) {
CFG_SECTION* skybox = cfg_section( s, "skybox" );
if( !skybox ) {
dlog( errstr, path, "skybox" );
- dlog( "using default skybox" );
+ dlog( "using default skybox\n" );
m->skybox = map_default_skybox();
}
else {
if( !OK( map_skybox_from_section( skybox, game, m ) ) ) {
dlog( errstr, path, "skybox" );
- dlog( "using default skybox" );
+ dlog( "using default skybox\n" );
m->skybox = map_default_skybox();
}
}
diff --git a/src/game/world/trace.cpp b/src/game/world/trace.cpp
index c8ad3be..43f5f68 100644
--- a/src/game/world/trace.cpp
+++ b/src/game/world/trace.cpp
@@ -152,7 +152,10 @@ U8 bsp_trace( BSP_TRACE* trace, BSP* bsp, VEC3 start, VEC3 end ) {
trace->in_start = start;
trace->in_end = end;
- return bsp_trace( trace, bsp );
+ U8 ret = bsp_trace( trace, bsp );
+ if( !ret )
+ trace->point = trace->in_end;
+ return ret;
}
U8 bsp_trace( BSP_TRACE* trace, BSP* bsp ) {
@@ -378,6 +381,8 @@ U8 bsp_trace( BSP_TRACE* trace, BSP* bsp, AABB hull ) {
VEC3 end = trace->in_end;
U8 ret = bsp_trace_sweep_aabb( trace, bsp, hull, start, end, bsp->root );
+ if( !ret )
+ trace->point = trace->in_end;
return ret;
}