Sarting to clean and implement core for SDL

This commit is contained in:
Ulysse Cura 2026-04-11 23:17:01 +02:00
parent e57a720439
commit 931a506a0d
29 changed files with 208 additions and 174 deletions

View File

@ -4,7 +4,7 @@
"name": "Default",
"includePath": [
"src/**/headers",
"core/**/headers"
"core/headers"
]
}
],

2
.vscode/tasks.json vendored
View File

@ -7,7 +7,7 @@
"type": "shell",
"command": "make",
"args": [
"-j$(nproc)"
// "-j$(nproc)"
],
"group": "build",
"presentation": {

View File

@ -3,6 +3,9 @@ SHELL = /bin/bash
# Build folder
BUILD_DIR = build
# Core output target name
CORE_OUTPUT := libCore.so
# Source output target name
SOURCE_OUTPUT := 2D_Engine
@ -16,18 +19,15 @@ Q :=
endif
# Colors
GREEN := \033[0;32m
YELLOW := \033[1;33m
RESET := \033[0m
GREEN := \033[32m
YELLOW := \033[33m
RESET := \033[m
# Default targets
#all: build_core build_src compress_assets end
all: build_src
all: build_core build_src
# Current file nb to process
CURRENT_FILE := 0
# Sub-Makefiles
# Sub Makefiles
SOURCE_DIR = src
CORE_DIR = core
ASSETS_DIR = assets
@ -36,9 +36,6 @@ include $(CORE_DIR)/Makefile
include $(SOURCE_DIR)/Makefile
include $(ASSETS_DIR)/Makefile
count_build:
$(eval export TOTAL_FILES := $(shell echo $$(($$(make -n $(OBJECTS) 2>/dev/null | grep -c "Building") + 1))))
# Print ending message
end:
@echo "Built target $(OUTPUT)"

View File

@ -0,0 +1,44 @@
# Source files
CORE_SOURCES := \
vector2d.c \
linked_list.c \
display.c
# Compiler and flags
CORE_CC = gcc
CORE_CFLAGS = $(sdl2-config --cflags --libs) -Wall -Wextra -std=c17 -fPIC
CORE_INCLUDE_DIRS = $(CORE_DIR)/headers
CORE_LDFLAGS =
# 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 $(BUILD_DIR)/$(CORE_OUTPUT)
# Core build directories
core_setup:
@echo "Building Core (1/3)"
$(Q)mkdir -p $(dir $(CORE_OBJECTS))
# Count
count_core_build:
$(eval export TOTAL_CORE_FILES := $(shell echo $$(($$(make -n $(CORE_OBJECTS) 2>/dev/null | grep -c "Building") + 1))))
# Link core target
$(BUILD_DIR)/$(CORE_OUTPUT): $(CORE_OBJECTS)
@echo -e "[100%] $(YELLOW)Linking $(CORE_OUTPUT)$(RESET)"
$(Q)$(CORE_CC) -shared $(CORE_LDFLAGS) -o $@ $(CORE_OBJECTS)
# 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:%=-I%) -MMD -MP -c $< -o $@
# Source files dependencies
-include $(SOURCE_OBJECTS:.o=.d)

36
core/display.c Normal file
View File

@ -0,0 +1,36 @@
#include "display.h"
#include <SDL2/SDL.h>
SDL_Window *window = NULL;
SDL_Renderer *renderer = NULL;
void display_init(void)
{
SDL_Init(SDL_INIT_EVERYTHING);
window = SDL_CreateWindow("2D_Engine", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, DISPLAY_WIDTH, DISPLAY_HEIGHT, SDL_WINDOW_SHOWN);
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
}
void display_update(void)
{
}
void display_clear(void)
{
SDL_SetRenderDrawColor(renderer, COLOR_WHITE);
SDL_RenderClear(renderer);
}
void display_subimage()
{
}
void display_exit_void(void)
{
SDL_DestroyRenderer(renderer);
SDL_DestroyWindow(window);
SDL_Quit();
}

17
core/headers/LICENSE.txt Normal file
View File

@ -0,0 +1,17 @@
Copyright (C) 1997-2026 Sam Lantinga <slouken@libsdl.org>
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

24
core/headers/display.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef DISPLAY_H
#define DISPLAY_H
#include <SDL2/SDL_render.h>
#define COLOR_WHITE 255, 255, 255, 255
#define DISPLAY_WIDTH 396
#define DISPLAY_HEIGHT 224
extern SDL_Window *window;
extern SDL_Renderer *renderer;
void display_init(void);
void display_update(void);
void display_clear(void);
void display_subimage();
void display_exit(void);
#endif // DISPLAY_H

View File

@ -8,4 +8,9 @@
#define KEYEV_UP SDL_KEYUP
#define KEYEV_DOWN SDL_KEYDOWN
#define KEY_UP SDL_SCANCODE_UP
#define KEY_DOWN SDL_SCANCODE_DOWN
#define KEY_LEFT SDL_SCANCODE_LEFT
#define KEY_RIGHT SDL_SCANCODE_RIGHT
#endif // KEYCODES_H

View File

@ -265,7 +265,7 @@ elem_t *linked_list_get_elem_if(const linked_list_t *linked_list, const conditio
void *linked_list_get_if(const linked_list_t *linked_list, const condition_t condition, ...);
/**
* @brief Remove element(s) that the condition verify, do nothing on error.
* @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
@ -276,10 +276,10 @@ void linked_list_remove_if(linked_list_t *linked_list, const condition_t conditi
/**
* @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 dont destroy the element.
* 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 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, ...);

View File

@ -1,7 +1,7 @@
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
* All of the functions declared in this file and *
* defined in vector2d.c are from the SDL2 source code. *
* They are just renamed. *
* They are just modified for float and renamed. *
* => https://github.com/libsdl-org/SDL *
\* * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
@ -38,6 +38,7 @@ typedef struct rect_t {
__attribute__((const)) float fabsf(float x);
#define is_equal_to_zero(X) (fabsf(X) <= EPSILON)
#define is_not_zero(X) (fabsf(X) > EPSILON)

View File

@ -1,14 +0,0 @@
#ifndef DISPLAY_H
#define DISPLAY_H
#include "SDL2/SDL_render.h"
#define C_WHITE 255, 255, 255, 255
void dclear(void)
{
SDL_SetRenderDrawColor(renderer, C_WHITE);
SDL_RenderClear(renderer);
}
#endif // DISPLAY_H

View File

@ -2,10 +2,7 @@
SOURCES := \
main.c \
game.c \
vector2d.c \
linked_list.c \
texture_manager.c \
map_manager.c \
ecs/ecs.c \
ecs/components/transform_component.c \
ecs/components/sprite_component.c \
@ -13,37 +10,40 @@ SOURCES := \
ecs/components/player_system.c
# Compiler and flags
CC = ccache gcc
CFLAGS = -Wall -Wextra -std=c17
INCLUDE_DIRS = $(SOURCE_DIR)/headers $(SOURCE_DIR)/ecs/headers $(SOURCE_DIR)/ecs/components/headers $(CORE_DIR)/src/headers
LDFLAGS =
SRC_CC = gcc
SRC_CFLAGS = -Wall -Wextra -std=c17
SRC_INCLUDE_DIRS = $(SOURCE_DIR)/headers $(SOURCE_DIR)/ecs/headers $(SOURCE_DIR)/ecs/components/headers $(CORE_DIR)/headers
SRC_LDFLAGS =
# Deduce objects
SOURCE_OBJECTS = $(SOURCES:%.c=$(BUILD_DIR)/$(SOURCE_DIR)/%.o)
# Build src target
build_src: src_build_dir count_src_build $(BUILD_DIR)/$(SOURCE_OUTPUT)
# Current file nb to process
CURRENT_SRC_FILE := 0
# Source build directories
src_build_dir:
echo $(INCLUDE_DIRS)
# Build src target
build_src: src_setup count_src_build $(BUILD_DIR)/$(SOURCE_OUTPUT)
# Source build directories and
src_setup:
@echo "Building Source (2/3)"
$(Q)mkdir -p $(dir $(SOURCE_OBJECTS))
# Count
count_src_build:
$(eval export TOTAL_FILES := $(shell echo $$(($$(make -n $(SOURCE_OBJECTS) 2>/dev/null | grep -c "Building") + 1))))
$(eval export TOTAL_SRC_FILES := $(shell echo $$(($$(make -n $(SOURCE_OBJECTS) 2>/dev/null | grep -c "Building") + 1))))
# Link game target
$(BUILD_DIR)/$(SOURCE_OUTPUT): $(SOURCE_OBJECTS)
@echo -e "[100%] $(YELLOW)Linking $(OUTPUT)$(RESET)"
$(Q)$(CC) -Wl,-r $(LDFLAGS) -o $@ $(SOURCE_OBJECTS)
@echo -e "[100%] $(YELLOW)Linking $(SOURCE_OUTPUT)$(RESET)"
$(Q)$(SRC_CC) $(SRC_LDFLAGS) -o $@ $(SOURCE_OBJECTS)
# Build .o files
$(BUILD_DIR)/$(SOURCE_DIR)/%.o: $(SOURCE_DIR)/%.c
$(eval CURRENT_FILE := $(shell echo $$(($(CURRENT_FILE)+1))))
$(eval PERCENTAGE := $(shell echo $$(($(CURRENT_FILE)*100/$(TOTAL_FILES)))))
$(eval CURRENT_SRC_FILE := $(shell echo $$(($(CURRENT_SRC_FILE)+1))))
$(eval PERCENTAGE := $(shell echo $$(($(CURRENT_SRC_FILE)*100/$(TOTAL_SRC_FILES)))))
@echo -e "[$(PERCENTAGE)%] $(GREEN)Building C object $@$(RESET)"
$(Q)$(CC) $(CFLAGS) $(INCLUDE_DIRS:%=-I%) -MMD -MP -c $< -o $@
$(Q)$(SRC_CC) $(SRC_CFLAGS) $(SRC_INCLUDE_DIRS:%=-I%) -MMD -MP -c $< -o $@
# Source files dependencies
-include $(SOURCE_OBJECTS:.o=.d)

View File

@ -18,16 +18,16 @@ void player_system_init(component_t *component, va_list args __attribute__((unus
}
// Only for this file
static void player_system_get_inputs(player_system_data_t *system_data)
static inline void player_system_get_inputs(player_system_data_t *system_data)
{
system_data->last_state = system_data->state;
system_data->state &= 0xF0; // 11110000
system_data->state |= game.keys[KEY_UP] * PLAYER_RUNNING_UP;
system_data->state |= game.keys[KEY_DOWN] * PLAYER_RUNNING_DOWN;
system_data->state |= game.keys[KEY_LEFT] * PLAYER_RUNNING_LEFT;
system_data->state |= game.keys[KEY_RIGHT] * PLAYER_RUNNING_RIGHT;
system_data->state |= game.events.keys[KEY_UP] * PLAYER_RUNNING_UP;
system_data->state |= game.events.keys[KEY_DOWN] * PLAYER_RUNNING_DOWN;
system_data->state |= game.events.keys[KEY_LEFT] * PLAYER_RUNNING_LEFT;
system_data->state |= game.events.keys[KEY_RIGHT] * PLAYER_RUNNING_RIGHT;
// Special cases
if(system_data->state & PLAYER_RUNNING_UP && system_data->state & PLAYER_RUNNING_DOWN) system_data->state &= 0xFC; // 11111100
@ -35,7 +35,7 @@ static void player_system_get_inputs(player_system_data_t *system_data)
}
// Only for this file
static void player_system_set_velocity(player_system_data_t *system_data)
static inline void player_system_set_velocity(player_system_data_t *system_data)
{
transform_component_data_t *transform_component_data = system_data->transform_component_data;
@ -52,7 +52,7 @@ static void player_system_set_velocity(player_system_data_t *system_data)
}
// Only for this file
static void player_system_set_animation(player_system_data_t *system_data)
static inline void player_system_set_animation(player_system_data_t *system_data)
{
sprite_component_data_t *sprite_component_data = system_data->sprite_component_data;
animation_system_data_t *animation_system_data = system_data->animation_system_data;

View File

@ -9,9 +9,11 @@ typedef enum component_type_t {
TRANSFORM_COMPONENT,
SPRITE_COMPONENT,
ANIMATION_SYSTEM,
PLAYER_SYSTEM
PLAYER_SYSTEM,
// Add new components types here
} component_type_t;
// Structs forwarding
typedef struct transform_component_data_t transform_component_data_t;
typedef struct sprite_component_data_t sprite_component_data_t;
typedef struct animation_system_data_t animation_system_data_t;
@ -19,10 +21,13 @@ typedef struct player_system_data_t player_system_data_t;
typedef struct component_t component_t;
// Component init function. It is called when component added to entity. This function is necessary.
typedef void (*component_init_t)(component_t *component, va_list args);
// Component update function. It is called in the main loop to update the component. This function is necessary.
typedef void (*component_update_t)(component_t *component);
// Component draw function. It is called in the main loop to draw the component on screen. This function is not necessary.
typedef void (*component_draw_t)(component_t *component);
// Component deleter function. It is called when the component is removed. It should free the data in the component data but not the component data itself.
typedef void (*component_deleter_t)(component_t *component);
typedef struct component_t {

View File

@ -6,8 +6,9 @@
void game_init(void)
{
display_init();
texture_manager_init(&game.texture_manager);
texture_manager_load_builtin_textures(&game.texture_manager);
entity_manager_init(&game.entity_manager);
@ -32,9 +33,9 @@ void game_handle_event(void)
while(pollevent(&event))
{
if(event.type == KEYEV_DOWN)
game.keys[event.key.keysym.scancode] = true;
game.events.keys[event.key.keysym.scancode] = true;
else if(event.type == KEYEV_UP)
game.keys[event.key.keysym.scancode] = false;
game.events.keys[event.key.keysym.scancode] = false;
if(event.type == SDL_QUIT)
game.is_running = false;
@ -58,15 +59,17 @@ void game_update(void)
void game_render(void)
{
dclear();
display_clear();
entity_manager_draw(&game.entity_manager);
dupdate();
display_update();
}
void game_exit(void)
{
entity_manager_clear(&game.entity_manager);
texture_manager_clear(&game.texture_manager);
display_exit();
}

12
src/headers/events.h Normal file
View File

@ -0,0 +1,12 @@
#ifndef EVENTS_H
#define EVENTS_H
#include <keycodes.h>
#include <vector2d.h>
typedef struct events_t {
bool keys[MAX_KEYCODES];
vector2d_t cursor_pos;
} events_t;
#endif // EVENTS_H

View File

@ -1,7 +1,7 @@
#ifndef GAME_H
#define GAME_H
#include <keycodes.h>
#include "events.h"
#include "texture_manager.h"
#include "ecs.h"
@ -16,7 +16,7 @@
* @param delta_time_ms Frame time
*/
typedef struct game_t {
bool keys[MAX_KEYCODES];
events_t events;
texture_manager_t texture_manager;
entity_manager_t entity_manager;
@ -24,34 +24,22 @@ typedef struct game_t {
double delta_time_ms;
} game_t;
/**
* @brief Global game instance
*/
// Global game instance
extern game_t game;
/**
* @brief Initialise game
*/
// Initialise game
void game_init(void);
/**
* @brief Handle event like inputs
*/
// Handle event like inputs
void game_handle_event(void);
/**
* @brief Update game
*/
// Update game
void game_update(void);
/**
* @brief Render game
*/
// Render game
void game_render(void);
/**
* @brief Free game instance
*/
// Free game instance
void game_exit(void);
#endif // GAME_H

View File

@ -1,8 +0,0 @@
#ifndef MAP_MANAGER_H
#define MAP_MANAGER_H
typedef struct map_t {
} map_t;
#endif // MAP_MANAGER_H

View File

@ -1,15 +0,0 @@
#ifndef MAPS_H
#define MAPS_H
#include "vector2d.h"
typedef unsigned int tile_t;
typedef struct builtin_map_t {
char *entities;
size_t width;
size_t height;
tile_t *tiles;
} builtin_map_t;
#endif // MAPS_H

View File

@ -46,17 +46,6 @@ typedef struct texture_manager_t {
@texture_manager Pointer to a texture manager */
void texture_manager_init(texture_manager_t *);
/* texture_manager_load_builtin_textures(): Load textures declared in "textures.h"
@texture_manager Pointer to a texture manager */
void texture_manager_load_builtin_textures(texture_manager_t *);
/* texture_manager_load_builtin_texture(): Load texture declared in "textures.h" wich have "name"
@texture_manager Pointer to a texture manager
@name Name of the texture to load */
texture_t *texture_manager_load_builtin_texture(texture_manager_t *, const char*);
/* texture_manager_add_texture(): Add a texture in the texture manager
@texture_manager Pointer to a texture manager

View File

@ -1,22 +0,0 @@
#ifndef TEXTURES_H
#define TEXTURES_H
#include <gint/display.h>
#include "texture_manager.h"
typedef struct builtin_texture_t {
const char *name;
bopti_image_t *image;
} builtin_texture_t;
extern bopti_image_t img_player_idle_sheet;
extern bopti_image_t img_player_run_sheet;
static struct builtin_texture_t builtin_textures[] = {
{"player_idle_sheet", &img_player_idle_sheet},
{"player_run_sheet", &img_player_run_sheet}
};
#define BUILTIN_TEXTURE_COUNT (sizeof(builtin_textures) / sizeof(builtin_texture_t))
#endif // TEXTURES_H

View File

@ -29,7 +29,7 @@ int main(void)
int main(void)
{
dclear(C_WHITE);
display_clear(COLOR_WHITE);
texture_manager_t texture_manager;
texture_manager_init(&texture_manager);
@ -57,7 +57,7 @@ int main(void)
texture_manager_clear(&texture_manager);
dupdate();
display_update();
getkey();
return 1;
@ -72,7 +72,7 @@ int main(void)
int main(void)
{
dclear(C_WHITE);
display_clear(COLOR_WHITE);
linked_list_t linked_list;
linked_list_init(&linked_list, sizeof(int), NULL);
@ -272,7 +272,7 @@ int main(void)
linked_list_clear(&linked_list);
Exit:
dupdate();
display_update();
getkey();
return 1;

View File

@ -1,13 +1,12 @@
#include <malloc.h>
#include <string.h>
#include "texture_manager.h"
//#include "textures.h"
texture_t *create_texture(image_t *image, const char *name)
{
if(!image) return NULL;
texture_t *texture = kmalloc(sizeof(texture_t), NULL);
texture_t *texture = malloc(sizeof(texture_t));
if (!texture) return NULL;
texture->name = name;
@ -18,12 +17,12 @@ texture_t *create_texture(image_t *image, const char *name)
inline void destroy_texture(texture_t *texture)
{
kfree(texture);
free(texture);
}
inline void draw_texture(const texture_t *texture, const rect_t *src, const rect_t *dst, bool flip)
{
dsubimage_rgb16_effect((int)dst->x, (int)dst->y, texture->image, (int)src->x, (int)src->y, (int)src->w, (int)src->h, flip ? IMAGE_HFLIP : DIMAGE_NONE);
display_subimage((int)dst->x, (int)dst->y, texture->image, (int)src->x, (int)src->y, (int)src->w, (int)src->h, flip);
}
inline void texture_manager_init(texture_manager_t *texture_manager)
@ -31,30 +30,6 @@ inline void texture_manager_init(texture_manager_t *texture_manager)
linked_list_init(&texture_manager->textures, sizeof(texture_t), NULL);
}
void texture_manager_load_builtin_textures(texture_manager_t *texture_manager)
{
for(size_t i = 0; i < BUILTIN_TEXTURE_COUNT; i++)
{
texture_t *texture = create_texture((image_t *)builtin_textures[i].image, builtin_textures[i].name);
texture_manager_add_texture(texture_manager, texture);
}
}
texture_t *texture_manager_load_builtin_texture(texture_manager_t *texture_manager, const char *name)
{
for(size_t i = 0; i < BUILTIN_TEXTURE_COUNT; i++)
{
if(!strcmp(builtin_textures[i].name, name))
{
texture_t *texture = create_texture((image_t *)builtin_textures[i].image, builtin_textures[i].name);
texture_manager_add_texture(texture_manager, texture);
return texture;
}
}
return NULL;
}
inline void texture_manager_add_texture(texture_manager_t *texture_manager, texture_t *texture)
{
linked_list_push_back(&texture_manager->textures, texture);
@ -70,9 +45,6 @@ static inline bool is_texture_name(elem_t *elem, va_list args)
texture_t *texture_manager_get_texture(texture_manager_t *texture_manager, const char *name)
{
texture_t *texture = linked_list_get_if(&texture_manager->textures, is_texture_name, name);
if(texture) return texture;
texture = texture_manager_load_builtin_texture(texture_manager, name);
return texture;
}