From 79f28100bdb0db7d71b131e3dbc8a728e1debeb4 Mon Sep 17 00:00:00 2001 From: Abdelrahman Date: Wed, 21 Sep 2022 19:55:45 +0100 Subject: [PATCH] Modified the ObjectStore and the Hashmap and added the ObjectStore to the GameManager --- CMakeLists.txt | 4 +- include/{Game.h => GameManager.h} | 4 ++ include/Hashmap.h | 16 +++-- include/ObjectStore.h | 2 +- src/{Game.c => GameManager.c} | 70 +++++++++++++++++++- src/Hashmap.c | 103 +++++++++++++++++------------- src/ObjectStore.c | 50 ++++++++++----- src/Window.c | 5 ++ 8 files changed, 181 insertions(+), 73 deletions(-) rename include/{Game.h => GameManager.h} (58%) rename src/{Game.c => GameManager.c} (51%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 157d3ec..19e9347 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,7 +22,7 @@ set(CMAKE_INSTALL_RPATH "$ORIGIN;$ORIGIN/../lib") # TARGETS add_library(${PROJECT_NAME} SHARED - src/Game.c + src/GameManager.c src/Window.c src/Renderer.c src/ObjectStore.c @@ -47,7 +47,7 @@ target_link_libraries(${PROJECT_NAME} PUBLIC install(FILES ${CMAKE_CURRENT_BINARY_DIR}/engine_build_config.h include/constants.h - include/Game.h + include/GameManager.h include/Window.h include/Renderer.h include/ObjectStore.h diff --git a/include/Game.h b/include/GameManager.h similarity index 58% rename from include/Game.h rename to include/GameManager.h index ebd68b3..c7fd355 100644 --- a/include/Game.h +++ b/include/GameManager.h @@ -1,11 +1,15 @@ #ifndef GAME_H #define GAME_H +#include "ObjectStore.h" #include bool init_game(const char *game_name, int window_width, int window_height, bool full_screen); bool game_running(); +void add_object(void *object, const char *object_tag, EventHandlerPtr eh, + UpdateFuncPtr uf, RenderFuncPtr rf); +void remove_object(const char *object_tag); void handle_events(); void update(); void render(); diff --git a/include/Hashmap.h b/include/Hashmap.h index 8144e28..0e7de19 100644 --- a/include/Hashmap.h +++ b/include/Hashmap.h @@ -9,15 +9,17 @@ #include #endif /* DEBUG_ENGINE */ -void init_hashmap(); -int32_t add_object_to_map(const char *key); -int32_t get_object_index(const char *key); -int32_t delete_object_from_map(const char *key); -void destroy_hashmap(); +typedef struct hashmap Hashmap; + +Hashmap *create_hashmap(); +int32_t add_object_to_map(Hashmap *map, const char *key); +int32_t get_object_index(Hashmap *map, const char *key); +int32_t delete_object_from_map(Hashmap *map, const char *key); +void destroy_hashmap(Hashmap *map); #ifdef DEBUG_ENGINE -void print_hashmap(); -void print_non_empty(); +void print_hashmap(Hashmap *map); +void print_non_empty(Hashmap *map); #endif // DEBUG_ENGINE #endif // !HASHMAP_H diff --git a/include/ObjectStore.h b/include/ObjectStore.h index a2c74bc..c7059ac 100644 --- a/include/ObjectStore.h +++ b/include/ObjectStore.h @@ -22,7 +22,7 @@ void render_all_objects(ObjectStore *os, Renderer *renderer); void destroy_object_store(ObjectStore *os); #ifdef DEBUG_ENGINE -void print_objects(); +void print_objects(ObjectStore *os); #endif /* DEBUG_ENGINE */ #endif // !OBJECT_STORE_H diff --git a/src/Game.c b/src/GameManager.c similarity index 51% rename from src/Game.c rename to src/GameManager.c index 7b6bb6c..063d63d 100644 --- a/src/Game.c +++ b/src/GameManager.c @@ -1,4 +1,5 @@ -#include "Game.h" +#include "GameManager.h" +#include "ObjectStore.h" #include "SDL.h" #include "SDL_error.h" #include "SDL_events.h" @@ -14,12 +15,16 @@ INTERNAL struct game { bool running; + float delta; Window window; SDL_Event event; + ObjectStore *object_store; } Game; bool init_game(const char *game_name, int window_width, int window_height, bool full_screen) { + bool initialisation_complete = true; + if (SDL_Init(SDL_INIT_EVERYTHING) != 0) { #ifdef DEBUG_ENGINE printf("Failed to initialise SDL. Error: %s\n", SDL_GetError()); @@ -34,10 +39,23 @@ bool init_game(const char *game_name, int window_width, int window_height, printf("Failed to initialise window\n"); #endif /* DEBUG_ENGINE */ + initialisation_complete = false; + } + + Game.object_store = create_object_store(); + + if (!(Game.object_store)) { + initialisation_complete = false; + } + + if (!initialisation_complete) { + close_game(); + return false; } Game.running = true; + Game.delta = 0.0f; #ifdef DEBUG_ENGINE printf("Game initialised successfully\n"); @@ -48,27 +66,75 @@ bool init_game(const char *game_name, int window_width, int window_height, bool game_running() { return Game.running; } +void add_object(void *object, const char *object_tag, + EventHandlerPtr event_handler, UpdateFuncPtr update_func, + RenderFuncPtr render_func) { + if (!(Game.running) || !(Game.object_store)) { + return; + } + + add_object_to_store(Game.object_store, object, object_tag, event_handler, + update_func, render_func); +} + +void remove_object(const char *object_tag) { + if (!(Game.running) || !(Game.object_store)) { + return; + } + + remove_object_from_store(Game.object_store, object_tag); +} + void handle_events() { + if (!(Game.running)) { + return; + } + while (SDL_PollEvent(&(Game.event))) { switch (Game.event.type) { case SDL_QUIT: Game.running = false; break; } + + if (!Game.object_store) { + break; + } + + handle_all_objects_events(Game.object_store, &(Game.event)); } } -void update() {} +void update() { + if (!(Game.running) || !(Game.object_store)) { + return; + } + + update_all_objects(Game.object_store, Game.delta); +} void render() { + if (!(Game.running)) { + return; + } + fill_window_with_color(&(Game.window), (SDL_Color){255, 255, 255, 255}); + if (Game.object_store) { + render_all_objects(Game.object_store, Game.window.renderer); + } + swap_render_buffers(&(Game.window)); } void close_game() { + destroy_object_store(Game.object_store); + Game.object_store = NULL; + destroy_window(&(Game.window)); + Game.delta = 0.0f; + Game.running = false; SDL_Quit(); diff --git a/src/Hashmap.c b/src/Hashmap.c index da15667..0385b3a 100644 --- a/src/Hashmap.c +++ b/src/Hashmap.c @@ -11,16 +11,24 @@ #include #endif /* DEBUG_ENGINE */ -INTERNAL struct objects_hashmap { +struct hashmap { size_t count; char *keys[MAX_OBJ_COUNT]; int32_t active_indices[MAX_OBJ_COUNT]; -} map = {}; +}; + +Hashmap *create_hashmap() { + Hashmap *map = malloc(sizeof(Hashmap)); + + map->count = 0; + + memset(map->keys, 0, MAX_OBJ_COUNT); -void init_hashmap() { for (int i = 0; i < MAX_OBJ_COUNT; ++i) { - map.active_indices[i] = -1; + map->active_indices[i] = -1; } + + return map; } size_t hash_key(const char *key) { @@ -35,8 +43,8 @@ size_t hash_key(const char *key) { return i; } -int32_t add_object_to_map(const char *key) { - if (map.count + 1 == MAX_OBJ_COUNT) { +int32_t add_object_to_map(Hashmap *map, const char *key) { + if (map->count + 1 == MAX_OBJ_COUNT) { #ifdef DEBUG_ENGINE printf("Map full\n"); #endif /* DEBUG_ENGINE */ @@ -46,8 +54,8 @@ int32_t add_object_to_map(const char *key) { size_t index = hash_key(key); - if (map.keys[index]) { - if (strcmp(map.keys[index], key) == 0) { + if (map->keys[index]) { + if (strcmp(map->keys[index], key) == 0) { #ifdef DEBUG_ENGINE printf("Key \"%s\" already exists\n", key); #endif /* DEBUG_ENGINE */ @@ -56,23 +64,23 @@ int32_t add_object_to_map(const char *key) { // multiple keys #ifdef DEBUG_ENGINE printf("Collision detected. Key \"%s\" collides with key \"%s\"\n", key, - map.keys[index]); + map->keys[index]); #endif /* DEBUG_ENGINE */ } return -1; } - map.keys[index] = malloc(strlen(key) + 1); - strcpy(map.keys[index], key); - map.active_indices[map.count] = index; - map.count += 1; + map->keys[index] = malloc(strlen(key) + 1); + strcpy(map->keys[index], key); + map->active_indices[map->count] = index; + map->count += 1; return index; } -int32_t get_object_index(const char *key) { - if (map.count == 0) { +int32_t get_object_index(Hashmap *map, const char *key) { + if (map->count == 0) { #ifdef DEBUG_ENGINE printf("Key \"%s\" doesn't exist\n", key); #endif /* DEBUG_ENGINE */ @@ -82,7 +90,7 @@ int32_t get_object_index(const char *key) { size_t index = hash_key(key); - if (!(map.keys[index]) || strcmp(map.keys[index], key) != 0) { + if (!(map->keys[index]) || strcmp(map->keys[index], key) != 0) { #ifdef DEBUG_ENGINE printf("Key \"%s\" doesn't exist\n", key); #endif /* DEBUG_ENGINE */ @@ -93,8 +101,8 @@ int32_t get_object_index(const char *key) { return (int32_t)index; } -int32_t delete_object_from_map(const char *key) { - if (map.count == 0) { +int32_t delete_object_from_map(Hashmap *map, const char *key) { + if (map->count == 0) { #ifdef DEBUG_ENGINE printf("Key \"%s\" doesn't exist\n", key); #endif /* DEBUG_ENGINE */ @@ -104,7 +112,7 @@ int32_t delete_object_from_map(const char *key) { size_t index = hash_key(key); - if (!(map.keys[index]) || strcmp(map.keys[index], key) != 0) { + if (!(map->keys[index]) || strcmp(map->keys[index], key) != 0) { #ifdef DEBUG_ENGINE printf("Key \"%s\" doesn't exist\n", key); #endif /* DEBUG_ENGINE */ @@ -112,70 +120,77 @@ int32_t delete_object_from_map(const char *key) { return -1; } - free(map.keys[index]); - map.keys[index] = NULL; + free(map->keys[index]); + map->keys[index] = NULL; size_t packing_start_index = 0; - for (size_t i = 0; i < map.count; ++i) { - if (map.active_indices[i] == index) { - map.active_indices[i] = -1; + for (size_t i = 0; i < map->count; ++i) { + if (map->active_indices[i] == index) { + map->active_indices[i] = -1; packing_start_index = i; break; } } // Make sure the indices are packed in the array - for (; packing_start_index < map.count; ++packing_start_index) { + for (; packing_start_index < map->count; ++packing_start_index) { if (packing_start_index + 1 == MAX_OBJ_COUNT) { // Make sure we don't go out of bounds if we are at the last item - map.active_indices[packing_start_index] = -1; + map->active_indices[packing_start_index] = -1; continue; } - map.active_indices[packing_start_index] = - map.active_indices[packing_start_index + 1]; + map->active_indices[packing_start_index] = + map->active_indices[packing_start_index + 1]; } - map.count -= 1; + map->count -= 1; return index; } -void destroy_hashmap() { - for (size_t i = 0; i < map.count; ++i) { - size_t index = map.active_indices[i]; +void destroy_hashmap(Hashmap *map) { + if (!map) { + return; + } + + for (size_t i = 0; i < map->count; ++i) { + size_t index = map->active_indices[i]; if (index == -1) { continue; } - if (map.keys[index]) { - free(map.keys[index]); - map.keys[index] = NULL; + if (map->keys[index]) { + free(map->keys[index]); + map->keys[index] = NULL; } - map.active_indices[i] = -1; + map->active_indices[i] = -1; } - map.count = 0; + map->count = 0; + + free(map); + map = NULL; } #ifdef DEBUG_ENGINE -void print_hashmap() { - if (map.count == 0) { +void print_hashmap(Hashmap *map) { + if (map->count == 0) { return; } - for (int i = 0; i < map.count; ++i) { - size_t index = map.active_indices[i]; - printf("%d: %s\n", i, map.keys[index]); + for (int i = 0; i < map->count; ++i) { + size_t index = map->active_indices[i]; + printf("%d: %s\n", i, map->keys[index]); } } -void print_non_empty() { +void print_non_empty(Hashmap *map) { for (int i = 0; i < MAX_OBJ_COUNT; ++i) { - if (map.active_indices[i] != -1) { + if (map->active_indices[i] != -1) { printf("%d is not set to -1\n", i); } } diff --git a/src/ObjectStore.c b/src/ObjectStore.c index 2de9c89..5a0e08d 100644 --- a/src/ObjectStore.c +++ b/src/ObjectStore.c @@ -5,9 +5,12 @@ #include #include +#include + struct object_store { size_t count; int32_t active_indices[MAX_OBJ_COUNT]; + Hashmap *map; void **object_ptrs; EventHandlerPtr *event_handlers; UpdateFuncPtr *update_funcs; @@ -15,19 +18,20 @@ struct object_store { }; ObjectStore *create_object_store() { - init_hashmap(); - bool allocation_complete = true; ObjectStore *os = (ObjectStore *)malloc(sizeof(ObjectStore)); if (!os) { - // If allocating memory to the store fails, we still need to call the - // destroy function to make sure that the memory allocated for the - // hashmap is freed. - destroy_object_store(os); + // If allocating memory to the store fails, we just return NULL. No need to + // continue with the rest of the function or to call any cleanup functions return NULL; } + os->map = create_hashmap(); + if (!(os->map)) { + allocation_complete = false; + } + os->count = 0; os->object_ptrs = malloc(sizeof(void *) * MAX_OBJ_COUNT); @@ -70,7 +74,7 @@ ObjectStore *create_object_store() { void add_object_to_store(ObjectStore *os, void *object, const char *object_tag, EventHandlerPtr eh, UpdateFuncPtr uf, RenderFuncPtr rf) { - int32_t index = add_object_to_map(object_tag); + int32_t index = add_object_to_map(os->map, object_tag); if (index < 0) { return; @@ -89,7 +93,7 @@ void remove_object_from_store(ObjectStore *os, const char *object_tag) { return; } - int32_t index = delete_object_from_map(object_tag); + int32_t index = delete_object_from_map(os->map, object_tag); if (index < 0) { return; @@ -132,8 +136,11 @@ void handle_all_objects_events(ObjectStore *os, const SDL_Event *event) { for (int i = 0; i < os->count; ++i) { int32_t index = os->active_indices[i]; - void *object = os->object_ptrs[index]; - (os->event_handlers[index])(event, object); + + if (os->event_handlers[index]) { + void *object = os->object_ptrs[index]; + (os->event_handlers[index])(event, object); + } } } @@ -144,8 +151,11 @@ void update_all_objects(ObjectStore *os, float delta) { for (int i = 0; i < os->count; ++i) { int32_t index = os->active_indices[i]; - void *object = os->object_ptrs[index]; - (os->update_funcs[index])(delta, object); + + if (os->update_funcs[index]) { + void *object = os->object_ptrs[index]; + (os->update_funcs[index])(delta, object); + } } } @@ -156,14 +166,15 @@ void render_all_objects(ObjectStore *os, Renderer *renderer) { for (int i = 0; i < os->count; ++i) { int32_t index = os->active_indices[i]; - void *object = os->object_ptrs[index]; - (os->render_funcs[index])(renderer, object); + + if (os->render_funcs[index]) { + void *object = os->object_ptrs[index]; + (os->render_funcs[index])(renderer, object); + } } } void destroy_object_store(ObjectStore *os) { - destroy_hashmap(); - if (!os) { return; } @@ -194,10 +205,15 @@ void destroy_object_store(ObjectStore *os) { os->object_ptrs = NULL; } + if (os->map) { + destroy_hashmap(os->map); + os->map = NULL; + } + free(os); os = NULL; } #ifdef DEBUG_ENGINE -void print_objects() { print_hashmap(); } +void print_objects(ObjectStore *os) { print_hashmap(os->map); } #endif /* DEBUG_ENGINE */ diff --git a/src/Window.c b/src/Window.c index 85326c7..31cc4cd 100644 --- a/src/Window.c +++ b/src/Window.c @@ -49,9 +49,14 @@ void fill_window_with_color(const Window *wnd, SDL_Color color) { void swap_render_buffers(const Window *wnd) { swap_buffers(wnd->renderer); } void destroy_window(Window *wnd) { + if (!wnd) { + return; + } + if (wnd->SDL_base_window) { if (wnd->renderer) { destroy_renderer(wnd->renderer); + wnd->renderer = NULL; } SDL_DestroyWindow(wnd->SDL_base_window);