#pragma once #include #include #include #include #include #include // Add any new fields into the concept below #define DECLARE_ENTITY(entity) \ Entity* Base; \ static const Juliet::Class* Kind; // Will register the class globally at launch #define DEFINE_ENTITY(entity) \ constexpr Juliet::Class entityKind##entity(#entity, sizeof(#entity) / sizeof(char)); \ const Juliet::Class* entity::Kind = &entityKind##entity; namespace Game { using DerivedType = void*; struct Entity final { EntityID ID; const Juliet::Class* Kind; DerivedType Derived; float X, Y; }; template concept EntityConcept = requires(EntityType entity) { requires std::same_as; requires std::same_as; }; template requires EntityConcept bool IsA(const Entity* entity) { return entity->Kind == EntityType::Kind; } template requires EntityConcept EntityType* MakeEntity(EntityManager& manager, float x, float y) { EntityType* result = static_cast(Juliet::Calloc(1, sizeof(EntityType))); Entity* base = result->Base = static_cast(Juliet::Calloc(1, sizeof(Entity))); base->X = x; base->Y = y; base->Derived = result; base->Kind = EntityType::Kind; RegisterEntity(manager, base); return result; } template requires EntityConcept EntityType* DownCast(Entity* entity) { Assert(IsA(entity)); return static_cast(entity->Derived); } } // namespace Game