1
1
Fork 0
Browse Source

fixed collision detection and added red collision box

thread-physics
user 5 years ago
parent
commit
d553f6fdef
  1. 6
      draw.c
  2. 103
      game.c
  3. 11
      game.h

6
draw.c

@ -61,7 +61,11 @@ void draw_collision_poly(SDL_Renderer* ren, Body *body) { @@ -61,7 +61,11 @@ void draw_collision_poly(SDL_Renderer* ren, Body *body) {
return;
}
SDL_SetRenderDrawColor(ren, 0, 255, 0, 255);
if (body->colliding) {
SDL_SetRenderDrawColor(ren, 255, 0, 0, 255);
} else {
SDL_SetRenderDrawColor(ren, 0, 255, 0, 255);
}
if (body->collision_poly_size == 1) {
SDL_Rect dot;
dot.x = body->collision_poly[0].x;

103
game.c

@ -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:

11
game.h

@ -39,6 +39,17 @@ typedef struct { @@ -39,6 +39,17 @@ typedef struct {
} Point;
typedef struct BodyStruct{
// turn on dynamic physics
// For moving objects.
// eg. on for payer, off for walls
bool dynamics;
// unique identifier
int uid;
bool colliding;
int x_pos;
int y_pos;

Loading…
Cancel
Save