1
1
Fork 0
Browse Source

fixed bug and improved efficeincee

thread-physics
= 5 years ago
parent
commit
b390ab0965
  1. 16
      draw.c
  2. 172
      game.c
  3. 3
      logger.c
  4. 1
      vect.c

16
draw.c

@ -71,8 +71,17 @@ void draw_floor(SDL_Renderer *ren, FloorPoly *poly) { @@ -71,8 +71,17 @@ void draw_floor(SDL_Renderer *ren, FloorPoly *poly) {
SDL_Point left;
SDL_Point right;
left.x = poly->left.x - viewport_pos.x;
left.y = poly->left.y - viewport_pos.y;
if (left.x > width) {
return;
}
right.x = poly->right.x - viewport_pos.x;
if (right.x < 0) {
return;
}
left.y = poly->left.y - viewport_pos.y;
right.y = poly->right.y - viewport_pos.y;
SDL_SetRenderDrawColor(ren, 100,100,100, 255);
@ -97,6 +106,7 @@ void draw_collision_poly(SDL_Renderer* ren, Body *body) { @@ -97,6 +106,7 @@ void draw_collision_poly(SDL_Renderer* ren, Body *body) {
} else {
SDL_SetRenderDrawColor(ren, 0, 255, 0, 255);
}
if (body->collision_poly_size == 1) {
SDL_Rect dot;
Vect V;
@ -127,8 +137,8 @@ void draw_collision_poly(SDL_Renderer* ren, Body *body) { @@ -127,8 +137,8 @@ void draw_collision_poly(SDL_Renderer* ren, Body *body) {
x_st = x_en;
y_st = y_en;
}
x_en = body->collision_poly[0].x -viewport_pos.x;
y_en = body->collision_poly[0].y -viewport_pos.y;
x_en = body->collision_poly[0].x-viewport_pos.x;
y_en = body->collision_poly[0].y-viewport_pos.y;
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en);
}
SDL_SetRenderDrawColor(ren, 0,0,0, 255);

172
game.c

@ -214,20 +214,36 @@ Vect get_normal(Vect start, Vect end) { @@ -214,20 +214,36 @@ Vect get_normal(Vect start, Vect end) {
double y = (end.y - start.y);
norm.x = -y;
norm.y = x;
double len = vect_mag(norm);
norm.x /= len;
norm.y /= len;
return norm;
}
// reference:
// http://www.dyn4j.org/2010/01/sat/#sat-inter
//
// TODO: Maybe avoid calculating the centre of the boxes; have body->position
// be the centre and translate the collision box to be around that. It does
// make placing a little more complex but no bother.
bool sat_collision_check(Body *one, Body *two, Vect *translation) {
int num_axes = one->collision_poly_size + two->collision_poly_size;
Vect *axes = calloc(num_axes, sizeof(Vect));
Vect end;
Vect start = one->collision_poly[0];
Vect one_position;
Vect two_position;
two_position = two->collision_poly[0];
one_position = one->collision_poly[0];
for (int i = 1; i < one->collision_poly_size; i++) {
one_position = vect_add(one_position, one->collision_poly[i]);
end = one->collision_poly[i];
axes[i-1] = get_normal(start, end);
printf(".%d\n", i-1);
@ -240,6 +256,7 @@ bool sat_collision_check(Body *one, Body *two, Vect *translation) { @@ -240,6 +256,7 @@ bool sat_collision_check(Body *one, Body *two, Vect *translation) {
start = two->collision_poly[0];
for (int i = 1; i < two->collision_poly_size; i++) {
two_position = vect_add(two_position, two->collision_poly[i]);
end = two->collision_poly[i];
axes[i - 1 + one->collision_poly_size] = get_normal(start, end);
printf(".%d\n", i-1 + one->collision_poly_size);
@ -250,15 +267,6 @@ bool sat_collision_check(Body *one, Body *two, Vect *translation) { @@ -250,15 +267,6 @@ bool sat_collision_check(Body *one, Body *two, Vect *translation) {
axes[two->collision_poly_size + one->collision_poly_size - 1] = get_normal(start, end);
printf(".%d\n",two->collision_poly_size + one->collision_poly_size - 1);
// normalise
for (int i = 0; i < num_axes; i++) {
printf("AXIS TO CHECK :(num %d) %f %f\n", i, axes[i].x, axes[i].y);
double len = vect_mag(axes[i]);
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;
proj_one = proj_two = 0;
@ -289,17 +297,41 @@ bool sat_collision_check(Body *one, Body *two, Vect *translation) { @@ -289,17 +297,41 @@ bool sat_collision_check(Body *one, Body *two, Vect *translation) {
double right = proj_one[0] > proj_two[0] ? proj_one[0] : proj_two[0];
overlap = left - right;
printf("OVERLAP : %e\n", overlap);
if (overlap < min_overlap) {
if (overlap < min_overlap && overlap > 0) {
min_overlap = overlap;
min_axis = axes[i];
}
}
}
// return the MTV
// flip the MTV if it is pointing INTO the object
Vect trans;
trans.x = min_overlap * min_axis.x;
trans.y = min_overlap * min_axis.y;
// https://gamedev.stackexchange.com/questions/27596/implementing-separating-axis-theorem-sat-and-minimum-translation-vector-mtv/27629#27629
Vect direction;
one_position.x /= one->collision_poly_size;
one_position.y /= one->collision_poly_size;
two_position.x /= two->collision_poly_size;
two_position.y /= two->collision_poly_size;
printf("ONE POS: %f %f", one_position.x, one_position.y);
printf("TWO POS: %f %f", two_position.x, one_position.y);
direction.x = one_position.x - two_position.x;
direction.y = one_position.y - two_position.y;
double dot = vect_scalar_projection(trans, direction);
printf("DIRECTION: %f %f\n\n", direction.x, direction.y);
printf("DOT: %f\n\n", dot);
if (dot > 0) {
trans = vect_scalar(trans, -1);
}
// return the MTV
*translation = trans;
printf("Trans Vect: %e, %e\n", trans.x, trans.y);
@ -440,31 +472,57 @@ void add_motor(Body *thing, double x, double y) { @@ -440,31 +472,57 @@ void add_motor(Body *thing, double x, double y) {
}
// basic collision handler for testing
int process_collisions(Body *thing, Vect **trans) {
*trans = calloc(10, sizeof(Vect));
//
// TODO: Maybe adding all the MTVs together for the body will make it work better,
// will this solve the problem of negative normals? noo.. idk. But anyway it is more
// efficient for processing many collisions because you only do the physics for an
// MTV once rather than for all of the collisions separately.
int process_collisions(Body *thing, Vect *trans) {
Vect translation;
translation.x = translation.y = 0;
Vect temptrans;
int num_cols = 0;
int num = 0;
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, *trans + num_cols)) {
num_cols++;
if ((world[k].wall->physics->position.x - viewport_pos.x) > (width * 2)
|| world[k].wall->physics->position.x - viewport_pos.x < 0) {
continue;
} else {
num++;
}
if (check_collision(world[k].wall->physics, thing, &temptrans)) {
num++;
thing->colliding = true;
translation = vect_add(translation, temptrans);
}
} else if (world[k].kind == FLOOR) {
for (int i = 0; i < world[k].floor->numPolys; i++) {
if (check_collision(world[k].floor->polys[i].physics, thing, *trans + num_cols)) {
if ((world[k].floor->polys[i].physics->position.x - viewport_pos.x) > (2 *width)
|| (world[k].floor->polys[i].physics->position.x - viewport_pos.x) < 0) {
continue;
} else {
num++;
}
if (check_collision(world[k].floor->polys[i].physics, thing, &temptrans)) {
num_cols++;
thing->colliding = true;
translation = vect_add(translation, temptrans);
}
}
}
}
printf("Tested %d collisions\n", num);
if (!num_cols) {
thing->colliding = false;
free (*trans);
return false;
} else {
return num_cols;
*trans = translation;
return true;
}
}
@ -474,64 +532,71 @@ int process_collisions(Body *thing, Vect **trans) { @@ -474,64 +532,71 @@ int process_collisions(Body *thing, Vect **trans) {
* object's position.
*/
void advance_thing(Body * thing) {
// TODO: fix ordering of collision detection + physics sim so that collisions
// are less bad.
// TODO: Implement broad phase and narrow phase, else massively speed up collisions somehow.
thing->acc.x = 0;
thing->acc.y = 0;
printf("Position: %f %f\n", thing->position.x, thing->position.y);
thing->updateCollisionPoly(thing);
if (!thing->collision_poly[0].y) {
thing->updateCollisionPoly(thing);
}
if (!thing->dynamics) {
return;
}
Vect *translations;
thing->updateCollisionPoly(thing);
Vect translation;
translation.x = translation.y = 0;
int numcols = 0;
if ((numcols = process_collisions(thing, &translations))) {
for (int i = 0; i < numcols; i++) {
Vect translation = translations[i];
double mag = vect_mag(translation);
double check = vect_scalar_projection(translation, thing->vel);
if (check >= 0) {
translation.x *= -1;
translation.y *= -1;
}
if ((numcols = process_collisions(thing, &translation))) {
double mag = vect_mag(translation);
thing->position.x += translation.x;
thing->position.y += translation.y;
translation.x = translation.x / mag;
translation.y = translation.y / mag;
/*double check = vect_scalar_projection(translation, thing->vel);*/
/*if (check >= 0) {*/
/*translation.x *= -1;*/
/*translation.y *= -1;*/
/*}*/
mag = vect_scalar_projection(thing->vel, translation);
thing->position.x += translation.x;
thing->position.y += translation.y;
Vect revert_vel;
translation.x = translation.x / mag;
translation.y = translation.y / mag;
revert_vel.x = cos(vect_dir(translation)) * mag;
revert_vel.y = sin(vect_dir(translation)) * mag;
mag = vect_scalar_projection(thing->vel, translation);
thing->vel.x -= revert_vel.x;
thing->vel.y -= revert_vel.y;
Vect revert_vel;
// restitution force
Vect rest;
/*rest.x = 0;*/
/*rest.y = 0;*/
/*double impulse = thing->obj_mass * vect_mag(thing->vel) * thing->obj_elasticity;*/
/*rest.x = cos(vect_dir(translation)) * impulse;*/
/*rest.y = sin(vect_dir(translation)) * impulse;*/
/*accel_thing(thing, rest.x, rest.y);*/
revert_vel.x = cos(vect_dir(translation)) * mag;
revert_vel.y = sin(vect_dir(translation)) * mag;
thing->vel.x -= revert_vel.x;
thing->vel.y -= revert_vel.y;
// restitution force
Vect rest;
/*rest.x = 0;*/
/*rest.y = 0;*/
/*double impulse = thing->obj_mass * vect_mag(thing->vel) * thing->obj_elasticity;*/
/*rest.x = cos(vect_dir(translation)) * impulse;*/
/*rest.y = sin(vect_dir(translation)) * impulse;*/
/*accel_thing(thing, rest.x, rest.y);*/
}
free(translations);
}
uint32_t now = SDL_GetTicks();
uint32_t time_delta = now - thing->last_advance_time ;
thing->last_advance_time = SDL_GetTicks(); // in milliseconds
time_delta = 15;
if (time_delta > 18) {
logwrite(ERROR, "Simulation too slow\n");
return;
}
// motors
for (int i = 0; i < thing->num_motors; i++) {
@ -599,7 +664,6 @@ void advance_thing(Body * thing) { @@ -599,7 +664,6 @@ void advance_thing(Body * thing) {
thing->position.y += (thing->vel.y * 1/2 * (double)time_delta);
// revert if this caused collision
thing->updateCollisionPoly(thing);
/*if (process_collisions(thing)) {*/
/*thing->x_pos = oldx;*/
/*thing->y_pos = oldy;*/
@ -685,7 +749,7 @@ void startgame(SDL_Renderer * ren) { @@ -685,7 +749,7 @@ void startgame(SDL_Renderer * ren) {
memset(world, 0, sizeof(world_thing) * 100);
SDL_GetRendererOutputSize(ren, &width, &height);
player = get_player(700,600);
player = get_player(20 * width,600);
world_thing player_world;
@ -714,7 +778,7 @@ float get_abs(float x,float y) { @@ -714,7 +778,7 @@ 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 * y);
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);

3
logger.c

@ -1,10 +1,9 @@ @@ -1,10 +1,9 @@
#include "logger.h"
// Defaults
loggerlevel LOGLEVEL = SILENT;
loggerlevel STDOUTLEVEL = WARN;
loggerlevel STDOUTLEVEL = SILENT;
void set_loglevel(loggerlevel echo, loggerlevel write) {
LOGLEVEL = write;

1
vect.c

@ -42,7 +42,6 @@ Vect project_vect(Vect one, Vect two) { @@ -42,7 +42,6 @@ Vect project_vect(Vect one, Vect two) {
double vect_scalar_projection(Vect V, Vect P) {
double angle = vect_dir(V) - vect_dir(P);
return cos(angle) * vect_mag(V);
}
double vect_dir(Vect V) {

Loading…
Cancel
Save