1
1
Fork 0
Browse Source

generalise

thread-physics
user 5 years ago
parent
commit
8ba7cee519
  1. 4
      Makefile
  2. 98
      draw.c
  3. 382
      game.c
  4. 49
      game.h
  5. 4
      logger.c
  6. 45
      main.c

4
Makefile

@ -1,10 +1,8 @@ @@ -1,10 +1,8 @@
CXX = gcc
CXX = gcc -g
SDL_INCLUDE = -lSDL2 -lm -lSDL2_image
CXXFLAGS = -Wall $(SDL_INCLUDE)
EXE = main
run: all
./$(EXE)
all: $(EXE)

98
draw.c

@ -53,15 +53,111 @@ void draw_player(SDL_Renderer * ren, int x, int y) { @@ -53,15 +53,111 @@ void draw_player(SDL_Renderer * ren, int x, int y) {
}
void draw_wall(SDL_Renderer *ren, Wall *wall) {
float x_st, x_en, y_st, y_en;
x_st = wall->nodes[0].physics.x_pos;
y_st = wall->nodes[0].physics.y_pos;
for (int i = 1; i < wall->numNodes; i++) {
x_en = wall->nodes[i].physics.x_pos;
y_en = wall->nodes[i].physics.y_pos;
printf("wall: %f %f %f %f\n", x_st, y_st, x_en, y_en);
SDL_SetRenderDrawColor(ren, 120, 85, 188, 255);
SDL_RenderDrawLine(ren, x_st, y_st, x_en, y_en);
SDL_SetRenderDrawColor(ren, 0,0,0, 255);
x_st = x_en;
y_st = y_en;
}
}
int distance_colour(int x, int y, int x2, int y2, int blackpoint) {
int dist = (int) sqrt((x2 - x)*(x2 - x) + (y2 - y)*(y2 - y) );
if (dist == 0) {
return 255;
}
if (dist > blackpoint) {
return 0;
}
int frac = blackpoint / dist;
// int frac = 255 * (int) sin((double)dist / blackpoint);
if (frac > 255) {
return 255;
}
return frac;
}
void redraw_buffer(SDL_Renderer * ren) {
static int width = 0;
static int height = 0;
static int mousex = 0;
static int mousey = 0;
static int newmousex = 0;
static int newmousey = 0;
static SDL_Point *bgPixels[256];
static int numpixels[256];
if (!width && !height) {
SDL_GetRendererOutputSize(ren, &width, &height);
for (int i = 0; i < 256; i++) {
bgPixels[i] = malloc(sizeof(SDL_Point) * width * height);
memset(bgPixels[i], 0, sizeof(SDL_Point) * width * height);
memset(numpixels, 0, (sizeof(int) * 256));
}
}
int col = 0;
//SDL_GetMouseState(&newmousex, &newmousey);
for (int i=0; i<things_in_world; i++) {
world_thing thing;
thing = world[i];
printf("draw thing: %d\n, no %d of %d\n", thing.kind, thing.nid, things_in_world);
switch (thing.kind) {
case PLAYER:
draw_player(ren, (*thing.player).physics.x_pos, (*thing.player).physics.y_pos);
draw_player(ren, (*thing.player).physics->x_pos, (*thing.player).physics->y_pos);
break;
case STATIC_WALL_W:
draw_wall(ren, thing.wall);
break;
}
}
/*if (newmousex != mousex || newmousey != mousey) {*/ /*mousey = newmousey;*/
/*mousex = newmousex;*/
/*for (int i = 0; i < 256; i++) {*/
/*memset(bgPixels[i], 0, sizeof(SDL_Point) * width * height);*/
/*memset(numpixels, 0, (sizeof(int) * 256));*/
/*}*/
/*for (int i=0; i < width; i++) {*/
/*for (int j = 0; j < height; j++) {*/
/*col = distance_colour(i, j, mousex, mousey, 10000);*/
/*SDL_Point *row = bgPixels[col];*/
/*SDL_Point point;*/
/*point.x = i;*/
/*point.y = j;*/
/*row[numpixels[col]] = point;*/
/*numpixels[col] += 1;*/
/*}*/
/*}*/
/*}*/
/*for (int i = 0; i < 255; i++) {*/
/*SDL_Point *row = bgPixels[i];*/
/*col = i;*/
/*SDL_SetRenderDrawColor(ren, col, col, col, 255);*/
/*SDL_RenderDrawPoints(ren, row, numpixels[i]);*/
/*}*/
}

382
game.c

@ -1,51 +1,156 @@ @@ -1,51 +1,156 @@
#include "game.h"
#define GRAVITY_ACCEL 2
player_st *glob_player;
// @param uninitialised physics_thing pointer
// @result: malloc and configure a physics thing pointer
void get_new_physics(physics_thing **phys) {
/* physics */
physics_thing * physics = malloc(sizeof(physics_thing));
memset(physics, 0, sizeof(physics_thing));
/*
*typedef enum {
* sdl_shape;
* image;
*
*} render_type;
*/
physics->glob_gravity = false;
physics->glob_friction = 0.0000;
/*
*typedef struct {
* char image_path[];
* // poly
*} sprite;
*/
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;
add_motor(physics, 0.0, 0.0);
*phys = physics;
}
player_st get_player(int x, int y) {
/* creates player at given postion and zeroes physics */
player_st player;
memset(&player, 0, sizeof(player));
player.max_walking_speed = 100;
/* physics */
get_new_physics(&player.physics);
player.physics->x_pos = x;
player.physics->y_pos = y;
player.physics.x_pos = x;
player.physics.y_pos = y;
add_motor(player.physics, 0.0, 0.0);
player.physics.x_acc = 0;
player.physics.y_acc = 0;
return (player);
}
player.physics.x_vel = 0;
player.physics.y_vel = 0;
player.max_walking_speed = 1001;
wall_node get_wall_node(int x, int y) {
wall_node wn;
memset(&wn, 0, sizeof(wn));
player.physics.glob_gravity = false;
player.physics.glob_friction = 0.0000005;
wn.physics.x_pos = x;
wn.physics.y_pos = y;
player.physics.obj_mass = 100;
//kgs
wn.physics.x_acc = 0;
wn.physics.y_acc = 0;
wn.physics.obj_mass = 10;
wn.physics.glob_gravity = false;
wn.physics.glob_friction = 0.00000000;
player.physics.motor_x= 0;
player.physics.motor_y = 0;
wn.physics.x_vel = 0;
wn.physics.y_vel = 0;
return (player);
return wn;
}
Wall *get_stat_wall(int st_x, int st_y, int en_x, int en_y) {
Wall wall;
memset(&wall, 0, sizeof(wall));
wall.numNodes = 2;
wall.nodes = malloc(sizeof(wall_node) * wall.numNodes);
wall.nodes[0] = get_wall_node(st_x, st_y);
wall.nodes[1] = get_wall_node(en_x, en_y);
Wall *wallwall = malloc(sizeof(wall));
*wallwall = wall;
return wallwall;
}
void collision(int numNodes1, physics_thing *nodes1,
int numNodes2, physics_thing *nodes2) {
int x_1, y_1, x_2, y_2, xa_1, ya_1, xa_2, ya_2;
for (int i = 0; i < numNodes1; i++) {
x_1 = nodes1[2*i].x_pos;
y_1 = nodes1[2*i].y_pos;
x_2 = nodes1[2*i+1].x_pos;
y_2 = nodes1[2*i+1].y_pos;
for (int j = 0; j < numNodes2; j++) {
xa_1 = nodes2[2*j].x_pos;
ya_1 = nodes2[2*j].y_pos;
xa_2 = nodes2[2*j+1].x_pos;
ya_2 = nodes2[2*j+1].y_pos;
}
}
}
physics_thing *get_player_collision_test(physics_thing *player) {
physics_thing up, right;
physics_thing *nodes = malloc(sizeof(physics_thing) * 2);
up = *player;
right = *player;
up.y_pos += 1;
right.x_pos += 1;
nodes[0] = up;
nodes[1] = right;
return nodes;
}
void check_collision(int numNodes, physics_thing *things) {
for (int i = 0; i < things_in_world; i++) {
world_thing worldThing = world[i];
Wall *wall;
physics_thing *nodes;
if (worldThing.collisions) {
switch (worldThing.kind) {
case PLAYER_W:
collision(2, get_player_collision_test(things), 1, worldThing.player->physics);
break;
case STATIC_WALL_W:
wall = worldThing.wall;
nodes = malloc(sizeof(physics_thing) * wall->numNodes);
for (int i = 0; i < wall->numNodes; i++) {
nodes[i] = wall->nodes[i].physics;
}
collision(numNodes, things, wall->numNodes, nodes);
free(nodes);
break;
}
}
}
}
Wall *get_long_wall(int numNodes, int *nodes) {
Wall wall;
memset(&wall, 0, sizeof(wall));
wall.numNodes = numNodes;
wall.nodes = malloc(sizeof(wall_node) * numNodes);
for (int i = 0; i < numNodes; i++) {
wall.nodes[i] = get_wall_node(nodes[2*i], nodes[2*i+1]);
//set_motor_ms(&(wall.nodes[i].physics), 2.0 , 1.0);
}
Wall *wallwall = malloc(sizeof(wall));
*wallwall = wall;
return wallwall;
}
void accel_thing(physics_thing * thing, float x, float y) {
@ -53,8 +158,9 @@ void accel_thing(physics_thing * thing, float x, float y) { @@ -53,8 +158,9 @@ void accel_thing(physics_thing * thing, float x, float y) {
* it to physics_thing
*/
float x_adj = x / 1000.0;
float y_adj = y / 1000.0;
// convert to m / millisecond
float x_adj = x / 1000.0;
float y_adj = y / 1000.0;
(*thing).y_acc += (float)y_adj;
(*thing).x_acc += (float)x_adj;
@ -63,28 +169,30 @@ void accel_thing(physics_thing * thing, float x, float y) { @@ -63,28 +169,30 @@ void accel_thing(physics_thing * thing, float x, float y) {
}
void set_motor_ms(physics_thing * thing, float x, float y) {
// set motor force in newtons
float x_adj = x;
float y_adj = y;
(*thing).motor_x = (float)y_adj;
(*thing).motor_y = (float)x_adj;
void set_motor_newtons(physics_thing *thing, int motorID, double x, double y) {
thing->motors[motorID].x =x;
thing->motors[motorID].y =y;
}
logwrite(DEBUG, "set motor thing\n");
void add_motor_newtons(physics_thing *thing, int motorID, double x, double y) {
thing->motors[motorID].x +=x;
thing->motors[motorID].y +=y;
}
void add_motor_ms(physics_thing * thing, float x, float y) {
// set motor force in newtons
float x_adj = x;
float y_adj = y;
void add_motor(physics_thing *thing, double x, double y) {
(*thing).motor_x += (float)y_adj;
(*thing).motor_y += (float)x_adj;
Motor motor;
memset(&motor, 0, sizeof(Motor));
motor.x = x;
motor.y = y;
if (thing->num_motors == thing->max_motors) {
thing->motors = realloc(thing->motors, sizeof(Motor) * (thing->max_motors *=2));
}
logwrite(DEBUG, "set motor thing\n");
thing->motors[thing->num_motors] = motor;
thing->num_motors += 1;
}
@ -93,15 +201,13 @@ int advance_glob(physics_thing * thing) { @@ -93,15 +201,13 @@ int advance_glob(physics_thing * thing) {
// gravity
if ((*thing).glob_gravity == true) {
accel_thing(thing, 0, 9.81);
accel_thing(thing, 0, GRAVITY_ACCEL);
}
// friction
if ((*thing).glob_friction != 0.0) {
logwrite(DEBUG, "Friction\n");
/* god this is so jank */
float normal = (*thing).obj_mass * 9.81;
float F_force = normal * (*thing).glob_friction;
float dir = atan2((*thing).y_vel, (*thing).x_vel);
@ -121,57 +227,60 @@ int advance_glob(physics_thing * thing) { @@ -121,57 +227,60 @@ int advance_glob(physics_thing * thing) {
(*thing).y_acc += f_y;
}
/*
* if (fabs((*thing).x_acc ) < fabs(f_x)) {
* (*thing).x_acc = 0;
* }
* else {
* (*thing).x_acc += f_x;
* }
* if (fabs((*thing).y_acc) < fabs(f_y)) {
* (*thing).y_acc = 0;
*
* }
* else {
* (*thing).y_acc += f_y;
* }
*/
/*if (fabs((*thing).x_acc ) < fabs(f_x)) {*/
/*(*thing).x_acc = 0;*/
/*}*/
/*else {*/
/*(*thing).x_acc += f_x;*/
/*}*/
/*if (fabs((*thing).y_acc) < fabs(f_y)) {*/
/*(*thing).y_acc = 0;*/
/*}*/
/*else {*/
/*(*thing).y_acc += f_y;*/
/*}*/
}
}
void advance_thing(physics_thing * thing) {
thing->x_acc = 0;
thing->y_acc = 0;
(*thing).x_acc = 0;
(*thing).y_acc = 0;
uint32_t time_delta = SDL_GetTicks() - thing->last_advance_time ;
static uint32_t last_advance_time;
thing->last_advance_time = SDL_GetTicks(); // in milliseconds
uint32_t time_delta = SDL_GetTicks() - last_advance_time ;
last_advance_time = SDL_GetTicks(); // in milliseconds
for (int i = 0; i < thing->num_motors; i++) {
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);
}
// motor
float motor_x = (float)(*thing).motor_x / (float)(*thing).obj_mass ;
float motor_y = (float)(*thing).motor_y / (float)(*thing).obj_mass ;
//float motor_x = (float)(*thing).motor_x / (float)(*thing).obj_mass ;
//float motor_y = (float)(*thing).motor_y / (float)(*thing).obj_mass ;
//printf("MOTOR: %f, %f\n", motor_x, motor_y);
//accel_thing(thing, motor_x, motor_y);
accel_thing(thing, motor_x, motor_y);
advance_glob(thing);
// accelerate based on accel
(*thing).x_vel += (*thing).x_acc * (float)time_delta;
(*thing).y_vel += (*thing).y_acc * (float)time_delta;
printf("time: %f", (float)time_delta);
(*thing).x_vel = (*thing).x_acc * (float)time_delta;
(*thing).y_vel = (*thing).y_acc * (float)time_delta;
(*thing).x_pos += (int)((*thing).x_vel * 1/2 * (float)time_delta);
(*thing).y_pos += (int)((*thing).y_vel * 1/2 * (float)time_delta);
printf("player position: %d, %d \n", (*thing).x_pos, (*thing).y_pos );
printf("player acc: %f, %f \n", (*thing).x_acc, (*thing).y_acc);
printf("player position: %d, %d ", (*thing).x_pos, (*thing).y_pos );
printf(" player acc: %f, %f \n", (*thing).x_acc, (*thing).y_acc);
if (fabs((*thing).x_vel) < 0.00001) {
(*thing).x_vel = 0;
@ -179,107 +288,96 @@ void advance_thing(physics_thing * thing) { @@ -179,107 +288,96 @@ void advance_thing(physics_thing * thing) {
if (fabs((*thing).y_vel) < 0.00001) {
(*thing).y_vel = 0;
}
// apply global forces
}
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");
for (int j = 0; j < world[i].wall->numNodes; j++) {
advance_thing(&(world[i].wall->nodes[j].physics));
}
}
}
}
// grow array of world things if needed
void add_to_world(world_thing thing) {
world[things_in_world] = 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;
logwrite(INFO, "Added object to world\n");
//printf("Added to world: %d\n", thing.kind);
}
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);
player = get_player(100,400);
world_thing player_world;
player_world.kind = PLAYER_W;
player_world.player = &player;
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;
printf("WALLNODES");
for (int i = 0; i < 4; i++) {
printf(": %d", wall_world.wall->nodes[i].physics.x_pos);
}
printf("\n\n\n\n");
add_to_world(wall_world);
}
float get_abs(float x,float y) {
return (sqrt(x*x + y*y));
}
void walk(physics_thing * thing, float max_walking_speed, int x, int y) {
if (get_abs((*thing).x_vel, (*thing).y_vel) < max_walking_speed/1000 ) {
// accel_thing(thing, max_walking_speed * x, max_walking_speed * y );
(*thing).x_acc += max_walking_speed * 0.001 * x ;
(*thing).y_acc += max_walking_speed * 0.001 * y ;
}
}
void walk_player(int x, int y) {
// walk(&player.physics, player.max_walking_speed, x, y);
//set_motor_ms(&player.physics, player.max_walking_speed * 0.01 * x, player.max_walking_speed * 0.01 * y);
add_motor_ms(&player.physics, 100 * y , 100 * x);
// player.physics.x_acc = player.max_walking_speed * 0.00001 * x ;
// player.physics.y_acc = player.max_walking_speed * 0.00001 * y ;
add_motor_newtons(glob_player->physics, M_PLAYER_WALK, 100 * x , 100 * y);
}
void process_keydown(SDL_Keysym key) {
/*
*switch (key.sym) {
* case SDLK_w:
* walk_player(0, 1);
* break;
* case SDLK_a:
* walk_player(-1, 0);
* break;
* case SDLK_s:
* walk_player(0, -1);
* break;
* case SDLK_d:
* walk_player(1, 0);
* break;
*}
*/
}
void process_keyup(SDL_Keysym key) {
/*
*switch (key.sym) {
* case SDLK_w:
* walk_player(0, -1);
* break;
* case SDLK_a:
* walk_player(1, 0);
* break;
* case SDLK_s:
* walk_player(0, 1);
* break;
* case SDLK_d:
* walk_player(-1, 0);
* break;
*}
*/
}
void step(int interval) {
const uint8_t * keyboard;
// player.physics.x_acc = 0;
// player.physics.y_acc = 0;
printf("THINGS IN WORLD: %d\n", things_in_world);
keyboard = SDL_GetKeyboardState(NULL);
set_motor_ms(&player.physics, 0 ,0);
//set_motor_ms(&player.physics, 0 ,0);
if (keyboard[SDL_SCANCODE_W]) {
walk_player(0, -1);
} if (keyboard[SDL_SCANCODE_A]) {
@ -290,7 +388,7 @@ void step(int interval) { @@ -290,7 +388,7 @@ void step(int interval) {
walk_player(1, 0);
}
advance_thing(&(player.physics));
advance_things();
logwrite(DEBUG, "Update Physics \n");
}

49
game.h

@ -12,8 +12,6 @@ @@ -12,8 +12,6 @@
#include "garbo.h"
#include "draw.h"
// unused since I'm implementing 2D physics
typedef union {
struct {
float x;
@ -24,6 +22,19 @@ typedef union { @@ -24,6 +22,19 @@ typedef union {
float vect[3];
} vector;
enum motors {
M_GRAVITY = 0,
M_PLAYER_WALK = 1
};
// Exert a force on an object
typedef struct {
double x; // positive is right
double y; // positive is down
double torque; // positive is anticlockwise
double max_velocity; // max motor output velocity
} Motor;
typedef struct {
int x_pos;
int y_pos;
@ -43,34 +54,53 @@ typedef struct { @@ -43,34 +54,53 @@ typedef struct {
float glob_friction;
bool glob_gravity; // t/f
float motor_x;
float motor_y;
uint32_t last_advance_time;
int num_motors;
int max_motors;
Motor *motors;
} physics_thing;
typedef struct {
bool has_physics;
physics_thing physics;
physics_thing *physics;
int max_walking_speed;
} player_st;
typedef struct {
bool has_physics;
physics_thing physics;
//void setup(struct stat_wall_st *self);
} wall_node;
typedef struct {
int numNodes;
wall_node *nodes;
} Wall;
enum world_thing_kind {
PLAYER_W
PLAYER_W = 0,
STATIC_WALL_W = 1
};
typedef struct {
enum world_thing_kind kind;
int nid;
bool collisions;
bool physics;
union {
player_st * player;
player_st *player;
Wall *wall;
};
} world_thing;
/* array of all the things in the world and their kinds */
world_thing world[100];
world_thing *world;
int things_in_world;
int world_size;
void startgame(SDL_Renderer * ren) ;
@ -81,4 +111,5 @@ void step(int interval); @@ -81,4 +111,5 @@ void step(int interval);
player_st player;
void add_motor(physics_thing *thing, double x, double y);
#endif

4
logger.c

@ -3,8 +3,8 @@ @@ -3,8 +3,8 @@
// Defaults
loggerlevel LOGLEVEL = DEBUG;
loggerlevel STDOUTLEVEL = INFO;
loggerlevel LOGLEVEL = WARN;
loggerlevel STDOUTLEVEL = WARN;
void set_loglevel(loggerlevel echo, loggerlevel write) {
LOGLEVEL = write;

45
main.c

@ -27,13 +27,6 @@ struct SDL_Window* make_window(void) { @@ -27,13 +27,6 @@ struct SDL_Window* make_window(void) {
}
void redraw(struct SDL_Renderer * ren) {
// check time
// redraw if 1/60th of second passed
redraw_buffer(ren);
SDL_RenderPresent(ren);
SDL_RenderClear(ren);
}
void draw_pictures(struct SDL_Renderer * ren) {
logwrite(INFO, "Draw pictures\n");
@ -55,8 +48,16 @@ void draw_pictures(struct SDL_Renderer * ren) { @@ -55,8 +48,16 @@ void draw_pictures(struct SDL_Renderer * ren) {
}
int main () {
void redraw(struct SDL_Renderer * ren) {
// check time
// redraw if 1/60th of second passed
SDL_RenderClear(ren);
redraw_buffer(ren);
SDL_RenderPresent(ren);
}
int main () {
LOGLEVEL = DEBUG;
STDOUTLEVEL = DEBUG;
@ -76,46 +77,24 @@ int main () { @@ -76,46 +77,24 @@ int main () {
int close = 0;
draw_pictures(ren);
bool splashscreen = true;
bool once = true;
startgame(ren);
while (!close) {
/* Update Physics */
step(100);
/* Redraw Screen */
redraw(ren);
/* Process events */
SDL_Event event;
SDL_PollEvent(&event);
switch (event.type) {
case SDL_QUIT:
close = 1;
break;
case SDL_KEYDOWN:
if (splashscreen) {
splashscreen = false;
logwrite(DEBUG, "Starting Game");
startgame(ren);
}
SDL_Keysym key;
key = event.key.keysym;
process_keydown(key);
// send key to game engine
break;
case SDL_KEYUP:
process_keyup(key);
default:
if (splashscreen) {
draw_pictures(ren);
}
break;
}
}
empty_cleanup_queue();
printf("Cleanup queue length: %d\n", cleanup_queue_length);
logwrite(DEBUG, "Emptied cleanup queue\n");

Loading…
Cancel
Save