1
1
Fork 0
Browse Source

fix buggy motor timeout

thread-physics
alistair 4 years ago
parent
commit
782b9c79a7
  1. 256
      colours.c
  2. 39
      colours.h
  3. 3
      draw.c
  4. 2
      draw.h
  5. 96
      game.c
  6. 4
      game.h

256
colours.c

@ -1,256 +0,0 @@ @@ -1,256 +0,0 @@
#include "colours.h"
struct colour get_random_color(unsigned int seed) {
int red = rand_r(&seed) % 255;
int blue = rand_r(&seed) % 255;
int green = rand_r(&seed) % 255;
struct colour col;
col.r = red;
col.g = green;
col.b = blue;
return col;
}
double m_min(double arr[], int len) {
double largest = arr[0];
for (int i = 0; i < len; i ++) {
if (arr[i] < largest) {
largest = arr[i];
}
}
return largest;
}
double m_max(double arr[], int len) {
double largest = arr[0];
for (int i = 0; i < len; i ++) {
if (arr[i] > largest) {
largest = arr[i];
}
}
return largest;
}
bool m_equal(double a, double b) {
return (a - b) * (a - b) < 0.00001;
}
// https://en.wikipedia.org/wiki/HSL_and_HSV#From_RGB
// h = [0,360], s = [0,1], v = [0,1]
// if s == 0, then h = -1 (undefined)
struct colour get_hs_l_v(struct colour c, enum colour_space sp) {
struct colour ret;
memset(&ret, 0, sizeof(struct colour));
double r = (double)c.r / 255;
double g = (double)c.g / 255;
double b = (double)c.b / 255;
double arr[] = {r, g, b};
double max = m_max(arr, 3);
double min = m_min(arr, 3);
ret.v = max;
double chroma = max - min;
double lum = (max + min) / 2;
ret.l = lum;
if (m_equal(chroma, 0)) {
ret.h = 0;
} else if (m_equal(ret.v,r)) {
ret.h = (g - b) / chroma;
} else if (m_equal(max,g)) {
ret.h = 2 + (b - r) / chroma;
} else if (m_equal(max,b)) {
ret.h = 4 + (r - g) / chroma;
} else {
printf("NOPE BAD ERROR\n");
}
ret.h *= 60;
ret.h = fmod(ret.h, 360);
if (ret.h < 0) {
ret.h += 360;
}
if (sp == CS_HSV) {
if (m_equal(max,0)) {
ret.s = 0;
} else {
ret.s = chroma / max;
}
} else {
double arr[] = {ret.l, 1 - ret.l};
if (m_equal(0, lum) || m_equal(1, lum)) {
ret.s = 0;
} else {
ret.s = (ret.v - ret.l) / m_min(arr, 2);
}
}
return ret;
}
struct colour get_hsl(struct colour c) {
return get_hs_l_v(c, CS_HSL);
}
struct colour get_hsv(struct colour c) {
return get_hs_l_v(c, CS_HSV);
}
double magic_hsv_function(int n, struct colour c) {
double res = 0;
double k = fmod(n + (c.h / 60), 6);
double arr[] = {k, 4 - k, 1};
double k_b = m_min(arr, 3);
double k_c = 0 > k_b ? 0 : k_b;
res = c.v - c.v * c.s * k_c;
return res;
}
struct colour get_rgb_from_hsv(struct colour c) {
double r = magic_hsv_function(5, c);
double g = magic_hsv_function(3, c);
double b = magic_hsv_function(1, c);
struct colour res;
res.r = round(r * 255);
res.g = round(g * 255);
res.b = round(b * 255);
return res;
}
double magic_hsl_function(int n, struct colour c) {
double arr[] = {c.l, 1-c.l};
double a = c.s * ( c.l < (1-c.l) ? c.l : 1 - c.l );
double k = fmod(n + c.h / 30, 12);
double b[] = {k - 3, 9 -k, 1};
double d[] = {-1, m_min(b, 3)};
return c.l - a * (d[0] > d[1] ? d[0] : d[1]);
}
struct colour get_rgb_from_hsl(struct colour c) {
double r = magic_hsl_function(0, c);
double g = magic_hsl_function(8, c);
double b = magic_hsl_function(4, c);
struct colour res;
res.r = round(r * 255);
res.g = round(g * 255);
res.b = round(b * 255);
return res;
}
struct colour get_rgb(struct colour c) {
if (c.sp == CS_HSL) {
return get_rgb_from_hsl(c);
}
if (c.sp == CS_HSV) {
return get_rgb_from_hsv(c);
}
struct colour d;
memset(&d, 0, sizeof(struct colour));
return d;
}
int compare_perceived_lum(const void* c1, const void* c2) {
struct colour rgb_c1 = *(struct colour*)c1;
struct colour rgb_c2 = *(struct colour*)c2;
double lum1 = 0.299*rgb_c1.r + 0.587*rgb_c1.g + 0.114*rgb_c1.b;
double lum2 = 0.299*rgb_c2.r + 0.587*rgb_c2.g + 0.114*rgb_c2.b;
return lum1 - lum2;
}
struct colour *get_adjacent(struct colour base, int deg, int num) {
struct colour col = get_hsl(base);
num += 1;
struct colour* colours = alloca(sizeof(struct colour) * num);
for (int i = 0; i < num; i++) {
int m = (i % 2 == 0) ? -i : i;
colours[i] = col;
colours[i].h += m * deg;
colours[i].h += fmod(colours[i].h, 360);
}
struct colour *ret_colours = calloc(num, sizeof(struct colour) * num);
for (int i = 0; i < num; i++) {
ret_colours[i] = get_rgb(colours[i]);
}
// sort from dark to bright
qsort(ret_colours, num, sizeof(struct colour), compare_perceived_lum);
return ret_colours;
}
void print_colour(struct colour c) {
char *colour = calloc(20, sizeof(char));
sprintf(colour, "#%02x%02x%02x", c.r, c.g, c.b);
printf("\x1b[38;2;%d;%d;%dm%s\x1b[0m\n", c.r, c.g, c.b, colour);
free(colour);
}
void test(int seed) {
struct colour c = get_random_color(seed);
//print_colour(c);
struct colour hsl = get_hsl(c);
struct colour hsv = get_hsv(c);
/*printf("RGB: %d %d %d\n",c.r,c.g,c.b);*/
/*printf("HSL: %f %f %f\n",hsl.h, hsl.s, hsl.l);*/
/*printf("HSV: %f %f %f\n",hsv.h, hsv.s, hsv.v);*/
struct colour *adj = get_adjacent(c, 5, 4);
for (int i = 0; i < 5; i++) {
print_colour(adj[i]);
}
free(adj);
printf("\n");
}
void test_print_wheel() {
struct colour c;
c.s = 0.999;
c.v = 0.99;
c.l = 0.5;
c.sp = CS_HSV;
for(int i = 0; i < 360; i+=5) {
c.h = (double)i;
struct colour rgb = get_rgb(c);
/*printf("HSL: %f %f %f\n",c.h, c.s, c.l);*/
/*printf("RGB: %d %d %d\n",rgb.r,rgb.g,rgb.b);*/
print_colour(rgb);
}
}
int main() {
/*test(100);*/
/*test(400);*/
/*test(310);*/
/*test(2900);*/
/*test(2100);*/
/*test(260);*/
/*test(240);*/
struct colour c = get_random_color(128);
struct colour *adj = get_adjacent(c, 2, 20);
for (int i = 0; i < 20; i++) {
print_colour(adj[i]);
}
free(adj);
}

