From 2981e05419b8af34c7279613d9de0312d22aca76 Mon Sep 17 00:00:00 2001 From: Sara Date: Sun, 24 Sep 2023 00:31:11 +0200 Subject: [PATCH] implemented mvp for camera and tilemap rendering --- src/camera.c | 37 +++++++++++++++++++++++++++++-------- src/camera.h | 4 ++-- src/program.c | 4 +++- src/tilemap.c | 10 ++++++---- 4 files changed, 40 insertions(+), 15 deletions(-) diff --git a/src/camera.c b/src/camera.c index 3c3089b..5e0dfe3 100644 --- a/src/camera.c +++ b/src/camera.c @@ -5,16 +5,37 @@ Camera g_camera; void camera_init() { g_camera.centre = ZeroVector; - g_camera.width = 1; + g_camera.width = 10; } -SDL_FRect render_calculate_unit_rect() { - // If the camera's width is 1, this rectangle should fill the width of the screen. - // If the camera's width is 2, this rectangle should fill half the width of the screen. +static inline +float _camera_height(Camera* self) { + return self->width * ((float)g_render_resolution.y / (float)g_render_resolution.x); +} + +static inline +float _one() { + return g_render_resolution.x / g_camera.width; +} + +SDL_FRect camera_world_to_screen_space(Camera* self, SDL_FRect* world_space) { + float unit = _one(); return (SDL_FRect) { - .x = -g_camera.centre.x * g_render_resolution.x, - .y = -g_camera.centre.y * g_render_resolution.x, - .w = g_render_resolution.x / g_camera.width, - .h = g_render_resolution.x / g_camera.width + .x = (world_space->x - g_camera.centre.x + g_camera.width/2.0) * unit, + .y = (world_space->y - g_camera.centre.y + _camera_height(&g_camera)/2.0) * unit, + .w = world_space->w * unit, + .h = world_space->h * unit + }; +} + +SDL_FRect camera_calculate_unit_rect() { + // If the camera's width is 1, this rectangle should fill the width of the screen. + // If the camera's width is 2, this rectangle should fill half the width of the screen. + float unit = _one(); + return (SDL_FRect) { + .x = (-g_camera.centre.x + g_camera.width/2) * unit, + .y = (-g_camera.centre.y + _camera_height(&g_camera)/2) * unit, + .w = unit, + .h = unit }; } diff --git a/src/camera.h b/src/camera.h index 5bd9f4e..b03e035 100644 --- a/src/camera.h +++ b/src/camera.h @@ -18,7 +18,7 @@ extern void camera_init(); // generate a screen-space rectangle that is exactly 1x1 in world units. // With it's centre on the world origin. extern SDL_FRect camera_calculate_world_unit_rect(Camera* self); -extern SDL_FRect camera_to_world_space(Camera* self, SDL_FRect* camera_space); -extern SDL_FRect camera_world_to_camera_space(Camera* self, SDL_FRect* world_space); +extern SDL_FRect camera_screen_to_world_space(Camera* self, SDL_FRect* camera_space); +extern SDL_FRect camera_world_to_screen_space(Camera* self, SDL_FRect* world_space); #endif // !_fencer_camera_h diff --git a/src/program.c b/src/program.c index 4cf1be6..96640fb 100644 --- a/src/program.c +++ b/src/program.c @@ -1,7 +1,8 @@ #include "program.h" +#include "tilemap.h" +#include "camera.h" #include #include -#include "tilemap.h" SDL_Window* g_window; double g_delta_time; @@ -22,6 +23,7 @@ int program_run(const struct ProgramSettings* settings) { SDL_WINDOW_FULLSCREEN | SDL_WINDOW_RESIZABLE); render_init(g_window, settings); + camera_init(); struct Tilemap map = tilemap_load("resources/box.tilemap.xml"); struct Tileset set = { diff --git a/src/tilemap.c b/src/tilemap.c index 496af9b..8c6deec 100644 --- a/src/tilemap.c +++ b/src/tilemap.c @@ -171,14 +171,16 @@ void tilemap_render(struct Tilemap* self) { size_t num_tiles = self->dimensions.x * self->dimensions.y; SDL_Rect source_rect = {0, 0, self->tileset.tile_size.x, self->tileset.tile_size.y}; - SDL_FRect dest_rect = { .w = 1, .h = 1 }; + SDL_FRect world_dest_rect = { .w = 1, .h = 1 }; for(int i = 0; i < num_tiles; ++i) { source_rect = tileset_index_to_rect(&self->tileset, self->tiles[i]); - dest_rect.x = (i % self->dimensions.x) * dest_rect.w; - dest_rect.y = (float)floor((float)i / self->dimensions.y) * dest_rect.h; + world_dest_rect.x = (i % self->dimensions.x) * world_dest_rect.w; + world_dest_rect.y = (float)floor((float)i / self->dimensions.y) * world_dest_rect.h; - SDL_RenderCopyF(g_renderer, self->tileset.texture, &source_rect, &dest_rect); + SDL_FRect camera_dest_rect = camera_world_to_screen_space(&g_camera, &world_dest_rect); + + SDL_RenderCopyF(g_renderer, self->tileset.texture, &source_rect, &camera_dest_rect); } } \ No newline at end of file