diff --git a/.ccls b/.ccls index b08d5af..839952d 100644 --- a/.ccls +++ b/.ccls @@ -1 +1,3 @@ -gcc \ No newline at end of file +gcc +# Macros +-DDEBUG=2 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 0c38e9d..152c44d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ .vscode/ccls-cache -.cache -.config +config.mk build diff --git a/Makefile b/Makefile index ea2d679..820687f 100644 --- a/Makefile +++ b/Makefile @@ -1,12 +1,41 @@ SHELL = /usr/bin/env bash -# Build folder -BUILD_DIR = build +ROOT := $(realpath $(dir $(lastword $(MAKEFILE_LIST)))) -# Outputs target name and path -SOURCE_OUTPUT = $(BUILD_DIR)/2D_Engine -CORE_OUTPUT = $(BUILD_DIR)/libcore.a -ASSET_OUTPUT = $(BUILD_DIR)/game.data +ifneq ($(realpath $(ROOT)/config.mk), $(ROOT)/config.mk) +$(error ERROR: Please run the configure script before building.) +endif + +include $(ROOT)/config.mk + +# +# User config +# + +BUILD_DIR_NAME = build + +SOURCE_DIR = src +CORE_DIR = core +HOST_DIR = host + +OUTPUT = 2D_Engine +ASSET_OUTPUT = game.data + +ifneq ($(DEBUG),) +CFLAGS += -O1 -g -DDEBUG=$(DEBUG) -Wextra -Wall --pedantic -Wno-missing-braces \ + -Wno-missing-field-initializers -Wformat=2 -Wswitch-default -Wswitch \ + -Wcast-align -Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 \ + -Wstrict-prototypes -Winline -Wundef -Wnested-externs -Wcast-qual \ + -Wshadow -Wunreachable-code -Wlogical-op -Wfloat-equal -Wstrict-aliasing=2 \ + -Wredundant-decls -Wold-style-definition +endif + +# +# End +# + +# Relocate build dir +BUILD_DIR := $(ROOT)/$(BUILD_DIR_NAME)/$(HOST) # Verbosity Q := @ @@ -15,33 +44,26 @@ Q := endif # Colors -export GREEN := \033[32m -export YELLOW := \033[33m -export RESET := \033[m +GREEN := \033[32m +YELLOW := \033[33m +RESET := \033[m # Default targets -all: $(SOURCE_OUTPUT) +all: setup $(BUILD_DIR)/$(OUTPUT) -# Sub Makefiles -SOURCE_DIR = src -CORE_DIR = core/src -ASSETS_DIR = assets +include $(ROOT)/$(SOURCE_DIR)/Makefile +include $(ROOT)/$(CORE_DIR)/Makefile -include $(SOURCE_DIR)/Makefile -include $(CORE_DIR)/Makefile -include $(ASSETS_DIR)/Makefile +setup: + $(eval export TOTAL_BUILD_FILES := $(shell echo $$(($$(make -n $(OBJECTS) $(CORE_OBJECTS) 2>/dev/null | grep -c $(CC)) + 2)))) + $(Q)mkdir -p $(dir $(OBJECTS) $(CORE_OBJECTS)) -# Clean -.PHONY: clean +.PHONY: clean run print-var-% clean: - $(Q)rm -rf $(BUILD_DIR) - @echo "Build dir cleaned" + $(Q)rm -rf $(dir $(BUILD_DIR)) -# Run executable -.PHONY: run run: all - $(Q)cd $(BUILD_DIR) && ./$(notdir $(SOURCE_OUTPUT)) + $(Q)cd $(BUILD_DIR) && ./$(OUTPUT) -.PHONY: print-% -print-% : +print-var-% : @echo $($*) diff --git a/assets/Makefile b/assets/Makefile index 7a5051d..b6afc74 100644 --- a/assets/Makefile +++ b/assets/Makefile @@ -13,7 +13,6 @@ ASSETS := $(addprefix $(ASSETS_DIR)/,$(ASSETS)) ASSETS_OBJECTS = $(ASSETS:%=$(BUILD_DIR)/%.o) - ASSET_BUILDER_DIR = $(ASSETS_DIR)/asset_builder/src ASSET_BUILDER_OUTPUT = $(BUILD_DIR)/$(ASSETS_DIR)/asset_builder/asset_builder include $(ASSET_BUILDER_DIR)/Makefile diff --git a/assets/asset_builder/src/.ccls b/assets/asset_builder/.ccls similarity index 73% rename from assets/asset_builder/src/.ccls rename to assets/asset_builder/.ccls index 767e25a..bc24403 100644 --- a/assets/asset_builder/src/.ccls +++ b/assets/asset_builder/.ccls @@ -1,7 +1,7 @@ gcc # Headers -Iassets/asset_builder/src/headers --Isrc/components/headers +-Isrc/components # Macros -DDEBUG=2 diff --git a/assets/asset_builder/src/Makefile b/assets/asset_builder/Makefile similarity index 100% rename from assets/asset_builder/src/Makefile rename to assets/asset_builder/Makefile diff --git a/assets/asset_builder/src/errors.h b/assets/asset_builder/errors.h similarity index 100% rename from assets/asset_builder/src/errors.h rename to assets/asset_builder/errors.h diff --git a/assets/asset_builder/src/image.c b/assets/asset_builder/image.c similarity index 100% rename from assets/asset_builder/src/image.c rename to assets/asset_builder/image.c diff --git a/assets/asset_builder/src/image.h b/assets/asset_builder/image.h similarity index 100% rename from assets/asset_builder/src/image.h rename to assets/asset_builder/image.h diff --git a/assets/asset_builder/src/main.c b/assets/asset_builder/main.c similarity index 100% rename from assets/asset_builder/src/main.c rename to assets/asset_builder/main.c diff --git a/assets/asset_builder/src/map.c b/assets/asset_builder/map.c similarity index 100% rename from assets/asset_builder/src/map.c rename to assets/asset_builder/map.c diff --git a/assets/asset_builder/src/map.h b/assets/asset_builder/map.h similarity index 100% rename from assets/asset_builder/src/map.h rename to assets/asset_builder/map.h diff --git a/assets/asset_builder/src/object.c b/assets/asset_builder/object.c similarity index 100% rename from assets/asset_builder/src/object.c rename to assets/asset_builder/object.c diff --git a/assets/asset_builder/src/object.h b/assets/asset_builder/object.h similarity index 100% rename from assets/asset_builder/src/object.h rename to assets/asset_builder/object.h diff --git a/assets/asset_builder/src/utils.c b/assets/asset_builder/utils.c similarity index 100% rename from assets/asset_builder/src/utils.c rename to assets/asset_builder/utils.c diff --git a/assets/asset_builder/src/utils.h b/assets/asset_builder/utils.h similarity index 100% rename from assets/asset_builder/src/utils.h rename to assets/asset_builder/utils.h diff --git a/configure b/configure index 16cd580..e7b4f05 100755 --- a/configure +++ b/configure @@ -10,9 +10,7 @@ # Project settings no matter current and target hosts # -#CACHE_DIR=".cache" -#LIB_DIR="lib" -#CONFIG_FILE=".config" +CONFIG_FILE="config.mk" #LUA_VERSION="5.5.1" #LUA_CHECKSUM="1c4b4068d67061f2a2231ad2b5422e77acea1487ea9890f6320af614f4373dce" @@ -21,11 +19,6 @@ # Main # -### Setup dirs and logs -# -## Cache dir -#mkdir -p "${CACHE_DIR}" - print_error() { echo -e "\033[31merror\033[m: $1" @@ -77,8 +70,7 @@ done ## Clean if [ -n "${CLEAN}" ]; then make clean - rm -rf .config .cache lib - echo "Cleaned project." + rm -rf ${CONFIG_FILE} fi if [ -n "${EXIT_AFTER_CLEAN}" ]; then @@ -118,6 +110,55 @@ esac echo +if [ "${CURRENT_HOST}" != "${TARGET_HOST}" ]; then + CROSS_COMPILE=TRUE +fi + +if [ -n "${CROSS_COMPILE}" ]; then + case "${TARGET_HOST}" in + fxcg50) + case "${CURRENT_HOST}" in + linux) + ;; + *) + print_error "Cross compiling from ${CURRENT_HOST} for ${TARGET_HOST} is not supported yet." + ;; + esac + + CC="sh-elf-gcc" + AR="sh-elf-ar" + LIBCORE="libcore.a" + ;; + esac +else + case "${TARGET_HOST}" in + linux) + CC="gcc" + AR="ar" + CFLAGS="--std=c17 -Os -DASSET_FILE_NAME=\\\"\$(notdir \$(ASSET_OUTPUT))\\\" -D_GNU_SOURCE=1 \$(shell pkg-config --cflags sdl3)" + LDFLAGS="\$(shell pkg-config --libs sdl3) -lm" + + LIBCORE="libcore.a" + ;; + *) + ;; + esac +fi + +echo "Writing config file." +echo +echo "${CONFIG_FILE}:" +echo "\`\`\`" +echo "HOST = ${TARGET_HOST}" | tee ${CONFIG_FILE} +echo | tee -a ${CONFIG_FILE} +echo "CC = ${CC}" | tee -a ${CONFIG_FILE} +echo "AR = ${AR}" | tee -a ${CONFIG_FILE} +echo "CFLAGS = ${CFLAGS}" | tee -a ${CONFIG_FILE} +echo "LDFLAGS = ${LDFLAGS}" | tee -a ${CONFIG_FILE} +echo | tee -a ${CONFIG_FILE} +echo "LIBCORE = ${LIBCORE}" | tee -a ${CONFIG_FILE} +echo "\`\`\`" + # ### Download libs #echo "===== downloading lua =====" diff --git a/core/.ccls b/core/.ccls new file mode 100644 index 0000000..30de0d0 --- /dev/null +++ b/core/.ccls @@ -0,0 +1,8 @@ +gcc +# Headers +-Icore +-Icore/host/generic +-Isrc/components + +# Macros +-DASSET_FILE_NAME="$(make print-var-ASSET_OUTPUT)" diff --git a/core/Makefile b/core/Makefile new file mode 100644 index 0000000..a78084c --- /dev/null +++ b/core/Makefile @@ -0,0 +1,31 @@ +CORE_SOURCES += \ + main.c \ + camera.c \ + linked_list.c \ + event_bus.c \ + ecs.c \ + asset_manager.c \ + inputs.c \ + map.c + +CORE_INCLUDES += \ + $(CORE_DIR) \ + $(CORE_DIR)/$(HOST_DIR)/$(HOST) \ + $(SOURCE_DIR)/components + +include $(ROOT)/$(CORE_DIR)/$(HOST_DIR)/$(HOST)/Makefile +CORE_OBJECTS := $(CORE_SOURCES:%=$(BUILD_DIR)/$(CORE_DIR)/%.o) + +$(BUILD_DIR)/$(LIBCORE): $(CORE_OBJECTS) + $(eval CURRENT_FILE := $(shell echo $$(($(CURRENT_FILE) + 1)))) + $(eval PERCENTAGE := $(shell echo $$(($(CURRENT_FILE) * 100 / $(TOTAL_BUILD_FILES))))) + @echo -e "[$(PERCENTAGE)%] $(YELLOW)Creating Static Lib $@$(RESET)" + $(Q)$(AR) rcs $@ $(CORE_OBJECTS) + +$(BUILD_DIR)/$(CORE_DIR)/%.c.o: $(ROOT)/$(CORE_DIR)/%.c + $(eval CURRENT_FILE := $(shell echo $$(($(CURRENT_FILE) + 1)))) + $(eval PERCENTAGE := $(shell echo $$(($(CURRENT_FILE) * 100 / $(TOTAL_BUILD_FILES))))) + @echo -e "[$(PERCENTAGE)%] $(GREEN)Building C object $@$(RESET)" + $(Q)$(CC) $(CFLAGS) $(CORE_INCLUDES:%=-I%) -MMD -MP -c $< -o $@ + +-include $(CORE_OBJECTS:.o=.d) diff --git a/core/src/asset_manager.c b/core/asset_manager.c similarity index 96% rename from core/src/asset_manager.c rename to core/asset_manager.c index b6e0083..56cc655 100644 --- a/core/src/asset_manager.c +++ b/core/asset_manager.c @@ -102,10 +102,13 @@ int asset_manager_exit(void) if(linked_list_exit(&game.asset_manager.assets_header_defs)) return_failure_int; if(linked_list_exit(&game.asset_manager.assets)) return_failure_int; - if(fclose(game.asset_manager.asset_file)) + if(game.asset_manager.asset_file) { - error_printf("Failed to close asset file : %d", errno); - return EXIT_FAILURE; + if(fclose(game.asset_manager.asset_file)) + { + error_printf("Failed to close asset file : %d", errno); + return EXIT_FAILURE; + } } debug_printf("Exited asset manager."); diff --git a/core/src/asset_manager.h b/core/asset_manager.h similarity index 100% rename from core/src/asset_manager.h rename to core/asset_manager.h diff --git a/core/src/camera.c b/core/camera.c similarity index 100% rename from core/src/camera.c rename to core/camera.c diff --git a/core/src/camera.h b/core/camera.h similarity index 100% rename from core/src/camera.h rename to core/camera.h diff --git a/core/src/ecs.c b/core/ecs.c similarity index 100% rename from core/src/ecs.c rename to core/ecs.c diff --git a/core/src/ecs.h b/core/ecs.h similarity index 100% rename from core/src/ecs.h rename to core/ecs.h diff --git a/core/src/errors.h b/core/errors.h similarity index 79% rename from core/src/errors.h rename to core/errors.h index 9b5805b..f02d1d3 100644 --- a/core/src/errors.h +++ b/core/errors.h @@ -16,7 +16,20 @@ fputc('\n', stderr); \ } while (0) -#define return_failure_int \ +#define warning_printf(...) \ + do { \ + fprintf(stderr, "\033[35mWARNING\033[m: " __VA_ARGS__); \ + fputc('\n', stderr); \ + } while (0) + +#define error_printf(...) \ + do { \ + fprintf(stderr, "\033[31mERROR\033[m: %s:%d:%s(): ", __FILE__, __LINE__, __func__); \ + fprintf(stderr, __VA_ARGS__); \ + fputc('\n', stderr); \ + } while (0) + + #define return_failure_int \ do { \ fprintf(stderr, "\tin %s:%d:%s()\n", __FILE__, __LINE__, __func__); \ return EXIT_FAILURE; \ @@ -36,11 +49,6 @@ #else #define debug_printf(...) -#define return_failure_int return EXIT_FAILURE; -#define return_failure_ptr return NULL; -#define goto_failure goto failure; -#endif - #define warning_printf(...) \ do { \ fprintf(stderr, "\033[35mWARNING\033[m: " __VA_ARGS__); \ @@ -49,9 +57,13 @@ #define error_printf(...) \ do { \ - fprintf(stderr, "\033[31mERROR\033[m: %s:%d:%s(): ", __FILE__, __LINE__, __func__); \ - fprintf(stderr, __VA_ARGS__); \ + fprintf(stderr, "\033[31mERROR\033[m: " __VA_ARGS__); \ fputc('\n', stderr); \ } while (0) +#define return_failure_int return EXIT_FAILURE; +#define return_failure_ptr return NULL; +#define goto_failure goto failure; +#endif + #endif // ERRORS_H \ No newline at end of file diff --git a/core/src/event_bus.c b/core/event_bus.c similarity index 100% rename from core/src/event_bus.c rename to core/event_bus.c diff --git a/core/src/event_bus.h b/core/event_bus.h similarity index 100% rename from core/src/event_bus.h rename to core/event_bus.h diff --git a/core/src/game.h b/core/game.h similarity index 100% rename from core/src/game.h rename to core/game.h diff --git a/core/host/fxcg50/vector2d.c b/core/host/fxcg50/vector2d.c new file mode 100644 index 0000000..aa43058 --- /dev/null +++ b/core/host/fxcg50/vector2d.c @@ -0,0 +1,163 @@ +#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; +} + +inline bool point_in_rect(const vector2d_t *p, const rect_t *r) +{ + return (p && r && (p->x >= r->x) && (p->x < (r->x + r->w)) && (p->y >= r->y) && (p->y < (r->y + r->h))); +} + +inline bool fpoint_in_rect(const fvector2d_t *p, const frect_t *r) +{ + return (p && r && (p->x >= r->x) && (p->x < (r->x + r->w)) && (p->y >= r->y) && (p->y < (r->y + r->h))); +} + +inline bool rect_empty(const rect_t *r) +{ + return ((!r) || (r->w <= 0) || (r->h <= 0)); +} + +inline bool frect_empty(const frect_t *r) +{ + return ((!r) || (r->w <= 0) || (r->h <= 0)); +} + +inline bool has_intersection(const rect_t *a, const rect_t *b) +{ + int amin, amax, bmin, bmax; + + // Horizontal intersection + amin = a->x; + amax = amin + a->w; + bmin = b->x; + bmax = bmin + b->w; + if(bmin > amin) amin = bmin; + if(bmax < amax) amax = bmax; + + if((amax - EPSILON) < amin) return false; + + // Vertical intersection + amin = a->y; + amax = amin + a->h; + bmin = b->y; + bmax = bmin + b->h; + if(bmin > amin) amin = bmin; + if(bmax < amax) amax = bmax; + + if((amax - EPSILON) < amin) return false; + + return true; +} + +inline bool fhas_intersection(const frect_t *a, const frect_t *b) +{ + float amin, amax, bmin, bmax; + + // Horizontal intersection + amin = a->x; + amax = amin + a->w; + bmin = b->x; + bmax = bmin + b->w; + if(bmin > amin) amin = bmin; + if(bmax < amax) amax = bmax; + + if((amax - EPSILON) < amin) return false; + + // Vertical intersection + amin = a->y; + amax = amin + a->h; + bmin = b->y; + bmax = bmin + b->h; + if(bmin > amin) amin = bmin; + if(bmax < amax) amax = bmax; + + if((amax - EPSILON) < amin) return false; + + return true; +} + +inline bool intersect_rect(const rect_t *a, const rect_t *b, rect_t *result) +{ + int amin, amax, bmin, bmax; + + // Horizontal intersection + amin = a->x; + amax = amin + a->w; + bmin = a->x; + bmax = bmin + a->w; + if (bmin > amin) amin = bmin; + result->x = amin; + if (bmax < amax) amax = bmax; + result->w = amax - amin; + + // Vertical intersection + amin = a->y; + amax = amin + a->h; + bmin = b->y; + bmax = bmin + b->h; + if (bmin > amin) amin = bmin; + result->y = amin; + if (bmax < amax) amax = bmax; + result->h = amax - amin; + + return !rect_empty(result); +} + +inline bool intersect_frect(const frect_t *a, const frect_t *b, frect_t *result) +{ + float Amin, Amax, Bmin, Bmax; + + // Horizontal intersection + Amin = a->x; + Amax = Amin + a->w; + Bmin = a->x; + Bmax = Bmin + a->w; + if (Bmin > Amin) { + Amin = Bmin; + } + result->x = Amin; + if (Bmax < Amax) { + Amax = Bmax; + } + result->w = Amax - Amin; + + // Vertical intersection + Amin = a->y; + Amax = Amin + a->h; + Bmin = b->y; + Bmax = Bmin + b->h; + if (Bmin > Amin) { + Amin = Bmin; + } + result->y = Amin; + if (Bmax < Amax) { + Amax = Bmax; + } + result->h = Amax - Amin; + + return !frect_empty(result); +} + +inline float lerp(float a, float b, float s) +{ + return a * (1 - s) + b * s; +} + +inline float lerp_time(float a, float b, float s, float t) +{ + return lerp(a, b, 1 - powf(1 - s, t * 60.0f)); +} \ No newline at end of file diff --git a/core/host/fxcg50/vector2d.h b/core/host/fxcg50/vector2d.h new file mode 100644 index 0000000..81a5c2d --- /dev/null +++ b/core/host/fxcg50/vector2d.h @@ -0,0 +1,163 @@ +#ifndef VECTOR2D_H +#define VECTOR2D_H + +#include +#include + +/** + * @brief Point struct. (int) + * + * @param x X pos + * @param y Y pos +*/ +typedef struct vector2d_t { + int x, y; +} vector2d_t; + +/** + * @brief Point struct. (float) + * + * @param x X pos + * @param y Y pos +*/ +typedef struct fvector2d_t { + float x, y; +} fvector2d_t; + +/** + * @brief Rectangle struct. (int) + * + * @param x X pos + * @param y Y pos + * @param w Width + * @param h Height +*/ +typedef struct rect_t { + int x, y; + int w, h; +} rect_t; + +/** + * @brief Rectangle struct. (float) + * + * @param x X pos + * @param y Y pos + * @param w Width + * @param h Height +*/ +typedef struct frect_t { + float x, y; + float w, h; +} frect_t; + +#define EPSILON 0.0f + +#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. +*/ +bool point_in_rect(const vector2d_t *p, const rect_t *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. +*/ +bool fpoint_in_rect(const fvector2d_t *p, const frect_t *r); + +/** + * @brief Verify if a rectangle is empty + * + * @param r Rectangle + * + * @return True if the rectangle is empty, else false. +*/ +bool rect_empty(const rect_t *r); + +/** + * @brief Verify if a rectangle is empty + * + * @param r Rectangle + * + * @return True if the rectangle is empty, else false. +*/ +bool frect_empty(const frect_t *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. +*/ +bool has_intersection(const rect_t *a, const rect_t *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. +*/ +bool fhas_intersection(const frect_t *a, const frect_t *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. +*/ +bool intersect_rect(const rect_t *a, const rect_t *b, rect_t *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. +*/ +bool intersect_frect(const frect_t *a, const frect_t *b, frect_t *result); + +/** + * @brief Lerp a to b with smoothing factor s. + * + * @param a Current value + * @param b Target value + * @param s Smoothing factor + */ +float lerp(float a, float b, float s); + +/** + * @brief Lerp a to b with smoothing factor s and time basis t. + * Smoothing factor is for 60 fps call time. + * + * @param a Current value + * @param b Target value + * @param s Smoothing factor + * @param t Delta time + */ +float lerp_time(float a, float b, float s, float t); + +#endif // VECTOR2D_H \ No newline at end of file diff --git a/core/host/generic/display.c b/core/host/generic/display.c deleted file mode 100644 index e69de29..0000000 diff --git a/core/host/generic/display.h b/core/host/generic/display.h index e69de29..6ab412f 100644 --- a/core/host/generic/display.h +++ b/core/host/generic/display.h @@ -0,0 +1,31 @@ +#ifndef DISPLAY_H +#define DISPLAY_H + +#include "texture.h" +#include "vector2d.h" + +#define C_BLACK 0, 0, 0 +#define C_RED 255, 0, 0 +#define C_GREEN 0, 255, 0 +#define C_BLUE 0, 0, 255 +#define C_WHITE 255, 255, 255 + +#define DISPLAY_WIDTH 720 +#define DISPLAY_HEIGHT 480 + +//#define DRIVERS NULL +#define DRIVERS "vulkan,gpu,software" + +typedef struct display_t { +} display_t; + +int display_init(void); +void display_exit(void); + +int display_clear(void); +int display_update(void); + +int display_draw_texture(texture_t *texture, const rect_t *src_rect, const rect_t *dst_rect, bool flip); +int display_draw_frect(const frect_t *frect, unsigned int r, unsigned int g, unsigned int b, unsigned int a); + +#endif // DISPLAY_H \ No newline at end of file diff --git a/core/src/memory_alloc.h b/core/host/generic/memory_alloc.h similarity index 100% rename from core/src/memory_alloc.h rename to core/host/generic/memory_alloc.h diff --git a/core/host/generic/texture.h b/core/host/generic/texture.h new file mode 100644 index 0000000..b71c4dd --- /dev/null +++ b/core/host/generic/texture.h @@ -0,0 +1,14 @@ +#ifndef TEXTURE_H +#define TEXTURE_H + +#define TEXTURE_TRANSPARENT_COLOR 0x0001 + +typedef struct texture_t texture_t; + +#define get_width(T) 1 +#define get_height(T) 1 + +texture_t *load_texture(void); +void destroy_texture(texture_t *texture); + +#endif // TEXTURE_H \ No newline at end of file diff --git a/core/host/generic/vector2d.h b/core/host/generic/vector2d.h new file mode 100644 index 0000000..81a5c2d --- /dev/null +++ b/core/host/generic/vector2d.h @@ -0,0 +1,163 @@ +#ifndef VECTOR2D_H +#define VECTOR2D_H + +#include +#include + +/** + * @brief Point struct. (int) + * + * @param x X pos + * @param y Y pos +*/ +typedef struct vector2d_t { + int x, y; +} vector2d_t; + +/** + * @brief Point struct. (float) + * + * @param x X pos + * @param y Y pos +*/ +typedef struct fvector2d_t { + float x, y; +} fvector2d_t; + +/** + * @brief Rectangle struct. (int) + * + * @param x X pos + * @param y Y pos + * @param w Width + * @param h Height +*/ +typedef struct rect_t { + int x, y; + int w, h; +} rect_t; + +/** + * @brief Rectangle struct. (float) + * + * @param x X pos + * @param y Y pos + * @param w Width + * @param h Height +*/ +typedef struct frect_t { + float x, y; + float w, h; +} frect_t; + +#define EPSILON 0.0f + +#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. +*/ +bool point_in_rect(const vector2d_t *p, const rect_t *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. +*/ +bool fpoint_in_rect(const fvector2d_t *p, const frect_t *r); + +/** + * @brief Verify if a rectangle is empty + * + * @param r Rectangle + * + * @return True if the rectangle is empty, else false. +*/ +bool rect_empty(const rect_t *r); + +/** + * @brief Verify if a rectangle is empty + * + * @param r Rectangle + * + * @return True if the rectangle is empty, else false. +*/ +bool frect_empty(const frect_t *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. +*/ +bool has_intersection(const rect_t *a, const rect_t *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. +*/ +bool fhas_intersection(const frect_t *a, const frect_t *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. +*/ +bool intersect_rect(const rect_t *a, const rect_t *b, rect_t *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. +*/ +bool intersect_frect(const frect_t *a, const frect_t *b, frect_t *result); + +/** + * @brief Lerp a to b with smoothing factor s. + * + * @param a Current value + * @param b Target value + * @param s Smoothing factor + */ +float lerp(float a, float b, float s); + +/** + * @brief Lerp a to b with smoothing factor s and time basis t. + * Smoothing factor is for 60 fps call time. + * + * @param a Current value + * @param b Target value + * @param s Smoothing factor + * @param t Delta time + */ +float lerp_time(float a, float b, float s, float t); + +#endif // VECTOR2D_H \ No newline at end of file diff --git a/core/host/linux/.ccls b/core/host/linux/.ccls new file mode 100644 index 0000000..537a5ae --- /dev/null +++ b/core/host/linux/.ccls @@ -0,0 +1,5 @@ +gcc +# Headers +-Icore +-Icore/host/linux +-Isrc/components diff --git a/core/host/linux/Makefile b/core/host/linux/Makefile index e69de29..39f3124 100644 --- a/core/host/linux/Makefile +++ b/core/host/linux/Makefile @@ -0,0 +1,7 @@ +CORE_SOURCES += \ + $(HOST_DIR)/$(HOST)/display.c \ + $(HOST_DIR)/$(HOST)/vector2d.c \ + $(HOST_DIR)/$(HOST)/texture.c + +CORE_INCLUDES += \ + $(CORE_DIRE) \ No newline at end of file diff --git a/core/src/display.c b/core/host/linux/display.c similarity index 100% rename from core/src/display.c rename to core/host/linux/display.c diff --git a/core/src/display.h b/core/host/linux/display.h similarity index 96% rename from core/src/display.h rename to core/host/linux/display.h index f1ed137..5978833 100644 --- a/core/src/display.h +++ b/core/host/linux/display.h @@ -2,7 +2,6 @@ #define DISPLAY_H #include -#include "asset_manager.h" #include "texture.h" #include "vector2d.h" diff --git a/core/host/linux/memory_alloc.h b/core/host/linux/memory_alloc.h new file mode 100644 index 0000000..ef8e8b6 --- /dev/null +++ b/core/host/linux/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/core/src/texture.c b/core/host/linux/texture.c similarity index 100% rename from core/src/texture.c rename to core/host/linux/texture.c diff --git a/core/src/texture.h b/core/host/linux/texture.h similarity index 81% rename from core/src/texture.h rename to core/host/linux/texture.h index bcd641e..b61aabf 100644 --- a/core/src/texture.h +++ b/core/host/linux/texture.h @@ -7,6 +7,9 @@ typedef SDL_Texture texture_t; +#define get_width(T) T->w +#define get_height(T) T->h + texture_t *load_texture(void); void destroy_texture(texture_t *texture); diff --git a/core/src/vector2d.c b/core/host/linux/vector2d.c similarity index 68% rename from core/src/vector2d.c rename to core/host/linux/vector2d.c index d52ae03..928b5f6 100644 --- a/core/src/vector2d.c +++ b/core/host/linux/vector2d.c @@ -1,13 +1,5 @@ #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; diff --git a/core/src/vector2d.h b/core/host/linux/vector2d.h similarity index 97% rename from core/src/vector2d.h rename to core/host/linux/vector2d.h index ab511b8..742f469 100644 --- a/core/src/vector2d.h +++ b/core/host/linux/vector2d.h @@ -40,13 +40,13 @@ typedef SDL_Rect rect_t; */ typedef SDL_FRect frect_t; -#define EPSILON 0.000001f +#define EPSILON 0.0f #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); +#define rect_to_frect(R, FR) SDL_RectToFRect(R, FR) void frect_to_rect(const frect_t *frect, rect_t *rect); diff --git a/core/src/inputs.c b/core/inputs.c similarity index 100% rename from core/src/inputs.c rename to core/inputs.c diff --git a/core/src/inputs.h b/core/inputs.h similarity index 100% rename from core/src/inputs.h rename to core/inputs.h diff --git a/core/src/keycodes.h b/core/keycodes.h similarity index 100% rename from core/src/keycodes.h rename to core/keycodes.h diff --git a/core/src/linked_list.c b/core/linked_list.c similarity index 100% rename from core/src/linked_list.c rename to core/linked_list.c diff --git a/core/src/linked_list.h b/core/linked_list.h similarity index 100% rename from core/src/linked_list.h rename to core/linked_list.h diff --git a/core/src/main.c b/core/main.c similarity index 100% rename from core/src/main.c rename to core/main.c diff --git a/core/src/map.c b/core/map.c similarity index 99% rename from core/src/map.c rename to core/map.c index cb8b8c9..737bbf2 100644 --- a/core/src/map.c +++ b/core/map.c @@ -406,8 +406,8 @@ static inline int draw_tile(uint16_t tile_x, uint16_t tile_y, uint16_t tile_id) if(!tile_id) return EXIT_SUCCESS; rect_t src_frect = { - .x = tile_id * TILE_SIZE % game.map->tileset->w, - .y = tile_id * TILE_SIZE / game.map->tileset->w * TILE_SIZE, + .x = tile_id * TILE_SIZE % get_width(game.map->tileset), + .y = tile_id * TILE_SIZE / get_height(game.map->tileset) * TILE_SIZE, .w = TILE_SIZE, .h = TILE_SIZE }; diff --git a/core/src/map.h b/core/map.h similarity index 100% rename from core/src/map.h rename to core/map.h diff --git a/core/src/.ccls b/core/src/.ccls deleted file mode 100644 index 478d903..0000000 --- a/core/src/.ccls +++ /dev/null @@ -1,8 +0,0 @@ -gcc -# Headers --Icore/src --Isrc/components - -# Macros --DDEBUG=2 --DASSET_FILE_NAME="$(make print-ASSET_OUTPUT)" diff --git a/core/src/Makefile b/core/src/Makefile deleted file mode 100644 index 58849c0..0000000 --- a/core/src/Makefile +++ /dev/null @@ -1,74 +0,0 @@ -# Source files -CORE_SOURCES := \ - linked_list.c \ - vector2d.c \ - inputs.c \ - asset_manager.c \ - texture.c \ - map.c \ - camera.c \ - event_bus.c \ - ecs.c \ - display.c \ - main.c - -# Compiler and flags -CORE_CC = gcc -ifeq ($(RELEASE), 1) -CORE_CFLAGS = --std=c17 --pedantic -O3 -DASSET_FILE_NAME=\"$(notdir $(ASSET_OUTPUT))\" -D_GNU_SOURCE=1 $(shell pkg-config --cflags sdl3) # RELEASE -else -CORE_CFLAGS = --std=c17 --pedantic -O1 -g -DDEBUG=2 -DASSET_FILE_NAME=\"$(notdir $(ASSET_OUTPUT))\" -D_GNU_SOURCE=1 $(shell pkg-config --cflags sdl3) \ - -Wall -Wno-missing-braces -Wextra -Wno-missing-field-initializers \ - -Wformat=2 -Wswitch-default -Wswitch -Wcast-align \ - -Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 \ - -Wstrict-prototypes -Winline -Wundef -Wnested-externs \ - -Wcast-qual -Wshadow -Wunreachable-code -Wlogical-op \ - -Wfloat-equal -Wstrict-aliasing=2 -Wredundant-decls \ - -Wold-style-definition # DEVELOPEMENT -endif - -CORE_INCLUDE_DIRS = $(SOURCE_DIR)/components $(CORE_DIR) -CORE_INCLUDE_DIRS := $(addprefix -I, $(CORE_INCLUDE_DIRS)) - -CORE_AR = ar -CORE_ARFLAGS = - -# Used in final linking. -CORE_DEPS_FLAGS = $(shell pkg-config --libs sdl3) -lm - -# Deduce objects -CORE_OBJECTS = $(CORE_SOURCES:%.c=$(BUILD_DIR)/$(CORE_DIR)/%.o) - -# Current file nb to process -CURRENT_CORE_FILE := 0 - -# Build core target -build_core: core_setup count_core_build core_end - -# Core build directories -core_setup: - @echo "Building $(notdir $(CORE_OUTPUT))" - $(Q)mkdir -p $(dir $(CORE_OBJECTS)) - -# Count nb of files to build -count_core_build: - $(eval export TOTAL_CORE_FILES := $(shell echo $$(($$(make -n $(CORE_OBJECTS) 2>/dev/null | grep -c "Building") + 1)))) - -# Link core target -$(CORE_OUTPUT): $(CORE_OBJECTS) - @echo -e "[100%] $(YELLOW)Linking $(notdir $(CORE_OUTPUT))$(RESET)" - $(Q)$(CORE_AR) rcs $(CORE_ARFLAGS) $@ $^ - -# Build .o files -$(BUILD_DIR)/$(CORE_DIR)/%.o: $(CORE_DIR)/%.c - $(eval CURRENT_CORE_FILE := $(shell echo $$(($(CURRENT_CORE_FILE)+1)))) - $(eval PERCENTAGE := $(shell echo $$(($(CURRENT_CORE_FILE)*100/$(TOTAL_CORE_FILES))))) - @echo -e "[$(PERCENTAGE)%] $(GREEN)Building C object $@$(RESET)" - $(Q)$(CORE_CC) $(CORE_CFLAGS) $(CORE_INCLUDE_DIRS) -MMD -MP -c $< -o $@ - -# Print ending message -core_end: $(CORE_OUTPUT) - @echo "Built target $(notdir $(CORE_OUTPUT))" - -# Source files dependencies --include $(CORE_OBJECTS:.o=.d) diff --git a/src/.ccls b/src/.ccls index 0603b1e..aa80df8 100644 --- a/src/.ccls +++ b/src/.ccls @@ -1,7 +1,5 @@ gcc # Headers -Isrc/components --Icore/src - -# Macros --DDEBUG=2 +-Icore +-Icore/host/generic diff --git a/src/Makefile b/src/Makefile index 38999f5..feb2f79 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,5 +1,4 @@ -# Source files -SOURCES := \ +SOURCES += \ game.c \ components/transform_component.c \ components/sprite_component.c \ @@ -12,61 +11,21 @@ SOURCES := \ components/door_component.c \ components/lua_component.c -# Compiler and flags -SRC_CC = gcc -ifeq ($(RELEASE), 1) -SRC_CFLAGS = --std=c17 --pedantic -O3 # RELEASE +INCLUDES += \ + $(SOURCE_DIR)/components \ + $(CORE_DIR) \ + $(CORE_DIR)/$(HOST_DIR)/$(HOST) -SRC_LDFLAGS = -O3 -else -SRC_CFLAGS = --std=c17 --pedantic -O1 -g -DDEBUG=2 \ - -Wall -Wno-missing-braces -Wextra -Wno-missing-field-initializers \ - -Wformat=2 -Wswitch-default -Wswitch -Wcast-align \ - -Wpointer-arith -Wbad-function-cast -Wstrict-overflow=5 \ - -Wstrict-prototypes -Winline -Wundef -Wnested-externs \ - -Wcast-qual -Wshadow -Wunreachable-code -Wlogical-op \ - -Wfloat-equal -Wstrict-aliasing=2 -Wredundant-decls \ - -Wold-style-definition # DEVELOPEMENT +OBJECTS := $(SOURCES:%=$(BUILD_DIR)/$(SOURCE_DIR)/%.o) -SRC_LDFLAGS = -O1 -endif +$(BUILD_DIR)/$(OUTPUT): $(BUILD_DIR)/$(LIBCORE) $(OBJECTS) + @echo -e "[100%] $(YELLOW)Linking $(OUTPUT)$(RESET)" + $(Q)$(CC) $(CFLAGS) $(LDFLAGS) $(OBJECTS) $(BUILD_DIR)/$(LIBCORE) -o $@ -SRC_INCLUDE_DIRS = $(SOURCE_DIR)/components $(CORE_DIR) -SRC_INCLUDE_DIRS := $(addprefix -I, $(SRC_INCLUDE_DIRS)) - -# Deduce objects -SOURCE_OBJECTS = $(SOURCES:%.c=$(BUILD_DIR)/$(SOURCE_DIR)/%.o) - -# Current file nb to process -CURRENT_SRC_FILE := 0 - -# Build src target -build_src: src_setup count_src_build src_end - -# Source build directories -src_setup: - @echo "Building $(notdir $(SOURCE_OUTPUT))" - $(Q)mkdir -p $(dir $(SOURCE_OBJECTS)) - -# Count nb of files to build -count_src_build: - $(eval export TOTAL_SRC_FILES := $(shell echo $$(($$(make -n $(SOURCE_OBJECTS) 2>/dev/null | grep -c "Building") + 1)))) - -# Link game target -$(SOURCE_OUTPUT): $(SOURCE_OBJECTS) $(CORE_OUTPUT) - @echo -e "[100%] $(YELLOW)Linking $(notdir $(SOURCE_OUTPUT))$(RESET)" - $(Q)$(SRC_CC) $(SOURCE_OBJECTS) -L./$(BUILD_DIR) $(CORE_OUTPUT) -o $@ $(SRC_LDFLAGS) $(CORE_DEPS_FLAGS) - -# Build .o files -$(BUILD_DIR)/$(SOURCE_DIR)/%.o: $(SOURCE_DIR)/%.c - $(eval CURRENT_SRC_FILE := $(shell echo $$(($(CURRENT_SRC_FILE)+1)))) - $(eval PERCENTAGE := $(shell echo $$(($(CURRENT_SRC_FILE)*100/$(TOTAL_SRC_FILES))))) +$(BUILD_DIR)/$(SOURCE_DIR)/%.c.o: $(ROOT)/$(SOURCE_DIR)/%.c + $(eval CURRENT_FILE := $(shell echo $$(($(CURRENT_FILE) + 1)))) + $(eval PERCENTAGE := $(shell echo $$(($(CURRENT_FILE) * 100 / $(TOTAL_BUILD_FILES))))) @echo -e "[$(PERCENTAGE)%] $(GREEN)Building C object $@$(RESET)" - $(Q)$(SRC_CC) $(SRC_CFLAGS) $(SRC_INCLUDE_DIRS) -MMD -MP -c $< -o $@ + $(Q)$(CC) $(CFLAGS) $(INCLUDES:%=-I%) -MMD -MP -c $< -o $@ -# Print ending message -src_end: $(SOURCE_OUTPUT) - @echo "Built target $(notdir $(SOURCE_OUTPUT))" - -# Source files dependencies --include $(SOURCE_OBJECTS:.o=.d) +-include $(OBJECTS:.o=.d) diff --git a/src/components/physics_system.c b/src/components/physics_system.c index 30d04d7..785c01e 100644 --- a/src/components/physics_system.c +++ b/src/components/physics_system.c @@ -96,11 +96,11 @@ static inline int action_detect_solve_entities_collision(elem_t *elem, void *arg const frect_t *hitbox_bounds = &hitbox_component_data->bounds; const frect_t *target_hitbox_bounds = &target_hitbox_component_data->bounds; - frect_t intersect_frect; + frect_t intersect; - if(intersect_frect(hitbox_bounds, target_hitbox_bounds, &intersect_frect)) + if(intersect_frect(hitbox_bounds, target_hitbox_bounds, &intersect)) { - if(intersect_frect.w < intersect_frect.h) + if(intersect.w < intersect.h) { const float left_correction = hitbox_bounds->x + hitbox_bounds->w - target_hitbox_bounds->x; const float right_correction = target_hitbox_bounds->x + target_hitbox_bounds->w - hitbox_bounds->x;