From 1821d2092357eecc3ed4999751fb1a71b521324b Mon Sep 17 00:00:00 2001 From: Ulysse Cura Date: Wed, 22 Jul 2026 15:37:29 +0200 Subject: [PATCH] Compiling with ncurses. --- src/Makefile | 6 +- src/asset_manager.c | 213 ++++++++++++++++++++ src/display.c | 27 +++ src/event.c | 6 + src/headers/asset_manager.h | 57 ++++++ src/headers/display.h | 20 ++ src/headers/event.h | 17 ++ src/headers/keycodes.h | 8 + src/headers/linked_list.h | 288 +++++++++++++++++++++++++++ src/headers/memory_alloc.h | 6 + src/headers/vector2d.h | 133 +++++++++++++ src/linked_list.c | 377 ++++++++++++++++++++++++++++++++++++ src/vector2d.c | 17 ++ 13 files changed, 1172 insertions(+), 3 deletions(-) create mode 100644 src/asset_manager.c create mode 100644 src/display.c create mode 100644 src/event.c create mode 100644 src/headers/asset_manager.h create mode 100644 src/headers/display.h create mode 100644 src/headers/event.h create mode 100644 src/headers/keycodes.h create mode 100644 src/headers/linked_list.h create mode 100644 src/headers/memory_alloc.h create mode 100644 src/headers/vector2d.h create mode 100644 src/linked_list.c create mode 100644 src/vector2d.c diff --git a/src/Makefile b/src/Makefile index 9069a6d..240cffc 100644 --- a/src/Makefile +++ b/src/Makefile @@ -8,8 +8,8 @@ CORE_SOURCES := \ # Compiler and flags CORE_CC = gcc -#CORE_CFLAGS = --std=c17 --pedantic -O3 -DASSET_FILE_NAME=\"$(ASSET_OUTPUT)\" $(shell pkg-config --cflags sdl2) # RELEASE -CORE_CFLAGS = --std=c17 --pedantic -O1 -g -DASSET_FILE_NAME=\"$(ASSET_OUTPUT)\" $(shell pkg-config --cflags sdl2) \ +#CORE_CFLAGS = --std=c17 --pedantic -O3 -DASSET_FILE_NAME=\"$(ASSET_OUTPUT)\" $(shell pkg-config --cflags ncurses) # RELEASE +CORE_CFLAGS = --std=c17 --pedantic -O1 -g -DASSET_FILE_NAME=\"$(ASSET_OUTPUT)\" $(shell pkg-config --cflags ncurses) \ -Wall -Wno-missing-braces -Wextra -Wno-missing-field-initializers \ -Wformat=2 -Wswitch-default -Wswitch-enum -Wcast-align \ -Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 \ @@ -25,7 +25,7 @@ CORE_AR = ar CORE_ARFLAGS = # Used in final linking. -CORE_DEPS_FLAGS = $(shell pkg-config --libs sdl2) +CORE_DEPS_FLAGS = $(shell pkg-config --libs ncurses) # Deduce objects CORE_OBJECTS = $(CORE_SOURCES:%.c=$(BUILD_DIR)/$(CORE_DIR)/%.o) diff --git a/src/asset_manager.c b/src/asset_manager.c new file mode 100644 index 0000000..0202559 --- /dev/null +++ b/src/asset_manager.c @@ -0,0 +1,213 @@ +#include "asset_manager.h" + +#include +#include +#include +#include +#include "linked_list.h" +#include "memory_alloc.h" +#include "display.h" + +asset_t *create_asset(asset_type_t asset_type) +{ + asset_t *asset = malloc(sizeof(asset_t)); + + asset->type = asset_type; + asset->nb_refs = 1; + + return asset; +} + +void destroy_asset(asset_t *asset) +{ + free(asset->name); + + switch(asset->type) + { + case ASSET_TEXTURE: + free(asset->data.texture->pixels); + free(asset->data.texture); + + default: + break; + } + + free(asset); +} + +void destroy_asset_header_def(asset_header_def_t *asset_header_def) +{ + free(asset_header_def->name); + free(asset_header_def); +} + +void asset_manager_init(asset_manager_t *asset_manager) +{ + linked_list_init(&asset_manager->assets, sizeof(asset_t), (deleter_t)destroy_asset); + linked_list_init(&asset_manager->assets_header_defs, sizeof(asset_header_def_t), (deleter_t)destroy_asset_header_def); + + asset_manager->asset_file = fopen(ASSET_FILE_NAME, "rb"); + if(!asset_manager->asset_file) + { + printf("can't open asset file : %s.\n", ASSET_FILE_NAME); + return; + } + + size_t nb_assets; + size_t ret = fread(&nb_assets, sizeof(nb_assets), 1, asset_manager->asset_file); + if(ret != 1) + { + printf("can't read asset file."); + return; + } + + for(size_t i = 0; i < nb_assets; i++) + { + elem_t *elem = elem_create(&asset_manager->assets_header_defs); + + size_t cap = 0; + + ret = getdelim(&((asset_header_def_t *)elem->data)->name, &cap, '\0', asset_manager->asset_file); + if(ret == SIZE_MAX) + { + printf("can't read asset file."); + return; + } + + ret = fread(&((asset_header_def_t *)elem->data)->start, sizeof(((asset_header_def_t *)elem->data)->start), 1, asset_manager->asset_file); + if(ret != 1) + { + printf("can't read asset file."); + return; + } + + linked_list_push_back_elem(&asset_manager->assets_header_defs, elem); + } +} + +void asset_manager_exit(asset_manager_t *asset_manager) +{ + linked_list_clear(&asset_manager->assets_header_defs); + linked_list_clear(&asset_manager->assets); + fclose(asset_manager->asset_file); +} + +// Only for this file +// No args +static inline bool condition_is_asset_unused(elem_t *elem, va_list args __attribute__((unused))) +{ + return !((asset_t *)elem->data)->nb_refs; +} + +inline void asset_manager_collect_garbage(asset_manager_t *asset_manager) +{ + linked_list_remove_if(&asset_manager->assets, condition_is_asset_unused); +} + +// Only for this file +// Arg : const char *asset_name +static inline bool condition_is_asset_name(elem_t *elem, va_list args) +{ + return !strcmp(((asset_t *)elem->data)->name, va_arg(args, const char *)); +} + +//Only for this file +// Arg : const char *asset_name +static inline bool condition_is_asset_header_def_name(elem_t *elem, va_list args) +{ + return !strcmp(((asset_header_def_t *)elem->data)->name, va_arg(args, const char *)); +} + +static inline void load_texture(asset_manager_t *asset_manager, asset_t *asset, asset_header_def_t *asset_header_def) +{ + if(fseek(asset_manager->asset_file, asset_header_def->start, SEEK_SET)) + { + printf("Couldn't seek in asset file."); + return; + } + + size_t width, height; + + if(fread(&width, sizeof(width), 1, asset_manager->asset_file) != 1) + { + printf("Failed to read in asset file."); + return; + } + + if(fread(&height, sizeof(height), 1, asset_manager->asset_file) != 1) + { + printf("Failed to read in asset file."); + return; + } + + asset->data.texture = malloc(sizeof(texture_t)); + asset->data.texture->width = width; + asset->data.texture->height = height; + asset->data.texture->pixels = malloc(width * height * sizeof(uint16_t)); + + if(fread(asset->data.texture->pixels, sizeof(uint16_t), width * height, asset_manager->asset_file) != width * height) + { + printf("Failed to read asset file."); + return; + } +} + +void asset_manager_load_asset(asset_manager_t *asset_manager, const char *asset_name, asset_type_t asset_type) +{ + asset_t *asset = linked_list_get_if(&asset_manager->assets, condition_is_asset_name, asset_name); + if(asset) + { + asset->nb_refs++; + return; + } + + asset_header_def_t *asset_header_def = linked_list_get_if(&asset_manager->assets_header_defs, condition_is_asset_header_def_name, asset_name); + if(!asset_header_def) + { + printf("Asset doesn't exist in asset file : %s\n", asset_name); + return; + } + + asset = create_asset(asset_type); + asset->name = malloc(strlen(asset_name) + 1); + strcpy(asset->name, asset_name); + asset->type = asset_type; + + switch(asset_type) + { + case ASSET_TEXTURE: + load_texture(asset_manager, asset, asset_header_def); + break; + + default: + return; + } + + linked_list_push_back(&asset_manager->assets, asset); +} + +void asset_manager_let_go_asset(asset_manager_t *asset_manager, const char *asset_name) +{ + asset_t *asset = linked_list_get_if(&asset_manager->assets, condition_is_asset_name, asset_name); + if(asset) + { + asset->nb_refs--; + } +} + +texture_t *asset_manager_get_texture(asset_manager_t *asset_manager, const char *asset_name) +{ + asset_t *asset = linked_list_get_if(&asset_manager->assets, condition_is_asset_name, asset_name); + if(!asset) + return NULL; + + if(asset->type != ASSET_TEXTURE) + return NULL; + + return asset->data.texture; +} + +void asset_manager_draw_texture(texture_t *texture, rect_t *src_rect, rect_t *dst_rect, bool flip) +{ + +} diff --git a/src/display.c b/src/display.c new file mode 100644 index 0000000..5da7e7e --- /dev/null +++ b/src/display.c @@ -0,0 +1,27 @@ +#include "display.h" + +#include +#include + +inline void display_init(void) +{ + initscr(); + raw(); + noecho(); + keypad(stdscr, TRUE); +} + +inline void display_update(void) +{ + refresh(); +} + +inline void display_clear(void) +{ + clear(); +} + +inline void display_exit(void) +{ + endwin(); +} diff --git a/src/event.c b/src/event.c new file mode 100644 index 0000000..0fa4bc0 --- /dev/null +++ b/src/event.c @@ -0,0 +1,6 @@ +#include "event.h" + +inline int pollevent(event_t *event) +{ + return 0; +} diff --git a/src/headers/asset_manager.h b/src/headers/asset_manager.h new file mode 100644 index 0000000..8c91a29 --- /dev/null +++ b/src/headers/asset_manager.h @@ -0,0 +1,57 @@ +#ifndef ASSET_MANAGER_H +#define ASSET_MANAGER_H + +#include +#include +#include "linked_list.h" +#include "vector2d.h" + +typedef struct texture_t { + size_t width, height; + uint16_t *pixels; +} texture_t; + +typedef enum asset_type_t { + ASSET_TEXTURE +} asset_type_t; + +typedef struct asset_t { + char *name; + + union { + texture_t *texture; + } data; + + size_t nb_refs; + + asset_type_t type; +} asset_t; + +asset_t *create_asset(asset_type_t asset_type); + +void destroy_asset(asset_t *asset); + +typedef struct asset_header_def_t { + char *name; + size_t start; +} asset_header_def_t; + +void destroy_asset_header_def(asset_header_def_t *asset_header_def); + +typedef struct asset_manager_t { + linked_list_t assets_header_defs; + linked_list_t assets; + FILE *asset_file; +} asset_manager_t; + +void asset_manager_init(asset_manager_t *asset_manager); +void asset_manager_exit(asset_manager_t *asset_manager); +void asset_manager_collect_garbage(asset_manager_t *asset_manager); + +void asset_manager_load_asset(asset_manager_t *asset_manager, const char *asset_name, asset_type_t asset_type); +void asset_manager_let_go_asset(asset_manager_t *asset_manager, const char *asset_name); + +texture_t *asset_manager_get_texture(asset_manager_t *asset_manager, const char *asset_name); +void asset_manager_draw_texture(texture_t *texture, rect_t *src_rect, rect_t *dst_rect, bool flip); + +#endif // ASSET_MANAGER_H \ No newline at end of file diff --git a/src/headers/display.h b/src/headers/display.h new file mode 100644 index 0000000..e43207e --- /dev/null +++ b/src/headers/display.h @@ -0,0 +1,20 @@ +#ifndef DISPLAY_H +#define DISPLAY_H + +#include "vector2d.h" + +#define C_BLACK 0, 0, 0, 255 + +#define DISPLAY_WIDTH 396 +#define DISPLAY_HEIGHT 224 +#define RENDER_SCALE 2 + +void display_init(void); + +void display_update(void); + +void display_clear(void); + +void display_exit(void); + +#endif // DISPLAY_H \ No newline at end of file diff --git a/src/headers/event.h b/src/headers/event.h new file mode 100644 index 0000000..86eda57 --- /dev/null +++ b/src/headers/event.h @@ -0,0 +1,17 @@ +#ifndef KEYBOARD_H +#define KEYBOARD_H + +#include + +#define EVENT_KEY_UP 1 +#define EVENT_KEY_DOWN 2 +#define EVENT_QUIT 3 + +typedef struct event_t { + uint32_t type; + int key; +} event_t; + +int pollevent(event_t *event); + +#endif // KEYBOARD_H \ No newline at end of file diff --git a/src/headers/keycodes.h b/src/headers/keycodes.h new file mode 100644 index 0000000..dd5d862 --- /dev/null +++ b/src/headers/keycodes.h @@ -0,0 +1,8 @@ +#ifndef KEYCODES_H +#define KEYCODES_H + +#include + +#define MAX_KEYCODES KEY_MAX - KEY_MIN + +#endif // KEYCODES_H \ No newline at end of file diff --git a/src/headers/linked_list.h b/src/headers/linked_list.h new file mode 100644 index 0000000..c3a3315 --- /dev/null +++ b/src/headers/linked_list.h @@ -0,0 +1,288 @@ +#ifndef LINKED_LIST_H +#define LINKED_LIST_H + +#include +#include +#include +#include + +/** + * @brief Element struct for linked lists. + * This struct is the base for storing data in a linked list. + * + * @param data Raw pointer to any type of data + * @param prev Pointer to the prev element in the linked list + * @param next Pointer to the next element in the linked list +*/ +typedef struct elem_t { + void *data; + struct elem_t *prev; + struct elem_t *next; +} elem_t; + +/** + * @brief A type for deleters used during the destruction of data stored in elements. + * + * During the initialisation of linked lists you can pass in argument a deleter. + * It is used during the destruction of an element. + * You can pass NULL to the initialisation to use the default deleter (free(elem->data)). + * Your deleter_t function declaration must look like this : + * + * void name_of_your_deleter(void *data); + * + * Then do what you need to destroy your data (don't forget to free the data itself...) but not the elements. + * You should always define your function with "inline" if it's no too long. +*/ +typedef void (*deleter_t)(void *data); + +/** + * @brief A type for condition used for function like linked_list_remove_if + * + * For function like linked_list_remove_if you need a condition. + * It have two argument which are "elem_t *" and "va_list", that is because it passes the element on the actual index + * and the args passed to the function. + * Your condition_t function declaration must look like this : + * + * bool name_of_your_condition(elem_t *elem, va_list); + * + * Then return true if you want the element to be removed from the list or false if not. + * You should always define your function with "static", and "inline". +*/ +typedef bool (*condition_t)(elem_t *elem, va_list args); + +/** + * @brief A type for action used for function like linked_list_for_each + * + * For function like linked_list_for_each you need an action to do. + * It have two argument which are "elem_t *" and "va_list", that is because it passes the element on the actual index + * and the args passed to the function. + * Your condition_t function declaration must look like this : + * + * void name_of_your_condition(elem_t *elem, va_list); + * + * Then do whatever you want with the element data, just don't remove it. + * You should always define your function with "static", and "inline". +*/ +typedef void (*action_t)(elem_t *elem, va_list args); + +/** + * @brief Base of linked lists. + * This struct is the base for creating linked lists. + * + * @param data_size Size of the data stored in elements of the linked list (used while creating new elements) + * @param first Pointer to the first element in the linked list + * @param last Pointer to the last element in the linked list + * @param size Size of the linked list + * @param deleter Deleter of the data when removing an element +*/ +typedef struct linked_list_t { + size_t data_size; + elem_t *first; + elem_t *last; + size_t size; + deleter_t elem_deleter; +} linked_list_t; + +/** + * @brief Init a linked list + * This function is necessary if you create a linked list. + * + * WARNING : It doesn't allocate the memory for you ! + * + * @param linked_list Pointer to an linked list + * @param data_size Data size for elements in the linked list + * @param deleter The deleter used during destroyement of an elem +*/ +void linked_list_init(linked_list_t *linked_list, const size_t data_size, deleter_t deleter); + +/** + * @brief Create an elem to fill with data to insert in a linked list. + * This function is usefull when you want to initialise an elem with the proper data_size strored in the linked list. + * + * WARNING : Don't change the "data" ptr after calling this function or it will lead to memory leaks ! + * Instead do something like this : *(int *)elem->data = 42; + * + * @param linked_list Pointer to an linked list + * + * @return Address of initialised elem, NULL on error. +*/ +elem_t *elem_create(const linked_list_t *linked_list); + +/** + * @brief Destroy the given element and its data. + * This function is usefull when you want to free an element. + * The deleter is used for the data only and you can pass NULL to use the default deleter. + * + * @param elem Pointer to an element + * @param elem_deleter Function to use to free the data +*/ +void destroy_elem(elem_t *elem, const deleter_t elem_deleter); + +/** + * @brief Insert an element from the back in a linked list, do nothing on error. + * + * @param linked_list Pointer to a linked list + * @param elem Pointer to an element +*/ +void linked_list_push_back_elem(linked_list_t *linked_list, elem_t *elem); + +/** + * @brief Insert an element from the front in a linked list, do nothing on error. + * + * @param linked_list Pointer to a linked list + * @param elem Pointer to an element +*/ +void linked_list_push_front_elem(linked_list_t *linked_list, elem_t *elem); + +/** + * @brief Insert an element initialised and filled with data from the back in a linked list, do nothing on error. + * + * @param linked_list Pointer to a linked list + * @param data Pointer to any data +*/ +void linked_list_push_back(linked_list_t *linked_list, void *data); + +/** + * @brief Insert an element filled with data from the front in a linked list. + * + * @param linked_list Pointer to a linked list + * @param data Pointer to any data +*/ +void linked_list_push_front(linked_list_t *linked_list, void *data); + +/** + * @brief Delete the last element in the given linked list, do nothing on error. + * + * @param linked_list Pointer to a linked list +*/ +void linked_list_pop_back(linked_list_t *linked_list); + +/** + * @brief Delete the first element in the given linked list, do nothing on error. + * + * @param linked_list Pointer to a linked list +*/ +void linked_list_pop_front(linked_list_t *linked_list); + +/** + * @brief Clear the given linked list, do nothing on error. + * + * @brief linked_list Pointer to a linked list +*/ +void linked_list_clear(linked_list_t *linked_list); + +/** + * @brief Check if the given linked list is empty. + * + * @param linked_list Pointer to a linked list + * + * @return True if the given linked list is empty else false. +*/ +bool linked_list_is_empty(const linked_list_t *linked_list); + +/** + * @brief Check if the given index is whithin the range of the linked list. + * + * @param linked_list Pointer to an linked_list_t + * + * @return True if index in within the range of the linked list else false. +*/ +bool linked_list_is_in_bound(const linked_list_t *linked_list, const size_t index); + +/** + * @brief Get element at the given index in the linked list. + * + * @param linked_list Pointer to a linked list + * @param index Index of the element + * + * @return Element, NULL on error. +*/ +elem_t *linked_list_get_elem(const linked_list_t *linked_list, const size_t index); + +/** + * @brief Get data in the element at the given index in the linked list. + * + * @param linked_list Pointer to an linked list + * @param index Index of the wanted element + * + * @return Data, NULL on error. +*/ +void *linked_list_get(const linked_list_t *linked_list, const size_t index); + +/** + * @brief Insert element at the given index in the linked list, do nothing on error. + * + * @param linked_list Pointer to a linked list + * @param elem Pointer to an element + * @param index Index to insert element +*/ +void linked_list_insert_elem(linked_list_t *linked_list, elem_t *elem, const size_t index); + +/** + * @brief Insert element with data at the given index in the linked list, do nothing on error. + * + * @param linked_list Pointer to a linked list + * @param data Data to put in the new element + * @param index Index to insert the element +*/ +void linked_list_insert(linked_list_t *linked_list, void *data, const size_t index); + +/** + * @brief Remove the given elem in the linked list, do nothing on error. + * + * @param linked_list Pointer to a linked list + * @param elem Element to remove +*/ +void linked_list_remove_elem(linked_list_t *linked_list, elem_t *elem); + +/** + * @brief Remove element at the given index in the linked list, do nothing on error. + * + * @param linked_list Pointer to a linked list + * @param index Index of the element +*/ +void linked_list_remove(linked_list_t *linked_list, const size_t index); + +/** + * @brief Return first element that the condition verify + * + * @param linked_list Pointer to a linked list + * @param condition Condition to verify + * @param ... Argument to pass to the condition + * + * @return Element, NULL if no element verify the condition or if an error ocurred. +*/ +elem_t *linked_list_get_elem_if(const linked_list_t *linked_list, const condition_t condition, ...); + +/** + * @brief Return data in the first element that the condition verify + * + * @param linked_list Pointer to a linked list + * @param condition Condition to verify + * @param ... Argument to pass to the condition + * + * @return Element data, NULL if no element verify the condition or if an error ocurred. +*/ +void *linked_list_get_if(const linked_list_t *linked_list, const condition_t condition, ...); + +/** + * @brief Remove every elements that the condition verify, do nothing on error. + * + * @param linked_list Pointer to an linked list + * @param condition Condition to verify + * @param ... Argument to pass to the condition +*/ +void linked_list_remove_if(linked_list_t *linked_list, const condition_t condition, ...); + +/** + * @brief Apply an action to every elements in the list. + * Useful for changing a value in every single element data. + * The action can be anything that doesn't destroy the element. + * + * @param linked_list Pointer to an linked list + * @param action Action to apply + * @param ... Argument to pass to the action +*/ +void linked_list_for_each(const linked_list_t *linked_list, const action_t action, ...); + +#endif // LINKED_LIST_H diff --git a/src/headers/memory_alloc.h b/src/headers/memory_alloc.h new file mode 100644 index 0000000..ef8e8b6 --- /dev/null +++ b/src/headers/memory_alloc.h @@ -0,0 +1,6 @@ +#ifndef MEMORY_ALLOC_H +#define MEMORY_ALLOC_H + +#include + +#endif // MEMORY_ALLOC_H \ No newline at end of file diff --git a/src/headers/vector2d.h b/src/headers/vector2d.h new file mode 100644 index 0000000..67802a4 --- /dev/null +++ b/src/headers/vector2d.h @@ -0,0 +1,133 @@ +#ifndef VECTOR2D_H +#define VECTOR2D_H + +#include +#include + +/** + * @brief Point struct. (int) + * + * @param x X pos + * @param y Y pos +*/ +typedef SDL_Point vector2d_t; + +/** + * @brief Point struct. (float) + * + * @param x X pos + * @param y Y pos +*/ +typedef SDL_FPoint fvector2d_t; + +/** + * @brief Rectangle struct. (int) + * + * @param x X pos + * @param y Y pos + * @param w Width + * @param h Height +*/ +typedef SDL_Rect rect_t; + +/** + * @brief Rectangle struct. (float) + * + * @param x X pos + * @param y Y pos + * @param w Width + * @param h Height +*/ +typedef SDL_FRect frect_t; + +#define EPSILON 0.000001f + +#define f_is_zero(X) (fabsf(X) <= EPSILON) + +#define f_is_not_zero(X) (fabsf(X) > EPSILON) + +void rect_to_frect(const rect_t *rect, frect_t *frect); + +void frect_to_rect(const frect_t *frect, rect_t *rect); + +/** + * @brief Verify if a point is in a rectangle. (int) + * + * @param P Vector2d + * @param R Rectangle + * + * @return True if the point is in the rectangle, else false. +*/ +#define point_in_rect(P, R) SDL_PointInRect(P, R) + +/** + * @brief Verify if a point is in a rectangle. (float) + * + * @param P Vector2d + * @param R Rectangle + * + * @return True if the point is in the rectangle, else false. +*/ +#define fpoint_in_frect(P, R) SDL_PointInRectF(P, R) + +/** + * @brief Verify if a rectangle is empty + * + * @param R Rectangle + * + * @return True if the rectangle is empty, else false. +*/ +#define rect_empty(R) SDL_RectEmpty(R) + +/** + * @brief Verify if a rectangle is empty + * + * @param R Rectangle + * + * @return True if the rectangle is empty, else false. +*/ +#define frect_empty(R) SDL_FRectEmpty(R) + +/** + * @brief Verify if there is a intersction between two rectangles. (int) + * + * @param A Rectangle A + * @param B Rectangle B + * + * @return True if there is an intersection, else false. +*/ +#define has_intersection(A, B) SDL_HasIntersection(A, B) + +/** + * @brief Verify if there is a intersction between two rectangles. (float) + * + * @param A Rectangle A + * @param B Rectangle B + * + * @return True if there is an intersection, else false. +*/ +#define fhas_intersection(A, B) SDL_HasIntersectionF(A, B) + +/** + * @brief Verify if there is an intersection between two rectangles and get the intersection rectangle. (int) + * + * @param A Rectangle A + * @param B Rectangle B + * @param result The intersection rectangle + * + * @return True if there is an intersection, else false. +*/ +#define intersect_rect(A, B, result) SDL_IntersectRect(A, B, result) + +/** + * @brief Verify if there is an intersection between two rectangles and get the intersection rectangle. (float) + * + * @param A Rectangle A + * @param B Rectangle B + * @param result The intersection rectangle + * + * @return True if there is an intersection, else false. +*/ +#define intersect_frect(A, B, result) SDL_IntersectFRect(A, B, result) + +#endif // VECTOR2D_H \ No newline at end of file diff --git a/src/linked_list.c b/src/linked_list.c new file mode 100644 index 0000000..6d7cf42 --- /dev/null +++ b/src/linked_list.c @@ -0,0 +1,377 @@ +#include +#include "memory_alloc.h" +#include "linked_list.h" + +elem_t *elem_create(const linked_list_t *linked_list) +{ + elem_t *tmp; + tmp = malloc(sizeof(elem_t)); + if(!tmp) return NULL; + + tmp->data = malloc(linked_list->data_size); + if(!tmp->data) + { + free(tmp); + return NULL; + } + + return tmp; +} + +inline void destroy_elem(elem_t *elem, const deleter_t elem_deleter) +{ + if(!elem) return; + + if(elem_deleter) + elem_deleter(elem->data); + else + free(elem->data); + + free(elem); +} + +void linked_list_init(linked_list_t *linked_list, const size_t data_size, const deleter_t elem_deleter) +{ + linked_list->first = NULL; + linked_list->last = NULL; + linked_list->size = 0; + + linked_list->data_size = data_size; + linked_list->elem_deleter = elem_deleter; +} + +void linked_list_push_back_elem(linked_list_t *linked_list, elem_t *elem) +{ + if(!elem) return; + + elem->prev = linked_list->last; + elem->next = NULL; + + if(linked_list->last) + linked_list->last->next = elem; + else + linked_list->first = elem; + + linked_list->last = elem; + + linked_list->size++; +} + +void linked_list_push_front_elem(linked_list_t *linked_list, elem_t *elem) +{ + if(!elem) return; + + elem->next = linked_list->first; + elem->prev = NULL; + + if(linked_list->first) + linked_list->first->prev = elem; + else + linked_list->last = elem; + + linked_list->first = elem; + + linked_list->size++; +} + +void linked_list_push_back(linked_list_t *linked_list, void *data) +{ + elem_t *tmp = malloc(sizeof(elem_t)); + if(!tmp) return; + tmp->data = data; + + linked_list_push_back_elem(linked_list, tmp); +} + +void linked_list_push_front(linked_list_t *linked_list, void *data) +{ + elem_t *tmp = malloc(sizeof(elem_t)); + if(!tmp) return; + tmp->data = data; + + linked_list_push_front_elem(linked_list, tmp); +} + +void linked_list_pop_back(linked_list_t *linked_list) +{ + elem_t *tmp = linked_list->last; + if(!tmp) return; + + linked_list->last = tmp->prev; + + if(linked_list->last) + linked_list->last->next = NULL; + else + linked_list->first = NULL; + + destroy_elem(tmp, linked_list->elem_deleter); + + linked_list->size--; +} + +void linked_list_pop_front(linked_list_t *linked_list) +{ + elem_t *tmp = linked_list->first; + if(!tmp) return; + + linked_list->first = tmp->next; + + if(linked_list->first) + linked_list->first->prev = NULL; + else + linked_list->last = NULL; + + destroy_elem(tmp, linked_list->elem_deleter); + + linked_list->size--; +} + +void linked_list_clear(linked_list_t *linked_list) +{ + elem_t *actual_elem = linked_list->first; + elem_t *tmp; + + while(actual_elem) + { + tmp = actual_elem; + + actual_elem = actual_elem->next; + + destroy_elem(tmp, linked_list->elem_deleter); + } + + linked_list->first = NULL; + linked_list->last = NULL; + + linked_list->size = 0; +} + +inline bool linked_list_is_empty(const linked_list_t *linked_list) +{ + return !linked_list->first; +} + +inline bool linked_list_is_in_bound(const linked_list_t *linked_list, size_t index) +{ + return index < linked_list->size; +} + +elem_t *linked_list_get_elem(const linked_list_t *linked_list, size_t index) +{ + if(!linked_list_is_in_bound(linked_list, index)) return NULL; + + if(index == 0) + return linked_list->first; + if(index == linked_list->size - 1) + return linked_list->last; + + elem_t *actual_elem = linked_list->first; + if(!actual_elem) return NULL; + + for (size_t i = 0; i < index; i++) + { + actual_elem = actual_elem->next; + } + + return actual_elem; +} + +void *linked_list_get(const linked_list_t *linked_list, size_t index) +{ + elem_t *tmp = linked_list_get_elem(linked_list, index); + if(!tmp) return NULL; + return tmp->data; +} + +void linked_list_insert_elem(linked_list_t *linked_list, elem_t *elem, size_t index) +{ + if(!elem) return; + if(!linked_list_is_in_bound(linked_list, index)) return; + + if(index == 0) + { + linked_list_push_front_elem(linked_list, elem); + } + else if(index == (linked_list->size - 1)) + { + linked_list_push_back_elem(linked_list, elem); + } + else + { + elem_t *next_insert_elem = linked_list_get_elem(linked_list, index); + elem_t *prev_insert_elem = next_insert_elem->prev; + + elem->prev = prev_insert_elem; + elem->next = next_insert_elem; + + prev_insert_elem->next = elem; + next_insert_elem->prev = elem; + + linked_list->size++; + } +} + +void linked_list_insert(linked_list_t *linked_list, void *data, size_t index) +{ + elem_t *tmp = malloc(sizeof(elem_t)); + if(!tmp) return; + tmp->data = data; + + linked_list_insert_elem(linked_list, tmp, index); +} + +void linked_list_remove_elem(linked_list_t *linked_list, elem_t *elem) +{ + if(!elem) return; + + if(elem == linked_list->first) + { + linked_list_pop_front(linked_list); + } + else if(elem == linked_list->last) + { + linked_list_pop_back(linked_list); + } + else + { + elem_t *prev_insert_elem = elem->prev; + elem_t *next_insert_elem = elem->next; + + prev_insert_elem->next = next_insert_elem; + next_insert_elem->prev = prev_insert_elem; + + destroy_elem(elem, linked_list->elem_deleter); + + linked_list->size--; + } +} + +void linked_list_remove(linked_list_t *linked_list, size_t index) +{ + elem_t *tmp = linked_list_get_elem(linked_list, index); + if(tmp) linked_list_remove_elem(linked_list, tmp); +} + +elem_t *linked_list_get_elem_if(const linked_list_t *linked_list, const condition_t condition, ...) +{ + if(!condition) return NULL; + + va_list args; + va_start(args, condition); + + elem_t *actual_elem = linked_list->first; + elem_t *next_elem; + + while(actual_elem) + { + next_elem = actual_elem->next; + + va_list args_copy; + va_copy(args_copy, args); + + if(condition(actual_elem, args_copy)) + { + va_end(args_copy); + va_end(args); + + return actual_elem; + } + + va_end(args_copy); + + actual_elem = next_elem; + } + + va_end(args); + + return NULL; +} + +void *linked_list_get_if(const linked_list_t *linked_list, const condition_t condition, ...) +{ + if(!condition) return NULL; + + va_list args; + va_start(args, condition); + + elem_t *actual_elem = linked_list->first; + elem_t *next_elem; + + while(actual_elem) + { + next_elem = actual_elem->next; + + va_list args_copy; + va_copy(args_copy, args); + + if(condition(actual_elem, args_copy)) + { + va_end(args_copy); + va_end(args); + + return actual_elem->data; + } + + va_end(args_copy); + + actual_elem = next_elem; + } + + va_end(args); + + return NULL; +} + +void linked_list_remove_if(linked_list_t *linked_list, const condition_t condition, ...) +{ + if(!condition) return; + + va_list args; + va_start(args, condition); + + elem_t *actual_elem = linked_list->first; + elem_t *next_elem; + + while(actual_elem) + { + next_elem = actual_elem->next; + + va_list args_copy; + va_copy(args_copy, args); + + if(condition(actual_elem, args_copy)) + { + linked_list_remove_elem(linked_list, actual_elem); + } + + va_end(args_copy); + + actual_elem = next_elem; + } + + va_end(args); +} + +void linked_list_for_each(const linked_list_t *linked_list, const action_t action, ...) +{ + if(!action) return; + + va_list args; + va_start(args, action); + + elem_t *actual_elem = linked_list->first; + + while(actual_elem) + { + va_list args_copy; + va_copy(args_copy, args); + + action(actual_elem, args_copy); + + va_end(args_copy); + + actual_elem = actual_elem->next; + } + + va_end(args); +} diff --git a/src/vector2d.c b/src/vector2d.c new file mode 100644 index 0000000..17fe128 --- /dev/null +++ b/src/vector2d.c @@ -0,0 +1,17 @@ +#include "vector2d.h" + +void rect_to_frect(const rect_t *rect, frect_t *frect) +{ + frect->x = (float)rect->x; + frect->y = (float)rect->y; + frect->w = (float)rect->w; + frect->h = (float)rect->h; +} + +void frect_to_rect(const frect_t *frect, rect_t *rect) +{ + rect->x = (int)frect->x; + rect->y = (int)frect->y; + rect->w = (int)frect->w; + rect->h = (int)frect->h; +}