From 52477daac0695a2a0b4957fc31e5419facd61e3a Mon Sep 17 00:00:00 2001 From: KikooDX Date: Wed, 23 Sep 2020 12:19:40 +0200 Subject: [PATCH] Camera clamping in stage limits and related --- include/camera.h | 10 +++++++++- include/conf.h | 4 +++- include/gen_levels.h | 1 + include/level.h | 4 ++-- include/player.h | 7 ++++--- include/vec.h | 3 +++ src/camera.c | 34 ++++++++++++++++++++++++++-------- src/collide.c | 2 +- src/level.c | 9 +++++---- src/main.c | 7 ++++--- src/player.c | 4 ++-- src/vec.c | 8 ++++++++ 12 files changed, 68 insertions(+), 25 deletions(-) diff --git a/include/camera.h b/include/camera.h index ea8c9e8..67f2175 100644 --- a/include/camera.h +++ b/include/camera.h @@ -2,18 +2,26 @@ #define _DEF_CAMERA #include "vec.h" -#include "debug.h" typedef struct Camera { Vec pos; Vec offset; /* adjusted pixel offset based on pos */ Vec *target; /* the target position to lerp on */ + Vec min; /* Values set by level_set used to limit camera position */ + Vec max; /* See min comment */ float speed; /* camera lerp speed with 0 < speed <= 1 */ } Camera; +#include "player.h" +#include "level.h" + +/* update camera position */ void camera_step(Camera *camera); +/* set the min and max position of the camera and center it on player */ +void camera_init(Camera *camera, Player *player, const Level *level); + /* draw a dot corresponding to camera position */ void camera_draw_debug(Camera *camera); diff --git a/include/conf.h b/include/conf.h index c4a082d..c7bfd23 100644 --- a/include/conf.h +++ b/include/conf.h @@ -1,7 +1,7 @@ #define VEC_PRECISION 1024 #define UPS 256 #define PXS (VEC_PRECISION / UPS) -#define TILE_SIZE 8 +#define TILE_SIZE 8 * VEC_PRECISION #define VEC_DCENTER (Vec){DWIDTH / 2, DHEIGHT / 2} #ifdef FX9860G @@ -12,3 +12,5 @@ #define SCALE 2 #define FPS 32 #endif /* FXCG50 */ + +#define VEC_SCALED_DCENTER (Vec){DWIDTH / (2 * SCALE), DHEIGHT / (2 * SCALE)} diff --git a/include/gen_levels.h b/include/gen_levels.h index 6d98eb0..6dda8f4 100644 --- a/include/gen_levels.h +++ b/include/gen_levels.h @@ -2,6 +2,7 @@ #define _DEF_GEN_LEVELS #include "level.h" +#include "camera.h" void level_set(const Level **level, uint level_id); diff --git a/include/level.h b/include/level.h index 1478ebc..888dfff 100644 --- a/include/level.h +++ b/include/level.h @@ -3,8 +3,6 @@ #include -#include "camera.h" - typedef struct Level { int width; /* in tiles */ @@ -13,6 +11,8 @@ typedef struct Level int layers_count; } Level; +#include "camera.h" + void level_step(const Level *level); void level_draw(const Level *level, Camera *camera); void layer_draw(const Level *level, Camera *camera, uint layer_id); diff --git a/include/player.h b/include/player.h index 673646e..c9512c9 100644 --- a/include/player.h +++ b/include/player.h @@ -2,9 +2,6 @@ #define _DEF_PLAYER #include "vec.h" -#include "level.h" -#include "camera.h" -#include "input.h" typedef struct Player { @@ -14,6 +11,10 @@ typedef struct Player Vec origin; /* the origin of the player (offset) */ } Player; +#include "level.h" +#include "camera.h" +#include "input.h" + void player_step(Player *player, Input *input); void player_draw(Player *player, Camera *camera); void player_draw_debug(Player *player, uint step, const Level *level, uint layer_id); diff --git a/include/vec.h b/include/vec.h index 61e85eb..8fe076e 100644 --- a/include/vec.h +++ b/include/vec.h @@ -28,6 +28,9 @@ void vec_divf(Vec *vector, float scale); * Require a scale ranging from 0 to 1 (0 is instant, 1 is completly still). */ void vec_lerp(Vec *from, Vec to, float scale); +/* limit a vector between two positions */ +void vec_clamp(Vec *to_limit, Vec min, Vec max); + /* Draw a rectangle using two Vec as coordinates */ void vec_drect(Vec top_left, Vec bottom_right, int color); diff --git a/src/camera.c b/src/camera.c index 0d47587..9c0dd7a 100644 --- a/src/camera.c +++ b/src/camera.c @@ -3,32 +3,50 @@ #include "camera.h" #include "conf.h" #include "vec.h" -#include "debug.h" +#include "player.h" +#include "level.h" void camera_step(Camera *camera) { /* lerp towards target */ vec_lerp(&camera->pos, *camera->target, camera->speed); + /* put the camera in the right place */ + vec_clamp(&camera->pos, camera->min, camera->max); /* calculate pixel offset */ Vec * const offset = &camera->offset; /* DRY */ vec_cpy(offset, camera->pos); vec_div(offset, VEC_PRECISION); - Vec scaled_dcenter = VEC_DCENTER; - vec_div(&scaled_dcenter, SCALE); - vec_sub(offset, scaled_dcenter); + vec_sub(offset, VEC_SCALED_DCENTER); +} + +void camera_init(Camera *camera, Player *player, const Level *level) +{ + /* calculate min and max */ + vec_cpy(&camera->min, VEC_SCALED_DCENTER); + vec_mul(&camera->min, VEC_PRECISION); + vec_cpy(&camera->max, (Vec){0, 0}); + vec_sub(&camera->max, VEC_SCALED_DCENTER); + vec_mul(&camera->max, VEC_PRECISION); + vec_add(&camera->max, (Vec){TILE_SIZE * level->width, TILE_SIZE * level->height}); + vec_cpy(&camera->pos, player->pos); + vec_clamp(&camera->pos, camera->min, camera->max); } void camera_draw_debug(Camera *camera) { - Vec draw_pos; + dprint(0, 0, C_BLACK, "-x: %d, -y: %d", camera->min.x, camera->min.y); + dprint(0, 10, C_BLACK, "+x: %d, +y: %d", camera->max.x, camera->max.y); + dprint(0, 20, C_BLACK, "cx: %d, cy: %d", camera->pos.x, camera->pos.y); + dprint(0, 30, C_BLACK, "px: %d, py: %d", camera->offset.x, camera->offset.y); + /*Vec draw_pos; vec_cpy(&draw_pos, camera->pos); vec_mul(&draw_pos, SCALE); vec_div(&draw_pos, VEC_PRECISION); #ifdef FX9860G const int color = C_BLACK; - #endif /* FX9860G */ + #endif /* FX9860G *//* #ifdef FXCG50 const int color = C_RED; - #endif /* FXCG50 */ - dpixel(draw_pos.x, draw_pos.y, color); + #endif /* FXCG50 *//* + dpixel(draw_pos.x, draw_pos.y, color);*/ } diff --git a/src/collide.c b/src/collide.c index 2f60c78..fcc45a9 100644 --- a/src/collide.c +++ b/src/collide.c @@ -8,7 +8,7 @@ uint8_t collide_point(Vec point, const Level *level, uint layer_id) { Vec cursor; /* the final position to test */ vec_cpy(&cursor, point); - vec_div(&cursor, VEC_PRECISION * TILE_SIZE); /* get the expected tile ID */ + vec_div(&cursor, TILE_SIZE); /* get the expected tile ID */ if (point.x < 0 || point.y < 0 || cursor.x >= level->width || cursor.y >= level->height) { diff --git a/src/level.c b/src/level.c index bf72492..e14014a 100644 --- a/src/level.c +++ b/src/level.c @@ -23,8 +23,8 @@ void layer_draw(const Level *level, Camera *camera, uint layer_id) vec_cpy(&display_br, display_tl); vec_sub(&display_tl, VEC_PRECISE_HALF_DISP); vec_add(&display_br, VEC_PRECISE_HALF_DISP); - vec_div(&display_tl, VEC_PRECISION * TILE_SIZE); - vec_div(&display_br, VEC_PRECISION * TILE_SIZE); + vec_div(&display_tl, TILE_SIZE); + vec_div(&display_br, TILE_SIZE); int start_x = (display_tl.x > 0) ? display_tl.x : 0; int start_y = (display_tl.y > 0) ? display_tl.y : 0; int end_x = (display_br.x < level->width) ? display_br.x + 1 : level->width; @@ -44,12 +44,13 @@ void layer_draw(const Level *level, Camera *camera, uint layer_id) { Vec tl = {x, y}; Vec br; - vec_mul(&tl, VEC_PRECISION * TILE_SIZE); + vec_mul(&tl, TILE_SIZE); vec_div(&tl, VEC_PRECISION); vec_sub(&tl, camera->offset); vec_mul(&tl, SCALE); vec_cpy(&br, tl); - vec_add(&br, (Vec){TILE_SIZE * SCALE - 1, TILE_SIZE * SCALE - 1}); + vec_add(&br, (Vec){TILE_SIZE / VEC_PRECISION * SCALE - 1, + TILE_SIZE / VEC_PRECISION * SCALE - 1}); vec_drect(tl, br, color); } } diff --git a/src/main.c b/src/main.c index a2ebdd7..80c5aab 100644 --- a/src/main.c +++ b/src/main.c @@ -31,7 +31,7 @@ int play_level(uint level_id) { /* create player */ Player player = { - .pos = {16 * VEC_PRECISION, 16 * VEC_PRECISION}, + .pos = {64 * VEC_PRECISION, 64 * VEC_PRECISION}, .hbox = {7 * VEC_PRECISION, 7 * VEC_PRECISION}, .vbox = {7, 7}, .origin = {4 * VEC_PRECISION, 4 * VEC_PRECISION} @@ -47,6 +47,7 @@ int play_level(uint level_id) .target = &player.pos, .speed = 0.02 }; + camera_init(&camera, &player, level); /* create input manager */ Input input; @@ -98,9 +99,9 @@ void draw_event(Player *player, const Level *level, Camera *camera, Input *input level_draw(level, camera); player_draw(player, camera); #ifdef DEBUG - //camera_draw_debug(camera); + camera_draw_debug(camera); //input_draw_debug(input); - player_draw_debug(player, step, level, 0); + //player_draw_debug(player, step, level, 0); #endif dupdate(); } diff --git a/src/player.c b/src/player.c index dde51bb..6845a02 100644 --- a/src/player.c +++ b/src/player.c @@ -39,7 +39,7 @@ void player_draw_debug(Player *player, uint step, const Level *level, uint layer dprint(0, 10, C_BLACK, "y: %d", player->pos.y); dprint(0, 20, C_BLACK, "vp: %d", VEC_PRECISION); dprint(0, 30, C_BLACK, "st: %u", step); - dprint(0, 40, C_BLACK, "cx: %d", player->pos.x / (VEC_PRECISION * TILE_SIZE)); - dprint(0, 50, C_BLACK, "cy: %d", player->pos.y / (VEC_PRECISION * TILE_SIZE)); + dprint(0, 40, C_BLACK, "cx: %d", player->pos.x / TILE_SIZE); + dprint(0, 50, C_BLACK, "cy: %d", player->pos.y / TILE_SIZE); dprint(0, 60, C_BLACK, "cl: %d", collide_point(player->pos, level, layer_id)); } diff --git a/src/vec.c b/src/vec.c index 9529532..2c1db28 100644 --- a/src/vec.c +++ b/src/vec.c @@ -57,6 +57,14 @@ void vec_lerp(Vec *from, Vec to, float scale) vec_add(from, temp); } +void vec_clamp(Vec *to_limit, Vec min, Vec max) +{ + if (to_limit->x < min.x) to_limit->x = min.x; + if (to_limit->y < min.y) to_limit->y = min.y; + if (to_limit->x > max.x) to_limit->x = max.x; + if (to_limit->y > max.y) to_limit->y = max.y; +} + void vec_drect(Vec top_left, Vec bottom_right, int color) { drect(top_left.x, top_left.y, bottom_right.x, bottom_right.y, color);