From bf23ff877ab2ee95bc9d2e19590d044c64255d9c Mon Sep 17 00:00:00 2001 From: Sara <sara@saragerretsen.nl> Date: Thu, 11 Jan 2024 23:27:45 +0100 Subject: [PATCH] feat: replaced messagereceiver with mirror --- core/src/message_receiver.c | 13 ----- core/src/message_receiver.h | 36 ------------- core/src/mirror.c | 10 ++++ core/src/mirror.h | 101 ++++++++++++++++++++++++++++++++++++ core/src/physics_entity.h | 9 ++-- core/src/strutil.c | 15 ++++++ core/src/strutil.h | 10 ++++ game/src/Damagable.h | 31 +++++++++++ game/src/DamageEvent.h | 11 ---- game/src/Enemy.c | 40 +++++++------- game/src/Enemy.h | 16 ++++-- game/src/Player.c | 15 ++++-- game/src/Player.h | 5 +- game/src/PlayerStates.c | 18 ++++--- game/src/Prop.c | 16 +++--- game/src/Prop.h | 6 +-- 16 files changed, 236 insertions(+), 116 deletions(-) delete mode 100644 core/src/message_receiver.c delete mode 100644 core/src/message_receiver.h create mode 100644 core/src/mirror.c create mode 100644 core/src/mirror.h create mode 100644 core/src/strutil.c create mode 100644 core/src/strutil.h create mode 100644 game/src/Damagable.h delete mode 100644 game/src/DamageEvent.h diff --git a/core/src/message_receiver.c b/core/src/message_receiver.c deleted file mode 100644 index b0dec28..0000000 --- a/core/src/message_receiver.c +++ /dev/null @@ -1,13 +0,0 @@ -#include "message_receiver.h" -#include "stddef.h" - -void* message_receiver_refuse(void* self, MessageID id, uintptr_t data) { - return NULL; -} - -MessageReceiver message_receiver_no_implementation(void* data) { - static IMessageReceiver const tc = { - .handle_message = message_receiver_refuse - }; - return (MessageReceiver){.data = data, .tc = &tc}; -} diff --git a/core/src/message_receiver.h b/core/src/message_receiver.h deleted file mode 100644 index f4a3043..0000000 --- a/core/src/message_receiver.h +++ /dev/null @@ -1,36 +0,0 @@ -#ifndef _fencer_message_receiver_h -#define _fencer_message_receiver_h - -#include "stdint.h" -#include "typeclass_helpers.h" - -typedef uint32_t MessageID; - -typedef struct IMessageReceiver { - void* (*const handle_message)(void*, MessageID, uintptr_t); -} IMessageReceiver; - -typedef struct MessageReceiver { - void* data; - IMessageReceiver const* tc; -} MessageReceiver; - -extern void* message_receiver_refuse(void* self, MessageID id, uintptr_t); - -extern MessageReceiver message_receiver_no_implementation(void* x); - -#define impl_no_MessageReceiver_for(T)\ -static inline MessageReceiver T##_as_MessageReceiver(T* x) {\ - return message_receiver_no_implementation(x);\ -} - -#define impl_MessageReceiver_for(T, handle_message_f)\ -static inline MessageReceiver T##_as_MessageReceiver(T* x) {\ - TC_FN_TYPECHECK(void*, handle_message_f, T*, MessageID, uintptr_t);\ - static IMessageReceiver const tc = {\ - .handle_message = (void*(*const)(void*,MessageID,uintptr_t)) handle_message_f,\ - };\ - return (MessageReceiver){.data = x, .tc = &tc};\ -} - -#endif // !_fencer_message_receiver_h diff --git a/core/src/mirror.c b/core/src/mirror.c new file mode 100644 index 0000000..f8e5f54 --- /dev/null +++ b/core/src/mirror.c @@ -0,0 +1,10 @@ +#include "mirror.h" + +void* mirror_get_converter(void* self, IMirror const* tc, const char* typeclass) { + uintptr_t target_hash = strhash(typeclass); + list_foreach(MirroredTypeclass*, class, tc->get_typeclasses(self)) { + if(target_hash == class->name_hash && strcmp(typeclass, class->typeclass_name) == 0) + return class->wrap; + } + return NULL; +} diff --git a/core/src/mirror.h b/core/src/mirror.h new file mode 100644 index 0000000..22475e5 --- /dev/null +++ b/core/src/mirror.h @@ -0,0 +1,101 @@ +#ifndef _fencer_mirror_h +#define _fencer_mirror_h + +#include "typeclass_helpers.h" +#include "stdint.h" +#include "string.h" +#include "list.h" +#include "strutil.h" + +typedef uintptr_t typeid; + +typedef struct { + const char* (*const get_typestring)(void* self); + typeid (*const get_typeid)(void* self); + List* (*const get_typeclasses)(void* self); +} IMirror; + +typedef struct { + void* data; + IMirror const* tc; +} Mirror; + +typedef struct { + const char* typeclass_name; + uintptr_t name_hash; + void* (*const wrap)(void*); +} MirroredTypeclass; + +static inline int mirror_is_typeid(const Mirror* mirror, typeid id) { + return mirror->tc->get_typeid(mirror->data) == id; +} +static inline int mirror_is_typestring(const Mirror* mirror, const char* id) { + return strcmp(id, mirror->tc->get_typestring(mirror->data)) == 0; +} +static inline int mirror_eq(const Mirror* lhs, const Mirror* rhs) { + return lhs->tc->get_typeid(lhs->data) == rhs->tc->get_typeid(rhs->data); +} + +extern void* mirror_get_converter(void* data, IMirror const* tc, const char* typeclass); + +#define MIRROR_TRY_WRAP(Into_, Mirror_, Typeclass_){\ + MirroredTypeclassWrapFunc fn_ = mirror_get_typeclass(Mirror_, #Typeclass_);\ + if(fn_ != NULL) {\ + Into_ = (TypeClass_)fn(Mirror_->data);\ + }\ +} + +#define impl_Mirror_for(T, get_typestring_f, get_typeid_f, get_typeclasses_f)\ +static inline Mirror T##_as_Mirror(T* x) {\ + TC_FN_TYPECHECK(const char*, get_typestring_f, T*);\ + TC_FN_TYPECHECK(typeid, get_typeid_f, T*);\ + TC_FN_TYPECHECK(List*, get_typeclasses_f, T*);\ + static IMirror const tc = {\ + .get_typestring = (const char*(*const)(void*)) get_typestring_f,\ + .get_typeid = (typeid (*const)(void*)) get_typeid_f,\ + .get_typeclasses = (List* (*const)(void*)) get_typeclasses_f,\ + };\ + return (Mirror){.tc = &tc, .data = x};\ +} + +#define DECL_REFLECT(T)\ +extern const char* T##_get_typestring(T* self);\ +extern typeid T##_get_typeid(T* self);\ +extern List* T##_get_typeclasses(T* self);\ +impl_Mirror_for(T, T##_get_typestring, T##_get_typeid, T##_get_typeclasses) + + +#define START_REFLECT(T)\ +const char* T##_get_typestring(T* self) {\ + static const char* const typestring = #T;\ + return typestring;\ +}\ +typeid T##_get_typeid(T* self) {\ + static char init_flag = 0;\ + static typeid id = 0;\ + if(!init_flag) {\ + init_flag = 1;\ + id = strhash(#T);\ + }\ + return id;\ +}\ +List* T##_get_typeclasses(T* self) {\ + static char init_flag = 0;\ + static List typeclasses;\ + if(!init_flag) {\ + init_flag = 1,\ + typeclasses = list_init(sizeof(MirroredTypeclass));\ + +#define REFLECT_TYPECLASS(T, TypeClass_)\ + list_add(&typeclasses, &(MirroredTypeclass){\ + .name_hash = strhash(#TypeClass_),\ + .typeclass_name = #TypeClass_,\ + .wrap = (void*(*const)(void*)) T##_as_##TypeClass_\ + }); + +#define END_REFLECT(T)\ + }\ + return &typeclasses;\ +}\ + +#endif // !_fencer_mirror_h diff --git a/core/src/physics_entity.h b/core/src/physics_entity.h index 212a606..acfef5d 100644 --- a/core/src/physics_entity.h +++ b/core/src/physics_entity.h @@ -4,12 +4,11 @@ #include "typeclass_helpers.h" #include "list.h" #include "transformable.h" -#include "message_receiver.h" +#include "mirror.h" typedef struct Collider Collider; typedef struct Collision Collision; typedef struct RigidBody RigidBody; - typedef struct PhysicsEntity PhysicsEntity; typedef struct IPhysicsEntity { @@ -22,7 +21,7 @@ typedef struct PhysicsEntity { void* data; IPhysicsEntity const* tc; ITransformable const* transformable; - IMessageReceiver const* message_receiver; + IMirror const* mirror; } PhysicsEntity; extern void physics_entity_debug_draw(PhysicsEntity self); @@ -40,8 +39,8 @@ static inline PhysicsEntity T##_as_PhysicsEntity(T* x) {\ .on_overlap = (void(*const)(void*,Collider*)) on_overlap_f,\ };\ Transformable transformable = T##_as_Transformable(x);\ - MessageReceiver receiver = T##_as_MessageReceiver(x);\ - return (PhysicsEntity){.data = x, .tc = &tc, .transformable = transformable.tc, .message_receiver = receiver.tc};\ + Mirror mirror = T##_as_Mirror(x);\ + return (PhysicsEntity){.data = x, .tc = &tc, .transformable = transformable.tc, .mirror = mirror.tc};\ } #endif // !_fencer_collidable_h diff --git a/core/src/strutil.c b/core/src/strutil.c new file mode 100644 index 0000000..d133af3 --- /dev/null +++ b/core/src/strutil.c @@ -0,0 +1,15 @@ +#include "strutil.h" +#include "string.h" + +uintptr_t strnhash(const char* s, size_t n) { + static const size_t shift = sizeof(uintptr_t) * 8 - 4; + uintptr_t hash = 0; + for(size_t i = 0; i < n; ++i) { + hash = ((hash << 4) | s[i]) ^ (((uintptr_t)0xF << shift) & hash); + } + return hash; +} + +uintptr_t strhash(const char* s) { + return strnhash(s, strlen(s)); +} diff --git a/core/src/strutil.h b/core/src/strutil.h new file mode 100644 index 0000000..55e36af --- /dev/null +++ b/core/src/strutil.h @@ -0,0 +1,10 @@ +#ifndef _fencer_strutil_h +#define _fencer_strutil_h + +#include "stdlib.h" +#include "stdint.h" + +extern uintptr_t strnhash(const char* s, size_t n); +extern uintptr_t strhash(const char* s); + +#endif // !_fencer_strutil_h diff --git a/game/src/Damagable.h b/game/src/Damagable.h new file mode 100644 index 0000000..453f938 --- /dev/null +++ b/game/src/Damagable.h @@ -0,0 +1,31 @@ +#ifndef FIGHT_DAMAGABLE_H +#define FIGHT_DAMAGABLE_H + +#include "typeclass_helpers.h" + +#include "vmath.h" + +typedef struct DamageEventData { + int damageAmount; + Vector origin; +} DamageEventData; + +typedef struct { + int (*const damage)(void*, DamageEventData*); +} IDamagable; + +typedef struct { + void* data; + IDamagable const* tc; +} Damagable; + +#define impl_Damagable_for(T, damage_f)\ +static inline 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,\ + };\ + return (Damagable){.data = x, .tc = &tc};\ +} + +#endif // !FIGHT_DAMAGABLE_H diff --git a/game/src/DamageEvent.h b/game/src/DamageEvent.h deleted file mode 100644 index 081e9c0..0000000 --- a/game/src/DamageEvent.h +++ /dev/null @@ -1,11 +0,0 @@ -#ifndef FIGHT_DAMAGE_EVENT_H -#define FIGHT_DAMAGE_EVENT_H - -#include "vmath.h" - -typedef struct DamageEventData { - int damageAmount; - Vector origin; -} DamageEventData; - -#endif // !FIGHT_DAMAGE_EVENT_H diff --git a/game/src/Enemy.c b/game/src/Enemy.c index b58ed91..4889107 100644 --- a/game/src/Enemy.c +++ b/game/src/Enemy.c @@ -1,12 +1,18 @@ #include "Enemy.h" #include "debug.h" -#include "Messages.h" -#include "DamageEvent.h" #include "game_world.h" #include "physics.h" #include "physics_world.h" #include "sprite.h" +START_REFLECT(Enemy) + REFLECT_TYPECLASS(Enemy, Transformable) + REFLECT_TYPECLASS(Enemy, Drop) + REFLECT_TYPECLASS(Enemy, PhysicsEntity) + REFLECT_TYPECLASS(Enemy, BehaviourEntity) + REFLECT_TYPECLASS(Enemy, Damagable) +END_REFLECT(Enemy) + Enemy* MakeEnemy() { Enemy* self = malloc(sizeof(Enemy)); ASSERT_RETURN(self != NULL, NULL, "Failed to allocate Enemy"); @@ -70,23 +76,6 @@ void EnemyDestroy(Enemy* self) { void EnemyOnCollision(Enemy* self, Collision collision) {} void EnemyOnOverlap(Enemy* self, Collider* other) {} -void* EnemyHandleMessage(Enemy* self, MessageID id, uintptr_t data) { - DamageEventData* damage = (DamageEventData*)data; - switch(id) { - case MESSAGE_DEAL_DAMAGE: - self->health -= damage->damageAmount; - self->hurt = 1; - self->facing = ((damage->origin.x - self->transform.position.x) > 0) * 2 - 1; - if(self->health <= 0) - game_world_destroy_entity(Enemy_as_BehaviourEntity(self)); - break; - default: - break; - } - - return NULL; -} - Transform* EnemyGetTransform(Enemy* self) { return &self->transform; } @@ -94,3 +83,16 @@ Transform* EnemyGetTransform(Enemy* self) { RigidBody* EnemyGetRigidBody(Enemy* self) { return self->rigidbody; } + +int EnemyDamage(Enemy* self, DamageEventData* data) { + self->health -= data->damageAmount; + LOG_INFO("Damage received"); + if(self->health <= 0) { + game_world_destroy_entity(Enemy_as_BehaviourEntity(self)); + return 1; + } else { + self->hurt = 1; + self->facing = ((data->origin.x - self->transform.position.x) > 0) * 2 - 1; + return 0; + } +} diff --git a/game/src/Enemy.h b/game/src/Enemy.h index 98adbd8..1e54323 100644 --- a/game/src/Enemy.h +++ b/game/src/Enemy.h @@ -1,6 +1,7 @@ #ifndef FIGHT_ENEMY_H #define FIGHT_ENEMY_H +#include "mirror.h" #include "transform.h" #include "state_machine.h" #include "rigidbody.h" @@ -9,6 +10,8 @@ #include "collider.h" #include "sprite.h" #include "animation_sprite.h" + +#include "Damagable.h" #include "EnemyStates.h" typedef struct Enemy { @@ -44,20 +47,19 @@ extern void EnemyDraw(Enemy* self); extern void EnemyOnCollision(Enemy* self, Collision collision); extern void EnemyOnOverlap(Enemy* self, Collider* other); -extern void* EnemyHandleMessage(Enemy* self, MessageID id, uintptr_t data); extern Transform* EnemyGetTransform(Enemy* self); extern RigidBody* EnemyGetRigidBody(Enemy* self); static long EnemyGetDepth(Enemy* self) { return (long)(-self->transform.position.y * 1000); } +extern int EnemyDamage(Enemy* self, DamageEventData* data); + +DECL_REFLECT(Enemy) + impl_Transformable_for(Enemy, EnemyGetTransform ) -impl_MessageReceiver_for(Enemy, - EnemyHandleMessage -) - impl_Drop_for(Enemy, EnemyDestroy ) @@ -75,4 +77,8 @@ impl_PhysicsEntity_for(Enemy, EnemyOnOverlap ) +impl_Damagable_for(Enemy, + EnemyDamage +) + #endif // !FIGHT_ENEMY_H diff --git a/game/src/Player.c b/game/src/Player.c index 64eb9e4..3976e6d 100644 --- a/game/src/Player.c +++ b/game/src/Player.c @@ -1,24 +1,31 @@ #include "Player.h" -#include "PlayerStates.h" -#include "Layers.h" #include "debug.h" #include "game_world.h" #include "input_axis.h" #include "physics_world.h" +#include "PlayerStates.h" +#include "Layers.h" + const Vector PLAYER_SPEED = { 1.0f, 0.70f }; +START_REFLECT(Player) + REFLECT_TYPECLASS(Player, Drop) + REFLECT_TYPECLASS(Player, PhysicsEntity) + REFLECT_TYPECLASS(Player, BehaviourEntity) +END_REFLECT(Player) + static inline void Internal_PlayerInitInput(Player* self) { playerinput_add(self->playerInput, CompositeAxis1D_as_InputAxis(compositeaxis1d_new( KeyBind_as_InputAxis(keybind_new(SDL_SCANCODE_A)), KeyBind_as_InputAxis(keybind_new(SDL_SCANCODE_D)), - InputEvent_Float)), (InputDelegateFn)PlayerHorizontalInput); + InputEvent_Float)), (InputDelegateFn)PlayerHorizontalInput); playerinput_add(self->playerInput, CompositeAxis1D_as_InputAxis(compositeaxis1d_new( KeyBind_as_InputAxis(keybind_new(SDL_SCANCODE_S)), KeyBind_as_InputAxis(keybind_new(SDL_SCANCODE_W)), - InputEvent_Float)), (InputDelegateFn)PlayerVerticalInput); + InputEvent_Float)), (InputDelegateFn)PlayerVerticalInput); playerinput_add(self->playerInput, KeyBind_as_InputAxis(keybind_new(SDL_SCANCODE_J)), (InputDelegateFn)PlayerAttackInput); } diff --git a/game/src/Player.h b/game/src/Player.h index 4b2cfad..146a6d7 100644 --- a/game/src/Player.h +++ b/game/src/Player.h @@ -2,10 +2,9 @@ #define FIGHT_PLAYER_H #include "state_machine.h" -#include "state.h" +#include "mirror.h" #include "behaviour_entity.h" #include "animation_sprite.h" -#include "input.h" #include "vmath.h" #include "transform.h" #include "player_input.h" @@ -60,7 +59,7 @@ void PlayerOnOverlap(Player* self, Collider* other); static long PlayerGetDepth(Player* self) { return (int)(-10-self->transform.position.y * 1000); } -impl_no_MessageReceiver_for(Player) +DECL_REFLECT(Player); impl_Drop_for(Player, DestroyPlayer diff --git a/game/src/PlayerStates.c b/game/src/PlayerStates.c index 99fd083..ccd226d 100644 --- a/game/src/PlayerStates.c +++ b/game/src/PlayerStates.c @@ -1,8 +1,10 @@ #include "PlayerStates.h" +#include "physics_world.h" + #include "DamageEvent.h" +#include "Damagable.h" #include "Player.h" #include "Layers.h" -#include "physics_world.h" static inline void InternalSpriteFlipWithMovement(Player* self) { @@ -58,11 +60,15 @@ void PlayerAttackTrigger(Player* self) { MakeVector(0.1f, 0.06f), PHYSICS_LAYER_COMBAT, self->rigidbody); if(found != NULL) { PhysicsEntity entity = collider_get_owner(found); - DamageEventData data = { - .damageAmount = 1, - .origin = self->transform.position - }; - entity.message_receiver->handle_message(entity.data, 1, (uintptr_t)&data); + Damagable(*const as_damagable)(void*) = mirror_get_converter(entity.data, entity.mirror, "Damagable"); + if(as_damagable) { + Damagable damagable = as_damagable(entity.data); + DamageEventData data = { + .damageAmount = 1, + .origin = self->transform.position + }; + damagable.tc->damage(entity.data, &data); + } } ++self->animationTriggers; } diff --git a/game/src/Prop.c b/game/src/Prop.c index ea5f7ab..caa0b53 100644 --- a/game/src/Prop.c +++ b/game/src/Prop.c @@ -1,10 +1,16 @@ #include "Prop.h" #include "DamageEvent.h" -#include "Messages.h" #include "debug.h" #include "game_world.h" +#include "mirror.h" #include "physics_world.h" +START_REFLECT(Prop) + REFLECT_TYPECLASS(Prop, Transformable) + REFLECT_TYPECLASS(Prop, Drop) + REFLECT_TYPECLASS(Prop, BehaviourEntity) +END_REFLECT(Prop) + Prop* MakeProp(Sprite* sprite, Shape* shape) { Prop* self = malloc(sizeof(Prop)); ASSERT_RETURN(self != NULL, NULL, "Failed to allocate space for Prop instance"); @@ -61,11 +67,3 @@ Transform* PropGetTransform(Prop* self) { RigidBody* PropGetRigidBody(Prop* self) { return self->rigidbody; } - -void* PropReceiveMessage(Prop* self, MessageID message, uintptr_t data) { - DamageEventData* damage = (DamageEventData*)data; - if(message == MESSAGE_DEAL_DAMAGE) { - LOG_INFO("Punching bag took %d damage", damage->damageAmount); - } - return 0; -} diff --git a/game/src/Prop.h b/game/src/Prop.h index 73bcddc..5fe516f 100644 --- a/game/src/Prop.h +++ b/game/src/Prop.h @@ -31,13 +31,9 @@ void PropOnOverlap(Prop* self, Collider* other); Transform* PropGetTransform(Prop* self); RigidBody* PropGetRigidBody(Prop* self); -void* PropReceiveMessage(Prop* self, MessageID message, uintptr_t data); - static long PropGetDepth(Prop* self) { return -(int)(self->transform.position.y * 1000); } -impl_MessageReceiver_for(Prop, - PropReceiveMessage -) +DECL_REFLECT(Prop) impl_Transformable_for(Prop, PropGetTransform