diff options
| author | Emil Williams | 2026-02-11 08:05:44 +0000 |
|---|---|---|
| committer | Emil Williams | 2026-02-11 08:05:44 +0000 |
| commit | 35bc8bc9f7df8bdb731d7d190b50d05ebd9c94ab (patch) | |
| tree | 81592743a5512e486913d796f7201a65825fc29f /source | |
| download | Monobomberman-35bc8bc9f7df8bdb731d7d190b50d05ebd9c94ab.tar.xz Monobomberman-35bc8bc9f7df8bdb731d7d190b50d05ebd9c94ab.tar.zst | |
init
Diffstat (limited to 'source')
| -rw-r--r-- | source/all.h | 38 | ||||
| -rw-r--r-- | source/chad.h | 119 | ||||
| -rw-r--r-- | source/game.c | 143 | ||||
| -rw-r--r-- | source/main.c | 16 | ||||
| -rw-r--r-- | source/raylib.c | 33 |
5 files changed, 349 insertions, 0 deletions
diff --git a/source/all.h b/source/all.h new file mode 100644 index 0000000..babc53f --- /dev/null +++ b/source/all.h @@ -0,0 +1,38 @@ +#ifndef EVERYTHING_ALWAYS_H_ +#define EVERYTHING_ALWAYS_H_ + +#include <stdio.h> +#include <stdint.h> +#include <math.h> + +#include <raylib.h> +#include <raygui.h> +#include <rlgl.h> + +#include "chad.h" + +typedef struct { + Font font __attribute__((aligned)); + i16 horizontal, vertical __attribute__((aligned)); + f32 ups, fps __attribute__((aligned)); +} game_t; + +/* game.c */ + +void GameInitialize(game_t * game, char * window_name); +void GameDeinitialize(game_t * game); +void GameFrame(game_t * game, size_t frame, f32 x, f32 y); +Vector2 GameFrameVector(game_t * game, size_t frame); +void GameLoop(game_t * game); +i16 GameUpdate(game_t * game, timespec_t now); +void GameRender(game_t * game, f64 interpolation); +void GameReport(game_t * game, f32 fps, f32 ups, u32 total_fps, u32 total_ups) ; + +/* raylib.c */ + +Font DefaultFont(char * choice); +void GuiLoadStyleDarkSimple(void); + +/* ... */ + +#endif /* EVERYTHING_ALWAYS_H_ */ diff --git a/source/chad.h b/source/chad.h new file mode 100644 index 0000000..ceaec36 --- /dev/null +++ b/source/chad.h @@ -0,0 +1,119 @@ +/* util.h & time.h */ + +#ifndef UTIL_H_ +#define UTIL_H_ + +/* these things that are highly portable among programs and thus written in a modular style */ + +#include <math.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <limits.h> +#include <stdint.h> + +#define always_inline static inline __attribute__((always_inline)) + +#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) + +always_inline void Root(char * filename) { + char path[PATH_MAX], * terminator; + if (!realpath(filename, path)) { return; } + if ((terminator = strrchr(path, '/'))) { + *terminator = '\0'; + if(chdir(path)) { abort(); } + } +} + +always_inline float Angle(float a_x, float a_y, float b_x, float b_y) { + return atan2f(b_y - a_y, b_x - a_x); +} + +always_inline float Distance(float a_x, float a_y, float b_x, float b_y) { + return sqrtf(powf(b_x - a_x, 2) + powf(b_y - a_y, 2)); +} + +typedef int8_t i8; +typedef int16_t i16; +typedef int32_t i32; +typedef int64_t i64; + +typedef uint8_t u8; +typedef uint16_t u16; +typedef uint32_t u32; +typedef uint64_t u64; + +typedef float f32; +typedef double f64; + +#endif + +/* time.h */ +#ifndef TIME_H_ +#define TIME_H_ +#include <time.h> + +#define TIMESPEC_TO_F64(ts) ((double)(ts).tv_sec + ((double)(ts).tv_nsec / TIMESPEC_HZ)) +enum { TIMESPEC_HZ = 1000000000 }; + +typedef struct timespec timespec_t; + +static const timespec_t one_second = {1, 0}, zero_seconds = {0, 0}; + +always_inline timespec_t timespec_add(timespec_t a, timespec_t 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; +} + +always_inline timespec_t timespec_sub(timespec_t a, timespec_t 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; +} + +always_inline int timespec_cmp(timespec_t a, timespec_t 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 + ); +} + +always_inline timespec_t timespec_max(timespec_t a, timespec_t b) { + return a.tv_sec > b.tv_sec ? + a : + a.tv_sec < b.tv_sec ? + b : + ( + a.tv_nsec > b.tv_nsec ? + a : b + ); +} + +always_inline timespec_t timespec_min(timespec_t a, timespec_t b) { + return a.tv_sec < b.tv_sec ? + a : + a.tv_sec > b.tv_sec ? + b : + ( + a.tv_nsec < b.tv_nsec ? + a : b + ); +} +#endif /* TIME_H_ */ diff --git a/source/game.c b/source/game.c new file mode 100644 index 0000000..2ade12a --- /dev/null +++ b/source/game.c @@ -0,0 +1,143 @@ +#include "all.h" + +void GameInitialize(game_t * game, char * window_name) { + SetConfigFlags(FLAG_WINDOW_RESIZABLE); + SetTraceLogLevel(LOG_NONE); + /* :config */ + game->horizontal = 1920; + game->vertical = 1080; + InitWindow(game->horizontal, game->vertical, window_name); + game->ups = 60; + game->fps = 30; + game->font = DefaultFont("fonts/Atkinson/mono/AtkinsonHyperlegibleMono-Bold.otf"); + /* :setup */ + SetWindowState(FLAG_WINDOW_HIDDEN); + InitAudioDevice(); + SetWindowPosition(0, 0); + GuiLoadStyleDarkSimple(); + GuiSetFont(game->font); + /* --- */ +} + +void GameDeinitialize(game_t * game) { + SetWindowState(FLAG_WINDOW_HIDDEN); + UnloadFont(game->font); + CloseAudioDevice(); + CloseWindow(); +} + +void GameLoop(game_t * game) { + + #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, (timespec_t){1.,0.}) >= 0) { \ + (void)0 + + #define StepSimpleStop(prefix) \ + prefix##_last = now; \ + } + + timespec_t + now, + update_interval = {0, (f64) TIMESPEC_HZ / game->ups}, + frame_interval = {0, (f64) TIMESPEC_HZ / game->fps}, + update_last, frame_last, print_last, + update_delta, frame_delta, print_delta, + wait; + + u16 + updates_per_second = 0, frames_per_second = 0; + + u32 + frame_total = 0, update_total = 0; + + f64 interpolation = 0.; + + ClearWindowState(FLAG_WINDOW_HIDDEN); + + clock_gettime(CLOCK_MONOTONIC, &now); + update_last = frame_last = print_last = now; + + while (1) { + StepStart(update); + if (GameUpdate(game, now)) { return; } + StepStop(update); + + StepStart(frame); + clock_gettime(CLOCK_MONOTONIC, &now); + interpolation = + CLAMP( + TIMESPEC_TO_F64(update_delta) + / TIMESPEC_TO_F64(update_interval), + 0.0, 1.0f); + GameRender(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); + GameReport(game, + round(frames_per_second / TIMESPEC_TO_F64(print_delta)), + round(updates_per_second / TIMESPEC_TO_F64(print_delta)), + frame_total, + update_total); + frames_per_second = updates_per_second = 0; + StepSimpleStop(print); + + clock_gettime(CLOCK_MONOTONIC, &now); + } +} + +i16 GameUpdate(game_t * game, timespec_t now) { + (void) now; + + PollInputEvents(); + if (IsWindowResized()) { + game->horizontal = GetScreenWidth(); + game->vertical = GetScreenHeight(); + } + switch (GetKeyPressed()) { + case KEY_ESCAPE: return 1; + } + return 0; +} + +void GameRender(game_t * game, f64 interpolation) { + (void)interpolation; + + BeginDrawing(); + ClearBackground(BLACK); + /* >>> */ + + /* --- */ + rlDrawRenderBatchActive(); + SwapScreenBuffer(); +} + +void GameReport(game_t * game, f32 fps, f32 ups, u32 total_fps, u32 total_ups) { + printf("[FPS|UPS|Total] (%3.0f : %3.0f) | [%7u/%7u]\n", + fps, ups, total_fps, total_ups); +} diff --git a/source/main.c b/source/main.c new file mode 100644 index 0000000..d00f7e7 --- /dev/null +++ b/source/main.c @@ -0,0 +1,16 @@ +#include "all.h" + +int Main(int count, char ** arguments) +{ + (void)count; + _Alignas(64) game_t game[1] = {0}; + 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/raylib.c b/source/raylib.c new file mode 100644 index 0000000..935feee --- /dev/null +++ b/source/raylib.c @@ -0,0 +1,33 @@ +/* raylib.c & raygui.c */ + +#include <raylib.h> + +Font DefaultFont(char * choice) { + Font font = LoadFont(choice); + if (!IsFontValid(font)) { font = GetFontDefault(); } + return font; +} + +/* raygui.c */ + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-parameter" +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wunused-function" +#pragma GCC diagnostic ignored "-Wunused-result" +#pragma GCC diagnostic ignored "-Wpragmas" +#pragma GCC diagnostic ignored "-Wunknown-warning-option" +#pragma GCC diagnostic ignored "-Walloc-size-larger-than=" +#pragma GCC diagnostic ignored "-Wunused-but-set-variable" + +#define RAYGUI_IMPLEMENTATION +#include <raygui.h> +#include <style_dark.h> +#pragma GCC diagnostic pop + +/* removes the timewaster of decompressing and loading a font never used */ +void GuiLoadStyleDarkSimple(void) { + for (int i = 0; i < DARK_STYLE_PROPS_COUNT; i++) { + GuiSetStyle(darkStyleProps[i].controlId, darkStyleProps[i].propertyId, darkStyleProps[i].propertyValue); + } +} |
