From 6fe5ca88c99a093d0dd765bef8814733e7b15a6b Mon Sep 17 00:00:00 2001 From: alistair Date: Tue, 4 Aug 2020 03:57:34 +1000 Subject: [PATCH] perf and better viewport --- Makefile | 2 + src/draw.c | 172 +++++++++++++++++++++++++++++++++++++++++++++------- src/game.c | 9 +++ src/main.c | 6 +- src/types.h | 1 + 5 files changed, 165 insertions(+), 25 deletions(-) diff --git a/Makefile b/Makefile index 69165c7..bf332d9 100644 --- a/Makefile +++ b/Makefile @@ -6,6 +6,8 @@ ifndef target target=linux endif +debug = true + ifeq ($(target),windows) CC=x86_64-w64-mingw32-gcc SDL_INCLUDE = -Dmain=SDL_main -Lsdllib -lSDL2main -lSDL2main -lSDL2 -lmingw32 -lSDL2main -lSDL2 -mwindows -Wl,-static -lpthread -lm diff --git a/src/draw.c b/src/draw.c index 018a887..544ed55 100644 --- a/src/draw.c +++ b/src/draw.c @@ -1,4 +1,6 @@ #include "draw.h" +#include +#include Vect viewport_pos; int width, height; @@ -8,6 +10,8 @@ int MAX_ONSCREEN_OBJECTS = 99; int num_onscreen = 0; +double time_delta = 0; + void render_texture_at(struct SDL_Renderer * ren, struct SDL_Texture * texture,int x, int y) { /* draw a texture at x.y */ @@ -34,6 +38,20 @@ void render_texture_at(struct SDL_Renderer * ren, struct SDL_Texture * texture,i /*return (png_image);*/ /*}*/ + +double sigmoid(double x) { + return exp(x) / (exp(x) + 1); +} + +struct timespec get_now_d() { + struct timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + if (now.tv_nsec >= 1000000000) { + now.tv_nsec -= 1000000000; + } + return now; +} + Vect in_view(Vect V) { Vect ret; ret.x = V.x -viewport_pos.x; @@ -58,13 +76,9 @@ void draw_player(SDL_Renderer * ren, int x, int y, bool red) { player_rect.w = 20; player_rect.h = 20; - if (red) { - SDL_SetRenderDrawColor(ren, 255, 0, 0, 255); - } else { - struct colour c = get_scene_at(viewport_pos, level).colours.bg; + struct colour c = get_scene_at(viewport_pos, level).colours.bg; - SDL_SetRenderDrawColor(ren, c.r, c.g, c.b, 255); - } + SDL_SetRenderDrawColor(ren, c.r, c.g, c.b, 255); SDL_RenderDrawRect(ren, &player_rect); SDL_RenderFillRect(ren, &player_rect); @@ -73,8 +87,8 @@ void draw_player(SDL_Renderer * ren, int x, int y, bool red) { if (!player.physics->strings[i].attached) { continue; } - Vect B; - B = in_view(player.physics->position); + Vect B = {x, y}; + B = in_view(B); Vect E; E = in_view(player.physics->strings[i].end_point); SDL_RenderDrawLine(ren, B.x, B.y, E.x, E.y); @@ -252,24 +266,119 @@ int distance_colour(int x, int y, int x2, int y2, int blackpoint) { return frac; } -void update_viewport(double x, double y) { +void new_update_viewport(Body const * const pl) { + int const xmargin = 100; // pixels + int const ymargin = 100; // pixels + int const xmovmagin = width / 4; + int const ymovmagin = height / 3; + double const xrange = width - (2 * xmargin); + double const yrange = height - (2 * ymargin); + double const x_max = 2; + double const y_max = 3; + static Vect target = {}; + static double dirchange = 0; + + printf("%f %f\n", pl->vel.x, pl->vel.y); + static Vect lmove = {}; + + Vect iv = in_view(pl->position); + printf("player pos: %f %f\n", pl->position.x, pl->position.y); + + Vect left_pos = {width / 4, height / 2}; + left_pos = vect_add(pl->position, vect_scalar(left_pos, -1)); + + Vect right_pos = {3 * (width / 4), height / 2}; + right_pos = vect_add(pl->position, vect_scalar(right_pos, -1)); + + bool recover = false; + + Vect screen_dist = vect_add(in_view(pl->position), vect_scalar(lmove, -1)); + + if (iv.x > width + || + (iv.x < 0 + || iv.y > height + || iv.y < 0)) + recover = true; + + if (recover //|| vect_mag((Vect){pl->vel.x, 0}) > 0.4 + || vect_mag(screen_dist) > width / 3) { + if (pl->vel.x > 0) { + target = left_pos; + } else { + target = right_pos; + } + lmove = target; + } + if (recover) + viewport_pos = target; + + // emergency + + /*if (!(iv.x > width / 3 && iv.x < (2 * (width / 3)))) {*/ + /*if (!(iv.y > height / 3 && iv.y < (2 * (height / 3)))) {*/ + + /*if ( true ||*/ + /*( in_view(pl->position).x > xmargin + xrange */ + /*|| in_view(pl->position).x < xmargin)*/ + /*) */ + + /*{*/ + + + /*double m = (width / 2) / (2.0 * x_max);*/ + /*double x = m * v;*/ + /*target.x = pl->position.x - x;*/ + + + /*}*/ + + //target.y = pl->position.y - height/2; // + y; + printf("viewport pos: %f %f\n", iv.x, iv.y); + + /*}*/ + /*}*/ + + double v = pl->vel.x; + if (v > x_max) + v = x_max; + if (v < -x_max) + v = -x_max; + if (v < 0) + v = -v; + + // move towards target a set proportion + Vect p = vect_add(target, vect_scalar(viewport_pos, -1)); + printf("drawtime: %f", time_delta); + + double proportion = sigmoid(v) * (sigmoid(time_delta) / 300); + printf("prop: %f", proportion); + + proportion > 0.4 ? proportion = 0.4 : 0; + proportion < 0 ? proportion = 0.000001 : 0; + p = vect_scalar(p, proportion); + viewport_pos = vect_add(viewport_pos, p); + +} + +void update_viewport(Body *pl) { float xmargin = 0.5; float ymargin = 0.2; - if (player.physics->position.x - viewport_pos.x > (1-xmargin) * width) { - viewport_pos.x = - ((1-xmargin) * width - player.physics->position.x); + if (pl->position.x - viewport_pos.x > (1-xmargin) * width) { + viewport_pos.x = - ((1-xmargin) * width - pl->position.x); } - if (player.physics->position.x - viewport_pos.x < xmargin * width) { - viewport_pos.x = -(xmargin * width - player.physics->position.x); + if (pl->position.x - viewport_pos.x < xmargin * width) { + viewport_pos.x = -(xmargin * width - pl->position.x); } - if (player.physics->position.y - viewport_pos.y > (1-ymargin) * height) { - viewport_pos.y = -((1-ymargin) * height - player.physics->position.y); + if (pl->position.y - viewport_pos.y > (1-ymargin) * height) { + viewport_pos.y = -((1-ymargin) * height - pl->position.y); } - if (player.physics->position.y - viewport_pos.y < ymargin * height) { - viewport_pos.y = -(ymargin * height - player.physics->position.y); + if (pl->position.y - viewport_pos.y < ymargin * height) { + viewport_pos.y = -(ymargin * height - pl->position.y); } } @@ -393,9 +502,25 @@ void redraw_buffer(SDL_Renderer * ren) { /*}*/ int col = 0; + Body lplayer; + + if (SDL_LockMutex(player.physics->lock) == 0){ + lplayer = *player.physics; + SDL_UnlockMutex(player.physics->lock); + } else { + return; + } + + new_update_viewport(&lplayer); + static struct timespec last = {}; + static struct timespec now; + now = get_now_d(); + time_delta = now.tv_nsec - last.tv_nsec; + time_delta *= 0.000001; // convert to ms from ns + + last = now; //SDL_GetMouseState(&newmousex, &newmousey); - update_viewport(player.physics->position.x, player.physics->position.y); struct environment scene = get_scene_at(viewport_pos, level); draw_environment(ren, &scene); @@ -405,11 +530,6 @@ void redraw_buffer(SDL_Renderer * ren) { thing = world.get(i); switch (thing.kind) { - case PLAYER: - draw_player(ren, (*thing.player).physics->position.x, (*thing.player).physics->position.y, thing.player->colliding); - draw_collision_poly(ren, thing.player->physics); - draw_forces(ren, thing.player->physics); - continue; case STATIC_WALL_W: draw_wall(ren, thing.wall); draw_collision_poly(ren, thing.wall->physics); @@ -438,6 +558,12 @@ void redraw_buffer(SDL_Renderer * ren) { } } + draw_player(ren, lplayer.position.x, lplayer.position.y, + lplayer.colliding); + draw_collision_poly(ren, &lplayer); + draw_forces(ren, &lplayer); + + /*if (newmousex != mousex || newmousey != mousey) {*/ /*mousey = newmousey;*/ /*mousex = newmousex;*/ /*for (int i = 0; i < 256; i++) {*/ diff --git a/src/game.c b/src/game.c index 1525406..2f1c4de 100644 --- a/src/game.c +++ b/src/game.c @@ -1,4 +1,5 @@ #include "game.h" +#include #define FLOOR_THICKNESS 200 #define MAX_ROPE_GRAB_LEN 80000 @@ -211,6 +212,7 @@ player_st get_player(int x, int y) { // physics settings get_new_physics(&player.physics); player.physics->dynamics = true; + player.physics->lock = SDL_CreateMutex(); player.physics->position.x = x; player.physics->position.y = y; @@ -1251,6 +1253,10 @@ void advance_thing(Body * thing) { double oldy = thing->position.y; thing->next_position.x += (thing->vel.x * 1/2 * (double)time_delta); thing->next_position.y += (thing->vel.y * 1/2 * (double)time_delta); + + if (thing->lock) { + SDL_LockMutex(thing->lock); + } thing->position = thing->next_position; if (!thing->collision_poly[0].y) { @@ -1258,6 +1264,9 @@ void advance_thing(Body * thing) { } thing->updateCollisionPoly(thing); + if (thing->lock) { + SDL_UnlockMutex(thing->lock); + } } diff --git a/src/main.c b/src/main.c index 700895a..42145cf 100644 --- a/src/main.c +++ b/src/main.c @@ -39,8 +39,8 @@ void redraw(struct SDL_Renderer * ren) { int physics_loop(void *ptr) { while (true) { - SDL_Delay(10); step(10); + SDL_Delay(5); } } @@ -72,10 +72,12 @@ int game(void) { SDL_Thread *physics_thread; int ignore; -// physics_thread = SDL_CreateThread(physics_loop, "Physics", (void *)NULL); bool once = true; startgame(ren); + +// physics_thread = SDL_CreateThread(physics_loop, "Physics", (void *)NULL); + while (!close) { SDL_Event event; diff --git a/src/types.h b/src/types.h index e40640b..f494916 100644 --- a/src/types.h +++ b/src/types.h @@ -82,6 +82,7 @@ typedef struct BodyStruct{ // position in viewport (pixels) SDL_Point screen_pos; + SDL_mutex * lock; // SI Unit kinematics /*------------------*/