|
|
|
@ -36,10 +36,17 @@ void default_motor_curve(Motor *motor) {
@@ -36,10 +36,17 @@ void default_motor_curve(Motor *motor) {
|
|
|
|
|
// @param uninitialised Body pointer
|
|
|
|
|
// @result: malloc and configure a physics thing pointer
|
|
|
|
|
void get_new_physics(Body **phys) { |
|
|
|
|
|
|
|
|
|
static int uid = 0; |
|
|
|
|
|
|
|
|
|
/* physics */ |
|
|
|
|
Body * physics = malloc(sizeof(Body)); |
|
|
|
|
memset(physics, 0, sizeof(Body)); |
|
|
|
|
|
|
|
|
|
// give it the next uid
|
|
|
|
|
physics->uid = uid++; |
|
|
|
|
|
|
|
|
|
physics->dynamics = false; |
|
|
|
|
physics->glob_gravity = false; |
|
|
|
|
physics->glob_friction = 0.0000; |
|
|
|
|
|
|
|
|
@ -64,29 +71,33 @@ void get_new_physics(Body **phys) {
@@ -64,29 +71,33 @@ void get_new_physics(Body **phys) {
|
|
|
|
|
player_st get_player(int x, int y) { |
|
|
|
|
/* creates player at given postion and zeroes physics */ |
|
|
|
|
|
|
|
|
|
// player
|
|
|
|
|
player_st player; |
|
|
|
|
memset(&player, 0, sizeof(player)); |
|
|
|
|
player.max_walking_speed = 100;
|
|
|
|
|
|
|
|
|
|
// physics settings
|
|
|
|
|
get_new_physics(&player.physics); |
|
|
|
|
player.physics->dynamics = true; |
|
|
|
|
|
|
|
|
|
player.physics->x_pos = x; |
|
|
|
|
player.physics->y_pos = y; |
|
|
|
|
player.physics->glob_friction = 40; // drag coef * area
|
|
|
|
|
|
|
|
|
|
player.physics->updateCollisionPoly = default_update_collision_poly; |
|
|
|
|
// friction (not in use)
|
|
|
|
|
player.physics->glob_friction = 40; // drag coef * area
|
|
|
|
|
|
|
|
|
|
// collisions
|
|
|
|
|
player.physics->collision_poly = calloc(4, sizeof(SDL_Point)); |
|
|
|
|
player.physics->collision_shape = calloc(4, sizeof(SDL_Point)); |
|
|
|
|
|
|
|
|
|
player.physics->collision_poly_size = 4; |
|
|
|
|
SDL_Point *rect = player.physics->collision_shape; |
|
|
|
|
rect[0].x = -5; rect[0].y = -5; |
|
|
|
|
rect[1].x = 5; rect[1].y = -5; |
|
|
|
|
rect[2].x = 5; rect[2].y = 5; |
|
|
|
|
rect[3].x = -5; rect[3].y = 5; |
|
|
|
|
rect[0].x = -5; rect[0].y = -20; |
|
|
|
|
rect[1].x = 5; rect[1].y = -20; |
|
|
|
|
rect[2].x = 5; rect[2].y = 20; |
|
|
|
|
rect[3].x = -5; rect[3].y = 20; |
|
|
|
|
|
|
|
|
|
set_motor_newtons(player.physics, M_GRAVITY, 0.0, player.physics->obj_mass * 5); |
|
|
|
|
//set_motor_newtons(player.physics, M_GRAVITY, 0.0, player.physics->obj_mass * 5);
|
|
|
|
|
|
|
|
|
|
// walking motor
|
|
|
|
|
add_motor(player.physics, 0.0, player.physics->obj_mass * 9.81); |
|
|
|
@ -110,7 +121,6 @@ typedef struct {
@@ -110,7 +121,6 @@ typedef struct {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool point_line_colcheck(SDL_Point line[2], SDL_Point point) { |
|
|
|
|
|
|
|
|
|
// 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) |
|
|
|
@ -134,14 +144,14 @@ bool point_line_colcheck(SDL_Point line[2], SDL_Point point) {
@@ -134,14 +144,14 @@ bool point_line_colcheck(SDL_Point line[2], SDL_Point point) {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
double *project_col_poly(Body *shape, Vect V) { |
|
|
|
|
printf("PROJECTION : \n"); |
|
|
|
|
double *proj = calloc(shape->collision_poly_size, sizeof(double)); |
|
|
|
|
for (int i = 0; i < shape->collision_poly_size; i++) { |
|
|
|
|
Vect point; |
|
|
|
|
point.x = shape->collision_poly[i].x; |
|
|
|
|
point.y = shape->collision_poly[i].y; |
|
|
|
|
printf("point: %f %f mag: %f\n", point.x, point.y, vect_mag(point)); |
|
|
|
|
printf("Vectp: %f %f mag: %f\n", V.x, V.y, vect_mag(V)); |
|
|
|
|
//double mag = vect_mag(point);
|
|
|
|
|
// printf("point: %f %f mag: %f\n", point.x, point.y, vect_mag(point));
|
|
|
|
|
// printf("Vectp: %f %f mag: %f\n", V.x, V.y, vect_mag(V));
|
|
|
|
|
proj[i] = vect_scalar_projection(point, V); |
|
|
|
|
} |
|
|
|
|
double min, max; |
|
|
|
@ -159,6 +169,8 @@ double *project_col_poly(Body *shape, Vect V) {
@@ -159,6 +169,8 @@ double *project_col_poly(Body *shape, Vect V) {
|
|
|
|
|
res[0] = min; |
|
|
|
|
res[1] = max; |
|
|
|
|
|
|
|
|
|
printf("POLY PROJ: %f, %f\n", min, max); |
|
|
|
|
free(proj); |
|
|
|
|
return res; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -172,6 +184,9 @@ Vect get_normal(SDL_Point start, SDL_Point end) {
@@ -172,6 +184,9 @@ Vect get_normal(SDL_Point start, SDL_Point end) {
|
|
|
|
|
return norm; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// reference:
|
|
|
|
|
// http://www.dyn4j.org/2010/01/sat/#sat-inter
|
|
|
|
|
bool sat_collision_check(Body *one, Body *two) { |
|
|
|
|
int num_axes = one->collision_poly_size + two->collision_poly_size; |
|
|
|
|
Vect *axes = calloc(num_axes, sizeof(Vect)); |
|
|
|
@ -208,7 +223,6 @@ bool sat_collision_check(Body *one, Body *two) {
@@ -208,7 +223,6 @@ bool sat_collision_check(Body *one, Body *two) {
|
|
|
|
|
axes[i].x = axes[i].x / len; |
|
|
|
|
axes[i].y = axes[i].y / len; |
|
|
|
|
printf("AXIS TO CHECK normed: %f %f\n", axes[i].x, axes[i].y); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
double *proj_one, *proj_two; |
|
|
|
@ -221,21 +235,28 @@ bool sat_collision_check(Body *one, Body *two) {
@@ -221,21 +235,28 @@ bool sat_collision_check(Body *one, Body *two) {
|
|
|
|
|
if (proj_two) { |
|
|
|
|
free(proj_two); |
|
|
|
|
} |
|
|
|
|
printf("Testing on axis: %f %f\n", axes[i].x, axes[i].y); |
|
|
|
|
proj_one = project_col_poly(one, axes[i]); |
|
|
|
|
proj_two = project_col_poly(two, axes[i]); |
|
|
|
|
|
|
|
|
|
printf("Testing on : %f %f\n", axes[i].x, axes[i].y); |
|
|
|
|
|
|
|
|
|
if (!(proj_one[1] > proj_two[1] && proj_one[0] < proj_two[0])
|
|
|
|
|
&& !(proj_one[1] < proj_two[1] && proj_one[0] > proj_two[0])) { |
|
|
|
|
/*if (!(proj_one[1] >= proj_two[1] && proj_one[0] <= proj_two[0]) */ |
|
|
|
|
/*&& !(proj_one[1] <= proj_two[1] && proj_one[0] >= proj_two[0])) {*/ |
|
|
|
|
if ((proj_one[1] >= proj_two[1] && proj_one[0] >= proj_two[1])
|
|
|
|
|
|| (proj_one[0] >= proj_two[1] && proj_one[1] >= proj_two[1])) { |
|
|
|
|
printf("not overlapping\n"); |
|
|
|
|
free(axes); |
|
|
|
|
free(proj_one); |
|
|
|
|
free(proj_two); |
|
|
|
|
return false; |
|
|
|
|
} else { |
|
|
|
|
printf("overlapping\n"); |
|
|
|
|
double overlap; |
|
|
|
|
double left = proj_one[0] < proj_two[0] ? proj_one[0] : proj_two[0]; |
|
|
|
|
double right = proj_one[1] > proj_two[1] ? proj_one[1] : proj_two[1]; |
|
|
|
|
overlap = left - right; |
|
|
|
|
printf("OVERLAP : %f\n", overlap); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
free(axes); |
|
|
|
|
free(proj_one); |
|
|
|
|
free(proj_two); |
|
|
|
@ -378,6 +399,21 @@ void add_motor(Body *thing, double x, double y) {
@@ -378,6 +399,21 @@ void add_motor(Body *thing, double x, double y) {
|
|
|
|
|
thing->num_motors += 1; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// basic collision handler for testing
|
|
|
|
|
bool process_collisions(Body *thing) { |
|
|
|
|
for (int k = 0; k < things_in_world; k++) { |
|
|
|
|
if (world[k].kind == STATIC_WALL_W |
|
|
|
|
&& world[k].wall->physics->uid != thing->uid) { |
|
|
|
|
if (check_collision(world[k].wall->physics, thing)) { |
|
|
|
|
thing->colliding = true; |
|
|
|
|
return true; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
thing->colliding = false; |
|
|
|
|
return false; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/* 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
|
|
|
|
@ -389,6 +425,10 @@ void advance_thing(Body * thing) {
@@ -389,6 +425,10 @@ void advance_thing(Body * thing) {
|
|
|
|
|
|
|
|
|
|
thing->updateCollisionPoly(thing); |
|
|
|
|
|
|
|
|
|
if (!thing->dynamics) { |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
uint32_t time_delta = SDL_GetTicks() - thing->last_advance_time ; |
|
|
|
|
thing->last_advance_time = SDL_GetTicks(); // in milliseconds
|
|
|
|
|
time_delta = 17; |
|
|
|
@ -457,9 +497,23 @@ void advance_thing(Body * thing) {
@@ -457,9 +497,23 @@ void advance_thing(Body * thing) {
|
|
|
|
|
(*thing).y_vel = 0;
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int oldx = thing->x_pos; |
|
|
|
|
int oldy = thing->y_pos; |
|
|
|
|
(*thing).x_pos += (int)((*thing).x_vel * 1/2 * (float)time_delta);
|
|
|
|
|
(*thing).y_pos += (int)((*thing).y_vel * 1/2 * (float)time_delta);
|
|
|
|
|
|
|
|
|
|
// revert if this caused collision
|
|
|
|
|
thing->updateCollisionPoly(thing); |
|
|
|
|
if (process_collisions(thing)) { |
|
|
|
|
/*thing->x_pos = oldx;*/ |
|
|
|
|
/*thing->y_pos = oldy;*/ |
|
|
|
|
thing->updateCollisionPoly(thing); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// wrap screen
|
|
|
|
|
if (thing->x_pos > width) { |
|
|
|
|
thing->x_pos = 0; |
|
|
|
@ -477,29 +531,14 @@ void advance_thing(Body * thing) {
@@ -477,29 +531,14 @@ void advance_thing(Body * thing) {
|
|
|
|
|
thing->x_pos = width; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
thing->updateCollisionPoly(thing); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// 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->y_vel = 0; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void advance_things(void) { |
|
|
|
|
for (int i = 0; i < things_in_world; i++) { |
|
|
|
|
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: |
|
|
|
|