From: Lukas Krickl Date: Tue, 3 Mar 2026 11:46:20 +0000 (+0100) Subject: map: WIP camera viewport rendering X-Git-Url: https://git.krickl.dev/?a=commitdiff_plain;h=1eae3cf812eccfe5c9ad3924579013584db16ecd;p=lrts%2F.git map: WIP camera viewport rendering --- diff --git a/src/r_assets.c b/src/r_assets.c index b68499e..05588a2 100644 --- a/src/r_assets.c +++ b/src/r_assets.c @@ -53,6 +53,12 @@ void r_draw_solid_isometric_tile(i32 x, i32 y, r_color color) { r_color final_color; struct u_vec2 t = u_tile_to_screen(x, y); t = u_screen_to_camera(&t_main_camera, t); + + /* do not draw if tile is not visible at all */ + if (!t_camera_is_visible_world(&t_main_camera, t.x, t.y) + && !t_camera_is_visible_world(&t_main_camera, t.x + R_TILE_W, t.y + R_TILE_H)) { + return; + } /* converted origin point in isometric space */ diff --git a/src/t_camera.c b/src/t_camera.c index bb60a64..896dd79 100644 --- a/src/t_camera.c +++ b/src/t_camera.c @@ -1,4 +1,5 @@ #include "t_camera.h" +#include "u_math.h" struct t_camera t_main_camera; @@ -13,12 +14,21 @@ struct t_camera t_camera_init(i32 viewport_x, i32 viewport_y) { } void t_camera_scroll(struct t_camera *c, i32 by_x, i32 by_y) { + /* TODO: calculate min/max viewport based on map in a better way */ c->x += by_x; c->y += by_y; +} + +lrts_bool t_camera_is_visible_screen(struct t_camera *c, i32 x, i32 y) { + return u_point_in_rect(x, y, c->x, c->y, c->x + c->viewport_x, c->y + c->viewport_y); +} - /* TODO: calculate max viewport based on map */ - U_CLAMP(c->x, -4096, 4096); - U_CLAMP(c->y, -4096, 4096); +lrts_bool t_camera_is_visible_world(struct t_camera *c, i32 x, i32 y) { + struct u_vec2 t; + t.x = c->x; + t.y = c->y; + + return u_point_in_rect(x, y, t.x, t.y, t.x + c->viewport_x, t.y + c->viewport_y); } diff --git a/src/t_camera.h b/src/t_camera.h index 347d349..3a9d57c 100644 --- a/src/t_camera.h +++ b/src/t_camera.h @@ -20,4 +20,10 @@ void t_camera_scroll(struct t_camera *c, i32 by_x, i32 by_y); /* adjusts a screen coodrinate by the camera offset */ struct u_vec2 u_screen_to_camera(struct t_camera *c, struct u_vec2 v); +/* tests if a point is visible in screen sapce */ +lrts_bool t_camera_is_visible_screen(struct t_camera *c, i32 x, i32 y); + +/* tests if a point is visible in world space */ +lrts_bool t_camera_is_visible_world(struct t_camera *c, i32 x, i32 y); + #endif diff --git a/src/t_map.c b/src/t_map.c index 4f3995c..55608a1 100644 --- a/src/t_map.c +++ b/src/t_map.c @@ -26,19 +26,12 @@ void t_map_draw(struct t_map *m) { struct u_vec2 start; struct u_vec2 end; - /* estimate the viewport based on the orthogonal map - * This is not perfect, but it is good enough to avoid drawing a - * full size map. - */ - start.x = t_main_camera.x / R_TILE_W; - start.y = t_main_camera.y / R_TILE_H; - - end.x = ((t_main_camera.x + t_main_camera.viewport_x) / R_TILE_W) * 2; - end.y = ((t_main_camera.y + t_main_camera.viewport_y) / R_TILE_H) * 2; - start.x = 0; start.y = 0; + end.x = t_map.width; + end.y = t_map.height; + for (i = start.x; i < end.x; i++) { for (j = start.y; j < end.y; j++) { r_draw_tile(&m->tiles[j * m->width + i], i, j); diff --git a/src/u_math.c b/src/u_math.c index 52908e5..e4c40a6 100644 --- a/src/u_math.c +++ b/src/u_math.c @@ -19,6 +19,15 @@ struct u_vec2 u_tile_to_screen(i32 x, i32 y) { return r; } +struct u_vec2 u_point_to_screen(i32 x, i32 y) { + struct u_vec2 r; + + r.x = (x) + (y); + r.y = (y) - (x); + + return r; +} + lrts_bool u_point_in_rect(i32 x, i32 y, i32 rx, i32 ry, i32 rw, i32 rh) { return x >= rx && x <= rx + rw && y >= ry && y <= ry + rh; diff --git a/src/u_math.h b/src/u_math.h index c299f55..af63f6c 100644 --- a/src/u_math.h +++ b/src/u_math.h @@ -50,6 +50,9 @@ struct u_vec2 u_vec2_mul(i32 n, struct u_vec2 v); */ struct u_vec2 u_tile_to_screen(i32 x, i32 y); +/* convers a point to screen space */ +struct u_vec2 u_point_to_screen(i32 x, i32 y); + /* tests if a point is contained inside a rectangle */ lrts_bool u_point_in_rect(i32 x, i32 y, i32 rx, i32 ry, i32 rw, i32 rh);