From 5eb065b1cfeeeeb5be4a386943a8d898af0f6328 Mon Sep 17 00:00:00 2001 From: Ulysse Cura Date: Wed, 19 Aug 2026 14:12:46 +0200 Subject: [PATCH] Added camera and started to add map drawing. --- src/Makefile | 1 + src/camera.c | 29 ++++++++++ src/display.c | 46 +++++++++++----- src/headers/camera.h | 16 ++++++ src/headers/display.h | 7 +-- src/headers/game.h | 9 ++- src/headers/map.h | 22 ++++++++ src/map.c | 124 +++++++++++++++++++++++++++++++++++++++++- 8 files changed, 232 insertions(+), 22 deletions(-) create mode 100644 src/camera.c create mode 100644 src/headers/camera.h diff --git a/src/Makefile b/src/Makefile index cea3e6f..d362217 100644 --- a/src/Makefile +++ b/src/Makefile @@ -6,6 +6,7 @@ CORE_SOURCES := \ asset_manager.c \ texture.c \ map.c \ + camera.c \ event_bus.c \ ecs.c \ display.c \ diff --git a/src/camera.c b/src/camera.c new file mode 100644 index 0000000..29d274b --- /dev/null +++ b/src/camera.c @@ -0,0 +1,29 @@ +#include "camera.h" + +#include "game.h" +#include "display.h" + +void camera_init(void) +{ + game.camera.view_rect = (frect_t) { + .x = 0.0f, + .y = 0.0f, + .w = DISPLAY_WIDTH / 2, + .h = DISPLAY_HEIGHT / 2 + }; + + game.camera.tracking_pos = NULL; + game.camera.tracking_center_offset = (fvector2d_t) { + .x = 0.0f, + .y = 0.0f + }; +} + +void camera_update(void) +{ + if(game.camera.tracking_pos) + { + game.camera.view_rect.x = game.camera.tracking_pos->x + game.camera.tracking_center_offset.x - game.camera.view_rect.w / 2; + game.camera.view_rect.y = game.camera.tracking_pos->y + game.camera.tracking_center_offset.y - game.camera.view_rect.h / 2; + } +} diff --git a/src/display.c b/src/display.c index ff76464..4c8d866 100644 --- a/src/display.c +++ b/src/display.c @@ -24,7 +24,7 @@ inline int display_init(void) return EXIT_FAILURE; } - window = SDL_CreateWindow("2D_Engine", DISPLAY_WIDTH * RENDER_SCALE, DISPLAY_HEIGHT * RENDER_SCALE, 0); + window = SDL_CreateWindow("2D_Engine", DISPLAY_WIDTH, DISPLAY_HEIGHT, 0); if(!window) { error_printf("Failed to create window : %s", SDL_GetError()); @@ -51,12 +51,6 @@ inline int display_init(void) return EXIT_FAILURE; } - if(!SDL_SetRenderScale(renderer, RENDER_SCALE, RENDER_SCALE)) - { - error_printf("Failed to set renderer scale presentation : %s", SDL_GetError()); - return EXIT_FAILURE; - } - if(!SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND)) { error_printf("Failed to set renderer draw blend mode : %s", SDL_GetError()); @@ -148,15 +142,30 @@ inline int display_update(void) return EXIT_SUCCESS; } -int display_draw_texture(texture_t *texture, const rect_t *src_rect, const frect_t *dst_frect, bool flip) +int display_draw_texture(texture_t *texture, const frect_t *src_frect, const frect_t *dst_frect, bool flip) { - frect_t src_frect; - rect_to_frect(src_rect, &src_frect); - - if(!SDL_RenderTextureRotated(renderer, texture, &src_frect, dst_frect, 0, NULL, flip)) + if(dst_frect) { - error_printf("Failed to copy texture to renderer : %s", SDL_GetError()); - return EXIT_FAILURE; + frect_t display_frect = { + .x = (dst_frect->x - game.camera.view_rect.x) * (DISPLAY_WIDTH / game.camera.view_rect.w), + .y = (dst_frect->y - game.camera.view_rect.y) * (DISPLAY_HEIGHT / game.camera.view_rect.h), + .w = dst_frect->w * (DISPLAY_WIDTH / game.camera.view_rect.w), + .h = dst_frect->h * (DISPLAY_HEIGHT / game.camera.view_rect.h) + }; + + if(!SDL_RenderTextureRotated(renderer, texture, src_frect, &display_frect, 0, NULL, flip)) + { + error_printf("Failed to copy texture to renderer : %s", SDL_GetError()); + return EXIT_FAILURE; + } + } + else + { + if(!SDL_RenderTextureRotated(renderer, texture, src_frect, NULL, 0, NULL, flip)) + { + error_printf("Failed to copy texture to renderer : %s", SDL_GetError()); + return EXIT_FAILURE; + } } return EXIT_SUCCESS; @@ -170,7 +179,14 @@ int display_draw_frect(const frect_t *frect, unsigned int r, unsigned int g, uns return EXIT_FAILURE; } - if(!SDL_RenderRect(renderer, frect)) + frect_t display_frect = { + .x = (frect->x - game.camera.view_rect.x) * (DISPLAY_WIDTH / game.camera.view_rect.w), + .y = (frect->y - game.camera.view_rect.y) * (DISPLAY_HEIGHT / game.camera.view_rect.h), + .w = frect->w * (DISPLAY_WIDTH / game.camera.view_rect.w), + .h = frect->h * (DISPLAY_HEIGHT / game.camera.view_rect.h) + }; + + if(!SDL_RenderRect(renderer, &display_frect)) { error_printf("Failed to draw rectangle to renderer : %s", SDL_GetError()); return EXIT_FAILURE; diff --git a/src/headers/camera.h b/src/headers/camera.h new file mode 100644 index 0000000..06c64a4 --- /dev/null +++ b/src/headers/camera.h @@ -0,0 +1,16 @@ +#ifndef CAMERA_H +#define CAMERA_H + +#include "vector2d.h" + +typedef struct camera_t { + frect_t view_rect; + fvector2d_t *tracking_pos; + fvector2d_t tracking_center_offset; +} camera_t; + +void camera_init(void); + +void camera_update(void); + +#endif // CAMERA_H \ No newline at end of file diff --git a/src/headers/display.h b/src/headers/display.h index e1f195f..f950005 100644 --- a/src/headers/display.h +++ b/src/headers/display.h @@ -12,9 +12,8 @@ #define C_BLUE 0, 0, 255 #define C_WHITE 255, 255, 255 -#define DISPLAY_WIDTH 396 -#define DISPLAY_HEIGHT 224 -#define RENDER_SCALE 2 +#define DISPLAY_WIDTH 720 +#define DISPLAY_HEIGHT 480 //#define DRIVERS NULL #define DRIVERS "vulkan,gpu,software" @@ -28,7 +27,7 @@ void display_exit(void); int display_clear(void); int display_update(void); -int display_draw_texture(texture_t *texture, const rect_t *src_rect, const frect_t *dst_frect, bool flip); +int display_draw_texture(texture_t *texture, const frect_t *src_frect, const frect_t *dst_frect, bool flip); int display_draw_frect(const frect_t *frect, unsigned int r, unsigned int g, unsigned int b, unsigned int a); #endif // DISPLAY_H \ No newline at end of file diff --git a/src/headers/game.h b/src/headers/game.h index 2436bc0..f581f67 100644 --- a/src/headers/game.h +++ b/src/headers/game.h @@ -3,8 +3,10 @@ #include #include "asset_manager.h" -#include "ecs.h" +#include "camera.h" #include "event_bus.h" +#include "ecs.h" +#include "map.h" #include "inputs.h" /** @@ -18,10 +20,13 @@ * @param delta_time_ms Frame time */ typedef struct game_t { + camera_t camera; asset_manager_t asset_manager; - entity_manager_t entity_manager; event_bus_t event_bus; + entity_manager_t entity_manager; + tilemap_display_t tilemap_display; inputs_t inputs; + map_t *map; float delta_time_ms; bool is_running; diff --git a/src/headers/map.h b/src/headers/map.h index 61f0334..0039d4d 100644 --- a/src/headers/map.h +++ b/src/headers/map.h @@ -2,6 +2,8 @@ #define MAP_H #include +#include "vector2d.h" +#include "texture.h" typedef struct map_entity_component_def_t { uint32_t type; @@ -33,4 +35,24 @@ int map_load_entities(map_t *map); int map_remove_entities(map_t *map); +#define TILE_SIZE 16 + +typedef struct tilemap_display_t { + frect_t view_rect; + texture_t *tileset; + texture_t *background; + texture_t *foreground; + texture_t *buffer; +} tilemap_display_t; + +int tilemap_display_init(void); + +int tilemap_display_update(void); + +int tilemap_display_background(void); + +int tilemap_display_foreground(void); + +void tilemap_display_exit(void); + #endif // MAP_H \ No newline at end of file diff --git a/src/map.c b/src/map.c index 2e163ea..ad69e41 100644 --- a/src/map.c +++ b/src/map.c @@ -5,6 +5,7 @@ #include "ecs.h" #include "components.h" #include "vector2d.h" +#include "display.h" #include "memory_alloc.h" #include "errors.h" @@ -219,6 +220,7 @@ int map_load_entities(map_t *map) map_entity_component_def_t *component_def = &entity_def->components_defs[j]; component_t *component = entity_new_component(entity, component_def->type); + if(!entity) return_failure_int; switch(component_def->type) { @@ -267,7 +269,7 @@ int map_load_entities(map_t *map) system_data->loop = data->loop; system_data->reverse = data->reverse; - animation_system_apply_changes(component); + if(animation_system_apply_changes(component)) return_failure_int; break; } @@ -394,3 +396,123 @@ int map_remove_entities(map_t *map) return EXIT_SUCCESS; } + +int tilemap_display_init(void) +{ + game.tilemap_display.view_rect = (frect_t) { + .x = 0.0f, + .y = 0.0f, + .w = 0.0f, + .h = 0.0f + }; + + game.tilemap_display.background = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_TARGET, DISPLAY_WIDTH, DISPLAY_HEIGHT); + if(!game.tilemap_display.background) + { + error_printf("Failed to create texture : %s", SDL_GetError()); + return EXIT_FAILURE; + } + + game.tilemap_display.foreground = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_TARGET, DISPLAY_WIDTH, DISPLAY_HEIGHT); + if(!game.tilemap_display.foreground) + { + error_printf("Failed to create texture : %s", SDL_GetError()); + return EXIT_FAILURE; + } + + game.tilemap_display.buffer = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB565, SDL_TEXTUREACCESS_TARGET, DISPLAY_WIDTH, DISPLAY_HEIGHT); + if(!game.tilemap_display.buffer) + { + error_printf("Failed to create texture : %s", SDL_GetError()); + return EXIT_FAILURE; + } + + return EXIT_SUCCESS; +} + +int tilemap_display_update(void) +{ + frect_t buffer_view_rect = { + .x = game.tilemap_display.view_rect.x - game.camera.view_rect.x, + .y = game.tilemap_display.view_rect.y - game.camera.view_rect.y, + .w = game.tilemap_display.view_rect.w - game.camera.view_rect.w, + .h = game.tilemap_display.view_rect.h - game.camera.view_rect.h + }; + + if(game.tilemap_display.view_rect.x != game.camera.view_rect.x + || game.tilemap_display.view_rect.y != game.camera.view_rect.y + || game.tilemap_display.view_rect.w != game.camera.view_rect.w + || game.tilemap_display.view_rect.h != game.camera.view_rect.h) + { + // Update background + if(!SDL_SetRenderTarget(renderer, game.tilemap_display.buffer)) + { + error_printf("Failed to set texture as render target : %s", SDL_GetError()); + return EXIT_FAILURE; + } + + if(!SDL_SetRenderDrawColor(renderer, C_WHITE, 255)) + { + error_printf("Failed to change renderer draw color : %s", SDL_GetError()); + return EXIT_FAILURE; + } + + if(!SDL_RenderClear(renderer)) + { + error_printf("Failed to clear renderer : %s", SDL_GetError()); + return EXIT_FAILURE; + } + + if(!SDL_RenderTexture(renderer, game.tilemap_display.background, &game.tilemap_display.view_rect, &buffer_view_rect)) + { + error_printf("Failed to render texture : %s", SDL_GetError()); + return EXIT_FAILURE; + } + + if(display_draw_frect(&game.tilemap_display.view_rect, C_BLACK, 255)) return_failure_int; + + // Rewrite buffer to background texture + if(!SDL_SetRenderTarget(renderer, game.tilemap_display.background)) + { + error_printf("Failed to reset render target : %s", SDL_GetError()); + return EXIT_FAILURE; + } + + if(!SDL_RenderTexture(renderer, game.tilemap_display.buffer, NULL, NULL)) + { + error_printf("Failed to render texture : %s", SDL_GetError()); + return EXIT_FAILURE; + } + + if(!SDL_SetRenderTarget(renderer, NULL)) + { + error_printf("Failed to reset render target : %s", SDL_GetError()); + return EXIT_FAILURE; + } + } + + game.tilemap_display.view_rect = game.camera.view_rect; + + return EXIT_SUCCESS; +} + +int tilemap_display_background(void) +{ + if(display_draw_texture(game.tilemap_display.background, NULL, NULL, false)) return_failure_int; + + return EXIT_SUCCESS; +} + +int tilemap_display_foreground(void) +{ +// if(display_draw_texture(game.tilemap_display.foreground, NULL, NULL, false)) return_failure_int; + + return EXIT_SUCCESS; +} + +void tilemap_display_exit(void) +{ + SDL_DestroyTexture(game.tilemap_display.background); + SDL_DestroyTexture(game.tilemap_display.foreground); + SDL_DestroyTexture(game.tilemap_display.buffer); +}