@ -1,16 +1,34 @@
@@ -1,16 +1,34 @@
# include "game.h"
# include "vect.h"
# define GRAVITY_ACCEL 2
player_st * glob_player ;
// @param uninitialised physics_thing pointer
void set_motor_newtons ( Body * thing , int motorID , double x , double y ) ;
void set_motor_max_velocity ( Body * thing , int motorID , double max ) ;
void default_update_collision_poly ( Body * body ) {
return ;
}
// would probably be useful xd
enum collision_definition_type {
CIRCLE ,
LINE ,
CONVEX_POLY
} ;
void default_motor_curve ( Motor * motor ) {
// constant
return ;
}
// @param uninitialised Body pointer
// @result: malloc and configure a physics thing pointer
void get_new_physics ( physics_thing * * phys ) {
void get_new_physics ( Body * * phys ) {
/* physics */
physics_thing * physics = malloc ( sizeof ( physics_thing ) ) ;
memset ( physics , 0 , sizeof ( physics_thing ) ) ;
Body * physics = malloc ( sizeof ( Body ) ) ;
memset ( physics , 0 , sizeof ( Body ) ) ;
physics - > glob_gravity = false ;
physics - > glob_friction = 0.0000 ;
@ -24,7 +42,14 @@ void get_new_physics(physics_thing **phys) {
@@ -24,7 +42,14 @@ void get_new_physics(physics_thing **phys) {
physics - > num_motors = 0 ;
add_motor ( physics , 0.0 , 0.0 ) ;
* phys = physics ;
physics - > updateCollisionPoly = default_update_collision_poly ;
* phys = physics ; return ;
}
void updatePlayerCollision ( Body * physics ) {
physics - > collision_poly [ 0 ] . x = physics - > x_pos ;
physics - > collision_poly [ 0 ] . y = physics - > y_pos ;
}
player_st get_player ( int x , int y ) {
@ -38,28 +63,28 @@ player_st get_player(int x, int y) {
@@ -38,28 +63,28 @@ player_st get_player(int x, int y) {
player . physics - > x_pos = x ;
player . physics - > y_pos = y ;
player . physics - > glob_friction = 40 ; // drag coef * area
player . physics - > updateCollisionPoly = updatePlayerCollision ;
add_motor ( player . physics , 0.0 , 0.0 ) ;
player . physics - > collision_poly = calloc ( 1 , sizeof ( SDL_Point ) ) ;
set_motor_newtons ( player . physics , M_GRAVITY , 0.0 , player . physics - > obj_mass * 7 ) ;
// walking motor
add_motor ( player . physics , 0.0 , player . physics - > obj_mass * 9.81 ) ;
set_motor_max_velocity ( player . physics , M_PLAYER_WALK , 6 ) ; // has to be > grav
set_motor_max_velocity ( player . physics , M_GRAVITY , 5 ) ;
return ( player ) ;
}
wall_node get_wall_node ( int x , int y ) {
wall_node wn ;
memset ( & wn , 0 , sizeof ( wn ) ) ;
wn . physics . x_pos = x ;
wn . physics . y_pos = y ;
wn . physics . x_acc = 0 ;
wn . physics . y_acc = 0 ;
wn . physics . obj_mass = 10 ;
wn . physics . glob_gravity = false ;
wn . physics . glob_friction = 0.00000000 ;
wn . physics . x_vel = 0 ;
wn . physics . y_vel = 0 ;
wn . x = x ;
wn . y = y ;
return wn ;
}
@ -78,62 +103,96 @@ Wall *get_stat_wall(int st_x, int st_y, int en_x, int en_y) {
@@ -78,62 +103,96 @@ Wall *get_stat_wall(int st_x, int st_y, int en_x, int en_y) {
return wallwall ;
}
void collision ( int numNodes1 , physics_thing * nodes1 ,
int numNodes2 , physics_thing * nodes2 ) {
int x_1 , y_1 , x_2 , y_2 , xa_1 , ya_1 , xa_2 , ya_2 ;
for ( int i = 0 ; i < numNodes1 ; i + + ) {
x_1 = nodes1 [ 2 * i ] . x_pos ;
y_1 = nodes1 [ 2 * i ] . y_pos ;
x_2 = nodes1 [ 2 * i + 1 ] . x_pos ;
y_2 = nodes1 [ 2 * i + 1 ] . y_pos ;
for ( int j = 0 ; j < numNodes2 ; j + + ) {
xa_1 = nodes2 [ 2 * j ] . x_pos ;
ya_1 = nodes2 [ 2 * j ] . y_pos ;
xa_2 = nodes2 [ 2 * j + 1 ] . x_pos ;
ya_2 = nodes2 [ 2 * j + 1 ] . y_pos ;
}
bool point_point_colcheck ( SDL_Point one , SDL_Point two ) {
if ( one . x = = two . x & & one . y = = two . y ) {
return true ;
}
return false ;
}
physics_thing * get_player_collision_test ( physics_thing * player ) {
physics_thing up , right ;
physics_thing * nodes = malloc ( sizeof ( physics_thing ) * 2 ) ;
typedef struct {
Vect one ;
Vect two ;
} Collision ;
up = * player ;
right = * player ;
bool point_line_colcheck ( SDL_Point line [ 2 ] , SDL_Point point ) {
up . y_pos + = 1 ;
right . x_pos + = 1 ;
// point is outside the rectangle made by the line
if ( ( point . x > line [ 0 ] . x & & point . x > line [ 1 ] . x )
| | ( point . x < line [ 0 ] . x & & point . x < line [ 0 ] . x )
| | ( point . y > line [ 0 ] . y & & point . y > line [ 0 ] . y )
| | ( point . y < line [ 0 ] . y & & point . y < line [ 0 ] . y )
) {
return false ;
}
nodes [ 0 ] = up ;
nodes [ 1 ] = right ;
double m = ( double ) ( line [ 1 ] . y - line [ 0 ] . y ) / ( double ) ( line [ 1 ] . x - line [ 0 ] . x ) ;
double c = ( double ) ( line [ 0 ] . y - ( m * line [ 0 ] . x ) ) ;
double y = point . x * m + c ;
// point is in the line +- 1
if ( ( int ) y = = point . y | | ( ( int ) y < point . y & & ( int ) y + 1 > point . y ) ) {
return true ;
}
return nodes ;
return false ;
}
void check_collision ( int numNodes , physics_thing * things ) {
for ( int i = 0 ; i < things_in_world ; i + + ) {
world_thing worldThing = world [ i ] ;
Wall * wall ;
physics_thing * nodes ;
if ( worldThing . collisions ) {
switch ( worldThing . kind ) {
case PLAYER_W :
collision ( 2 , get_player_collision_test ( things ) , 1 , worldThing . player - > physics ) ;
break ;
case STATIC_WALL_W :
wall = worldThing . wall ;
nodes = malloc ( sizeof ( physics_thing ) * wall - > numNodes ) ;
for ( int i = 0 ; i < wall - > numNodes ; i + + ) {
nodes [ i ] = wall - > nodes [ i ] . physics ;
}
collision ( numNodes , things , wall - > numNodes , nodes ) ;
free ( nodes ) ;
break ;
}
bool route_collision ( Body * one , Body * two ) {
int onesize = one - > collison_poly_size ;
int twosize = two - > collison_poly_size ;
// point-point
if ( one - > collison_poly_size = = 1 & & two - > collison_poly_size = = 1 ) {
if ( point_point_colcheck ( one - > collision_poly [ 0 ] , two - > collision_poly [ 0 ] ) ) {
return true ;
}
}
// point-line
if ( ( onesize = = 1 | | twosize = = 1 ) & & ( onesize = = 2 | | twosize = = 2 ) ) {
SDL_Point line [ 2 ] ;
SDL_Point point ;
if ( onesize > twosize ) {
line [ 0 ] = one - > collision_poly [ 0 ] ;
line [ 1 ] = one - > collision_poly [ 1 ] ;
point = two - > collision_poly [ 0 ] ;
} else {
line [ 0 ] = two - > collision_poly [ 0 ] ;
line [ 1 ] = two - > collision_poly [ 1 ] ;
point = one - > collision_poly [ 0 ] ;
}
return point_line_colcheck ( line , point ) ;
}
// line-line
if ( ( onesize = = 2 & & twosize = = 2 ) ) {
return false ;
}
// point-poly
if ( ( onesize = = 1 | | twosize = = 1 ) & & ( onesize > 2 | | twosize > 2 ) ) {
return false ;
}
// line-poly
if ( ( onesize = = 2 | | twosize = = 2 ) & & ( onesize > 2 | | twosize > 2 ) ) {
return false ;
}
// poly-poly
if ( ( onesize > 2 & & twosize > 2 ) ) {
return false ;
}
}
bool check_collision ( Body * one , Body * two ) {
return route_collision ( one , two ) ;
}
Wall * get_long_wall ( int numNodes , int * nodes ) {
@ -142,10 +201,15 @@ Wall *get_long_wall(int numNodes, int *nodes) {
@@ -142,10 +201,15 @@ Wall *get_long_wall(int numNodes, int *nodes) {
wall . numNodes = numNodes ;
wall . nodes = malloc ( sizeof ( wall_node ) * numNodes ) ;
wall . physics = calloc ( 1 , sizeof ( Body ) ) ;
wall . physics - > collision_poly = calloc ( numNodes , sizeof ( SDL_Point ) ) ;
// collisions
//SDL_Point *collision_poly;
for ( int i = 0 ; i < numNodes ; i + + ) {
wall . nodes [ i ] = get_wall_node ( nodes [ 2 * i ] , nodes [ 2 * i + 1 ] ) ;
//set_motor_ms(&(wall.nodes[i].physics), 2.0 , 1.0);
wall . physics - > collision_poly [ i ] . x = nodes [ 2 * i ] ;
wall . physics - > collision_poly [ i ] . y = nodes [ 2 * i + 1 ] ;
}
Wall * wallwall = malloc ( sizeof ( wall ) ) ;
@ -153,7 +217,7 @@ Wall *get_long_wall(int numNodes, int *nodes) {
@@ -153,7 +217,7 @@ Wall *get_long_wall(int numNodes, int *nodes) {
return wallwall ;
}
void accel_thing ( physics_thing * thing , float x , float y ) {
void accel_thing ( Body * thing , float x , float y ) {
/* takes acceleration in m/s2 and converts to m/ms adding
* it to physics_thing
*/
@ -169,24 +233,37 @@ void accel_thing(physics_thing * thing, float x, float y) {
@@ -169,24 +233,37 @@ void accel_thing(physics_thing * thing, float x, float y) {
}
void set_motor_newtons ( physics_thing * thing , int motorID , double x , double y ) {
void set_motor_max_velocity ( Body * thing , int motorID , double max ) {
thing - > motors [ motorID ] . max_velocity = max ;
}
void set_motor_ttl ( Body * thing , int motorID , double ttl ) {
thing - > motors [ motorID ] . TTL = ttl ;
}
void set_motor_newtons ( Body * thing , int motorID , double x , double y ) {
thing - > motors [ motorID ] . x = x ;
thing - > motors [ motorID ] . y = y ;
}
void add_motor_newtons ( physics_thing * thing , int motorID , double x , double y ) {
void add_motor_newtons ( Body * thing , int motorID , double x , double y ) {
thing - > motors [ motorID ] . x + = x ;
thing - > motors [ motorID ] . y + = y ;
}
void add_motor ( physics_thing * thing , double x , double y ) {
// @param thing: the body to apply the motor to
// @param x, y: The initial motor force vector.
void add_motor ( Body * thing , double x , double y ) {
Motor motor ;
memset ( & motor , 0 , sizeof ( Motor ) ) ;
motor . x = x ;
motor . y = y ;
motor . TTL = INFINITY ;
motor . max_velocity = 999899 ;
motor . update_motor = default_motor_curve ;
if ( thing - > num_motors = = thing - > max_motors ) {
thing - > motors = realloc ( thing - > motors , sizeof ( Motor ) * ( thing - > max_motors * = 2 ) ) ;
}
@ -195,100 +272,112 @@ void add_motor(physics_thing *thing, double x, double y) {
@@ -195,100 +272,112 @@ void add_motor(physics_thing *thing, double x, double y) {
thing - > num_motors + = 1 ;
}
/* Basic physics works by adding up the acceleratino caused by all the forces on
* the object , converting it to velocity , then doing collision detection and
* applying various reactive forces ( friction etc ) and finally adjusting the
* object ' s position .
*/
void advance_thing ( Body * thing ) {
thing - > x_acc = 0 ;
thing - > y_acc = 0 ;
int advance_glob ( physics_thing * thing ) {
logwrite ( DEBUG , " Global physics \n " ) ;
// gravity
if ( ( * thing ) . glob_gravity = = true ) {
accel_thing ( thing , 0 , GRAVITY_ACCEL ) ;
}
thing - > updateCollisionPoly ( thing ) ;
// friction
uint32_t time_delta = SDL_GetTicks ( ) - thing - > last_advance_time ;
thing - > last_advance_time = SDL_GetTicks ( ) ; // in milliseconds
time_delta = 17 ;
if ( ( * thing ) . glob_friction ! = 0.0 ) {
logwrite ( DEBUG , " Friction \n " ) ;
float normal = ( * thing ) . obj_mass * 9.81 ;
float F_force = normal * ( * thing ) . glob_friction ;
float dir = atan2 ( ( * thing ) . y_vel , ( * thing ) . x_vel ) ;
dir + = M_PI ;
// motors
for ( int i = 0 ; i < thing - > num_motors ; i + + ) {
float f_x = ( float ) ( cos ( ( double ) dir ) ) * F_force ;
float f_y = ( float ) ( sin ( ( double ) dir ) ) * F_force ;
Vect F ;
Vect V ;
F . x = thing - > motors [ i ] . x ;
F . y = thing - > motors [ i ] . y ;
V . x = thing - > x_vel ;
V . y = thing - > y_vel ;
printf ( " Friction %f, %f " , f_x , f_y ) ;
Vect vel_in_dir = project_vect ( V , F ) ;
if ( fabs ( ( * thing ) . x_vel ) > 0.0000001 ) {
( * thing ) . x_acc + = f_x ;
if ( thing - > motors [ i ] . TTL < = 0 ) {
continue ;
}
if ( fabs ( ( * thing ) . y_vel ) > 0.0000001 ) {
( * thing ) . y_acc + = f_y ;
if ( thing - > motors [ i ] . TTL ! = INFINITY ) {
thing - > motors [ i ] . TTL - - ;
}
/*if (fabs((*thing).x_acc ) < fabs(f_x)) {*/
/*(*thing).x_acc = 0;*/
/*}*/
/*else {*/
/*(*thing).x_acc += f_x;*/
/*}*/
/*if (fabs((*thing).y_acc) < fabs(f_y)) {*/
/*(*thing).y_acc = 0;*/
/*}*/
/*else {*/
/*(*thing).y_acc += f_y;*/
/*}*/
if ( thing - > motors [ i ] . max_velocity > vect_mag ( vel_in_dir ) ) {
double acc_x = thing - > motors [ i ] . x / thing - > obj_mass ;
double acc_y = thing - > motors [ i ] . y / thing - > obj_mass ;
accel_thing ( thing , acc_x , acc_y ) ;
}
}
}
void advance_thing ( physics_thing * thing ) {
thing - > x_acc = 0 ;
thing - > y_acc = 0 ;
uint32_t time_delta = SDL_GetTicks ( ) - thing - > last_advance_time ;
thing - > last_advance_time = SDL_GetTicks ( ) ; // in milliseconds
// accelerate based on accel
printf ( " time: %f " , ( float ) time_delta ) ;
thing - > x_vel + = thing - > x_acc * ( float ) time_delta ;
thing - > y_vel + = thing - > y_acc * ( float ) time_delta ;
double velocity = sqrt ( ( double ) ( thing - > x_vel * thing - > x_vel + thing - > y_vel * thing - > y_vel ) ) ;
printf ( " \n vels %e %e \n \n " , thing - > x_vel , thing - > y_vel ) ;
for ( int i = 0 ; i < thing - > num_motors ; i + + ) {
double acc_x = thing - > motors [ i ] . x / thing - > obj_mass ;
double acc_y = thing - > motors [ i ] . y / thing - > obj_mass ;
accel_thing ( thing , acc_x , acc_y ) ;
}
// simple air drag
// motor
//float motor_x = (float)(*thing).motor_x / (float)(*thing).obj_mass ;
//float motor_y = (float)(*thing).motor_y / (float)(*thing).obj_mass ;
//printf("MOTOR: %f, %f\n", motor_x, motor_y);
//accel_thing(thing, motor_x, motor_y);
/*if (velocity > 0.000000000000000) {*/
/*double dir = atan2((double)thing->y_vel, (double)thing->x_vel) + M_PI;*/
advance_glob ( thing ) ;
/*double absolute_force = 5 * thing->obj_mass * (velocity / time_delta); // 2 * 0.1231 * 5;*/
/*printf("dir %e %e\n\n", dir, dir - M_PI);*/
/*printf("force %e\n\n", absolute_force);*/
// accelerate based on accel
/*double f_x = (cos(dir)) * absolute_force;*/
/*double f_y = (sin(dir)) * absolute_force;*/
printf ( " time: %f " , ( float ) time_delta ) ;
( * thing ) . x_vel = ( * thing ) . x_acc * ( float ) time_delta ;
( * thing ) . y_vel = ( * thing ) . y_acc * ( float ) time_delta ;
/*accel_thing(thing, (float)f_x, (float)f_y);*/
/*}*/
if ( fabs ( ( * thing ) . x_vel ) < 0.00001 ) {
( * thing ) . x_vel = 0 ;
}
if ( fabs ( ( * thing ) . y_vel ) < 0.00001 ) {
( * thing ) . y_vel = 0 ;
}
( * thing ) . x_pos + = ( int ) ( ( * thing ) . x_vel * 1 / 2 * ( float ) time_delta ) ;
( * thing ) . y_pos + = ( int ) ( ( * thing ) . y_vel * 1 / 2 * ( float ) time_delta ) ;
printf ( " player position: %d, %d " , ( * thing ) . x_pos , ( * thing ) . y_pos ) ;
printf ( " player acc: %f, %f \n " , ( * thing ) . x_acc , ( * thing ) . y_acc ) ;
// wrap screen
if ( thing - > x_pos > width ) {
thing - > x_pos = 0 ;
}
if ( thing - > y_pos > height ) {
thing - > y_pos = 0 ;
}
if ( thing - > y_pos < 0 ) {
thing - > y_pos = height ;
}
if ( fabs ( ( * thing ) . x_vel ) < 0.00001 ) {
( * thing ) . x_vel = 0 ;
if ( thing - > x_pos < 0 ) {
thing - > x_pos = width ;
}
if ( fabs ( ( * thing ) . y_vel ) < 0.00001 ) {
( * thing ) . y_vel = 0 ;
}
// basic collision handler
void handle_collisions ( void ) {
for ( int k = 0 ; k < things_in_world ; k + + ) {
if ( world [ k ] . kind = = STATIC_WALL_W ) {
if ( check_collision ( world [ k ] . wall - > physics ,
player . physics ) ) {
player . physics - > x_vel = 0 ;
player . physics - > y_vel = 0 ;
}
}
}
}
void advance_things ( void ) {
@ -296,20 +385,20 @@ void advance_things(void) {
@@ -296,20 +385,20 @@ void advance_things(void) {
switch ( world [ i ] . kind ) {
case PLAYER_W :
logwrite ( INFO , " ADVANCE PLAYER \n " ) ;
handle_collisions ( ) ;
advance_thing ( ( world [ i ] . player - > physics ) ) ;
break ;
case STATIC_WALL_W :
logwrite ( INFO , " ADVANCE WALL \n " ) ;
for ( int j = 0 ; j < world [ i ] . wall - > numNodes ; j + + ) {
advance_thing ( & ( world [ i ] . wall - > nodes [ j ] . physics ) ) ;
}
// advance_thing(world[i].wall->physics);
break ;
}
}
}
// grow array of world things if needed
void add_to_world ( world_thing thing ) {
if ( things_in_world = = world_size ) {
logwrite ( INFO , " Increased world size. " ) ;
world = realloc ( world , sizeof ( world_thing ) * ( world_size * = 2 ) ) ;
@ -330,6 +419,7 @@ void startgame(SDL_Renderer * ren) {
@@ -330,6 +419,7 @@ void startgame(SDL_Renderer * ren) {
world_size = 100 ;
world = malloc ( sizeof ( world_thing ) * 100 ) ;
memset ( world , 0 , sizeof ( world_thing ) * 100 ) ;
SDL_GetRendererOutputSize ( ren , & width , & height ) ;
player = get_player ( 100 , 400 ) ;
@ -346,11 +436,6 @@ void startgame(SDL_Renderer * ren) {
@@ -346,11 +436,6 @@ void startgame(SDL_Renderer * ren) {
int wall_nodes [ ] = { 500 , 100 , 200 , 100 , 100 , 200 , 900 , 200 } ;
wall_world . wall = get_long_wall ( 4 , wall_nodes ) ;
wall_world . kind = STATIC_WALL_W ;
printf ( " WALLNODES " ) ;
for ( int i = 0 ; i < 4 ; i + + ) {
printf ( " : %d " , wall_world . wall - > nodes [ i ] . physics . x_pos ) ;
}
printf ( " \n \n \n \n " ) ;
add_to_world ( wall_world ) ;
}
@ -359,36 +444,38 @@ float get_abs(float x,float y) {
@@ -359,36 +444,38 @@ float get_abs(float x,float y) {
}
void walk_player ( int x , int y ) {
if ( y = = - 1 ) {
add_motor_newtons ( glob_player - > physics , M_PLAYER_WALK , 0 , 100 * 10 * y ) ;
return ;
}
add_motor_newtons ( glob_player - > physics , M_PLAYER_WALK , 100 * x , 100 * y ) ;
}
void process_keydown ( SDL_Keysym key ) {
}
void process_keyup ( SDL_Keysym key ) {
}
void step ( int interval ) {
const uint8_t * keyboard ;
printf ( " THINGS IN WORLD: %d \n " , things_in_world ) ;
keyboard = SDL_GetKeyboardState ( NULL ) ;
//set_motor_ms(&player.physics, 0 ,0);
//
set_motor_newtons ( player . physics , M_PLAYER_WALK , 0 , 0 ) ;
if ( keyboard [ SDL_SCANCODE_W ] ) {
walk_player ( 0 , - 1 ) ;
} if ( keyboard [ SDL_SCANCODE_SPACE ] ) {
walk_player ( 0 , - 1 ) ;
} if ( keyboard [ SDL_SCANCODE_A ] ) {
walk_player ( - 1 , 0 ) ;
} if ( keyboard [ SDL_SCANCODE_S ] ) {
walk_player ( 0 , 1 ) ;
} if ( keyboard [ SDL_SCANCODE_D ] ) {
walk_player ( 1 , 0 ) ;
} if ( ! keyboard [ SDL_SCANCODE_W ]
& & ! keyboard [ SDL_SCANCODE_A ]
& & ! keyboard [ SDL_SCANCODE_S ]
& & ! keyboard [ SDL_SCANCODE_D ] ) {
set_motor_ttl ( player . physics , M_PLAYER_WALK , 90 ) ;
}
advance_things ( ) ;
logwrite ( DEBUG , " Update Physics \n " ) ;
}