You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
837 lines
24 KiB
837 lines
24 KiB
#include "game.h" |
|
player_st *glob_player; |
|
|
|
void set_motor_newtons(Body *thing, int motorID, double x, double y); |
|
void set_motor_max_velocity(Body *thing, int motorID, double max); |
|
|
|
void get_new_physics(Body **phys); |
|
|
|
// move the collision poly to the position of the player |
|
void default_update_collision_poly(Body *body) { |
|
for (int i=0; i < body->collision_poly_size; i++) { |
|
|
|
double x = body->collision_shape[i].x + body->position.x; |
|
double y = body->collision_shape[i].y + body->position.y; |
|
|
|
body->collision_poly[i].x = x; |
|
body->collision_poly[i].y = y; |
|
} |
|
fflush(stdout); |
|
} |
|
|
|
void default_motor_curve(Motor *motor) { |
|
// constant |
|
return; |
|
} |
|
|
|
FloorPoly* generate_floor_simple(int num_polys) { |
|
FloorPoly *floor = calloc(num_polys, sizeof(FloorPoly)); |
|
Vect last, next; |
|
last.x = 10; |
|
last.y = 900; |
|
|
|
for (int i = 0; i < num_polys; i++) { |
|
double run = (rand() % 900); |
|
double rise = (rand() % 100) - (rand() % 100); |
|
next.x = last.x + run; |
|
next.y = last.y + rise; |
|
|
|
FloorPoly poly; |
|
poly.left = last; |
|
poly.right = next; |
|
get_new_physics(&poly.physics); |
|
|
|
poly.physics->position = last; |
|
|
|
poly.physics->collision_poly_size = 4; |
|
poly.physics->collision_poly = calloc(4, sizeof(Vect)); |
|
poly.physics->collision_shape = calloc(4, sizeof(Vect)); |
|
|
|
poly.physics->collision_shape[0].x = 0; |
|
poly.physics->collision_shape[0].y = 0; |
|
|
|
poly.physics->collision_shape[1].x = run; |
|
poly.physics->collision_shape[1].y = rise; |
|
|
|
poly.physics->collision_shape[2].x = run; |
|
poly.physics->collision_shape[2].y = rise+200; |
|
|
|
poly.physics->collision_shape[3].x = 0; |
|
poly.physics->collision_shape[3].y = rise+200; |
|
|
|
last = next; |
|
floor[i] = poly; |
|
} |
|
|
|
return floor; |
|
} |
|
|
|
// @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; |
|
|
|
physics->obj_mass = 100; |
|
//kgs |
|
|
|
physics->motors = malloc(sizeof(Motor) * 100); |
|
memset(physics->motors, 0, sizeof(Motor) * 100); |
|
physics->max_motors = 100; |
|
physics->num_motors = 0; |
|
// gravity |
|
add_motor(physics, 0.0, 0.0); |
|
// friction |
|
add_motor(physics, 0.0, 0.0); |
|
|
|
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) { |
|
/* 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->position.x = x; |
|
player.physics->position.y = y; |
|
|
|
// friction (not in use) |
|
player.physics->glob_friction = 40; // drag coef * area |
|
|
|
// collisions |
|
player.physics->obj_elasticity = 0.7; |
|
player.physics->collision_poly = calloc(4, sizeof(Vect)); |
|
player.physics->collision_shape = calloc(4, sizeof(Vect)); |
|
|
|
player.physics->collision_poly_size = 4; |
|
Vect *rect = player.physics->collision_shape; |
|
rect[0].x = -10; rect[0].y = -10; |
|
rect[1].x = 10; rect[1].y = -10; |
|
rect[2].x = 10; rect[2].y = 10; |
|
rect[3].x = -10; rect[3].y = 10; |
|
|
|
// gravity |
|
set_motor_newtons(player.physics, M_GRAVITY, 0.0, player.physics->obj_mass * 4); |
|
|
|
// walking motor |
|
add_motor(player.physics, 0.0, player.physics->obj_mass * 9.81); |
|
set_motor_max_velocity(player.physics, M_PLAYER_WALK, 5); // has to be > grav |
|
set_motor_max_velocity(player.physics, M_GRAVITY, 5); |
|
|
|
return (player); |
|
} |
|
|
|
bool point_point_colcheck(Vect one, Vect two) { |
|
if (one.x == two.x && one.y == two.y) { |
|
return true; |
|
} |
|
return false; |
|
} |
|
|
|
typedef struct { |
|
Vect one; |
|
Vect two; |
|
} Collision; |
|
|
|
bool point_line_colcheck(Vect line[2], Vect 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) |
|
|| (point.y > line[0].y && point.y > line[0].y) |
|
|| (point.y < line[0].y && point.y < line[0].y) |
|
){ |
|
return false; |
|
} |
|
|
|
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 false; |
|
} |
|
|
|
double *project_col_poly(Body *shape, Vect V) { |
|
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; |
|
//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; |
|
max = -99999999; |
|
min = 99999999; |
|
for (int i = 0; i < shape->collision_poly_size; i++) { |
|
if (proj[i] > max) { |
|
max = proj[i]; |
|
} |
|
if (proj[i] < min) { |
|
min = proj[i]; |
|
} |
|
} |
|
double *res = calloc(2, sizeof(double)); |
|
res[0] = min; |
|
res[1] = max; |
|
|
|
printf("POLY PROJ: %f, %f\n", min, max); |
|
free(proj); |
|
return res; |
|
} |
|
|
|
Vect get_normal(Vect start, Vect end) { |
|
Vect norm; |
|
double x = (end.x - start.x); |
|
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); |
|
start = end; |
|
} |
|
|
|
end = one->collision_poly[0]; |
|
axes[one->collision_poly_size - 1] = get_normal(start, end); |
|
|
|
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); |
|
start = end; |
|
} |
|
|
|
end = two->collision_poly[0]; |
|
axes[two->collision_poly_size + one->collision_poly_size - 1] = get_normal(start, end); |
|
|
|
double *proj_one, *proj_two; |
|
proj_one = proj_two = 0; |
|
|
|
Vect min_axis; |
|
double min_overlap = 99999999; |
|
for (int i = 0; i < num_axes; i++) { |
|
// project |
|
if (proj_one) { |
|
free(proj_one); |
|
} |
|
if (proj_two) { |
|
free(proj_two); |
|
} |
|
proj_one = project_col_poly(one, axes[i]); |
|
proj_two = project_col_poly(two, axes[i]); |
|
|
|
if ((proj_one[0] >= proj_two[1]) |
|
|| (proj_two[0] >= proj_one[1])) { |
|
logwrite(INFO, "No collision"); |
|
free(axes); |
|
free(proj_one); |
|
free(proj_two); |
|
return false; |
|
} else { |
|
double overlap; |
|
double left = proj_one[1] < proj_two[1] ? proj_one[1] : proj_two[1]; |
|
double right = proj_one[0] > proj_two[0] ? proj_one[0] : proj_two[0]; |
|
overlap = left - right; |
|
|
|
// one of the shapes is contained |
|
if ((overlap > (proj_one[1] - proj_one[0]) |
|
|| (overlap > (proj_two[1] - proj_two[0])))) { |
|
logwrite(INFO, "Contained collision"); |
|
|
|
double min = proj_one[0] - proj_two[0]; |
|
double max = proj_one[1] - proj_two[1]; |
|
|
|
min = min < 0 ? -min : min; |
|
max = max < 0 ? -max : max; |
|
|
|
overlap += min < max ? min : max; |
|
|
|
} |
|
|
|
if (overlap < min_overlap && overlap > 0) { |
|
min_overlap = overlap; |
|
min_axis = axes[i]; |
|
} |
|
} |
|
} |
|
|
|
// 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); |
|
|
|
free(axes); |
|
free(proj_one); |
|
free(proj_two); |
|
return true; |
|
} |
|
|
|
bool check_collision(Body *one, Body *two, Vect *translation) { |
|
int onesize = one->collision_poly_size; |
|
int twosize = two->collision_poly_size; |
|
|
|
// point-point |
|
if (one->collision_poly_size == 1 && two->collision_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)) { |
|
Vect line[2]; |
|
Vect 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 sat_collision_check(one, two, translation); |
|
|
|
} |
|
} |
|
|
|
Wall *get_long_wall(int numNodes, int *nodes) { |
|
Wall wall; |
|
memset(&wall, 0, sizeof(wall)); |
|
|
|
wall.numNodes = numNodes; |
|
wall.nodes = calloc(numNodes, sizeof(SDL_Point)); |
|
get_new_physics(&wall.physics); |
|
|
|
wall.physics->collision_poly = calloc(numNodes, sizeof(Vect)); |
|
wall.physics->collision_shape = calloc(numNodes, sizeof(Vect)); |
|
wall.physics->collision_poly_size = numNodes; |
|
|
|
// collisions |
|
//SDL_Point *collision_poly; |
|
for (int i = 0; i < numNodes; i++) { |
|
wall.nodes[i].x = nodes[2*i]; |
|
wall.nodes[i].y = nodes[2*i+1]; |
|
|
|
wall.physics->collision_shape[i].x = nodes[2*i]; |
|
wall.physics->collision_shape[i].y = nodes[2*i+1]; |
|
} |
|
|
|
Wall *wallwall = malloc(sizeof(wall)); |
|
*wallwall = wall; |
|
return wallwall; |
|
} |
|
|
|
void accel_thing(Body * thing, double x, double y) { |
|
/* takes acceleration in m/s2 and converts to m/ms adding |
|
* it to physics_thing |
|
*/ |
|
|
|
// convert to m / millisecond |
|
double x_adj = x / 1000.0; |
|
double y_adj = y / 1000.0; |
|
|
|
thing->acc.y += y_adj; |
|
thing->acc.x += x_adj; |
|
|
|
} |
|
|
|
void set_motor_max_velocity(Body *thing, int motorID, double max) { |
|
thing->motors[motorID].max_velocity = max; |
|
} |
|
|
|
void set_motor_timeout(Body *thing, int motorID, uint32_t timeout) { |
|
thing->motors[motorID].timeout = timeout; |
|
} |
|
|
|
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(Body *thing, int motorID, double x, double y) { |
|
thing->motors[motorID].x +=x; |
|
thing->motors[motorID].y +=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.timeout = -1; |
|
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)); |
|
} |
|
|
|
thing->motors[thing->num_motors] = motor; |
|
thing->num_motors += 1; |
|
} |
|
|
|
// basic collision handler for testing |
|
// |
|
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 ((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 ((world[k].floor->polys[i].physics->position.x - viewport_pos.x) > (2 *width) |
|
|| (world[k].floor->polys[i].physics->position.x - viewport_pos.x) < -width) { |
|
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; |
|
return false; |
|
} else { |
|
*trans = translation; |
|
return true; |
|
} |
|
} |
|
|
|
/* 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) { |
|
// 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->collision_poly[0].y) { |
|
thing->updateCollisionPoly(thing); |
|
} |
|
|
|
if (!thing->dynamics) { |
|
return; |
|
} |
|
|
|
thing->updateCollisionPoly(thing); |
|
Vect translation; |
|
Vect friction; |
|
translation.x = translation.y = 0; |
|
int numcols = 0; |
|
if ((numcols = process_collisions(thing, &translation))) { |
|
double mag = vect_mag(translation); |
|
|
|
/*double check = vect_scalar_projection(translation, thing->vel);*/ |
|
/*if (check >= 0) {*/ |
|
/*translation.x *= -1;*/ |
|
/*translation.y *= -1;*/ |
|
/*}*/ |
|
|
|
thing->position.x += translation.x; |
|
thing->position.y += translation.y; |
|
|
|
translation.x = translation.x / mag; |
|
translation.y = translation.y / mag; |
|
|
|
mag = vect_scalar_projection(thing->vel, translation); |
|
|
|
Vect revert_vel; |
|
|
|
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; |
|
|
|
// accel |
|
double norm = 9.81 * thing->obj_mass; |
|
double fric_const = 0.52; |
|
Vect x; |
|
x.y = 0; x.x = 1; |
|
if (vect_scalar_projection(thing->vel, translation) > 0) { |
|
friction.x = translation.y; |
|
friction.y = -translation.x; |
|
} else { |
|
friction.x = -translation.y; |
|
friction.y = translation.x; |
|
} |
|
|
|
// force |
|
friction.x = friction.x * norm * fric_const; |
|
friction.y = friction.y * norm * fric_const; |
|
printf("friction accel: %e %e\n", friction.x, friction.y); |
|
printf("velocity: %e %e\n", thing->vel.x, thing->vel.y); |
|
|
|
set_motor_newtons(thing, M_FRICTION, friction.x, friction.y); |
|
set_motor_max_velocity(thing, M_FRICTION, vect_mag(project_vect(thing->vel, friction))); |
|
|
|
// restitution force |
|
/*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);*/ |
|
|
|
} |
|
|
|
uint32_t now = SDL_GetTicks(); |
|
|
|
uint32_t time_delta = now - thing->last_advance_time ; |
|
thing->last_advance_time = SDL_GetTicks(); // in milliseconds |
|
if (time_delta > 18) { |
|
logwrite(ERROR, "Simulation too slow\n"); |
|
} |
|
|
|
// motors |
|
for (int i = 0; i < thing->num_motors; i++) { |
|
if (thing->motors[i].timeout < now) { |
|
continue; |
|
} |
|
|
|
Vect F; |
|
Vect V; |
|
F.x = thing->motors[i].x; |
|
F.y = thing->motors[i].y; |
|
V.x = thing->vel.x; |
|
V.y = thing->vel.y; |
|
|
|
Vect vel_in_dir = project_vect(V, F); |
|
double dirF = atan2(F.y, F.x); |
|
double dirV = atan2(V.y, V.x); |
|
|
|
double diff = dirV > dirF ? dirV - dirF: dirF - dirV; |
|
|
|
if (thing->motors[i].max_velocity > vect_mag(vel_in_dir) |
|
|| diff >= M_PI) { |
|
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); |
|
} |
|
// printf("\n diff angle: %f pi: %f \n", dirV - dirF, M_PI); |
|
// printf("Vel: %f, Force: %f\n\n", dirV, dirF); |
|
} |
|
|
|
// accelerate based on accel |
|
printf("time: %f", (float)time_delta); |
|
thing->vel.x += thing->acc.x * (float)time_delta; |
|
thing->vel.y += thing->acc.y * (float)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); |
|
|
|
// simple air drag |
|
|
|
/*if (velocity > 0.000000000000000) {*/ |
|
/*double dir = atan2((double)thing->y_vel, (double)thing->x_vel) + M_PI;*/ |
|
|
|
/*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);*/ |
|
|
|
/*double f_x = (cos(dir)) * absolute_force;*/ |
|
/*double f_y = (sin(dir)) * absolute_force;*/ |
|
|
|
/*accel_thing(thing, (float)f_x, (float)f_y);*/ |
|
|
|
/*}*/ |
|
|
|
if (fabsl((*thing).vel.x) < 0.001) { |
|
(*thing).vel.x = 0; |
|
} |
|
if (fabsl((*thing).vel.y) < 0.001) { |
|
(*thing).vel.y = 0; |
|
} |
|
|
|
double oldx = thing->position.x; |
|
double oldy = thing->position.y; |
|
thing->position.x += (thing->vel.x * 1/2 * (double)time_delta); |
|
thing->position.y += (thing->vel.y * 1/2 * (double)time_delta); |
|
|
|
// revert if this caused collision |
|
/*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;*/ |
|
/*}*/ |
|
|
|
/*if (thing->y_pos > height) {*/ |
|
/*thing->y_pos = 0;*/ |
|
/*}*/ |
|
|
|
/*if (thing->y_pos < 0) {*/ |
|
/*thing->y_pos = height;*/ |
|
/*}*/ |
|
|
|
/*if (thing->x_pos < 0) {*/ |
|
/*thing->x_pos = width;*/ |
|
/*}*/ |
|
|
|
} |
|
|
|
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"); |
|
advance_thing((world[i].player->physics)); |
|
break; |
|
case STATIC_WALL_W: |
|
logwrite(INFO, "ADVANCE WALL\n"); |
|
advance_thing(world[i].wall->physics); |
|
break; |
|
case FLOOR: |
|
for (int k = 0; k < world[i].floor->numPolys; k++) { |
|
advance_thing(world[i].floor->polys[k].physics); |
|
} |
|
} |
|
} |
|
} |
|
|
|
// 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)); |
|
} |
|
|
|
thing.nid = things_in_world; |
|
memcpy(world + things_in_world, &thing, sizeof(world_thing)); |
|
|
|
things_in_world += 1; |
|
|
|
//printf("Added to world: %d\n", thing.kind); |
|
|
|
} |
|
|
|
void get_floor(void) { |
|
int floorsize = 1000; |
|
FloorPoly *polys = generate_floor_simple(floorsize); |
|
|
|
Floor *floor = calloc(1, sizeof(Floor)); |
|
floor->polys = polys; |
|
floor->numPolys = floorsize; |
|
|
|
world_thing thing; |
|
|
|
thing.kind = FLOOR; |
|
thing.floor = floor; |
|
|
|
add_to_world(thing); |
|
} |
|
|
|
void startgame(SDL_Renderer * ren) { |
|
logwrite(INFO, "STARTGAME"); |
|
things_in_world = 0; |
|
world_size = 100; |
|
world = malloc(sizeof(world_thing) * 100); |
|
memset(world, 0, sizeof(world_thing) * 100); |
|
SDL_GetRendererOutputSize(ren, &width, &height); |
|
|
|
player = get_player(20 * width,600); |
|
|
|
world_thing player_world; |
|
|
|
player_world.kind = PLAYER_W; |
|
player_world.player = malloc(sizeof(player)); |
|
*player_world.player = player; |
|
glob_player = player_world.player; |
|
|
|
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_floor(); |
|
} |
|
|
|
float get_abs(float x,float y) { |
|
return (sqrt(x*x + y*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 *10* x , 100 * y); |
|
} |
|
|
|
void step(int interval) { |
|
const uint8_t * keyboard; |
|
keyboard = SDL_GetKeyboardState(NULL); |
|
|
|
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_timeout(player.physics, M_PLAYER_WALK, SDL_GetTicks()+1000*2); |
|
} |
|
|
|
advance_things(); |
|
logwrite(DEBUG, "Updated Physics \n"); |
|
}
|
|
|