diff --git a/App.c b/App.c index 139679b..ce77f56 100644 --- a/App.c +++ b/App.c @@ -15,6 +15,8 @@ App *app_NewApp() { app->player = player_NewSystem(app); app->entity = entity_NewSystem(app); + app->wantQuit = false; + return app; } diff --git a/App.h b/App.h index 713d451..2e28933 100644 --- a/App.h +++ b/App.h @@ -6,12 +6,18 @@ #include "Input.h" #include "Types.h" +#ifdef __cplusplus +extern "C" { +#endif + typedef struct _App { System_Physics *physics; System_Player *player; System_Input *input; System_Entity *entity; + + bool wantQuit; } App; App *app_NewApp(); @@ -19,3 +25,8 @@ void app_DeleteApp(App *app); void app_Advance(App *app, Duration deltaTime); void app_Render(); + + +#ifdef __cplusplus +} +#endif diff --git a/App_Render.cpp b/App_Render.cpp index 4fb57d5..d9af69e 100644 --- a/App_Render.cpp +++ b/App_Render.cpp @@ -3,5 +3,9 @@ #include +extern "C" { + + void app_Render() { } +} diff --git a/Input.c b/Input.c index 2a4ef77..835684c 100644 --- a/Input.c +++ b/Input.c @@ -3,9 +3,21 @@ #include "App.h" #include +#include #include +const char *input_KeyNames[input_Key_Count] = { + "Left", + "Right", + "Up", + "Down", + "Jump", + "Attack", + "Spell", + "Use", + "Escape"}; + void input_SetDefaultKeymap(System_Input *sys) { sys->systemKeymap[input_Key_Up] = 'W'; sys->systemKeymap[input_Key_Left] = 'A'; @@ -15,6 +27,7 @@ void input_SetDefaultKeymap(System_Input *sys) { sys->systemKeymap[input_Key_Attack] = 'J'; sys->systemKeymap[input_Key_Spell] = 'K'; sys->systemKeymap[input_Key_Use] = 'L'; + sys->systemKeymap[input_Key_Escape] = VK_ESCAPE; } System_Input *input_NewSystem(App *super) { @@ -36,9 +49,10 @@ void input_Advance(System_Input *sys) { // Checks the most significiant bit (of the SHORT returned) if ((GetAsyncKeyState(sys->systemKeymap[i]) & 0x8000) != 0) { // Pressed - if (sys->keys[i] == JustReleased || sys->keys[i] == Released) + if (sys->keys[i] == JustReleased || sys->keys[i] == Released) { + fprintf(stderr, "[input_Advance] Key %s pressed\n", input_KeyNames[i]); sys->keys[i] = JustPressed; - else + } else sys->keys[i] = Pressed; } else { // Released @@ -48,4 +62,9 @@ void input_Advance(System_Input *sys) { sys->keys[i] = Released; } } + + if (sys->keys[input_Key_Escape] == JustPressed) { + fprintf(stderr, "[input_Advance] Let's quit now!\n"); + sys->super->wantQuit = true; + } } diff --git a/Input.h b/Input.h index 79aef19..cb7bc04 100644 --- a/Input.h +++ b/Input.h @@ -19,19 +19,12 @@ typedef enum { input_Key_Attack, input_Key_Spell, input_Key_Use, + input_Key_Escape, input_Key_Count } input_Key; // Names for input_Key -const char *input_KeyNames[input_Key_Count] = { - "Left", - "Right", - "Up", - "Down", - "Jump", - "Attack", - "Spell", - "Use"}; +extern const char *input_KeyNames[input_Key_Count]; // States a key might in diff --git a/Main.cpp b/Main.cpp index 466d3e3..70b1a57 100644 --- a/Main.cpp +++ b/Main.cpp @@ -1,17 +1,37 @@ +#include #include #include +#include "App.h" #include "Types.h" int main() { TimePoint startup = time_Now(); + TimePoint lastFrame, lastUpdate, frameCounter; + lastFrame = lastUpdate = frameCounter = time_Now(); + int frameCount = 0; + + initgraph(1280, 720); + + App *app = app_NewApp(); + while (!app->wantQuit) { + if (time_Since(frameCounter).microseconds >= 1000000) { // 1 sec + Duration d = time_Reset(&frameCounter); + fprintf(stderr, "[Main] %d frames in the last %.4lf seconds\n", frameCount, duration_Seconds(d)); + frameCount = 0; + } + frameCount++; + + app_Advance(app, time_Reset(&lastUpdate)); + + app_Render(); + + Duration toSleep = {.microseconds = 1000000 / 30 - time_Reset(&lastFrame).microseconds}; + duration_Sleep(toSleep); + } - initgraph(640, 480); - circle(200, 200, 100); - Sleep(5000); closegraph(); - printf("%.6lf seconds has elapsed\n", duration_Seconds(time_Since(startup))); return 0; } diff --git a/Types.c b/Types.c index 5e7413a..aa5fe93 100644 --- a/Types.c +++ b/Types.c @@ -1,6 +1,8 @@ #include "Types.h" +#include #include +#include static inline double dmin(double x, double y) { return x < y ? x : y; @@ -75,6 +77,19 @@ Box2 box2_OffsetY(Box2 box, double offsetY) { static double freqInverse = 0.0; + +void duration_Sleep(const Duration t) { + if (t.microseconds <= 0) + return; + // https://learn.microsoft.com/zh-cn/windows/win32/api/timeapi/nf-timeapi-timebeginperiod + // timeBeginPeriod() and friends + TIMECAPS tc; + timeGetDevCaps(&tc, sizeof(TIMECAPS)); + timeBeginPeriod(tc.wPeriodMin); + Sleep((DWORD)(round(duration_Milliseconds(t)))); // Only millisecond precision. Sad + timeEndPeriod(tc.wPeriodMin); +} + TimePoint time_Now() { // Reference: https://github.com/SFML/SFML/blob/2.6.x/src/SFML/System/Win32/ClockImpl.cpp @@ -98,3 +113,9 @@ Duration time_Difference(TimePoint now, TimePoint prev) { Duration d = {.microseconds = now.microseconds - prev.microseconds}; return d; } +Duration time_Reset(TimePoint *prev) { + TimePoint now = time_Now(); + Duration d = time_Difference(now, *prev); + *prev = now; + return d; +} diff --git a/Types.h b/Types.h index 0232303..b0a8bb3 100644 --- a/Types.h +++ b/Types.h @@ -43,10 +43,12 @@ typedef struct { int64_t microseconds; } Duration; -static inline double duration_Seconds(const Duration t) { return ((double)t.microseconds) / 1000.0 / 1000.0; } +static inline double duration_Seconds(const Duration t) { return ((double)t.microseconds) / 1000000.0; } static inline double duration_Milliseconds(const Duration t) { return ((double)t.microseconds) / 1000.0; } +// This function has a precision of at most 1ms under Windows. Sad +void duration_Sleep(const Duration t); -// A Time point since the start of the program. +// A Time point, counted since a fixed point in the past. typedef struct { int64_t microseconds; } TimePoint; @@ -54,6 +56,7 @@ typedef struct { TimePoint time_Now(); Duration time_Since(TimePoint prev); Duration time_Difference(TimePoint now, TimePoint prev); +Duration time_Reset(TimePoint *prev); // 1e-6 extern const double EPS;