diff options
| author | Emil Williams | 2026-02-05 09:29:51 +0000 |
|---|---|---|
| committer | Emil Williams | 2026-02-05 09:29:51 +0000 |
| commit | 45570024a49b80359d848329f2c363d5bf9af44a (patch) | |
| tree | 31243e117a965569ecbc745eba88b25536b7fc99 /source | |
| parent | a5209153cf8df1cd58c2f70f9eabb0bf5dd071f8 (diff) | |
| download | EUROPAXI-8e8m.tar.xz EUROPAXI-8e8m.tar.zst | |
assets & core8e8m
Diffstat (limited to 'source')
| -rw-r--r-- | source/all.h | 25 | ||||
| -rw-r--r-- | source/game.c | 125 | ||||
| -rw-r--r-- | source/main.c | 116 | ||||
| -rw-r--r-- | source/render.c | 6 | ||||
| -rw-r--r-- | source/time.c | 56 | ||||
| -rw-r--r-- | source/time.h | 14 |
6 files changed, 249 insertions, 93 deletions
diff --git a/source/all.h b/source/all.h index 9d97653..df42641 100644 --- a/source/all.h +++ b/source/all.h @@ -9,32 +9,31 @@ #define TEXT_BUFFER_LIMIT (1<<12) #define FRAME_LIMIT (1<<4) -#define MIN(a,b) (a)<(b)?(a):(b) +#define MIN(a,b) ((a)<(b)?(a):(b)) +#define MAX(a,b) ((a)>(b)?(a):(b)) +#define CLAMP(a,b,c) (a)<(b)?(b):(a)>(c)?(c):(a) typedef struct { Font font; float frame_x[FRAME_LIMIT]; float frame_y[FRAME_LIMIT]; int horizontal, vertical; + float ups, fps; } game_t; /* render.c */ -/* Everything here assumes White On Black = OK. for now. */ -/* Things should be textured and have backgrounds which is a lot of extra params, - which are not important right now. */ - -/* I would prefer that things remain CENTERED as that makes preportional to WINDOW SIZE shit easier */ -/* The Window is resizable, by the way. */ - -void draw_square_grid (game_t * game, size_t frame, int size, Texture * texture, int * array, size_t length); -void draw_vertical_bargraph (game_t * game, size_t frame, int size, Color color, int * arr, size_t length); -void draw_centered_text (game_t * game, size_t frame, int font_size, Color color, char * format, ...); +void DrawSquareGrid (game_t * game, size_t frame, int size, Texture * texture, int * array, size_t length); +void DrawVerticalBargraph (game_t * game, size_t frame, int size, Color color, int * arr, size_t length); +void DrawCenteredText (game_t * game, size_t frame, int font_size, Color color, char * format, ...); /* game.c */ -void game_frame(game_t * game, size_t frame, float x, float y); -Vector2 game_frame_vector(game_t * game, size_t frame); +void GameInitialize(game_t * game, char * window_name); +void GameDeinitialize(game_t * game); +void GameFrame(game_t * game, size_t frame, float x, float y); +void GameFrameReset(game_t * game); +Vector2 GameFrameVector(game_t * game, size_t frame); /* ... */ diff --git a/source/game.c b/source/game.c index 941b176..fa7633f 100644 --- a/source/game.c +++ b/source/game.c @@ -1,10 +1,131 @@ #include "all.h" -void game_frame(game_t * game, size_t frame, float x, float y) { +Font DefaultFont(char * choice) { + Font font = LoadFont(choice); + if (!IsFontValid(font)) { font = GetFontDefault(); } + return font; +} + +void GameFrame(game_t * game, size_t frame, float x, float y) { game->frame_x[frame] = x; game->frame_y[frame] = y; } -Vector2 game_frame_vector(game_t * game, size_t frame) { +void GameFrameReset(game_t * game) { + GameFrame(game, 0, game->horizontal/3, game->vertical - game->vertical/8); + /* GameFrame(game, 1, game->horizontal/12, game->vertical/12); */ + /* GameFrame(game, 2, game->horizontal - game->horizontal/4, game->vertical/12); */ +} + +Vector2 GameFrameVector(game_t * game, size_t frame) { return (Vector2) { game->frame_x[frame], game->frame_y[frame]}; } + +void GameInitialize(game_t * game, char * window_name) { + SetConfigFlags(FLAG_WINDOW_RESIZABLE); + /* tell raylib to shut up */ + SetTraceLogLevel(LOG_NONE); + InitWindow(game->horizontal, game->vertical, window_name); + SetWindowState(FLAG_WINDOW_HIDDEN); + InitAudioDevice(); + SetWindowPosition(0, 0); + /* :config */ + game->horizontal = 1920; + game->vertical = 1080; + game->ups = 60; + game->fps = 30; + game->font = DefaultFont("fonts/Atkinson/mono/AtkinsonHyperlegibleMono-Bold.otf"); + GameFrameReset(game); +} + +void GameDeinitialize(game_t * game) { + SetWindowState(FLAG_WINDOW_HIDDEN); + UnloadFont(game->font); + CloseAudioDevice(); + CloseWindow(); +} + +void GameLoop(game_t * game) { + + extern int Update(game_t * game, struct timespec now); + extern void Frame(game_t * game, double interpolation); + + #define StepStart(prefix) \ + prefix##_delta = timespec_sub(now, prefix##_last); \ + if (timespec_cmp(prefix##_delta, prefix##_interval) >= 0) { (void) 0 + + #define StepStop(prefix) \ + prefix##s_per_second++; \ + prefix##_total++; \ + prefix##_last = timespec_add(prefix##_last, prefix##_interval); \ + if (timespec_cmp(prefix##_last, now) < 0) { \ + prefix##_last = now; \ + } \ + } + + #define StepSimpleStart(prefix,linear) \ + prefix##_delta = timespec_sub(now, prefix##_last); \ + if (timespec_cmp(prefix##_delta, (struct timespec){1.,0.}) >= 0) { \ + (void)0 + + #define StepSimpleStop(prefix) \ + prefix##_last = now; \ + } + + struct timespec + now, + update_interval = {0, (double) TIMESPEC_HZ / game->ups}, + frame_interval = {0, (double) TIMESPEC_HZ / game->fps}, + update_last, frame_last, print_last, + update_delta, frame_delta, print_delta, + wait; + + uint32_t + updates_per_second = 0, frames_per_second = 0, + frame_total = 0, update_total = 0; + + double interpolation = 0.; + + ClearWindowState(FLAG_WINDOW_HIDDEN); + + clock_gettime(CLOCK_MONOTONIC, &now); + update_last = frame_last = print_last = now; + + while (1) { + StepStart(update); + if (Update(game, now)) { return; } + StepStop(update); + + StepStart(frame); + clock_gettime(CLOCK_MONOTONIC, &now); + interpolation = + CLAMP( + TIMESPEC_TO_DOUBLE(update_delta) + / TIMESPEC_TO_DOUBLE(update_interval), + 0.0, 1.0f); + Frame(game, interpolation); + StepStop(frame); + + clock_gettime(CLOCK_MONOTONIC, &now); + + wait = timespec_sub( + timespec_min( + timespec_add(update_last, update_interval), + timespec_add(frame_last, frame_interval)), + now); + + if (timespec_cmp(wait, zero_seconds) > 0) { + nanosleep(&wait, NULL); + } + + StepSimpleStart(print, one_second); + printf("[FPS|UPS|Total] (%3.0f : %3.0f) | [%7u/%7u]\n", + round(frames_per_second / TIMESPEC_TO_DOUBLE(print_delta)), + round(updates_per_second / TIMESPEC_TO_DOUBLE(print_delta)), + frame_total, update_total); + frames_per_second = updates_per_second = 0; + StepSimpleStop(print); + + clock_gettime(CLOCK_MONOTONIC, &now); + } +} diff --git a/source/main.c b/source/main.c index c775851..4bcaac8 100644 --- a/source/main.c +++ b/source/main.c @@ -1,89 +1,55 @@ #include <time.h> +#include "time.h" #include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> #include <rlgl.h> #include "all.h" -/* I really like this in usage. */ +void Root(char * filename) { + char path[PATH_MAX], * terminator; + if (!realpath(filename, path)) { return; } + if ((terminator = strrchr(path, '/'))) { + *terminator = '\0'; + if(chdir(path)) { abort(); } + } +} + +int Update(game_t * game, struct timespec now) { + (void) now; + PollInputEvents(); + if (IsWindowResized()) { + game->horizontal = GetScreenWidth(), game->vertical = GetScreenHeight(); + GameFrameReset(game); + } + switch (GetKeyPressed()) { + case KEY_ESCAPE: return 1; + } + return 0; +} -static inline void frame_reset(game_t * game) { - game_frame(game, 0, game->horizontal/12, game->vertical/12); - game_frame(game, 1, game->horizontal/3, game->vertical - game->vertical/8); - game_frame(game, 2, game->horizontal - game->horizontal/4, game->vertical/12); +void Frame(game_t * game, double interpolation) { + (void)interpolation; + BeginDrawing(); + ClearBackground(BLACK); + DrawCenteredText(game, 0, 20, WHITE, "Snails are now preparing! %d", rand()); + rlDrawRenderBatchActive(); + SwapScreenBuffer(); } -int main (int count, char ** arguments) +int Main(int count, char ** arguments) { (void)count; game_t game[1] = {0}; - game->horizontal = 1920; - game->vertical = 1080; - /* :config */ - frame_reset(game); - { /* this idented (DENTED) style is autistic and dumb but I like it visually */ - SetConfigFlags(FLAG_WINDOW_RESIZABLE); - /* tell raylib to shut up */ - /* SetTraceLogLevel(LOG_NONE); */ - InitWindow(game->horizontal, game->vertical, arguments[0]); - SetWindowState(FLAG_WINDOW_HIDDEN); - InitAudioDevice(); - SetWindowPosition(0, 0); - } - game->font = LoadFont("fonts/Atkinson/mono/AtkinsonHyperlegibleMono-Bold.otf"); - if (!IsFontValid(game->font)) { game->font = GetFontDefault(); } - - /* :todo ping me I'll update this to a u/f seperated game loop */ - { /* loop to end all loops */ - uint64_t fc = 0; - /* :config */ - float fps = 30; - double wait = wait = 1.0 / fps, delta = wait; - struct timespec start, end; - - clock_gettime(CLOCK_MONOTONIC, &start); - ClearWindowState(FLAG_WINDOW_HIDDEN); - int test[200*200] = {0}; - for (int i = 0; i < 200*200; i++) { test[i] = i;} - while (1) { - if (delta > wait) { - clock_gettime(CLOCK_MONOTONIC, &start); - { /* update */ - ++fc; - PollInputEvents(); - if (IsWindowResized()) { - game->horizontal = GetScreenWidth(), game->vertical = GetScreenHeight(); - frame_reset(game); - } - /* physical keys */ - switch (GetKeyPressed()) { - /* case KEY_Q: goto stop; */ - case KEY_ESCAPE: goto stop; - } - /* routed keys */ - /* switch (GetCharPressed()) { case 'q': goto stop; } */ - } - { /* draw */ - BeginDrawing(); - ClearBackground(BLACK); - draw_square_grid(game, 0, MIN(game->vertical/20, game->horizontal/25), NULL, test, 200); - draw_centered_text(game, 1, 20, WHITE, "Snails are now preparing!"); - draw_centered_text(game, 2, 20, WHITE, "Gambling here"); - rlDrawRenderBatchActive(); - SwapScreenBuffer(); - } - } - clock_gettime(CLOCK_MONOTONIC, &end); - delta = (end.tv_sec - start.tv_sec) + (end.tv_nsec - start.tv_nsec) / 1e9; - if (delta < wait) { - double should = -(delta - wait); - if (should > 0) { usleep(1e6 * should); } - } - } - } -stop: - SetWindowState(FLAG_WINDOW_HIDDEN); - UnloadFont(game->font); - CloseAudioDevice(); - CloseWindow(); + char * program_name = arguments[0]; + srand(time(NULL)); + Root(program_name); + GameInitialize(game, program_name); + GameLoop(game); + GameDeinitialize(game); return 0; } + +int main (int count, char ** arguments) __attribute__((alias("Main"))); diff --git a/source/render.c b/source/render.c index ef7280e..ef28cba 100644 --- a/source/render.c +++ b/source/render.c @@ -1,6 +1,6 @@ #include "all.h" -void draw_square_grid(game_t * game, size_t frame, int size, Texture * texture, int * array, size_t length) { +void DrawSquareGrid(game_t * game, size_t frame, int size, Texture * texture, int * array, size_t length) { (void)texture; float x = game->frame_x[frame], y = game->frame_y[frame]; float square_length = size; @@ -15,10 +15,10 @@ void draw_square_grid(game_t * game, size_t frame, int size, Texture * texture, } } -/* void draw_vertical_bargraph(game_t * game, size_t frame, int size, Color color, int * array, size_t length) { */ +/* void DrawVerticalBargraph(game_t * game, size_t frame, int size, Color color, int * array, size_t length) { */ /* } */ -void draw_centered_text(game_t * game, size_t frame, int font_size, Color color, char * format, ...) { +void DrawCenteredText(game_t * game, size_t frame, int font_size, Color color, char * format, ...) { char buffer[TEXT_BUFFER_LIMIT]; float x = game->frame_x[frame], y = game->frame_y[frame]; va_list ap; diff --git a/source/time.c b/source/time.c new file mode 100644 index 0000000..e2c47b0 --- /dev/null +++ b/source/time.c @@ -0,0 +1,56 @@ +#include "time.h" + +struct timespec timespec_add(struct timespec a, struct timespec b) { + a.tv_sec += b.tv_sec; + a.tv_nsec += b.tv_nsec; + if (a.tv_nsec >= 1000000000) { + a.tv_sec++; + a.tv_nsec -= 1000000000; + } + return a; +} + +struct timespec timespec_sub(struct timespec a, struct timespec b) { + a.tv_sec -= b.tv_sec; + a.tv_nsec -= b.tv_nsec; + if (a.tv_nsec < 0) { + a.tv_sec--; + a.tv_nsec += 1000000000; + } + return a; +} + +int timespec_cmp(struct timespec a, struct timespec b) { + return a.tv_sec > b.tv_sec ? + (1) : + a.tv_sec < b.tv_sec ? + (-1) : + ( + a.tv_nsec > b.tv_nsec ? + (1) : + a.tv_nsec < b.tv_nsec ? + (-1) : 0 + ); +} + +struct timespec timespec_max(struct timespec a, struct timespec b) { + return a.tv_sec > b.tv_sec ? + a : + a.tv_sec < b.tv_sec ? + b : + ( + a.tv_nsec > b.tv_nsec ? + a : b + ); +} + +struct timespec timespec_min(struct timespec a, struct timespec b) { + return a.tv_sec < b.tv_sec ? + a : + a.tv_sec > b.tv_sec ? + b : + ( + a.tv_nsec < b.tv_nsec ? + a : b + ); +} diff --git a/source/time.h b/source/time.h new file mode 100644 index 0000000..ca151f1 --- /dev/null +++ b/source/time.h @@ -0,0 +1,14 @@ +#ifndef TIME_H_ +#define TIME_H_ +#include <time.h> +#define TIMESPEC_TO_DOUBLE(ts) ((double)(ts).tv_sec + ((double)(ts).tv_nsec / TIMESPEC_HZ)) +enum { TIMESPEC_HZ = 1000000000 }; + +const struct timespec one_second = {1, 0}, zero_seconds = {0, 0}; + +struct timespec timespec_add(struct timespec a, struct timespec b); +struct timespec timespec_sub(struct timespec a, struct timespec b); +int timespec_cmp(struct timespec a, struct timespec b); +struct timespec timespec_min(struct timespec a, struct timespec b); +struct timespec timespec_max(struct timespec a, struct timespec b); +#endif /* TIME_H_ */ |
