Adding ECS
This commit is contained in:
parent
57192d8b0e
commit
6d5379d2c3
|
@ -15,6 +15,11 @@ set(SOURCES
|
||||||
src/vector2d.c
|
src/vector2d.c
|
||||||
src/linked_list.c
|
src/linked_list.c
|
||||||
src/texture_manager.c
|
src/texture_manager.c
|
||||||
|
src/ecs/ecs.c
|
||||||
|
src/ecs/transform_component.c
|
||||||
|
src/ecs/sprite_component.c
|
||||||
|
src/ecs/animation_system.c
|
||||||
|
src/ecs/player_system.c
|
||||||
)
|
)
|
||||||
|
|
||||||
# fx-CG-50-only assets
|
# fx-CG-50-only assets
|
||||||
|
|
|
@ -0,0 +1,111 @@
|
||||||
|
#include <gint/kmalloc.h>
|
||||||
|
#include "animation_system.h"
|
||||||
|
#include "../game.h"
|
||||||
|
|
||||||
|
// Args : size_t nb_frames, size_t actual_frame, float frame_delay_ms, bool play, bool loop, bool reverse
|
||||||
|
void animation_system_init(component_t *component, va_list args)
|
||||||
|
{
|
||||||
|
animation_system_data_t *system_data = component->component_data.animation_system_data;
|
||||||
|
|
||||||
|
system_data->sprite_component_data = get_component(component->entity, SPRITE_COMPONENT)->component_data.sprite_component_data;
|
||||||
|
|
||||||
|
system_data->nb_frames = va_arg(args, size_t);
|
||||||
|
system_data->actual_frame_nb= va_arg(args, size_t);
|
||||||
|
system_data->frame_delay_ms = (float)va_arg(args, double);
|
||||||
|
system_data->play = (bool)va_arg(args, int);
|
||||||
|
system_data->loop = (bool)va_arg(args, int);
|
||||||
|
system_data->reverse = (bool)va_arg(args, int);
|
||||||
|
|
||||||
|
system_data->frame_timer_ms = 0;
|
||||||
|
|
||||||
|
linked_list_init(&system_data->frames, sizeof(rect_t), NULL);
|
||||||
|
|
||||||
|
animation_system_create_frames_clips(system_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void animation_system_update(component_t *component)
|
||||||
|
{
|
||||||
|
animation_system_data_t *system_data = component->component_data.animation_system_data;
|
||||||
|
|
||||||
|
if(system_data->play)
|
||||||
|
{
|
||||||
|
system_data->frame_timer_ms += (float)game.delta_time_ms;
|
||||||
|
|
||||||
|
if(system_data->frame_timer_ms >= system_data->frame_delay_ms)
|
||||||
|
{
|
||||||
|
system_data->frame_timer_ms = 0;
|
||||||
|
|
||||||
|
if(system_data->reverse)
|
||||||
|
{
|
||||||
|
if(system_data->actual_frame->prev)
|
||||||
|
{
|
||||||
|
system_data->actual_frame = system_data->actual_frame->prev;
|
||||||
|
system_data->actual_frame_nb--;
|
||||||
|
}
|
||||||
|
else if(!system_data->loop)
|
||||||
|
{
|
||||||
|
system_data->play = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
system_data->actual_frame = system_data->frames.last;
|
||||||
|
system_data->actual_frame_nb = system_data->frames.size - 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if(system_data->actual_frame->next)
|
||||||
|
{
|
||||||
|
system_data->actual_frame = system_data->actual_frame->next;
|
||||||
|
system_data->actual_frame_nb++;
|
||||||
|
}
|
||||||
|
else if(!system_data->loop)
|
||||||
|
{
|
||||||
|
system_data->play = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
system_data->actual_frame = system_data->frames.first;
|
||||||
|
system_data->actual_frame_nb = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
system_data->sprite_component_data->srcR = *(rect_t *)system_data->actual_frame->data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void animation_system_destroy(component_t *component)
|
||||||
|
{
|
||||||
|
linked_list_clear(&component->component_data.animation_system_data->frames);
|
||||||
|
kfree(component->component_data.animation_system_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
void animation_system_create_frames_clips(animation_system_data_t *system_data)
|
||||||
|
{
|
||||||
|
linked_list_clear(&system_data->frames);
|
||||||
|
|
||||||
|
rect_t *sprite_srcR = &system_data->sprite_component_data->srcR;
|
||||||
|
|
||||||
|
for(size_t actual_frame_nb = 0; actual_frame_nb < system_data->nb_frames; actual_frame_nb++)
|
||||||
|
{
|
||||||
|
elem_t *frame = elem_create(&system_data->frames);
|
||||||
|
|
||||||
|
((rect_t *)frame->data)->x = sprite_srcR->w * (float)actual_frame_nb;
|
||||||
|
((rect_t *)frame->data)->y = 0;
|
||||||
|
((rect_t *)frame->data)->w = sprite_srcR->w;
|
||||||
|
((rect_t *)frame->data)->h = sprite_srcR->h;
|
||||||
|
|
||||||
|
linked_list_push_back_elem(&system_data->frames, frame);
|
||||||
|
}
|
||||||
|
|
||||||
|
system_data->actual_frame = linked_list_get_elem(&system_data->frames, system_data->actual_frame_nb);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void animation_system_change_animation(animation_system_data_t *system_data, const char *name, size_t nb_frames)
|
||||||
|
{
|
||||||
|
system_data->nb_frames = nb_frames;
|
||||||
|
sprite_component_set_texture(system_data->sprite_component_data, name);
|
||||||
|
animation_system_create_frames_clips(system_data);
|
||||||
|
system_data->sprite_component_data->srcR = *(rect_t *)system_data->actual_frame->data;
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
#ifndef ANIMATION_SYSTEM_H
|
||||||
|
#define ANIMATION_SYSTEM_H
|
||||||
|
|
||||||
|
#include "ecs.h"
|
||||||
|
#include "sprite_component.h"
|
||||||
|
|
||||||
|
typedef struct animation_system_data_t {
|
||||||
|
sprite_component_data_t *sprite_component_data;
|
||||||
|
|
||||||
|
bool play :1;
|
||||||
|
bool loop :1;
|
||||||
|
bool reverse :1;
|
||||||
|
|
||||||
|
float frame_delay_ms;
|
||||||
|
float frame_timer_ms;
|
||||||
|
|
||||||
|
elem_t *actual_frame;
|
||||||
|
size_t actual_frame_nb;
|
||||||
|
|
||||||
|
size_t nb_frames;
|
||||||
|
linked_list_t frames;
|
||||||
|
} animation_system_data_t;
|
||||||
|
|
||||||
|
void animation_system_init(component_t *, va_list);
|
||||||
|
|
||||||
|
void animation_system_update(component_t *);
|
||||||
|
|
||||||
|
void animation_system_destroy(component_t *);
|
||||||
|
|
||||||
|
void animation_system_create_frames_clips(animation_system_data_t *);
|
||||||
|
|
||||||
|
void animation_system_change_animation(animation_system_data_t *, const char *, size_t);
|
||||||
|
|
||||||
|
#endif // SPRITE_COMPONENT_H
|
|
@ -0,0 +1,10 @@
|
||||||
|
#ifndef COMPONENTS_H
|
||||||
|
#define COMPONENTS_H
|
||||||
|
|
||||||
|
#include "transform_component.h"
|
||||||
|
#include "sprite_component.h"
|
||||||
|
#include "animation_system.h"
|
||||||
|
#include "player_system.h"
|
||||||
|
// Add new components header file here
|
||||||
|
|
||||||
|
#endif // COMPONENTS_H
|
|
@ -0,0 +1,194 @@
|
||||||
|
#include <gint/kmalloc.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "ecs.h"
|
||||||
|
#include "components.h"
|
||||||
|
|
||||||
|
component_t *create_component(component_type_t component_type)
|
||||||
|
{
|
||||||
|
component_t *component = kmalloc(sizeof(component_t), NULL);
|
||||||
|
component->component_type = component_type;
|
||||||
|
|
||||||
|
switch(component_type)
|
||||||
|
{
|
||||||
|
case TRANSFORM_COMPONENT:
|
||||||
|
component->component_init = transform_component_init;
|
||||||
|
component->component_update = transform_component_update;
|
||||||
|
component->component_draw = NULL;
|
||||||
|
|
||||||
|
component->component_data.transform_component_data = kmalloc(sizeof(transform_component_data_t), NULL);
|
||||||
|
if(!component->component_data.transform_component_data) return NULL;
|
||||||
|
|
||||||
|
component->component_deleter = transform_component_destroy;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SPRITE_COMPONENT:
|
||||||
|
component->component_init = sprite_component_init;
|
||||||
|
component->component_update = sprite_component_update;
|
||||||
|
component->component_draw = sprite_component_draw;
|
||||||
|
|
||||||
|
component->component_data.sprite_component_data = kmalloc(sizeof(sprite_component_data_t), NULL);
|
||||||
|
if(!component->component_data.sprite_component_data) return NULL;
|
||||||
|
|
||||||
|
component->component_deleter = sprite_component_destroy;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case ANIMATION_SYSTEM:
|
||||||
|
component->component_init = animation_system_init;
|
||||||
|
component->component_update = animation_system_update;
|
||||||
|
component->component_draw = NULL;
|
||||||
|
|
||||||
|
component->component_data.animation_system_data = kmalloc(sizeof(animation_system_data_t), NULL);
|
||||||
|
if(!component->component_data.animation_system_data) return NULL;
|
||||||
|
|
||||||
|
component->component_deleter = animation_system_destroy;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PLAYER_SYSTEM:
|
||||||
|
component->component_init = player_system_init;
|
||||||
|
component->component_update = player_system_update;
|
||||||
|
component->component_draw = NULL;
|
||||||
|
|
||||||
|
component->component_data.player_system_data = kmalloc(sizeof(player_system_data_t), NULL);
|
||||||
|
if(!component->component_data.player_system_data) return NULL;
|
||||||
|
|
||||||
|
component->component_deleter = player_system_destroy;
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Add new components attributions here
|
||||||
|
|
||||||
|
default:
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return component;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void destroy_component(component_t *component)
|
||||||
|
{
|
||||||
|
component->component_deleter(component);
|
||||||
|
kfree(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
entity_t *create_entity(const char *name)
|
||||||
|
{
|
||||||
|
entity_t *entity = kmalloc(sizeof(entity_t), NULL);
|
||||||
|
if(!entity) return NULL;
|
||||||
|
|
||||||
|
entity->name = name;
|
||||||
|
entity->draw_priority = 0;
|
||||||
|
linked_list_init(&entity->components, sizeof(component_t), (deleter_t)destroy_component);
|
||||||
|
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_component(entity_t *entity, component_t *component, ...)
|
||||||
|
{
|
||||||
|
if(!component) return;
|
||||||
|
|
||||||
|
component->entity = entity;
|
||||||
|
|
||||||
|
va_list args, args_copy;
|
||||||
|
va_start(args, component);
|
||||||
|
va_copy(args_copy, args);
|
||||||
|
|
||||||
|
component->component_init(component, args_copy);
|
||||||
|
|
||||||
|
va_end(args_copy);
|
||||||
|
va_end(args);
|
||||||
|
|
||||||
|
linked_list_push_back(&entity->components, component);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only for this file
|
||||||
|
// Arg : component_type_t component_type
|
||||||
|
static inline bool condition_is_component_type(elem_t *elem, va_list args)
|
||||||
|
{
|
||||||
|
return ((component_t *)elem->data)->component_type == va_arg(args, component_type_t);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline component_t *get_component(entity_t *entity, component_type_t component_type)
|
||||||
|
{
|
||||||
|
return linked_list_get_if(&entity->components, condition_is_component_type, component_type);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only for this file
|
||||||
|
// No args
|
||||||
|
static inline void action_update_component(elem_t *elem, va_list args __attribute__((unused)))
|
||||||
|
{
|
||||||
|
component_t *component = elem->data;
|
||||||
|
component->component_update(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void update_entity(entity_t *entity)
|
||||||
|
{
|
||||||
|
linked_list_for_each(&entity->components, action_update_component);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only for this file
|
||||||
|
// No args
|
||||||
|
static inline void action_draw_component(elem_t *elem, va_list args __attribute__((unused)))
|
||||||
|
{
|
||||||
|
component_t *component = elem->data;
|
||||||
|
if(component->component_draw) component->component_draw(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void draw_entity(entity_t *entity)
|
||||||
|
{
|
||||||
|
linked_list_for_each(&entity->components, action_draw_component);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void destroy_entity(entity_t *entity)
|
||||||
|
{
|
||||||
|
linked_list_clear(&entity->components);
|
||||||
|
kfree(entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void entity_manager_init(entity_manager_t *entity_manager)
|
||||||
|
{
|
||||||
|
linked_list_init(&entity_manager->entities, sizeof(entity_t), (deleter_t)destroy_entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline entity_t *entity_manager_add_entity(entity_manager_t *entity_manager, const char *name)
|
||||||
|
{
|
||||||
|
entity_t *entity = create_entity(name);
|
||||||
|
linked_list_push_back(&entity_manager->entities, entity);
|
||||||
|
return entity;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only for this file
|
||||||
|
static inline void action_update_entity(elem_t *elem, va_list args __attribute__((unused)))
|
||||||
|
{
|
||||||
|
update_entity(elem->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void entity_manager_update(entity_manager_t *entity_manager)
|
||||||
|
{
|
||||||
|
linked_list_for_each(&entity_manager->entities, action_update_entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only for this file
|
||||||
|
static inline void action_draw_entity(elem_t *elem, va_list args __attribute__((unused)))
|
||||||
|
{
|
||||||
|
draw_entity(elem->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void entity_manager_draw(entity_manager_t *entity_manager)
|
||||||
|
{
|
||||||
|
linked_list_for_each(&entity_manager->entities, action_draw_entity);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only for this file
|
||||||
|
static inline bool condition_is_entity_name(elem_t *elem, va_list args)
|
||||||
|
{
|
||||||
|
return ((entity_t *)elem->data)->name == va_arg(args, const char *);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void entity_manager_remove_entity(entity_manager_t *entity_manager, const char *name)
|
||||||
|
{
|
||||||
|
linked_list_remove_if(&entity_manager->entities, condition_is_entity_name, name);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void entity_manager_clear(entity_manager_t *entity_manager)
|
||||||
|
{
|
||||||
|
linked_list_clear(&entity_manager->entities);
|
||||||
|
}
|
|
@ -0,0 +1,84 @@
|
||||||
|
#ifndef ECS_H
|
||||||
|
#define ECS_H
|
||||||
|
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include "../linked_list.h"
|
||||||
|
|
||||||
|
typedef enum component_type_t {
|
||||||
|
TRANSFORM_COMPONENT,
|
||||||
|
SPRITE_COMPONENT,
|
||||||
|
ANIMATION_SYSTEM,
|
||||||
|
PLAYER_SYSTEM
|
||||||
|
} component_type_t;
|
||||||
|
|
||||||
|
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;
|
||||||
|
typedef struct player_system_data_t player_system_data_t;
|
||||||
|
|
||||||
|
typedef struct component_t component_t;
|
||||||
|
|
||||||
|
typedef void (*component_init_t)(component_t *, va_list);
|
||||||
|
typedef void (*component_update_t)(component_t *);
|
||||||
|
typedef void (*component_draw_t)(component_t *);
|
||||||
|
|
||||||
|
typedef void (*component_deleter_t)(component_t *);
|
||||||
|
|
||||||
|
typedef struct component_t {
|
||||||
|
component_type_t component_type;
|
||||||
|
|
||||||
|
struct entity_t *entity;
|
||||||
|
|
||||||
|
component_init_t component_init;
|
||||||
|
component_update_t component_update;
|
||||||
|
component_draw_t component_draw;
|
||||||
|
|
||||||
|
union {
|
||||||
|
transform_component_data_t *transform_component_data;
|
||||||
|
sprite_component_data_t *sprite_component_data;
|
||||||
|
animation_system_data_t *animation_system_data;
|
||||||
|
player_system_data_t *player_system_data;
|
||||||
|
} component_data;
|
||||||
|
|
||||||
|
component_deleter_t component_deleter;
|
||||||
|
} component_t;
|
||||||
|
|
||||||
|
component_t *create_component(component_type_t);
|
||||||
|
|
||||||
|
void destroy_component(component_t *);
|
||||||
|
|
||||||
|
typedef struct entity_t {
|
||||||
|
const char *name;
|
||||||
|
size_t draw_priority;
|
||||||
|
linked_list_t components;
|
||||||
|
} entity_t;
|
||||||
|
|
||||||
|
entity_t *create_entity(const char *name);
|
||||||
|
|
||||||
|
void add_component(entity_t *, component_t *, ...);
|
||||||
|
|
||||||
|
component_t *get_component(entity_t *, component_type_t);
|
||||||
|
|
||||||
|
void update_entity(entity_t *);
|
||||||
|
|
||||||
|
void draw_entity(entity_t *);
|
||||||
|
|
||||||
|
void destroy_entity(entity_t *);
|
||||||
|
|
||||||
|
typedef struct entity_manager_t {
|
||||||
|
linked_list_t entities;
|
||||||
|
} entity_manager_t;
|
||||||
|
|
||||||
|
void entity_manager_init(entity_manager_t *);
|
||||||
|
|
||||||
|
entity_t *entity_manager_add_entity(entity_manager_t *, const char *);
|
||||||
|
|
||||||
|
void entity_manager_update(entity_manager_t *);
|
||||||
|
|
||||||
|
void entity_manager_draw(entity_manager_t *);
|
||||||
|
|
||||||
|
void entity_manager_remove_entity(entity_manager_t *, const char *);
|
||||||
|
|
||||||
|
void entity_manager_clear(entity_manager_t *);
|
||||||
|
|
||||||
|
#endif // ECS_H
|
|
@ -0,0 +1,79 @@
|
||||||
|
#include <gint/kmalloc.h>
|
||||||
|
#include "player_system.h"
|
||||||
|
#include "animation_system.h"
|
||||||
|
#include "sprite_component.h"
|
||||||
|
#include "transform_component.h"
|
||||||
|
#include "../game.h"
|
||||||
|
|
||||||
|
// No args
|
||||||
|
void player_system_init(component_t *component, va_list args __attribute__((unused)))
|
||||||
|
{
|
||||||
|
player_system_data_t *system_data = component->component_data.player_system_data;
|
||||||
|
|
||||||
|
system_data->animation_system_data = get_component(component->entity, ANIMATION_SYSTEM)->component_data.animation_system_data;
|
||||||
|
system_data->sprite_component_data = system_data->animation_system_data->sprite_component_data;
|
||||||
|
system_data->transform_component_data = system_data->sprite_component_data->transform_component_data;
|
||||||
|
|
||||||
|
system_data->state = IDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only for this file
|
||||||
|
static void player_system_get_inputs(component_t *component)
|
||||||
|
{
|
||||||
|
player_system_data_t *system_data = component->component_data.player_system_data;
|
||||||
|
|
||||||
|
system_data->last_state = system_data->state;
|
||||||
|
|
||||||
|
system_data->state &= 0xF0;
|
||||||
|
|
||||||
|
system_data->state |= game.event.keys[KEY_UP] * RUNNING_UP;
|
||||||
|
system_data->state |= game.event.keys[KEY_DOWN] * RUNNING_DOWN;
|
||||||
|
system_data->state |= game.event.keys[KEY_LEFT] * RUNNING_LEFT;
|
||||||
|
system_data->state |= game.event.keys[KEY_RIGHT] * RUNNING_RIGHT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only for this file
|
||||||
|
static void player_system_set_state_velocity_and_animation(component_t *component)
|
||||||
|
{
|
||||||
|
player_system_data_t *system_data = component->component_data.player_system_data;
|
||||||
|
transform_component_data_t *transform_component_data = system_data->transform_component_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;
|
||||||
|
|
||||||
|
transform_component_data->velocity.x =
|
||||||
|
(float)((system_data->state & RUNNING_RIGHT) >> 3) - (float)((system_data->state & RUNNING_LEFT) >> 2);
|
||||||
|
transform_component_data->velocity.y =
|
||||||
|
(float)((system_data->state & RUNNING_DOWN) >> 1) - (float)(system_data->state & RUNNING_UP);
|
||||||
|
|
||||||
|
if(system_data->state & RUNNING_LEFT) sprite_component_data->flip = true;
|
||||||
|
if(system_data->state & RUNNING_RIGHT) sprite_component_data->flip = false;
|
||||||
|
|
||||||
|
if(is_not_zero(transform_component_data->velocity.x) && is_not_zero(transform_component_data->velocity.y))
|
||||||
|
{
|
||||||
|
transform_component_data->velocity.x *= 0.707106781186548f;
|
||||||
|
transform_component_data->velocity.y *= 0.707106781186548f;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((system_data->state & RUNNING) && !(system_data->last_state & RUNNING))
|
||||||
|
{
|
||||||
|
animation_system_data->frame_delay_ms = 200;
|
||||||
|
animation_system_change_animation(animation_system_data, "player_run_sheet", 6);
|
||||||
|
}
|
||||||
|
else if(!(system_data->state & RUNNING) && (system_data->last_state & RUNNING))
|
||||||
|
{
|
||||||
|
animation_system_data->actual_frame_nb = 0;
|
||||||
|
animation_system_data->frame_delay_ms = 200;
|
||||||
|
animation_system_change_animation(animation_system_data, "player_idle_sheet", 4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void player_system_update(component_t *component)
|
||||||
|
{
|
||||||
|
player_system_get_inputs(component);
|
||||||
|
player_system_set_state_velocity_and_animation(component);
|
||||||
|
}
|
||||||
|
|
||||||
|
void player_system_destroy(component_t *component)
|
||||||
|
{
|
||||||
|
kfree(component->component_data.player_system_data);
|
||||||
|
}
|
|
@ -0,0 +1,32 @@
|
||||||
|
#ifndef PLAYER_SYSTEM_H
|
||||||
|
#define PLAYER_SYSTEM_H
|
||||||
|
|
||||||
|
#include "ecs.h"
|
||||||
|
#include "transform_component.h"
|
||||||
|
|
||||||
|
typedef enum player_state_t {
|
||||||
|
IDLE = 0x00, // 00000000
|
||||||
|
RUNNING_UP = 0x01, // 00000001
|
||||||
|
RUNNING_DOWN = 0x02, // 00000010
|
||||||
|
RUNNING_LEFT = 0x04, // 00000100
|
||||||
|
RUNNING_RIGHT = 0x08, // 00001000
|
||||||
|
RUNNING = 0x0F, // 00001111
|
||||||
|
DEATH = 0x80 // 10000000
|
||||||
|
} player_state_t;
|
||||||
|
|
||||||
|
typedef struct player_system_data_t {
|
||||||
|
transform_component_data_t *transform_component_data;
|
||||||
|
sprite_component_data_t *sprite_component_data;
|
||||||
|
animation_system_data_t *animation_system_data;
|
||||||
|
|
||||||
|
player_state_t state;
|
||||||
|
player_state_t last_state;
|
||||||
|
} player_system_data_t;
|
||||||
|
|
||||||
|
void player_system_init(component_t *, va_list);
|
||||||
|
|
||||||
|
void player_system_update(component_t *);
|
||||||
|
|
||||||
|
void player_system_destroy(component_t *);
|
||||||
|
|
||||||
|
#endif // PLAYER_SYSTEM_H
|
|
@ -0,0 +1,41 @@
|
||||||
|
#include <gint/kmalloc.h>
|
||||||
|
#include "sprite_component.h"
|
||||||
|
#include "../game.h"
|
||||||
|
|
||||||
|
// Arg : const char *name
|
||||||
|
void sprite_component_init(component_t *component, va_list args)
|
||||||
|
{
|
||||||
|
sprite_component_data_t *component_data = component->component_data.sprite_component_data;
|
||||||
|
|
||||||
|
component_data->transform_component_data = get_component(component->entity, TRANSFORM_COMPONENT)->component_data.transform_component_data;
|
||||||
|
|
||||||
|
component_data->srcR = component_data->transform_component_data->bounds;
|
||||||
|
component_data->srcR.x = 0;
|
||||||
|
component_data->srcR.y = 0;
|
||||||
|
|
||||||
|
component_data->flip = false;
|
||||||
|
|
||||||
|
sprite_component_set_texture(component_data, va_arg(args, const char *));
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void sprite_component_update(component_t *component)
|
||||||
|
{
|
||||||
|
sprite_component_data_t *component_data = component->component_data.sprite_component_data;
|
||||||
|
component_data->dstR = component_data->transform_component_data->bounds;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void sprite_component_draw(component_t *component)
|
||||||
|
{
|
||||||
|
sprite_component_data_t *component_data = component->component_data.sprite_component_data;
|
||||||
|
draw_texture(component_data->texture, &component_data->srcR, &component_data->dstR, component_data->flip);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void sprite_component_destroy(component_t *component)
|
||||||
|
{
|
||||||
|
kfree(component->component_data.sprite_component_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void sprite_component_set_texture(sprite_component_data_t *component_data, const char *name)
|
||||||
|
{
|
||||||
|
component_data->texture = texture_manager_get_texture(&game.texture_manager, name);
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
#ifndef SPRITE_COMPONENT_H
|
||||||
|
#define SPRITE_COMPONENT_H
|
||||||
|
|
||||||
|
#include "ecs.h"
|
||||||
|
#include "transform_component.h"
|
||||||
|
#include "../texture_manager.h"
|
||||||
|
|
||||||
|
typedef struct sprite_component_data_t {
|
||||||
|
transform_component_data_t *transform_component_data;
|
||||||
|
|
||||||
|
texture_t *texture;
|
||||||
|
|
||||||
|
rect_t srcR;
|
||||||
|
rect_t dstR;
|
||||||
|
|
||||||
|
bool flip;
|
||||||
|
} sprite_component_data_t;
|
||||||
|
|
||||||
|
void sprite_component_init(component_t *, va_list);
|
||||||
|
|
||||||
|
void sprite_component_update(component_t *);
|
||||||
|
|
||||||
|
void sprite_component_draw(component_t *);
|
||||||
|
|
||||||
|
void sprite_component_destroy(component_t *);
|
||||||
|
|
||||||
|
void sprite_component_set_texture(sprite_component_data_t *, const char *);
|
||||||
|
|
||||||
|
#endif // SPRITE_COMPONENT_H
|
|
@ -0,0 +1,32 @@
|
||||||
|
#include <gint/kmalloc.h>
|
||||||
|
#include "transform_component.h"
|
||||||
|
#include "../game.h"
|
||||||
|
|
||||||
|
// Args : rect_t bounds, double speed
|
||||||
|
void transform_component_init(component_t *component, va_list args)
|
||||||
|
{
|
||||||
|
transform_component_data_t *const component_data = component->component_data.transform_component_data;
|
||||||
|
|
||||||
|
rect_t bounds = va_arg(args, rect_t);
|
||||||
|
float speed = (float)va_arg(args, double);
|
||||||
|
|
||||||
|
component_data->bounds = bounds;
|
||||||
|
|
||||||
|
component_data->velocity.x = 0;
|
||||||
|
component_data->velocity.y = 0;
|
||||||
|
|
||||||
|
component_data->speed = speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void transform_component_update(component_t *component)
|
||||||
|
{
|
||||||
|
transform_component_data_t *component_data = component->component_data.transform_component_data;
|
||||||
|
|
||||||
|
component_data->bounds.x += component_data->velocity.x * component_data->speed * (float)game.delta_time_ms / 1000.0f;
|
||||||
|
component_data->bounds.y += component_data->velocity.y * component_data->speed * (float)game.delta_time_ms / 1000.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void transform_component_destroy(component_t *component)
|
||||||
|
{
|
||||||
|
kfree(component->component_data.transform_component_data);
|
||||||
|
}
|
|
@ -0,0 +1,19 @@
|
||||||
|
#ifndef TRANSFORM_COMPONENT_H
|
||||||
|
#define TRANSFORM_COMPONENT_H
|
||||||
|
|
||||||
|
#include "ecs.h"
|
||||||
|
#include "../vector2d.h"
|
||||||
|
|
||||||
|
typedef struct transform_component_data_t {
|
||||||
|
rect_t bounds;
|
||||||
|
vector2d_t velocity;
|
||||||
|
float speed;
|
||||||
|
} transform_component_data_t;
|
||||||
|
|
||||||
|
void transform_component_init(component_t *, va_list);
|
||||||
|
|
||||||
|
void transform_component_update(component_t *);
|
||||||
|
|
||||||
|
void transform_component_destroy(component_t *);
|
||||||
|
|
||||||
|
#endif // TRANSFORM_COMPONENT_H
|
|
@ -3,7 +3,8 @@
|
||||||
|
|
||||||
#include <gint/keycodes.h>
|
#include <gint/keycodes.h>
|
||||||
|
|
||||||
typedef struct {
|
// Base struct
|
||||||
|
typedef struct event_t {
|
||||||
bool keys[0xa6];
|
bool keys[0xa6];
|
||||||
} event_t;
|
} event_t;
|
||||||
|
|
||||||
|
|
68
src/game.c
68
src/game.c
|
@ -1,11 +1,69 @@
|
||||||
#include <gint/kmalloc.h>
|
#include <gint/keyboard.h>
|
||||||
|
#include <gint/display.h>
|
||||||
#include "game.h"
|
#include "game.h"
|
||||||
|
#include "ecs/components.h"
|
||||||
|
|
||||||
int game_init(game_t *game)
|
void game_init(void)
|
||||||
{
|
{
|
||||||
game = kmalloc(sizeof(game_t), NULL);
|
texture_manager_init(&game.texture_manager);
|
||||||
|
texture_manager_load_builtin_textures(&game.texture_manager);
|
||||||
|
|
||||||
if(game == NULL) return 1;
|
entity_manager_init(&game.entity_manager);
|
||||||
|
|
||||||
return 0;
|
entity_t *player = entity_manager_add_entity(&game.entity_manager, "player");
|
||||||
|
|
||||||
|
rect_t player_bounds = {10.0f, 10.0f, 32.0f, 32.0f};
|
||||||
|
float player_speed = 50.0f;
|
||||||
|
|
||||||
|
add_component(player, create_component(TRANSFORM_COMPONENT), player_bounds, player_speed);
|
||||||
|
add_component(player, create_component(SPRITE_COMPONENT), "player_idle_sheet");
|
||||||
|
add_component(player, create_component(ANIMATION_SYSTEM), 4, 0, 200.0f, true, true, false);
|
||||||
|
add_component(player, create_component(PLAYER_SYSTEM));
|
||||||
|
|
||||||
|
game.last_clock_state = clock();
|
||||||
|
|
||||||
|
game.is_running = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_handle_event(void)
|
||||||
|
{
|
||||||
|
key_event_t key_event;
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
key_event = pollevent();
|
||||||
|
|
||||||
|
if (key_event.type == KEYEV_DOWN)
|
||||||
|
game.event.keys[key_event.key] = true;
|
||||||
|
else if (key_event.type == KEYEV_UP)
|
||||||
|
game.event.keys[key_event.key] = false;
|
||||||
|
|
||||||
|
if (key_event.type == KEYEV_DOWN && key_event.key == KEY_EXIT)
|
||||||
|
game.is_running = false;
|
||||||
|
}
|
||||||
|
while (key_event.type != KEYEV_NONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_update(void)
|
||||||
|
{
|
||||||
|
clock_t start_clock = clock();
|
||||||
|
game.delta_time_ms = (double)(start_clock - game.last_clock_state) * 1000.0f / CLOCKS_PER_SEC;
|
||||||
|
game.last_clock_state = start_clock;
|
||||||
|
|
||||||
|
entity_manager_update(&game.entity_manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_render(void)
|
||||||
|
{
|
||||||
|
dclear(C_WHITE);
|
||||||
|
|
||||||
|
entity_manager_draw(&game.entity_manager);
|
||||||
|
|
||||||
|
dupdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void game_exit(void)
|
||||||
|
{
|
||||||
|
entity_manager_clear(&game.entity_manager);
|
||||||
|
texture_manager_clear(&game.texture_manager);
|
||||||
}
|
}
|
28
src/game.h
28
src/game.h
|
@ -1,25 +1,31 @@
|
||||||
#ifndef GAME_H
|
#ifndef GAME_H
|
||||||
#define GAME_H
|
#define GAME_H
|
||||||
|
|
||||||
#include <gint/defs/types.h>
|
#include <time.h>
|
||||||
#include "event.h"
|
#include "event.h"
|
||||||
#include "texture_manager.h"
|
#include "texture_manager.h"
|
||||||
|
#include "ecs/ecs.h"
|
||||||
|
|
||||||
#define WINDOW_WIDTH 396
|
typedef struct game_t {
|
||||||
#define WINDOW_HEIGHT 224
|
|
||||||
|
|
||||||
typedef struct {
|
|
||||||
event_t event;
|
event_t event;
|
||||||
texture_manager_t *texture_manager;
|
texture_manager_t texture_manager;
|
||||||
|
entity_manager_t entity_manager;
|
||||||
|
|
||||||
bool is_running;
|
bool is_running;
|
||||||
|
clock_t last_clock_state;
|
||||||
|
double delta_time_ms;
|
||||||
} game_t;
|
} game_t;
|
||||||
|
|
||||||
int game_init(game_t*);
|
extern game_t game;
|
||||||
|
|
||||||
int game_handle_event(game_t*);
|
void game_init(void);
|
||||||
int game_update(game_t*);
|
|
||||||
int game_render(game_t*);
|
|
||||||
|
|
||||||
int game_exit(game_t*);
|
void game_handle_event(void);
|
||||||
|
|
||||||
|
void game_update(void);
|
||||||
|
|
||||||
|
void game_render(void);
|
||||||
|
|
||||||
|
void game_exit(void);
|
||||||
|
|
||||||
#endif // GAME_H
|
#endif // GAME_H
|
31
src/main.c
31
src/main.c
|
@ -1,19 +1,32 @@
|
||||||
//#include "game.h"
|
#include <gint/defs/types.h>
|
||||||
/*
|
|
||||||
|
//#include <gint/gdb.h>
|
||||||
|
|
||||||
|
#include "game.h"
|
||||||
|
|
||||||
|
//#define TEXTURE_TEST
|
||||||
|
//#define LINKED_LIST_TEST
|
||||||
|
|
||||||
|
game_t game;
|
||||||
|
|
||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
game_t *game;
|
//gdb_start();
|
||||||
|
|
||||||
game_init(game);
|
//__asm__("trapa #42");
|
||||||
|
|
||||||
while(game->is_running)
|
game_init();
|
||||||
|
|
||||||
|
while(game.is_running)
|
||||||
{
|
{
|
||||||
game_handle_event(game);
|
game_handle_event();
|
||||||
game_update(game);
|
game_update();
|
||||||
game_render(game);
|
game_render();
|
||||||
}
|
}
|
||||||
|
|
||||||
return game_exit(game);
|
game_exit();
|
||||||
|
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,28 @@
|
||||||
#include "vector2d.h"
|
#include "vector2d.h"
|
||||||
|
|
||||||
|
__attribute__((const)) float fabsf(float x)
|
||||||
|
{
|
||||||
|
union {
|
||||||
|
float f;
|
||||||
|
uint32_t i;
|
||||||
|
} u = { x };
|
||||||
|
|
||||||
|
u.i &= 0x7FFFFFFF;
|
||||||
|
return u.f;
|
||||||
|
}
|
||||||
|
|
||||||
bool has_intersection(const rect_t * A, const rect_t * B)
|
bool has_intersection(const rect_t * A, const rect_t * B)
|
||||||
{
|
{
|
||||||
int Amin, Amax, Bmin, Bmax;
|
float Amin, Amax, Bmin, Bmax;
|
||||||
|
|
||||||
if (!A || !B) {
|
if (!A || !B)
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Special cases for empty rects */
|
/* Special cases for empty rects */
|
||||||
if (rect_empty(A) || rect_empty(B)) {
|
if (rect_empty(A) || rect_empty(B))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,18 +55,20 @@ bool has_intersection(const rect_t * A, const rect_t * B)
|
||||||
|
|
||||||
bool intersect_rect(const rect_t * A, const rect_t * B, rect_t * result)
|
bool intersect_rect(const rect_t * A, const rect_t * B, rect_t * result)
|
||||||
{
|
{
|
||||||
int Amin, Amax, Bmin, Bmax;
|
if (!A || !B || !result)
|
||||||
|
{
|
||||||
if (!A || !B || !result) {
|
|
||||||
// TODO error message
|
// TODO error message
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Special cases for empty rects */
|
/* Special cases for empty rects */
|
||||||
if (rect_empty(A) || rect_empty(B)) {
|
if (rect_empty(A) || rect_empty(B))
|
||||||
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
float Amin, Amax, Bmin, Bmax;
|
||||||
|
|
||||||
/* Horizontal intersection */
|
/* Horizontal intersection */
|
||||||
Amin = A->x;
|
Amin = A->x;
|
||||||
Amax = Amin + A->w;
|
Amax = Amin + A->w;
|
||||||
|
|
|
@ -10,22 +10,67 @@
|
||||||
|
|
||||||
#include <gint/defs/types.h>
|
#include <gint/defs/types.h>
|
||||||
|
|
||||||
typedef struct {
|
/* vector2d_t: A point in space
|
||||||
int x, y;
|
This struct is the base for storing 2D positions.
|
||||||
|
|
||||||
|
@x X pos of the vector
|
||||||
|
@y Y pos of the vector */
|
||||||
|
typedef struct vector2d_t {
|
||||||
|
float x, y;
|
||||||
} vector2d_t;
|
} vector2d_t;
|
||||||
|
|
||||||
typedef struct {
|
/* vector2d_t: A point in space
|
||||||
int x, y;
|
This struct is the base for storing 2D positions.
|
||||||
int w, h;
|
|
||||||
|
@x X pos of the rectangle
|
||||||
|
@y Y pos of the rectangle
|
||||||
|
@w Width of the rectangle
|
||||||
|
@h Height of the rectangle */
|
||||||
|
typedef struct rect_t {
|
||||||
|
float x, y;
|
||||||
|
float w, h;
|
||||||
} rect_t;
|
} rect_t;
|
||||||
|
|
||||||
|
#define EPSILON 0.000001f
|
||||||
|
|
||||||
|
__attribute__((const)) float fabsf(float x);
|
||||||
|
|
||||||
|
#define is_equal_to_zero(X) (fabsf(X) <= EPSILON)
|
||||||
|
|
||||||
|
#define is_not_zero(X) (fabsf(X) > EPSILON)
|
||||||
|
|
||||||
|
/* point_in_rect(): Verify if a point is in a rectangle
|
||||||
|
This function is useful for verify if a point is in a rectangle.
|
||||||
|
|
||||||
|
@P A Vector2d
|
||||||
|
@R A rectangle
|
||||||
|
Return true if the condition is validated else false. */
|
||||||
#define point_in_rect(P, R) (((P)->x >= (R)->x) && ((P)->x < ((R)->x + (R)->w)) && \
|
#define point_in_rect(P, R) (((P)->x >= (R)->x) && ((P)->x < ((R)->x + (R)->w)) && \
|
||||||
((P)->y >= (R)->y) && ((P)->y < ((R)->y + (R)->h)))
|
((P)->y >= (R)->y) && ((P)->y < ((R)->y + (R)->h)))
|
||||||
|
|
||||||
#define rect_empty(X) ((!(X)) || ((X)->w <= 0) || ((X)->h <= 0))
|
/* rect_empty(): Verify if a rectangle is empty
|
||||||
|
This function is useful for verify if a rectangle exists.
|
||||||
|
|
||||||
bool has_intersection(const rect_t * A, const rect_t * B);
|
@R A rectangle
|
||||||
|
Return true if the condition is validated else false. */
|
||||||
|
#define rect_empty(R) ((!(R)) || (is_equal_to_zero((R)->w)) || (is_equal_to_zero((R)->h)))
|
||||||
|
|
||||||
bool intersect_rect(const rect_t * A, const rect_t * B, rect_t * result);
|
/* has_intersection(): Verify if there is a intersction between two rectangles
|
||||||
|
This function is useful for verify intersection between two rectangles.
|
||||||
|
|
||||||
|
@A A rectangle
|
||||||
|
@B Another rectangle
|
||||||
|
Return true if the condition is validated else false. */
|
||||||
|
bool has_intersection(const rect_t *, const rect_t *);
|
||||||
|
|
||||||
|
/* intersect_rect(): Like has_intersection but has a result rectangle
|
||||||
|
This function is useful for verify intersection between two rectangles
|
||||||
|
and get the intersection rectangle.
|
||||||
|
|
||||||
|
@A A rectangle
|
||||||
|
@B Another rectangle
|
||||||
|
@result The intersection rectangle
|
||||||
|
Return true if the condition is validated else false. */
|
||||||
|
bool intersect_rect(const rect_t *, const rect_t *, rect_t *);
|
||||||
|
|
||||||
#endif // VECTOR2D_H
|
#endif // VECTOR2D_H
|
Loading…
Reference in New Issue