39
colours.h

@ -1,39 +0,0 @@ @@ -1,39 +0,0 @@
#include <stdbool.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdio.h>
#ifndef H_COLOURS
#define H_COLOURS
enum colour_space {
CS_RGB = 0, // default to RGB
CS_HSV = 1,
CS_HSL = 2,
};
struct colour {
double h;
double s;
double v;
double l;
int r;
int g;
int b;
enum colour_space sp;
};
struct colour get_random_color(unsigned int seed);
// doesn't support hsl-hsv or converse, conversion
struct colour get_hsl(struct colour c);
struct colour get_hsv(struct colour c);
struct colour get_rgb(struct colour c);
struct colour *get_adjacent(struct colour base, int deg, int num);
void print_colour(struct colour c);
#endif

3
draw.c

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

2
draw.h

@ -6,7 +6,7 @@ @@ -6,7 +6,7 @@
#define _DEFDRAW
#define SHOWCOLLISION 1
#define SHOWFORCES 0
#define SHOWFORCES 1
#include "garbo.h"
#include "game.h"

96
game.c

@ -1,6 +1,7 @@ @@ -1,6 +1,7 @@
#include "game.h"
#include "environment.h"
#define FLOOR_THICKNESS 200
#define BREAKPOINT *(int *)0 = 1;
GlobWorld world;
@ -18,6 +19,8 @@ void process_keyup(SDL_Keysym key); @@ -18,6 +19,8 @@ void process_keyup(SDL_Keysym key);
void add_to_world(world_thing thing);
void step(int interval);
void set_motor_timeout(Body *thing, int motorID, uint32_t timeout);
void set_motor_status(Body *thing, int motorID, bool run);
player_st player;
@ -230,8 +233,10 @@ player_st get_player(int x, int y) { @@ -230,8 +233,10 @@ player_st get_player(int x, int y) {
rect[3].x = -10; rect[3].y = 10;
// gravity
//set_motor_newtons(player.physics, M_GRAVITY, 0.0,
// player.physics->obj_mass * 4);
set_motor_newtons(player.physics, M_GRAVITY, 0.0,
player.physics->obj_mass * 5);
set_motor_status(player.physics, M_GRAVITY, true);
set_motor_timeout(player.physics, M_GRAVITY, 99999999);
// walking motor
add_motor(player.physics, 0.0, player.physics->obj_mass * 9.81);
@ -655,15 +660,22 @@ void set_motor_max_velocity(Body *thing, int motorID, double max) { @@ -655,15 +660,22 @@ 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].stop = false;
// this don't work yo
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_status(Body *thing, int motorID, bool run) {
if (motorID == M_GRAVITY && run == false) {
*(int *)0 = 1;
}
thing->motors[motorID].stop = !run;
}
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;
}
@ -682,8 +694,8 @@ void add_motor(Body *thing, double x, double y) { @@ -682,8 +694,8 @@ void add_motor(Body *thing, double x, double y) {
motor.y = y;
motor.stop = true;
motor.timeout.tv_sec = 3600000000000 * 0.000000001;
motor.timeout.tv_nsec = 3600000000000;
motor.timeout.tv_sec = 0;
motor.timeout.tv_nsec = 0;
motor.max_velocity = 999899;
@ -753,6 +765,7 @@ void pull_rope(double newtons) { @@ -753,6 +765,7 @@ void pull_rope(double newtons) {
}
// set force
set_motor_newtons(player.physics, M_WINCH, 0, newtons);
set_motor_status(player.physics, M_WINCH, true);
// point it in the right direction
winch_motor_update(player.physics->motors + M_WINCH);
player.physics->motors[M_WINCH].stop = false;
@ -780,17 +793,20 @@ void add_rope(int mouse_x) { @@ -780,17 +793,20 @@ void add_rope(int mouse_x) {
end.x = mouse_x + viewport_pos.x;
}
Floor *ceiling = world.uniques_index[CEILING]->floor;
struct room *room = world.uniques_index[ROOM_W]->room;
struct physics_collection floor = room->floor;
struct physics_collection ceil = room->floor;
int y = 0;
for (int i = 0; i < ceiling->numPolys; i++) {
if (ceiling->polys[i].right.x > end.x) {
double width = ceiling->polys[i].right.x - ceiling->polys[i].left.x;
double m = (double)(ceiling->polys[i].right.y - ceiling->polys[i].left.y)
/ width;
for (int i = 0; i < floor.numItems; i++) {
if (floor.items[i]->collision_poly[0].x > end.x) {
// double width = ceiling->polys[i].right.x - ceiling->polys[i].left.x;
//double m = (double)(ceiling->polys[i].right.y - ceiling->polys[i].left.y)
// / width;
double delt = ceiling->polys[i].right.x - end.x;
end.y = ceiling->polys[i].right.y - (int)(m * delt);
//double delt = ceiling->polys[i].right.x - end.x;
//interpolate_h(left, right)
// end.y = ceiling->polys[i].right.y - (int)(m * delt);
break;
}
@ -893,6 +909,33 @@ int process_collisions(Body *thing, Vect *trans) { @@ -893,6 +909,33 @@ int process_collisions(Body *thing, Vect *trans) {
}
}
struct timespec get_now() {
struct timespec now;
clock_gettime(CLOCK_MONOTONIC_RAW, &now);
if (now.tv_nsec >= 1000000000) {
now.tv_nsec -= 1000000000;
}
return now;
}
bool get_motor_active(Body *thing, int i) {
if (thing->motors[i].stop) {
return false;
}
struct timespec now = get_now();
if (thing->motors[i].timeout.tv_nsec
|| thing->motors[i].timeout.tv_sec) {
// 0 is a sentinel for infinity
if (thing->motors[i].timeout.tv_sec > now.tv_sec
&& thing->motors[i].timeout.tv_nsec > now.tv_nsec) {
return false;
}
}
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
@ -914,16 +957,14 @@ void advance_thing(Body * thing) { @@ -914,16 +957,14 @@ 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 ;*/
struct timespec now;
// get time delta
struct timespec now = get_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;
time_delta *= 0.5; // run at half speed for accuracy
if (now.tv_nsec < thing->last_advance_time.tv_nsec) {
time_delta = now.tv_nsec - (thing->last_advance_time.tv_nsec - 1000000000);
@ -932,7 +973,7 @@ void advance_thing(Body * thing) { @@ -932,7 +973,7 @@ void advance_thing(Body * thing) {
thing->last_advance_time = now;
// cap the time delta: simulatino will slow down
printf("delta: %f\n", time_delta);
if (time_delta > 19) {
printf("ERROR too slow: %f\n", time_delta);
@ -1056,15 +1097,15 @@ void advance_thing(Body * thing) { @@ -1056,15 +1097,15 @@ void advance_thing(Body * thing) {
// motors
for (int i = 0; i < thing->num_motors; i++) {
if (thing->motors[i].timeout.tv_nsec < now.tv_nsec
&& thing->motors[i].timeout.tv_sec < now.tv_sec
|| thing->motors[i].stop) {
if (!get_motor_active(thing, i)) {
continue;
}
// dynamic motor curve
if (thing->motors[i].update_motor) {
thing->motors[i].update_motor(thing->motors + i);
}
Vect F;
Vect V;
F.x = thing->motors[i].x;
@ -1162,11 +1203,9 @@ void advance_things(void) { @@ -1162,11 +1203,9 @@ void advance_things(void) {
for (int i = 0; i < world.size; i++) {
switch (world.things[i].kind) {
case PLAYER_W :
logwrite(INFO, "ADVANCE PLAYER\n");
advance_thing((world.things[i].player->physics));
break;
case STATIC_WALL_W:
logwrite(INFO, "ADVANCE WALL\n");
advance_thing(world.things[i].wall->physics);
break;
case FLOOR:
@ -1286,7 +1325,7 @@ void startgame(SDL_Renderer * ren) { @@ -1286,7 +1325,7 @@ void startgame(SDL_Renderer * ren) {
SDL_GetRendererOutputSize(ren, &width, &height);
// player = get_player(200,1300);
player = get_player(0,100);
player = get_player(50,-100);
world_thing player_world;
@ -1310,6 +1349,7 @@ double get_abs(double x,double y) { @@ -1310,6 +1349,7 @@ double get_abs(double x,double y) {
void walk_player(int x, int y) {
set_motor_status(player.physics, M_PLAYER_WALK, true);
set_motor_newtons(player.physics, M_PLAYER_WALK, 0, 0);
// turned off special case for going down for TESTing
if (false && y == -1) {
@ -1344,6 +1384,7 @@ void handle_input_event(SDL_Event event) { @@ -1344,6 +1384,7 @@ void handle_input_event(SDL_Event event) {
|| sc == input_map.player_left
|| sc == input_map.player_right) {
set_motor_newtons(player.physics, M_PLAYER_WALK, 0, 0);
set_motor_status(player.physics, M_PLAYER_WALK, false);
} if (sc == input_map.player_pull_rope) {
stop_pull_rope();
}
@ -1355,6 +1396,7 @@ void handle_input_event(SDL_Event event) { @@ -1355,6 +1396,7 @@ void handle_input_event(SDL_Event event) {
pull_rope(900);
break;
case SDL_MOUSEBUTTONUP:
if (event.button.button == SDL_BUTTON_LEFT)
delete_rope();
if (event.button.button == SDL_BUTTON_RIGHT)
@ -1370,7 +1412,5 @@ void step(int interval) { @@ -1370,7 +1412,5 @@ void step(int interval) {
next_level();
}
printf("%f %f", player.physics->position.x, 0.9 * world.uniques_index[ROOM_W]->room->floor.items[world.uniques_index[ROOM_W]->room->floor.numItems - 1]->position.x);
advance_things();
}

4
game.h

@ -169,6 +169,7 @@ typedef struct Projectile { @@ -169,6 +169,7 @@ typedef struct Projectile {
struct room {
struct physics_collection ceil;
struct physics_collection floor;
struct environment *env; // TODO
};
typedef struct {
@ -196,12 +197,15 @@ struct world { @@ -196,12 +197,15 @@ struct world {
typedef struct world GlobWorld;
extern GlobWorld world;
extern int level;
void handle_input_event(SDL_Event event);
// add a motor to the world
void add_motor(Body *thing, double x, double y);
bool get_motor_active(Body *thing, int i);
/* array of all the things in the world and their kinds */
extern void startgame(SDL_Renderer * ren) ;
extern void process_keydown(SDL_Keysym key);

Loading…
Cancel
Save