Compiling with ncurses.
This commit is contained in:
parent
0ef33e0b09
commit
1821d20923
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,213 @@
|
|||
#include "asset_manager.h"
|
||||
|
||||
#include <ncurses.h>
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#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)
|
||||
{
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
#include "display.h"
|
||||
|
||||
#include <ncurses.h>
|
||||
#include <stdio.h>
|
||||
|
||||
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();
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#include "event.h"
|
||||
|
||||
inline int pollevent(event_t *event)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef ASSET_MANAGER_H
|
||||
#define ASSET_MANAGER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#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
|
||||
|
|
@ -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
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
#ifndef KEYBOARD_H
|
||||
#define KEYBOARD_H
|
||||
|
||||
#include <ncurses.h>
|
||||
|
||||
#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
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
#ifndef KEYCODES_H
|
||||
#define KEYCODES_H
|
||||
|
||||
#include <ncurses.h>
|
||||
|
||||
#define MAX_KEYCODES KEY_MAX - KEY_MIN
|
||||
|
||||
#endif // KEYCODES_H
|
||||
|
|
@ -0,0 +1,288 @@
|
|||
#ifndef LINKED_LIST_H
|
||||
#define LINKED_LIST_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
/**
|
||||
* @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
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef MEMORY_ALLOC_H
|
||||
#define MEMORY_ALLOC_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#endif // MEMORY_ALLOC_H
|
||||
|
|
@ -0,0 +1,133 @@
|
|||
#ifndef VECTOR2D_H
|
||||
#define VECTOR2D_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <SDL2/SDL_rect.h>
|
||||
|
||||
/**
|
||||
* @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
|
||||
|
|
@ -0,0 +1,377 @@
|
|||
#include <stdarg.h>
|
||||
#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);
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
Loading…
Reference in New Issue