1
1
Fork 0
Browse Source

improve timer precision

thread-physics
alistair 4 years ago
parent
commit
eb5643c335
  1. 3
      draw.c
  2. 119
      game.c
  3. 8
      game.h
  4. 4
      main.c

3
draw.c

@ -199,9 +199,6 @@ void draw_forces(SDL_Renderer *ren, Body *body) { @@ -199,9 +199,6 @@ void draw_forces(SDL_Renderer *ren, Body *body) {
Vect F;
for (int i = 0; i < body->num_motors; i++) {
if (body->motors[i].timeout < SDL_GetTicks()) {
continue;
}
F.x += body->motors[i].x;
F.y += body->motors[i].y;
Vect end = vect_add(start, F);

119
game.c

@ -146,6 +146,8 @@ void get_new_physics(Body **phys) { @@ -146,6 +146,8 @@ void get_new_physics(Body **phys) {
// friction
add_motor(physics, 0.0, 0.0);
clock_gettime(CLOCK_MONOTONIC_RAW, &physics->last_advance_time);
physics->updateCollisionPoly = default_update_collision_poly;
*phys = physics;
return;
@ -197,7 +199,7 @@ player_st get_player(int x, int y) { @@ -197,7 +199,7 @@ player_st get_player(int x, int y) {
player.physics->position.y = y;
player.physics->next_position = player.physics->position;
player.physics->obj_elasticity = 0.9;
player.physics->obj_friction = 0.3;
player.physics->obj_friction = 0.2;
// friction (not in use)
player.physics->glob_friction = 40; // drag coef * area
@ -537,10 +539,15 @@ void set_motor_max_velocity(Body *thing, int motorID, double max) { @@ -537,10 +539,15 @@ void set_motor_max_velocity(Body *thing, int motorID, double max) {
}
void set_motor_timeout(Body *thing, int motorID, uint32_t timeout) {
thing->motors[motorID].timeout = timeout;
thing->motors[motorID].stop = false;
clock_gettime(CLOCK_MONOTONIC_RAW, &thing->motors[motorID].timeout);
thing->motors[motorID].timeout.tv_nsec += 1000000 * timeout;
thing->motors[motorID].timeout.tv_sec
= thing->motors[motorID].timeout.tv_nsec * 0.000000001;
}
void set_motor_newtons(Body *thing, int motorID, double x, double y) {
thing->motors[motorID].stop = false;
thing->motors[motorID].x =x;
thing->motors[motorID].y =y;
}
@ -557,9 +564,11 @@ void add_motor(Body *thing, double x, double y) { @@ -557,9 +564,11 @@ void add_motor(Body *thing, double x, double y) {
memset(&motor, 0, sizeof(Motor));
motor.x = x;
motor.y = y;
motor.stop = false;
motor.stop = true;
motor.timeout.tv_sec = 3600000000000 * 0.000000001;
motor.timeout.tv_nsec = 3600000000000;
motor.timeout = -1;
motor.max_velocity = 999899;
motor.update_motor = default_motor_curve;
@ -724,7 +733,6 @@ int process_collisions(Body *thing, Vect *trans) { @@ -724,7 +733,6 @@ int process_collisions(Body *thing, Vect *trans) {
}
}
printf("Tested %d collisions\n", num);
if (!num_cols) {
thing->colliding = false;
@ -743,12 +751,10 @@ int process_collisions(Body *thing, Vect *trans) { @@ -743,12 +751,10 @@ int process_collisions(Body *thing, Vect *trans) {
void advance_thing(Body * thing) {
// TODO: fix ordering of collision detection + physics sim so that collisions
// are less bad.
thing->acc.x = 0;
thing->acc.y = 0;
set_motor_newtons(thing, M_FRICTION, 0,0);
set_motor_max_velocity(thing, M_FRICTION, 0);
if (!thing->dynamics) {
return;
}
@ -763,18 +769,30 @@ void advance_thing(Body * thing) { @@ -763,18 +769,30 @@ void advance_thing(Body * thing) {
translation.x = translation.y = 0;
int numcols = 0;
uint32_t now = SDL_GetTicks();
uint32_t time_delta = now - thing->last_advance_time ;
if (time_delta > 20) {
printf("ERROR too slow: %d\n", time_delta);
/*uint32_t now = SDL_GetTicks();*/
/*uint32_t time_delta = now - thing->last_advance_time ;*/
struct timespec now;
clock_gettime(CLOCK_MONOTONIC_RAW, &now);
if (now.tv_nsec >= 1000000000) {
now.tv_nsec -= 1000000000;
}
double time_delta = now.tv_nsec - thing->last_advance_time.tv_nsec;
if (now.tv_nsec < thing->last_advance_time.tv_nsec) {
time_delta = now.tv_nsec - (thing->last_advance_time.tv_nsec - 1000000000);
}
time_delta *= 0.000001; // convert to ms from ns
if (time_delta > 19) {
printf("ERROR too slow: %f\n", time_delta);
thing->last_advance_time = now;
time_delta = 20;
time_delta = 19;
}
printf("TimeDELTA: %d\n", time_delta);
printf("TimeDELTA: %f\n", time_delta);
thing->last_advance_time = now;
// collisions
if ((numcols = process_collisions(thing, &translation))) {
/*double check = vect_scalar_projection(translation, thing->vel);*/
/*if (check >= 0) {*/
/*translation.x *= -1;*/
@ -806,27 +824,27 @@ void advance_thing(Body * thing) { @@ -806,27 +824,27 @@ void advance_thing(Body * thing) {
thing->vel.y -= revert_vel.y * sqrt(thing->obj_elasticity);
// add friction
if (vect_mag(translation) < 0.1) {
Vect friction = vect_rotate(revert_vel, M_PI / 2);
double dir = vect_scalar_projection(thing->vel, friction);
if (dir > 0) {
friction = vect_rotate(friction, M_PI);
}
Vect friction = vect_rotate(revert_vel, M_PI / 2);
double dir = vect_scalar_projection(thing->vel, friction);
if (dir > 0) {
friction = vect_rotate(friction, M_PI);
}
double normal = vect_mag(revert_vel);
printf("norm: %f\n", normal);
if (fabs(thing->vel.x) <= fabs(friction.x)) {
thing->vel.x = 0;
} else {
thing->vel.x += thing->obj_friction * friction.x;
}
if (fabs(thing->vel.y) <= fabs(friction.y)) {
thing->vel.y = 0;
} else {
thing->vel.y += thing->obj_friction * friction.y;
}
if (fabs(thing->vel.x) <= fabs(friction.x)) {
thing->vel.x = 0;
} else {
thing->vel.x += thing->obj_friction * friction.x;
printf("velocity: %f %f\n", thing->vel.x, thing->vel.y);
}
if (fabs(thing->vel.y) <= fabs(friction.y)) {
thing->vel.y = 0;
} else {
thing->vel.y += thing->obj_friction * friction.y;
}
printf("velocity: %f %f\n", thing->vel.x, thing->vel.y);
/*double norm = 9.81 * thing->obj_mass;*/
/*Vect x;*/
@ -891,12 +909,13 @@ void advance_thing(Body * thing) { @@ -891,12 +909,13 @@ void advance_thing(Body * thing) {
thing->vel.y -= corr_mag * sin(angle);
}
}
// motors
for (int i = 0; i < thing->num_motors; i++) {
if (thing->motors[i].timeout < now
if (thing->motors[i].timeout.tv_nsec < now.tv_nsec
&& thing->motors[i].timeout.tv_sec < now.tv_sec
|| thing->motors[i].stop) {
printf("%ld %ld %d\n", thing->motors[i].timeout.tv_nsec, now.tv_nsec, thing->motors[i].stop);
continue;
}
if (thing->motors[i].update_motor) {
@ -925,8 +944,8 @@ void advance_thing(Body * thing) { @@ -925,8 +944,8 @@ void advance_thing(Body * thing) {
}
// accelerate based on accel
thing->vel.x += thing->acc.x * (float)time_delta;
thing->vel.y += thing->acc.y * (float)time_delta;
thing->vel.x += thing->acc.x * (double)time_delta;
thing->vel.y += thing->acc.y * (double)time_delta;
double velocity = sqrt((double)(thing->vel.x * thing->vel.x + thing->vel.y * thing->vel.y));
printf("\nvels %e %e\n\n", thing->vel.x, thing->vel.y);
@ -956,10 +975,10 @@ void advance_thing(Body * thing) { @@ -956,10 +975,10 @@ void advance_thing(Body * thing) {
double oldx = thing->position.x;
double oldy = thing->position.y;
thing->position = thing->next_position;
thing->next_position.x += (thing->vel.x * 1/2 * (double)time_delta);
thing->next_position.y += (thing->vel.y * 1/2 * (double)time_delta);
thing->last_advance_time = now; // in milliseconds
thing->position = thing->next_position;
//thing->last_advance_time = now; // in milliseconds
}
@ -1004,15 +1023,17 @@ void advance_things(void) { @@ -1004,15 +1023,17 @@ void advance_things(void) {
advance_thing(world.things[i].wall->physics);
break;
case FLOOR:
for (int k = 0; k < world.things[i].floor->numPolys; k++) {
advance_thing(world.things[i].floor->polys[k].physics);
}
break;
/*for (int k = 0; k < world.things[i].floor->numPolys; k++) {*/
/*advance_thing(world.things[i].floor->polys[k].physics);*/
/*}*/
/*break;*/
case CEILING:
for (int k = 0; k < world.things[i].floor->numPolys; k++) {
advance_thing(world.things[i].floor->polys[k].physics);
}
break;
/*for (int k = 0; k < world.things[i].floor->numPolys; k++) {*/
/*advance_thing(world.things[i].floor->polys[k].physics);*/
/*}*/
/*break;*/
case PROJECTILE:
if ((numcols = process_collisions(world.things[i].projectile->physics,
&translation))) {
@ -1120,19 +1141,13 @@ void startgame(SDL_Renderer * ren) { @@ -1120,19 +1141,13 @@ void startgame(SDL_Renderer * ren) {
add_to_world(player_world);
world_thing wall_world;
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;
add_to_world(wall_world);
viewport_pos.x = 700;
viewport_pos.y = 0;
get_room();
}
float get_abs(float x,float y) {
double get_abs(double x,double y) {
return (sqrt(x*x + y*y));
}

8
game.h

@ -3,10 +3,12 @@ @@ -3,10 +3,12 @@
#include <stdbool.h>
#include <stdint.h>
#include <math.h>
#include <time.h>
#ifndef _DEFGAME
#define _DEFGAME
#include "vect.h"
#include "garbo.h"
#include "draw.h"
@ -38,7 +40,7 @@ typedef struct motorstruct { @@ -38,7 +40,7 @@ typedef struct motorstruct {
// direction of the motor vector is greater than
// max_velocity
uint32_t timeout;// absolute time (in ms, from when the program starts)
struct timespec timeout;// absolute time (in ns, from when the program starts)
// for how long the motor runs before stopping
// automatically
// set to -1 for infinity
@ -113,7 +115,9 @@ typedef struct BodyStruct{ @@ -113,7 +115,9 @@ typedef struct BodyStruct{
double glob_friction;
bool glob_gravity; // t/f
uint32_t last_advance_time;
// uint32_t last_advance_time;
struct timespec last_advance_time;
// applying forces
int num_motors;

4
main.c

@ -93,7 +93,7 @@ int game(void) { @@ -93,7 +93,7 @@ int game(void) {
SDL_Thread *physics_thread;
int ignore;
// physics_thread = SDL_CreateThread(physics_loop, "Physics", (void *)NULL);
physics_thread = SDL_CreateThread(physics_loop, "Physics", (void *)NULL);
bool once = true;
startgame(ren);
@ -114,7 +114,7 @@ int game(void) { @@ -114,7 +114,7 @@ int game(void) {
}
/* Redraw Screen */
redraw(ren);
step(10);
// step(10);
}
}

Loading…
Cancel
Save