implemented mvp for camera and tilemap rendering

This commit is contained in:
Sara 2023-09-24 00:31:11 +02:00
parent 972a4d86fa
commit 2981e05419
4 changed files with 40 additions and 15 deletions

View file

@ -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
};
}

View file

@ -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

View file

@ -1,7 +1,8 @@
#include "program.h"
#include "tilemap.h"
#include "camera.h"
#include <SDL2/SDL_video.h>
#include <SDL2/SDL_image.h>
#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 = {

View file

@ -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);
}
}