Added support for desktop full screen with pillarboxing and letterboxing

and started adding some comments to the code
This commit is contained in:
abdelrahman committed 2022-10-02 02:16:28 +01:00
1 parent ffaa6e5ae7
commit e110b1f2fd
10 files changed
+351 -77

No files matched your search

+24
View File
@@ -22,14 +22,38 @@ typedef enum {
} AssetType; } AssetType;
typedef struct asset_manager AssetManager; typedef struct asset_manager AssetManager;
/**
* Attempts to allocate an AssetManager object on the heap.
*
* Returns the pointer to the object when it succeeds, or NULL if it fails.
*/
AssetManager *create_asset_manager(); AssetManager *create_asset_manager();
/**
* Attempts to load an asset to the manager from a file path.
*
* Returns the AssetID on success or an INVALID_ID in the case of failure.
*/
AssetID load_asset_to_manager(AssetManager *am, const char *path, AssetID load_asset_to_manager(AssetManager *am, const char *path,
AssetType type, Renderer *renderer); AssetType type, Renderer *renderer);
/**
* Removes an asset from the manager using its ID.
*
* Does nothing if the ID is not valid.
*/
void remove_asset_from_manager(AssetManager *am, AssetID *id_ptr); void remove_asset_from_manager(AssetManager *am, AssetID *id_ptr);
SDL_Texture *get_texture(AssetManager *am, AssetID id); SDL_Texture *get_texture(AssetManager *am, AssetID id);
TTF_Font *get_font(AssetManager *am, AssetID id); TTF_Font *get_font(AssetManager *am, AssetID id);
Mix_Chunk *get_audio_chunk(AssetManager *am, AssetID id); Mix_Chunk *get_audio_chunk(AssetManager *am, AssetID id);
Mix_Music *get_music(AssetManager *am, AssetID id); Mix_Music *get_music(AssetManager *am, AssetID id);
/**
* Frees the memory allocated to the AssetManager object and performs the
* necessary cleanup to free all memory that were allocated to the loaded
* assets.
*/
void destroy_asset_manager(AssetManager **am); void destroy_asset_manager(AssetManager **am);
#ifdef __cplusplus #ifdef __cplusplus
+55 -4
View File
@@ -4,6 +4,7 @@
#include "AssetManager.h" #include "AssetManager.h"
#include "ObjectStore.h" #include "ObjectStore.h"
#include "SDL_pixels.h" #include "SDL_pixels.h"
#include "SDL_rect.h"
#include "Window.h" #include "Window.h"
#include "reusable_ids.h" #include "reusable_ids.h"
#include <stdbool.h> #include <stdbool.h>
@@ -13,20 +14,68 @@
extern "C" { extern "C" {
#endif // !__cplusplus #endif // !__cplusplus
// GENERAL ENGINE API
/**
* Initialises the game engine. Returns true on success and false on failure.
*
* The audio_tracks parameter determines how many audio tracks to be allocated.
* Pass 0 if you want to allocate the default number.
*/
bool init_engine(const char *game_name, WindowSize window_size, bool init_engine(const char *game_name, WindowSize window_size,
SDL_Color window_background_color, bool full_screen, SDL_Color window_background_color, bool full_screen,
uint8_t audio_tracks); uint8_t audio_tracks);
bool game_running(); bool game_running();
WindowSize get_window_defined_size(); void close_engine();
WindowSize get_window_drawable_size(); // END GENERAL ENGINE API
// ASSET MANAGEMENT API
ObjectID add_object(void *object, EventHandlerPtr eh, UpdateFuncPtr uf, ObjectID add_object(void *object, EventHandlerPtr eh, UpdateFuncPtr uf,
RenderFuncPtr rf); RenderFuncPtr rf);
void remove_object(ObjectID *id); void remove_object(ObjectID *id);
// END ASSET MANAGEMENT API
// ASSET MANAGEMENT API
AssetID load_asset(const char *path, AssetType type); AssetID load_asset(const char *path, AssetType type);
void close_asset(AssetID *id);
// END ASSET MANAGEMENT API
// RENDERING API
/**
* Returns the user-defined window size or the screen size when in full screen.
*/
WindowSize get_window_defined_size();
/**
* Returns the actual window size which can be different from the user-defined
* size or the screen size if the window is on a display that supports high DPI.
*/
WindowSize get_window_real_size();
/**
* Returns the valid drawing area which can be a portion of the screen when
* running in full screen mode and the width to height ratio of the user-defined
* window size is different from the width to height ratio of the screen.
*/
WindowDrawingArea get_window_drawing_area();
void fill_rectangle(float x, float y, float w, float h, SDL_Color color);
/**
* Ensures that a rendered rectangle is clipped to the drawing area when it is
* smaller than the actual size of the window.
*/
void clip_render_rect_to_drawing_area(SDL_FRect *rect);
void render_texture_asset(AssetID id, float x, float y, float w, float h); void render_texture_asset(AssetID id, float x, float y, float w, float h);
void render_text_with_font_asset(AssetID id, const char *text, float x, void render_text_with_font_asset(AssetID id, const char *text, float x,
float y); float y);
void set_font_asset_size(AssetID id, uint32_t size); void set_font_asset_size(AssetID id, uint32_t size);
// END RENDERING API
// AUDIO API
int8_t play_audio_asset(AssetID id, int16_t loops, bool fade_in, int8_t play_audio_asset(AssetID id, int16_t loops, bool fade_in,
uint32_t fade_length_in_ms); uint32_t fade_length_in_ms);
void pause_audio_asset_on_track(AssetID id, uint8_t track); void pause_audio_asset_on_track(AssetID id, uint8_t track);
@@ -56,11 +105,13 @@ void stop_playing_music();
void fade_out_playing_music(uint32_t fade_length_in_ms); void fade_out_playing_music(uint32_t fade_length_in_ms);
void set_playing_music_volume(int8_t volume); void set_playing_music_volume(int8_t volume);
bool is_music_playing(); bool is_music_playing();
void close_asset(AssetID *id); // END AUDIO API
// GAME LOOP API
void handle_events(); void handle_events();
void update(); void update();
void render(); void render();
void close_engine(); // END GAME LOOP API
#ifdef __cplusplus #ifdef __cplusplus
} }
+23
View File
@@ -17,13 +17,36 @@ typedef void (*RenderFuncPtr)(void *object);
typedef struct object_store ObjectStore; typedef struct object_store ObjectStore;
/**
* Attempts to allocate an ObjectStore object on the heap.
*
* Returns the pointer to the object when it succeeds, or NULL if it fails.
*/
ObjectStore *create_object_store(); ObjectStore *create_object_store();
/**
* Attempts to add an object to the store.
*
* Returns the ObjectID on success or an INVALID_ID in the case of failure.
*/
ObjectID add_object_to_store(ObjectStore *os, void *object, EventHandlerPtr eh, ObjectID add_object_to_store(ObjectStore *os, void *object, EventHandlerPtr eh,
UpdateFuncPtr uf, RenderFuncPtr rf); UpdateFuncPtr uf, RenderFuncPtr rf);
/**
* Removes an object from the store using its ID.
*
* Does nothing if the ID is not valid.
*/
void remove_object_from_store(ObjectStore *os, ObjectID *id_ptr); void remove_object_from_store(ObjectStore *os, ObjectID *id_ptr);
void handle_all_objects_events(ObjectStore *os, const SDL_Event *event); void handle_all_objects_events(ObjectStore *os, const SDL_Event *event);
void update_all_objects(ObjectStore *os, float delta); void update_all_objects(ObjectStore *os, float delta);
void render_all_objects(ObjectStore *os); void render_all_objects(ObjectStore *os);
/**
* Frees the memory allocated to the ObjectStore object and performs the
* necessary cleanup.
*/
void destroy_object_store(ObjectStore **os); void destroy_object_store(ObjectStore **os);
#ifdef DEBUG_ENGINE #ifdef DEBUG_ENGINE
+28 -3
View File
@@ -14,16 +14,41 @@ extern "C" {
typedef struct renderer Renderer; typedef struct renderer Renderer;
Renderer *create_renderer(); /**
bool init_renderer(Renderer *renderer, SDL_Window *window); * Attempts to allocate a Renderer object on the heap.
void get_drawable_size(Renderer *renderer, int32_t *w, int32_t *h); *
* Returns the pointer to the object when it succeeds, or NULL if it fails.
*/
Renderer *create_renderer(SDL_Window *window);
/**
* Returns the valid drawable area that the renderer can use.
*
* Useful when rendering on screens that support high DPI since the drawable
* area is usually bigger than the user-defined size.
*/
void get_render_output_size(Renderer *renderer, int32_t *w, int32_t *h);
/**
* Attempts to load an SDL_Texture from a file path.
*
* Returns a pointer to the object if it succeeds or NULL when it fails.
*/
SDL_Texture *load_texture(const Renderer *renderer, const char *path); SDL_Texture *load_texture(const Renderer *renderer, const char *path);
void render_clear(const Renderer *renderer, SDL_Color color); void render_clear(const Renderer *renderer, SDL_Color color);
void fill_rect(const Renderer *renderer, SDL_Color color, float x, float y,
float w, float h);
void render_surface(const Renderer *renderer, SDL_Surface *surface, float x, void render_surface(const Renderer *renderer, SDL_Surface *surface, float x,
float y, float w, float h); float y, float w, float h);
void render_texture(const Renderer *renderer, SDL_Texture *texture, float x, void render_texture(const Renderer *renderer, SDL_Texture *texture, float x,
float y, float w, float h); float y, float w, float h);
void swap_buffers(const Renderer *renderer); void swap_buffers(const Renderer *renderer);
/**
* Frees the memory allocated to the Renderer object and performs the
* necessary cleanup.
*/
void destroy_renderer(Renderer **renderer); void destroy_renderer(Renderer **renderer);
#ifdef __cplusplus #ifdef __cplusplus
+16 -1
View File
@@ -16,12 +16,27 @@ typedef struct window_size {
int32_t height; int32_t height;
} WindowSize; } WindowSize;
typedef struct drawing_area {
float x;
float y;
float width;
float height;
} WindowDrawingArea;
typedef struct window { typedef struct window {
// We need to store the defined size because the coordinates of the mouse
// cursor are calculated according to it. In the case of displays that support
// high DPI, this creates a problem, because the mouse coordinates retrieved
// from an SDL_Event won't work with the actual window size. By storing the
// defined size of the window, this allows us to convert the mouse coordinates
// to a ratio of the defined size, then multiply that ratio by the real size.
WindowSize defined_size; WindowSize defined_size;
WindowSize drawable_size; WindowSize real_size;
WindowDrawingArea drawing_area;
Renderer *renderer; Renderer *renderer;
SDL_Window *SDL_base_window; SDL_Window *SDL_base_window;
SDL_Color background_color; SDL_Color background_color;
bool full_screen;
} Window; } Window;
bool init_window(Window *wnd, const char *title, WindowSize size, bool init_window(Window *wnd, const char *title, WindowSize size,
+22 -1
View File
@@ -46,6 +46,10 @@ struct asset_manager {
}; };
size_t hash_path(const char *path) { size_t hash_path(const char *path) {
/**
* Converts a string into a numerical index using a simple hashing algorithm
*/
size_t i = 0; size_t i = 0;
for (size_t j = 0; path[j]; ++j) { for (size_t j = 0; path[j]; ++j) {
@@ -125,6 +129,11 @@ void remove_id_node(IDNodeList *node_list, AssetID id) {
AssetID get_asset_id_from_id_node(AssetManager *am, IDNodeList *node_list, AssetID get_asset_id_from_id_node(AssetManager *am, IDNodeList *node_list,
const char *path) { const char *path) {
/**
* Checks to see if an asset with the same path exists and returns the ID of
* that asset if it exists, or an INVALID_ID otherwise
*/
if (node_list->node_count == 0) { if (node_list->node_count == 0) {
return INVALID_ID; return INVALID_ID;
} }
@@ -184,9 +193,14 @@ AssetID load_asset_to_manager(AssetManager *am, const char *path,
} }
++(am->user_counter[existing_id]); ++(am->user_counter[existing_id]);
return existing_id; return existing_id;
} }
if (am->count + 1 == MAX_ASSET_COUNT && am->deleted_count == 0) {
return INVALID_ID;
}
Asset asset = {}; Asset asset = {};
bool loaded = true; bool loaded = true;
@@ -363,7 +377,14 @@ void destroy_asset_manager(AssetManager **am) {
return; return;
} }
for (size_t i = 0; i < (*am)->count; ++i) { // TODO (Abdelrahman): Figure out if there is a better way to remove all of
// the existing assets without having to loop for the maximum number of
// assets allowed.
for (size_t i = 0; i < MAX_ASSET_COUNT; ++i) {
if (!(*am)->assets[i].path) {
continue;
}
(*am)->user_counter[i] = 0; (*am)->user_counter[i] = 0;
size_t hash_index = hash_path((*am)->assets[i].path); size_t hash_index = hash_path((*am)->assets[i].path);
+82 -39
View File
@@ -18,6 +18,7 @@
#include "constants.h" #include "constants.h"
#include "engine_build_config.h" #include "engine_build_config.h"
#include "reusable_ids.h" #include "reusable_ids.h"
#include <SDL2/SDL_pixels.h>
#include <stdbool.h> #include <stdbool.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
@@ -130,10 +131,32 @@ bool init_engine(const char *game_name, WindowSize window_size,
bool game_running() { return GameEngine.running; } bool game_running() { return GameEngine.running; }
WindowSize get_window_defined_size() { return GameEngine.window.defined_size; } void close_engine() {
destroy_asset_manager(&(GameEngine.asset_manager));
WindowSize get_window_drawable_size() { destroy_object_store(&(GameEngine.object_store));
return GameEngine.window.drawable_size;
destroy_window(&(GameEngine.window));
GameEngine.last_time = 0.0f;
GameEngine.delta = 0.0f;
GameEngine.running = false;
Mix_CloseAudio();
Mix_Quit();
TTF_Quit();
IMG_Quit();
SDL_Quit();
#ifdef DEBUG_ENGINE
printf("Game closed successfully\n");
#endif /* DEBUG_ENGINE */
} }
ObjectID add_object(void *object, EventHandlerPtr event_handler, ObjectID add_object(void *object, EventHandlerPtr event_handler,
@@ -162,6 +185,62 @@ AssetID load_asset(const char *path, AssetType type) {
NULL); NULL);
} }
void close_asset(AssetID *id) {
if (*id < 0) {
return;
}
remove_asset_from_manager(GameEngine.asset_manager, id);
}
WindowSize get_window_defined_size() { return GameEngine.window.defined_size; }
WindowSize get_window_real_size() { return GameEngine.window.real_size; }
WindowDrawingArea get_window_drawing_area() {
return GameEngine.window.drawing_area;
}
void fill_rectangle(float x, float y, float w, float h, SDL_Color color) {
fill_rect(GameEngine.window.renderer, color, x, y, w, h);
}
void clip_render_rect_to_drawing_area(SDL_FRect *rect) {
WindowDrawingArea area = get_window_drawing_area();
// If the rectangle is completely out of bounds, set its width and height to 0
if (rect->x > area.x + area.width || rect->x + rect->w < area.x ||
rect->y > area.y + area.height || rect->y + rect->h < area.y) {
rect->w = 0.0f;
rect->h = 0.0f;
return;
}
float x_diff = 0.0f;
float y_diff = 0.0f;
// If the rectangle is partially out of the horizontal bounds of the drawing
// area, calculate how much of its width will be clipped
if (rect->x < area.x) {
x_diff = area.x - rect->x;
rect->x += x_diff;
} else if (rect->x + rect->w > area.x + area.width) {
x_diff = (rect->x + rect->w) - (area.x + area.width);
}
// If the rectangle is partially out of the vertical bounds of the drawing
// area, calculate how much of its height will be clipped
if (rect->y < area.y) {
y_diff = area.y - rect->y;
rect->y += y_diff;
} else if (rect->y + rect->h > area.y + area.height) {
y_diff = (rect->y + rect->h) - (area.y + area.height);
}
rect->w -= x_diff;
rect->h -= y_diff;
}
void render_texture_asset(AssetID id, float x, float y, float w, float h) { void render_texture_asset(AssetID id, float x, float y, float w, float h) {
if (id < 0) { if (id < 0) {
return; return;
@@ -529,14 +608,6 @@ void set_playing_music_volume(int8_t volume) { Mix_VolumeMusic(volume); }
bool is_music_playing() { return Mix_PlayingMusic(); } bool is_music_playing() { return Mix_PlayingMusic(); }
void close_asset(AssetID *id) {
if (*id < 0) {
return;
}
remove_asset_from_manager(GameEngine.asset_manager, id);
}
void handle_events() { void handle_events() {
if (!(GameEngine.running)) { if (!(GameEngine.running)) {
return; return;
@@ -586,31 +657,3 @@ void render() {
swap_render_buffers(&(GameEngine.window)); swap_render_buffers(&(GameEngine.window));
} }
void close_engine() {
destroy_asset_manager(&(GameEngine.asset_manager));
destroy_object_store(&(GameEngine.object_store));
destroy_window(&(GameEngine.window));
GameEngine.last_time = 0.0f;
GameEngine.delta = 0.0f;
GameEngine.running = false;
Mix_CloseAudio();
Mix_Quit();
TTF_Quit();
IMG_Quit();
SDL_Quit();
#ifdef DEBUG_ENGINE
printf("Game closed successfully\n");
#endif /* DEBUG_ENGINE */
}
+18 -10
View File
@@ -41,9 +41,22 @@ ObjectStore *create_object_store() {
return os; return os;
} }
bool object_exists(ObjectStore *os, void *object) {
// This is a crude implementation for checking that an object has already
// been added.
// TODO (Abdelrahman): Figure out if there is a better way of doing this
for (size_t i = 0; i < MAX_OBJ_COUNT; ++i) {
if (object == os->object_ptrs[i]) {
return true;
}
}
return false;
}
ObjectID add_object_to_store(ObjectStore *os, void *object, EventHandlerPtr eh, ObjectID add_object_to_store(ObjectStore *os, void *object, EventHandlerPtr eh,
UpdateFuncPtr uf, RenderFuncPtr rf) { UpdateFuncPtr uf, RenderFuncPtr rf) {
if (!os || !object || if (!os || !object || object_exists(os, object) ||
(os->count + 1 == MAX_OBJ_COUNT && os->deleted_count == 0)) { (os->count + 1 == MAX_OBJ_COUNT && os->deleted_count == 0)) {
#ifdef DEBUG_ENGINE #ifdef DEBUG_ENGINE
printf("Failed to add object\n"); printf("Failed to add object\n");
@@ -52,14 +65,6 @@ ObjectID add_object_to_store(ObjectStore *os, void *object, EventHandlerPtr eh,
return INVALID_ID; return INVALID_ID;
} }
// TODO (Abdelrahman): Need to figure out a way to check that the object
// hasn't already been added to the store. If it has been added before, the
// function should return -1 indicating an error to ensure that there aren't
// two references to the same object without the user being aware that they
// refer to the same thing. If the user intentionally copies the ID of one
// object, then it would be their responsibility to make sure they don't
// delete the object using one of the IDs, then try to use it with the other.
ObjectID id; ObjectID id;
if (os->deleted_count > 0) { if (os->deleted_count > 0) {
@@ -141,7 +146,10 @@ void destroy_object_store(ObjectStore **os) {
return; return;
} }
for (size_t i = 0; i < (*os)->count; ++i) { // TODO (Abdelrahman): Figure out if there is a better way to remove all of
// the existing objects without having to loop for the maximum number of
// objects allowed.
for (size_t i = 0; i < MAX_OBJ_COUNT; ++i) {
(*os)->object_ptrs[i] = NULL; (*os)->object_ptrs[i] = NULL;
(*os)->event_handlers[i] = NULL; (*os)->event_handlers[i] = NULL;
(*os)->update_funcs[i] = NULL; (*os)->update_funcs[i] = NULL;
+20 -11
View File
@@ -15,24 +15,24 @@ struct renderer {
SDL_Renderer *SDL_base_renderer; SDL_Renderer *SDL_base_renderer;
}; };
Renderer *create_renderer() { return (Renderer *)malloc(sizeof(Renderer)); } Renderer *create_renderer(SDL_Window *window) {
Renderer *renderer = (Renderer *)malloc(sizeof(Renderer));
bool init_renderer(Renderer *renderer, SDL_Window *window) { if (!renderer) {
if (!renderer || !window) { return NULL;
return false;
} }
renderer->SDL_base_renderer = SDL_CreateRenderer( renderer->SDL_base_renderer = SDL_CreateRenderer(
window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC); window, -1, SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);
if (!(renderer->SDL_base_renderer)) {
destroy_renderer(&renderer);
// Technically speaking, I believe it should be possible to just return return NULL;
// the pointer. However, to make sure that everything is clear, I am }
// performing a test that returns true or false based on whether the
// pointer was initialised or not. return renderer;
return renderer->SDL_base_renderer ? true : false;
} }
void get_drawable_size(Renderer *renderer, int32_t *w, int32_t *h) { void get_render_output_size(Renderer *renderer, int32_t *w, int32_t *h) {
SDL_GetRendererOutputSize(renderer->SDL_base_renderer, w, h); SDL_GetRendererOutputSize(renderer->SDL_base_renderer, w, h);
} }
@@ -47,6 +47,15 @@ void render_clear(const Renderer *renderer, SDL_Color color) {
SDL_RenderClear(renderer->SDL_base_renderer); SDL_RenderClear(renderer->SDL_base_renderer);
} }
void fill_rect(const Renderer *renderer, SDL_Color color, float x, float y,
float w, float h) {
SDL_FRect dest = {x, y, w, h};
SDL_SetRenderDrawColor(renderer->SDL_base_renderer, color.r, color.g, color.b,
color.a);
SDL_RenderFillRectF(renderer->SDL_base_renderer, &dest);
}
void render_surface(const Renderer *renderer, SDL_Surface *surface, float x, void render_surface(const Renderer *renderer, SDL_Surface *surface, float x,
float y, float w, float h) { float y, float w, float h) {
SDL_Texture *texture = SDL_Texture *texture =
+63 -8
View File
@@ -4,8 +4,10 @@
#include "engine_build_config.h" #include "engine_build_config.h"
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdint.h>
#ifdef DEBUG_ENGINE #ifdef DEBUG_ENGINE
#include <stdio.h>
#endif /* DEBUG_ENGINE */ #endif /* DEBUG_ENGINE */
bool init_window(Window *wnd, const char *title, WindowSize size, bool init_window(Window *wnd, const char *title, WindowSize size,
@@ -32,22 +34,62 @@ bool init_window(Window *wnd, const char *title, WindowSize size,
wnd->defined_size.height = size.height; wnd->defined_size.height = size.height;
wnd->background_color = color; wnd->background_color = color;
wnd->full_screen = full_screen;
wnd->renderer = create_renderer(); wnd->renderer = create_renderer(wnd->SDL_base_window);
if (!wnd->renderer || !init_renderer(wnd->renderer, wnd->SDL_base_window)) { if (!wnd->renderer) {
destroy_window(wnd); destroy_window(wnd);
return false; return false;
} }
get_drawable_size(wnd->renderer, &(wnd->drawable_size.width), get_render_output_size(wnd->renderer, &(wnd->real_size.width),
&(wnd->drawable_size.height)); &(wnd->real_size.height));
wnd->drawing_area.x = 0;
wnd->drawing_area.y = 0;
wnd->drawing_area.width = wnd->real_size.width;
wnd->drawing_area.height = wnd->real_size.height;
if (full_screen) {
// Fit the window into the screen when running in full screen mode on
// a non-mobile platform. Mobile platforms will be handled differently
float window_size_ratio =
(float)wnd->defined_size.width / (float)wnd->defined_size.height;
// Fit the drawing area size to the smallest dimension of the screen and
// make sure the drawing area is centered
if (wnd->real_size.height <= wnd->real_size.width) {
wnd->drawing_area.width =
(int32_t)(window_size_ratio * wnd->real_size.height);
wnd->drawing_area.x =
0.0f + ((wnd->real_size.width - wnd->drawing_area.width) / 2.0f);
} else {
wnd->drawing_area.height =
(int32_t)((float)wnd->real_size.width / window_size_ratio);
wnd->drawing_area.y =
0.0f + ((wnd->real_size.height - wnd->drawing_area.height) / 2.0f);
}
// Update the defined size, because in full screen mode, it would be equal
// to the screen dimensions
SDL_DisplayMode mode;
if (SDL_GetWindowDisplayMode(wnd->SDL_base_window, &mode) != 0) {
destroy_window(wnd);
return false;
}
wnd->defined_size.width = mode.w;
wnd->defined_size.height = mode.h;
}
#ifdef DEBUG_ENGINE #ifdef DEBUG_ENGINE
printf("Renderer initialised successfully\n"); printf("Renderer initialised successfully\n");
printf("Window initialised successfully with width %d and height %d\n", printf("Window initialised successfully with width %d and height %d\n",
wnd->drawable_size.width, wnd->drawable_size.height); wnd->real_size.width, wnd->real_size.height);
#endif /* DEBUG_ENGINE */ #endif /* DEBUG_ENGINE */
return true; return true;
@@ -58,7 +100,18 @@ void clear_window(const Window *wnd) {
return; return;
} }
render_clear(wnd->renderer, wnd->background_color); if (wnd->full_screen) {
// When rendering in full screen on a non-mobile platform, we fill the
// entire screen with black, then fill an area that fits the window
// dimensions with the user-defined backgroud color of the window
render_clear(wnd->renderer, (SDL_Color){0, 0, 0, 255});
fill_rect(wnd->renderer, wnd->background_color, wnd->drawing_area.x,
wnd->drawing_area.y, wnd->drawing_area.width,
wnd->drawing_area.height);
} else {
render_clear(wnd->renderer, wnd->background_color);
}
} }
void swap_render_buffers(const Window *wnd) { void swap_render_buffers(const Window *wnd) {
@@ -82,8 +135,10 @@ void destroy_window(Window *wnd) {
SDL_DestroyWindow(wnd->SDL_base_window); SDL_DestroyWindow(wnd->SDL_base_window);
wnd->SDL_base_window = NULL; wnd->SDL_base_window = NULL;
wnd->full_screen = false;
wnd->defined_size = (WindowSize){0, 0}; wnd->defined_size = (WindowSize){0, 0};
wnd->drawable_size = (WindowSize){0, 0}; wnd->real_size = (WindowSize){0, 0};
wnd->drawing_area = (WindowDrawingArea){0.0f, 0.0f, 0.0f, 0.0f};
wnd->background_color = (SDL_Color){0, 0, 0, 255}; wnd->background_color = (SDL_Color){0, 0, 0, 255};
#ifdef DEBUG_ENGINE #ifdef DEBUG_ENGINE