From f46c66485b758385417431d290e1a2958dececea Mon Sep 17 00:00:00 2001 From: 3gg <3gg@shellblade.net> Date: Sat, 6 Sep 2025 10:50:07 -0700 Subject: Implement camera clipping for ortho maps --- src/gfx2d.c | 51 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/gfx2d.c b/src/gfx2d.c index f609c98..f1f26cb 100644 --- a/src/gfx2d.c +++ b/src/gfx2d.c @@ -20,6 +20,12 @@ /// Time between animation updates. #define ANIMATION_UPDATE_DELTA (1.0 / ANIMATION_FPS) +/// Take the maximum of two values. +#define max(a, b) ((a) > (b) ? (a) : (b)) + +/// Take the minimum of two values. +#define min(a, b) ((a) < (b) ? (a) : (b)) + typedef struct ivec2 { int x, y; } ivec2; @@ -565,7 +571,6 @@ static void draw_rect( // Rect origin can be outside screen bounds, so we must offset accordingly to // draw only the visible portion. -#define max(a, b) (a > b ? a : b) const int px_offset = max(0, -top_left.x); const int py_offset = max(0, -top_left.y); @@ -763,13 +768,11 @@ static void draw_sprites(Gfx2d* gfx) { } } -void gfx2d_set_camera(Gfx2d* gfx, int x, int y) { - assert(gfx); - gfx->camera = (ivec2){x, y}; -} - -void gfx2d_render(Gfx2d* gfx) { +void gfx2d_render(Gfx2d* gfx, int camera_x, int camera_y) { assert(gfx); + // Storing the camera mostly for debugging convenience. It could otherwise be + // passed around. + gfx->camera = (ivec2){camera_x, camera_y}; draw_map(gfx); draw_sprites(gfx); } @@ -789,6 +792,40 @@ void gfx2d_draw_tile(Gfx2d* gfx, int x, int y, Tile tile) { } } +static void clip_camera_ortho(const Gfx2d* gfx, float* x, float* y) { + assert(gfx); + assert(gfx->map); + + if (x != nullptr) { + const int width_pixels = gfx->map->world_width * gfx->map->base_tile_width; + const int x_max = width_pixels - gfx->screen.width; + *x = min((float)x_max, max(0.F, *x)); + } + if (y != nullptr) { + const int height_pixels = + gfx->map->world_height * gfx->map->base_tile_height; + const int y_max = height_pixels - gfx->screen.height; + *y = min((float)y_max, max(0.F, *y)); + } +} + +void gfx2d_clip_camera(const Gfx2d* gfx, float* x, float* y) { + assert(gfx); + assert(gfx->map); + assert(x); + assert(y); + + const Tm_Flags* flags = (const Tm_Flags*)&gfx->map->flags; + switch (flags->orientation) { + case Tm_Orthogonal: + clip_camera_ortho(gfx, x, y); + break; + case Tm_Isometric: + // TODO: Clip camera in isometric maps. + break; + } +} + void gfx2d_get_screen_size(const Gfx2d* gfx, int* width, int* height) { assert(gfx); assert(width); -- cgit v1.2.3