feat: reworked typeclasses to forward-declare then define

forward declarations are simplified with decl_typeclass_impl
impl_Typeclass_for now instead only define
static inline impl_Typeclass_for can be used to achieve the old behaviour
This commit is contained in:
Sara 2024-01-12 09:02:42 +01:00
parent 760d9f2879
commit 0c6f1dd8cf
24 changed files with 174 additions and 119 deletions

View file

@ -19,7 +19,7 @@ typedef struct Asset {
} Asset;
#define impl_Asset_for(T, get_id_f, set_id_f)\
static inline Asset T##_as_Asset(T* x) {\
Asset T##_as_Asset(T* x) {\
TC_FN_TYPECHECK(asset_id, get_id_f, T*);\
TC_FN_TYPECHECK(void, set_id_f, T*, asset_id);\
TC_FN_TYPECHECK(Drop, T##_as_Drop, T*);\

View file

@ -2,8 +2,8 @@
#define _update_entity_h
#include "drop.h"
#include "mirror.h"
#include "typeclass_helpers.h"
#include "vmath.h"
typedef struct {
void (*const update)(void* self, float dt);
@ -16,10 +16,11 @@ typedef struct {
void* data;
IEntityBehaviour const* tc;
IDrop const* drop;
IMirror const* mirror;
} BehaviourEntity;
#define impl_BehaviourEntity_for(T, start_f, update_f, draw_f, get_depth_f)\
static inline BehaviourEntity T##_as_BehaviourEntity(T* x) {\
BehaviourEntity T##_as_BehaviourEntity(T* x) {\
TC_FN_TYPECHECK(void, start_f, T*);\
TC_FN_TYPECHECK(void, update_f, T*, float);\
TC_FN_TYPECHECK(void, draw_f, T*);\
@ -31,8 +32,10 @@ static inline BehaviourEntity T##_as_BehaviourEntity(T* x) {\
.get_depth=(long(*const)(void*)) get_depth_f,\
};\
TC_FN_TYPECHECK(Drop, T##_as_Drop, T*);\
TC_FN_TYPECHECK(Mirror, T##_as_Mirror, T*);\
IDrop const* drop = T##_as_Drop(x).tc;\
return (BehaviourEntity){.tc = &tc, .drop = drop, .data = x};\
IMirror const* mirror = T##_as_Mirror(x).tc;\
return (BehaviourEntity){.data = x, .tc = &tc, .drop = drop, .mirror = mirror};\
}\
#endif // !_update_entity_h

View file

@ -13,7 +13,7 @@ typedef struct {
} Drop;
#define impl_Drop_for(T, drop_f)\
static inline Drop T##_as_Drop(T* x) {\
Drop T##_as_Drop(T* x) {\
TC_FN_TYPECHECK(void, drop_f, T*);\
static IDrop const tc = {\
.drop = (void(*const)(void*)) drop_f,\
@ -24,7 +24,7 @@ static inline Drop T##_as_Drop(T* x) {\
extern void default_drop(void*);
#define impl_default_Drop_for(T)\
static inline Drop T##_as_Drop(T* x) {\
Drop T##_as_Drop(T* x) {\
static IDrop const tc = {\
.drop = default_drop,\
};\

View file

@ -2,6 +2,42 @@
#include "debug.h"
#include "input.h"
impl_default_Drop_for(
KeyBind
)
impl_InputAxis_for(KeyBind,
keybind_is_changed_by,
keybind_evaluate,
keybind_set_device
)
impl_default_Drop_for(
ControllerAxis
)
impl_InputAxis_for(ControllerAxis,
controlleraxis_is_changed_by,
controlleraxis_evaluate,
controlleraxis_set_device
)
impl_default_Drop_for(
ControllerButton
)
impl_InputAxis_for(ControllerButton,
controllerbutton_is_changed_by,
controllerbutton_evaluate,
controllerbutton_set_device
)
impl_Drop_for(CompositeAxis1D,
compositeaxis1d_drop
)
impl_InputAxis_for(CompositeAxis1D,
compositeaxis1d_is_changed_by,
compositeaxis1d_evaluate,
compositeaxis1d_set_device
)
KeyBind* keybind_new(SDL_Scancode key) {
KeyBind* self = malloc(sizeof(KeyBind));
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate space for KeyBind instance");

View file

@ -40,7 +40,7 @@ typedef struct {
} InputAxis;
#define impl_InputAxis_for(T, is_changed_by_f, evaluate_f, set_device_f)\
static inline InputAxis T##_as_InputAxis(T* x) {\
InputAxis T##_as_InputAxis(T* x) {\
TC_FN_TYPECHECK(int, is_changed_by_f, T*, SDL_Event);\
TC_FN_TYPECHECK(struct InputEvent, evaluate_f, T*, SDL_Event);\
TC_FN_TYPECHECK(void, set_device_f, T*, struct InputDevice*);\
@ -64,12 +64,8 @@ extern int keybind_is_changed_by(KeyBind* self, SDL_Event event);
extern struct InputEvent keybind_evaluate(KeyBind* self, SDL_Event);
extern void keybind_set_device(KeyBind* self, struct InputDevice* device);
impl_default_Drop_for(KeyBind)
impl_InputAxis_for(KeyBind,
keybind_is_changed_by,
keybind_evaluate,
keybind_set_device
)
decl_typeclass_impl(InputAxis, KeyBind)
decl_typeclass_impl(Drop, KeyBind)
typedef struct ControllerAxis {
struct InputDevice* device;
@ -81,12 +77,8 @@ extern int controlleraxis_is_changed_by(ControllerAxis* self, SDL_Event event);
extern struct InputEvent controlleraxis_evaluate(ControllerAxis* self, SDL_Event event);
extern void controlleraxis_set_device(ControllerAxis* self, struct InputDevice* device);
impl_default_Drop_for(ControllerAxis)
impl_InputAxis_for(ControllerAxis,
controlleraxis_is_changed_by,
controlleraxis_evaluate,
controlleraxis_set_device
)
decl_typeclass_impl(InputAxis, ControllerAxis)
decl_typeclass_impl(Drop, ControllerAxis)
typedef struct ControllerButton {
struct InputDevice* device;
@ -98,12 +90,8 @@ extern int controllerbutton_is_changed_by(ControllerButton* self, SDL_Event even
extern struct InputEvent controllerbutton_evaluate(ControllerButton* self, SDL_Event event);
extern void controllerbutton_set_device(ControllerButton* self, struct InputDevice* device);
impl_default_Drop_for(ControllerButton)
impl_InputAxis_for(ControllerButton,
controllerbutton_is_changed_by,
controllerbutton_evaluate,
controllerbutton_set_device
)
decl_typeclass_impl(InputAxis, ControllerButton)
decl_typeclass_impl(Drop, ControllerButton)
typedef struct CompositeAxis1D {
InputAxis left;
@ -117,13 +105,7 @@ extern struct InputEvent compositeaxis1d_evaluate(CompositeAxis1D* self, SDL_Eve
extern void compositeaxis1d_set_device(CompositeAxis1D* self, struct InputDevice* device);
extern void compositeaxis1d_drop(CompositeAxis1D* self);
impl_Drop_for(CompositeAxis1D,
compositeaxis1d_drop
)
impl_InputAxis_for(CompositeAxis1D,
compositeaxis1d_is_changed_by,
compositeaxis1d_evaluate,
compositeaxis1d_set_device
)
decl_typeclass_impl(InputAxis, CompositeAxis1D)
decl_typeclass_impl(Drop, CompositeAxis1D)
#endif // !_fencer_input_axis_h

View file

@ -5,6 +5,7 @@
#include "transform.h"
#include "stdint.h"
#include "physics_entity.h"
#include "shape.h"
typedef uint32_t PhysicsMask;

View file

@ -29,7 +29,7 @@ extern void physics_entity_solve_contacts(PhysicsEntity self, List* contacts);
extern void physics_entity_update(PhysicsEntity self);
#define impl_PhysicsEntity_for(T, get_rigidbody_f, on_collision_f, on_overlap_f)\
static inline PhysicsEntity T##_as_PhysicsEntity(T* x) {\
PhysicsEntity T##_as_PhysicsEntity(T* x) {\
TC_FN_TYPECHECK(RigidBody*, get_rigidbody_f, T*);\
TC_FN_TYPECHECK(void, on_collision_f, T*, Collision);\
TC_FN_TYPECHECK(void, on_overlap_f, T*, Collider*);\

View file

@ -1,6 +1,10 @@
#include "player_input.h"
#include "debug.h"
impl_Drop_for(PlayerInput,
playerinput_drop
)
PlayerInput* playerinput_new(void* target, int device) {
PlayerInput* self = malloc(sizeof(PlayerInput));
ASSERT_RETURN(self != NULL, NULL, "Could not allocate memory for PlayerInput instance");

View file

@ -4,6 +4,7 @@
#include "list.h"
#include "input.h"
#include "input_axis.h"
#include "typeclass_helpers.h"
typedef struct PlayerInput {
InputDevice* device;
@ -16,8 +17,6 @@ extern void playerinput_add(PlayerInput* self, InputAxis axis, InputDelegateFn d
extern void playerinput_set_device(PlayerInput* self, int device);
extern void playerinput_drop(PlayerInput* self);
impl_Drop_for(PlayerInput,
playerinput_drop
)
decl_typeclass_impl(Drop, PlayerInput)
#endif // !_fencer_player_input_h

View file

@ -26,6 +26,10 @@ struct RigidBody {
List contacts;
};
impl_Transformable_for(RigidBody,
rigidbody_get_transform
)
RigidBody* rigidbody_make(PhysicsEntity owner) {
RigidBody* self = malloc(sizeof(RigidBody));
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate space for rigidbody");

View file

@ -1,10 +1,8 @@
#ifndef _fencer_rigidbody_h
#define _fencer_rigidbody_h
#include "shape.h"
#include "transformable.h"
#include "list.h"
#include "stdint.h"
#include "physics.h"
typedef struct {
@ -61,8 +59,6 @@ extern void rigidbody_debug_draw_contacts(RigidBody* self);
extern Transform* rigidbody_get_transform(RigidBody* self);
impl_Transformable_for(RigidBody,
rigidbody_get_transform
)
decl_typeclass_impl(Transformable, RigidBody)
#endif // !_fencer_rigidbody_h

View file

@ -20,6 +20,15 @@ struct Spritesheet {
IVector tile_size;
};
impl_Drop_for(Spritesheet,
_internal_spritesheet_destroy
)
impl_Asset_for(Spritesheet,
spritesheet_get_asset_id,
spritesheet_set_asset_id
)
void _internal_spritesheet_destroy(Spritesheet* self) {
SDL_DestroyTexture(self->texture);
free(self);

View file

@ -2,6 +2,7 @@
#define _fencer_spritesheet_h
#include "asset.h"
#include "typeclass_helpers.h"
#include "vmath.h"
#include <SDL2/SDL_render.h>
@ -21,13 +22,7 @@ extern void spritesheet_set_asset_id(Spritesheet* self, asset_id id);
extern void _internal_spritesheet_destroy(Spritesheet* self_void);
impl_Drop_for(Spritesheet,
_internal_spritesheet_destroy
)
impl_Asset_for(Spritesheet,
spritesheet_get_asset_id,
spritesheet_set_asset_id
)
decl_typeclass_impl(Drop, Spritesheet)
decl_typeclass_impl(Asset, Spritesheet)
#endif // !_fencer_spritesheet_h

5
core/src/transform.c Normal file
View file

@ -0,0 +1,5 @@
#include "transform.h"
impl_Transformable_for(Transform,
transform_get_transform
)

View file

@ -1,6 +1,7 @@
#ifndef _fencer_transform_h
#define _fencer_transform_h
#include "typeclass_helpers.h"
#include "vmath.h"
#include "transformable.h"
@ -56,8 +57,6 @@ Transform* transform_get_transform(Transform* self) {
return self;
}
impl_Transformable_for(Transform,
transform_get_transform
);
decl_typeclass_impl(Transformable, Transform)
#endif // !_fencer_transform_h

View file

@ -26,7 +26,7 @@ extern void transformable_set_rotation(Transformable self, float rotation);
extern void transformable_rotate(Transformable self, float delta);
#define impl_Transformable_for(T, get_transform_f)\
static inline Transformable T##_as_Transformable(T* x) {\
Transformable T##_as_Transformable(T* x) {\
TC_FN_TYPECHECK(Transform*, get_transform_f, T*);\
static ITransformable const tc = {\
.get_transform = (Transform*(*const)(void*)) get_transform_f\

View file

@ -4,4 +4,7 @@
#define TC_FN_TYPECHECK(__Return, __Name, ...)\
__Return (*const __Name##_)(__VA_ARGS__) = __Name; (void)__Name##_
#define decl_typeclass_impl(__Typeclass, __Type)\
extern __Typeclass __Type##_as_##__Typeclass(__Type*);
#endif // !_fencer_typeclass_helpers_h

View file

@ -20,7 +20,7 @@ typedef struct {
} Damagable;
#define impl_Damagable_for(T, damage_f)\
static inline Damagable T##_as_Damagable(T* x) {\
Damagable T##_as_Damagable(T* x) {\
TC_FN_TYPECHECK(int, damage_f, T*, DamageEventData*);\
static const IDamagable tc = {\
.damage = (int(*const)(void*, DamageEventData*)) damage_f,\

View file

@ -13,6 +13,31 @@ START_REFLECT(Enemy)
REFLECT_TYPECLASS(Enemy, Damagable)
END_REFLECT(Enemy)
impl_Transformable_for(Enemy,
EnemyGetTransform
)
impl_Drop_for(Enemy,
EnemyDestroy
)
impl_BehaviourEntity_for(Enemy,
EnemyStart,
EnemyUpdate,
EnemyDraw,
EnemyGetDepth
)
impl_PhysicsEntity_for(Enemy,
EnemyGetRigidBody,
EnemyOnCollision,
EnemyOnOverlap
)
impl_Damagable_for(Enemy,
EnemyDamage
)
Enemy* MakeEnemy() {
Enemy* self = malloc(sizeof(Enemy));
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate Enemy");

View file

@ -13,6 +13,7 @@
#include "Damagable.h"
#include "EnemyStates.h"
#include "typeclass_helpers.h"
typedef struct Enemy {
Transform transform;
@ -56,29 +57,10 @@ extern int EnemyDamage(Enemy* self, DamageEventData* data);
DECL_REFLECT(Enemy)
impl_Transformable_for(Enemy,
EnemyGetTransform
)
impl_Drop_for(Enemy,
EnemyDestroy
)
impl_BehaviourEntity_for(Enemy,
EnemyStart,
EnemyUpdate,
EnemyDraw,
EnemyGetDepth
)
impl_PhysicsEntity_for(Enemy,
EnemyGetRigidBody,
EnemyOnCollision,
EnemyOnOverlap
)
impl_Damagable_for(Enemy,
EnemyDamage
)
decl_typeclass_impl(Transformable, Enemy)
decl_typeclass_impl(Drop, Enemy)
decl_typeclass_impl(BehaviourEntity, Enemy)
decl_typeclass_impl(PhysicsEntity, Enemy)
decl_typeclass_impl(Damagable, Enemy)
#endif // !FIGHT_ENEMY_H

View file

@ -15,6 +15,27 @@ START_REFLECT(Player)
REFLECT_TYPECLASS(Player, BehaviourEntity)
END_REFLECT(Player)
impl_Drop_for(Player,
DestroyPlayer
)
impl_BehaviourEntity_for(Player,
PlayerStart,
PlayerUpdate,
PlayerDraw,
PlayerGetDepth
)
impl_Transformable_for(Player,
PlayerGetTransform
)
impl_PhysicsEntity_for(Player,
PlayerGetRigidBody,
PlayerOnCollision,
PlayerOnOverlap
)
static inline
void Internal_PlayerInitInput(Player* self) {
playerinput_add(self->playerInput, CompositeAxis1D_as_InputAxis(compositeaxis1d_new(

View file

@ -10,6 +10,7 @@
#include "player_input.h"
#include "rigidbody.h"
#include "collider.h"
#include "typeclass_helpers.h"
extern const Vector PLAYER_SPEED;
@ -61,25 +62,9 @@ static long PlayerGetDepth(Player* self) { return (int)(-10-self->transform.posi
DECL_REFLECT(Player);
impl_Drop_for(Player,
DestroyPlayer
)
impl_BehaviourEntity_for(Player,
PlayerStart,
PlayerUpdate,
PlayerDraw,
PlayerGetDepth
)
impl_Transformable_for(Player,
PlayerGetTransform
)
impl_PhysicsEntity_for(Player,
PlayerGetRigidBody,
PlayerOnCollision,
PlayerOnOverlap
)
decl_typeclass_impl(BehaviourEntity, Player)
decl_typeclass_impl(Drop, Player)
decl_typeclass_impl(Transformable, Player)
decl_typeclass_impl(PhysicsEntity, Player)
#endif // !FIGHT_PLAYER_H

View file

@ -10,6 +10,27 @@ START_REFLECT(Prop)
REFLECT_TYPECLASS(Prop, BehaviourEntity)
END_REFLECT(Prop)
impl_Transformable_for(Prop,
PropGetTransform
)
impl_PhysicsEntity_for(Prop,
PropGetRigidBody,
PropOnCollision,
PropOnOverlap
)
impl_Drop_for(Prop,
DestroyProp
)
impl_BehaviourEntity_for(Prop,
PropStart,
PropUpdate,
PropDraw,
PropGetDepth
)
Prop* MakeProp(Sprite* sprite, Shape* shape) {
Prop* self = malloc(sizeof(Prop));
ASSERT_RETURN(self != NULL, NULL, "Failed to allocate space for Prop instance");

View file

@ -9,6 +9,7 @@
#include "sprite.h"
#include "rigidbody.h"
#include "collider.h"
#include "typeclass_helpers.h"
typedef struct Prop {
Transform transform;
@ -35,25 +36,9 @@ static long PropGetDepth(Prop* self) { return -(int)(self->transform.position.y
DECL_REFLECT(Prop)
impl_Transformable_for(Prop,
PropGetTransform
)
impl_PhysicsEntity_for(Prop,
PropGetRigidBody,
PropOnCollision,
PropOnOverlap
)
impl_Drop_for(Prop,
DestroyProp
)
impl_BehaviourEntity_for(Prop,
PropStart,
PropUpdate,
PropDraw,
PropGetDepth
)
decl_typeclass_impl(Transformable, Prop)
decl_typeclass_impl(PhysicsEntity, Prop)
decl_typeclass_impl(Drop, Prop)
decl_typeclass_impl(BehaviourEntity, Prop)
#endif // !FIGHT_PROP_H