diff --git a/.gitignore b/.gitignore index 9491a2f..1269ce5 100644 --- a/.gitignore +++ b/.gitignore @@ -360,4 +360,8 @@ MigrationBackup/ .ionide/ # Fody - auto-generated XML schema -FodyWeavers.xsd \ No newline at end of file +FodyWeavers.xsd + + +*.o +*.exe diff --git a/Input.h b/Input.h new file mode 100644 index 0000000..638835c --- /dev/null +++ b/Input.h @@ -0,0 +1,40 @@ +#pragma once + +#include +#include + + +#ifdef __cplusplus +extern "C" { +#endif + + +// Types of input the player might want +typedef enum { + input_Key_Left, + input_Key_Right, + input_Key_Up, + input_Key_Down, + input_Key_Jump, + input_Key_Attack, + input_Key_Spell, + input_Key_Use, + input_Key_Count +} input_Key; + +// States a key might in +typedef enum { + Pressed, + JustPressed, + Released, + JustReleased +} input_KeyState; + +typedef struct { + input_KeyState keys[input_Key_Count]; // States of keys +} System_Input; + + +#ifdef __cplusplus +} +#endif diff --git a/Physics_Component.c b/Physics_Component.c index deb6a6f..8d876bc 100644 --- a/Physics_Component.c +++ b/Physics_Component.c @@ -60,7 +60,7 @@ void _physics_MoveX(System_Physics *sys, Entity *e, Duration deltaTime); void _physics_MoveY(System_Physics *sys, Entity *e, Duration deltaTime); -inline void _physics_AdvanceEntity(System_Physics *sys, Entity *e, Duration deltaTime) { +static inline void _physics_AdvanceEntity(System_Physics *sys, Entity *e, Duration deltaTime) { ASSERT(e->position && "_physics_AdvanceEntity() called on entity with no position"); // Short path diff --git a/Physics_Component.h b/Physics_Component.h index f197ff1..b06356a 100644 --- a/Physics_Component.h +++ b/Physics_Component.h @@ -16,6 +16,9 @@ typedef struct _Entity Entity; extern double physics_Gravity; +// Position component. +// +// If not exist, it's like it's at (0,0) typedef struct { Entity *super; Vec2 position; @@ -23,6 +26,9 @@ typedef struct { } Component_Position; +// Handler called when hitboxes are hit +typedef void (*physics_HitHandler)(Entity *me, Entity *other, Vec2 triedDelta); + // Box is relative to Position if exists // if not, Box is absolute // @@ -31,6 +37,8 @@ typedef struct { Entity *super; Box2 box; bool fixed; + + physics_HitHandler onHit; } Component_Hitbox; // Returns the absolute version of the hitbox. diff --git a/Physics_Move.c b/Physics_Move.c index 9f3c1a1..46b60ed 100644 --- a/Physics_Move.c +++ b/Physics_Move.c @@ -13,6 +13,11 @@ static inline double dabs(double x) { return x < 0 ? -x : x; } +static inline void call_hithandler(Entity *me, Entity *other, Vec2 triedDelta) { + if (me->hitbox->onHit) + me->hitbox->onHit(me, other, triedDelta); +} + void _physics_MoveX(System_Physics *sys, Entity *e, Duration deltaTime) { double delta = e->position->velocity.x * duration_Seconds(deltaTime); @@ -29,6 +34,7 @@ void _physics_MoveX(System_Physics *sys, Entity *e, Duration deltaTime) { continue; if (box2_Intersects(tohit, box2_OffsetX(mybox, delta), NULL)) { + call_hithandler(e, tohit_comp->super, vec2(delta, 0)); if (delta > 0) { // Moves right, hits left edge double maxdelta = tohit.lefttop.x - mybox.lefttop.x - mybox.size.x; @@ -63,6 +69,7 @@ void _physics_MoveY(System_Physics *sys, Entity *e, Duration deltaTime) { continue; if (box2_Intersects(tohit, box2_OffsetY(mybox, delta), NULL)) { + call_hithandler(e, tohit_comp->super, vec2(0, delta)); if (delta > 0) { // Moves down, hits top edge double maxdelta = tohit.lefttop.y - mybox.lefttop.y - mybox.size.y; diff --git a/Player_Component.h b/Player_Component.h new file mode 100644 index 0000000..90dbcfb --- /dev/null +++ b/Player_Component.h @@ -0,0 +1,35 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct _Entity Entity; + + +// Player controller component. +// Only one entity should have this. +typedef struct { + Entity *super; + int jumpCount; // Number of times the player has jumped since leaving ground + // (Initial jump does not count) + bool onGround; // If the player is on the ground? + bool moveLeft, moveRight; // If the player is moving left/right? +} Component_Player; + + +// Player controller instance. +// Reads input from the app. +typedef struct { + // The player in the world. + // Control is paused if equals NULL. + Component_Player *player; +} System_Player; + + +#ifdef __cplusplus +} +#endif diff --git a/Types.c b/Types.c index f6d19d8..0bd9f86 100644 --- a/Types.c +++ b/Types.c @@ -68,3 +68,11 @@ Box2 box2_OffsetY(Box2 box, double offsetY) { box.lefttop.y += offsetY; return box; } + + +Duration duration_Now() { + // TODO Use Windows.h + // Reference: https://github.com/SFML/SFML/blob/2.6.x/src/SFML/System/Win32/ClockImpl.cpp + Duration d = {.microseconds = 0}; + return d; +} diff --git a/Types.h b/Types.h index 8c11316..8b4f7ab 100644 --- a/Types.h +++ b/Types.h @@ -14,6 +14,11 @@ typedef struct { } Vec2; +inline Vec2 vec2(double x, double y) { + Vec2 v = {.x = x, .y = y}; + return v; +} + Vec2 vec2_Add(Vec2 x, Vec2 y); Vec2 vec2_Scale(Vec2 v, double scale); @@ -33,6 +38,7 @@ Box2 box2_OffsetX(Box2 box, double offsetX); Box2 box2_OffsetY(Box2 box, double offsetY); +// Time duration. typedef struct { uint64_t microseconds; } Duration; @@ -40,6 +46,12 @@ typedef struct { static inline double duration_Seconds(const Duration t) { return ((double)t.microseconds) / 1000.0 / 1000.0; } static inline double duration_Milliseconds(const Duration t) { return ((double)t.microseconds) / 1000.0; } +// Returns a relative duration since +// a static time point in the past. +// +// Its absolute value has no meaning. +Duration duration_Now(); + #ifdef __cplusplus }