aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rwxr-xr-xMakefile121
-rw-r--r--README.md0
-rw-r--r--fonts/Atkinson/info.txt68
-rw-r--r--fonts/Atkinson/mono/AtkinsonHyperlegibleMono-Bold.otfbin0 -> 33148 bytes
-rw-r--r--fonts/Atkinson/mono/AtkinsonHyperlegibleMono-BoldItalic.otfbin0 -> 33688 bytes
-rw-r--r--fonts/Atkinson/mono/AtkinsonHyperlegibleMono-Regular.otfbin0 -> 31624 bytes
-rw-r--r--fonts/Atkinson/mono/AtkinsonHyperlegibleMono-RegularItalic.otfbin0 -> 32840 bytes
-rw-r--r--fonts/Atkinson/regular/AtkinsonHyperlegibleNext-Bold.otfbin0 -> 45384 bytes
-rw-r--r--fonts/Atkinson/regular/AtkinsonHyperlegibleNext-BoldItalic.otfbin0 -> 48796 bytes
-rw-r--r--fonts/Atkinson/regular/AtkinsonHyperlegibleNext-Regular.otfbin0 -> 42916 bytes
-rw-r--r--fonts/Atkinson/regular/AtkinsonHyperlegibleNext-RegularItalic.otfbin0 -> 47304 bytes
-rw-r--r--fonts/TypeLightSans/TypeLightSans.otfbin0 -> 19636 bytes
-rw-r--r--fonts/TypeLightSans/info.txt2
-rw-r--r--fonts/UnitBlock/Unitblock.ttfbin0 -> 76092 bytes
-rw-r--r--fonts/UnitBlock/info.txt2
-rw-r--r--include/.gitignore1
-rw-r--r--library/.gitignore1
-rw-r--r--object/.gitignore1
-rw-r--r--source/all.h38
-rw-r--r--source/chad.h119
-rw-r--r--source/game.c143
-rw-r--r--source/main.c16
-rw-r--r--source/raylib.c33
24 files changed, 547 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..359ed7c
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+monobomberman
+!*/
diff --git a/Makefile b/Makefile
new file mode 100755
index 0000000..168eeec
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,121 @@
+#!/usr/bin/make -f
+
+SOURCE.dir := source
+OBJECT.dir := object
+INCLUDE.dir := include
+LIBRARY.dir := library
+LIBRARY := $(addprefix ${LIBRARY.dir}/, libraylib.amd64.a)
+HEADER := $(wildcard ${SOURCE.dir}/*.h) $(wildcard ${INCLUDE.dir}/*.h) include/raygui.h include/raylib.h
+HEADER.orig := $(HEADER:${SOURCE.dir}/%=%)
+HEADER.orig := $(HEADER.orig:${INCLUDE.dir}/%=%)
+HEADER.pch := $(filter-out ${OBJECT.dir}/style_dark.h,$(addprefix ${OBJECT.dir}/, ${HEADER.orig:.c=}))
+SOURCE.orig := $(wildcard ${SOURCE.dir}/*.c)
+SOURCE.orig := $(SOURCE.orig:${SOURCE.dir}/%=%)
+SOURCE := $(addprefix ${SOURCE.dir}/, ${SOURCE.orig})
+OBJECT := $(addprefix ${OBJECT.dir}/, ${SOURCE.orig:.c=.o})
+DEPEND := $(wildcard ${OBJECT.dir}/*.d)
+
+TARGET := $(shell basename $$PWD)
+
+CFLAGS := -std=c23 -pthread -MMD -MP
+CPPFLAGS := -Iinclude -D_GNU_SOURCE -I ${OBJECT.dir}
+LDFLAGS := -lm -lbsd
+
+ifneq ($(shell which mold 2> /dev/null),)
+ LDFLAGS += -fuse-ld=mold
+ LD := mold
+endif
+
+ifneq ($(shell which clang 2> /dev/null),)
+ CC := clang
+else
+ ifneq ($(shell which gcc 2> /dev/null),)
+ CC := gcc
+ else
+ $(error GCC & Clang not available.)
+ endif
+endif
+
+ifeq (${CC},gcc)
+ HEADER.pch := $(addsuffix .gch,${HEADER.pch})
+else
+ HEADER.pch := $(addsuffix .pch,${HEADER.pch})
+endif
+
+DEBUG ?= 0
+SANITIZE ?= 0
+VECTORIZED ?= 0
+
+ifeq (${DEBUG},1)
+ CFLAGS += -O2 -ggdb -pg -fno-inline -Wall -Wextra -Wpedantic -Wshadow -Wundef
+else
+ CFLAGS += -O0 -flto=auto -ftree-vectorize -march=x86-64 -mtune=generic
+ CPPFLAGS += -DNDEBUG -D_FORTIFY_SOURCE=2
+endif
+
+ifeq (${SANITIZE},1)
+ CFLAGS += -fsanitize=address,undefined
+endif
+
+ifeq (${VECTORIZED},1)
+ ifeq (${CC},clang)
+ CFLAGS += -Rpass=loop-vectorize
+ else
+ CFLAGS += -fopt-info-vec-all
+ endif
+endif
+
+ifeq (${VECTORIZED_ALL},1)
+ ifeq (${CC},clang)
+ CFLAGS += -Rpass=loop-vectorize -Rpass-missed=loop-vectorize
+ else
+ CFLAGS += -fopt-info-vec-all
+ endif
+endif
+
+vpath %.c ${SOURCE.dir}
+vpath %.h ${SOURCE.dir} ${INCLUDE.dir}
+
+${OBJECT.dir}/%.o: %.c
+ @echo "CC $<"
+ @${COMPILE.c} -o $@ $<
+
+# The tree builds incorrectly if these two are merged
+# at the target level at a bare build.
+${OBJECT.dir}/%.h.pch: %.h
+ @echo "PCH $<"
+ @${COMPILE.c} ${PCHFLAGS} -x c-header -o $@ $<
+
+ ${OBJECT.dir}/%.h.gch: %.h
+ @echo "GCH $<"
+ @${COMPILE.c} ${PCHFLAGS} -x c-header -o $@ $<
+
+.PHONY: all clean
+all: include/raylib.h include/raygui.h .WAIT ${HEADER.pch} ${TARGET}
+
+${HEADER.pch}: ${LIBRARY.dir}/libraylib.amd64.a include/raygui.h include/style_dark.h
+
+clean:
+ rm -f ${OBJECT.dir}/*.o ${OBJECT.dir}/*.pch ${OBJECT.dir}/*.gch ${OBJECT.dir}/*.d ${LIBRARY.dir}/*.a ${INCLUDE.dir}/*.h ${TARGET}
+ rm -f /tmp/raygui.tgz /tmp/raylib.tgz
+
+${TARGET}: ${LIBRARY.dir}/libraylib.amd64.a ${OBJECT}
+ @echo "LD $@"
+ @${LINK.c} -o "$@" $+ ${LDFLAGS}
+
+include/raylib.h ${LIBRARY.dir}/libraylib.amd64.a &:
+ @echo Updating Raylib
+ @[ ! -e /tmp/raylib.tgz ] && wget -qO /tmp/raylib.tgz "https://github.com/raysan5/raylib/releases/download/5.5/raylib-5.5_linux_amd64.tar.gz" || true
+ @tar xvC /tmp/ -f /tmp/raylib.tgz raylib-5.5_linux_amd64/lib/libraylib.a raylib-5.5_linux_amd64/LICENSE raylib-5.5_linux_amd64/include > /dev/null
+ @mv -f /tmp/raylib-5.5_linux_amd64/lib/libraylib.a library/libraylib.amd64.a
+ @mv -f /tmp/raylib-5.5_linux_amd64/include/* include/
+ @mv -f /tmp/raylib-5.5_linux_amd64/LICENSE library/libraylib.LICENSE.a
+
+include/raygui.h include/style_dark.h &:
+ @echo Updating RayGUI
+ @[ ! -e /tmp/raygui.tgz ] && wget -qO /tmp/raygui.tgz https://github.com/raysan5/raygui/archive/refs/tags/4.0.tar.gz || true
+ @tar xvC /tmp/ -f /tmp/raygui.tgz raygui-4.0/src/raygui.h raygui-4.0/styles/dark/style_dark.h > /dev/null
+ @mv -f /tmp/raygui-4.0/src/raygui.h include/
+ @mv -f /tmp/raygui-4.0/styles/dark/style_dark.h include/
+
+-include ${DEPEND}
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/README.md
diff --git a/fonts/Atkinson/info.txt b/fonts/Atkinson/info.txt
new file mode 100644
index 0000000..2d696c3
--- /dev/null
+++ b/fonts/Atkinson/info.txt
@@ -0,0 +1,68 @@
+https://www.brailleinstitute.org/freefont
+
+Copyright 2020, Braille Institute of America, Inc. (https://www.brailleinstitute.org/), with
+Reserved Font Names: “ATKINSON” and “HYPERLEGIBLE”.
+This Font Software is licensed under the SIL Open Font License, Version 1.1. This
+license is copied below, and is also available with a FAQ at: https://openfontlicense.org
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide development of
+collaborative font projects, to support the font creation efforts of academic and
+linguistic communities, and to provide a free and open framework in which fonts may be
+shared and improved in partnership with others.
+The OFL allows the licensed fonts to be used, studied, modified and redistributed freely
+as long as they are not sold by themselves. The fonts, including any derivative works,
+can be bundled, embedded, redistributed and/or sold with any software provided that
+any reserved names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The requirement for fonts
+to remain under this license does not apply to any document created using the fonts or
+their derivatives.
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright Holder under this
+license and clearly marked as such. This may include source files, build scripts and
+documentation.
+"Reserved Font Names" refers to any names specified as such after the copyright
+statement.
+"Original Version" refers to the collection of Font Software components as distributed by
+the Copyright Holder.
+"Modified Version" refers to any derivative made by adding to, deleting, or substituting --
+in part or in whole -- any of the components of the Original Version, by changing
+formats or by porting the Font Software to a new environment.
+"Author" refers to any designer, engineer, programmer, technical writer or other person
+who contributed to the Font Software.
+PERMISSION & CONDITIONS
+VP/#68933639.2
+Permission is hereby granted, free of charge, to any person obtaining a copy of the Font
+Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and
+unmodified copies of the Font Software, subject to the following conditions:
+1) Neither the Font Software nor any of its individual components, in Original or
+Modified Versions, may be sold by itself.
+2) Original or Modified Versions of the Font Software may be bundled, redistributed
+and/or sold with any software, provided that each copy contains the above copyright
+notice and this license. These can be included either as stand-alone text files, human-
+readable headers or in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+3) No Modified Version of the Font Software may use the Reserved Font Names unless
+explicit written permission is granted by the Copyright Holder. This restriction only
+applies to the primary font name as presented to the users.
+4) The name of the Copyright Holder or the Author(s) of the Font Software shall not be
+used to promote, endorse or advertise any Modified Version, except to acknowledge the
+contributions of the Copyright Holder and the Author(s) or with their explicit written
+permission.
+5) The Font Software, modified or unmodified, in part or in whole, must be distributed
+entirely under this license, and must not be distributed under any other license. The
+requirement for fonts to remain under this license does not apply to any document
+created using the Font Software.
+TERMINATION
+This license becomes null and void if any of the above conditions are not met.
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO
+EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR
+CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR
+OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT
+SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
+VP/#68933639.2
diff --git a/fonts/Atkinson/mono/AtkinsonHyperlegibleMono-Bold.otf b/fonts/Atkinson/mono/AtkinsonHyperlegibleMono-Bold.otf
new file mode 100644
index 0000000..e092ce8
--- /dev/null
+++ b/fonts/Atkinson/mono/AtkinsonHyperlegibleMono-Bold.otf
Binary files differ
diff --git a/fonts/Atkinson/mono/AtkinsonHyperlegibleMono-BoldItalic.otf b/fonts/Atkinson/mono/AtkinsonHyperlegibleMono-BoldItalic.otf
new file mode 100644
index 0000000..ac99b71
--- /dev/null
+++ b/fonts/Atkinson/mono/AtkinsonHyperlegibleMono-BoldItalic.otf
Binary files differ
diff --git a/fonts/Atkinson/mono/AtkinsonHyperlegibleMono-Regular.otf b/fonts/Atkinson/mono/AtkinsonHyperlegibleMono-Regular.otf
new file mode 100644
index 0000000..36c0a22
--- /dev/null
+++ b/fonts/Atkinson/mono/AtkinsonHyperlegibleMono-Regular.otf
Binary files differ
diff --git a/fonts/Atkinson/mono/AtkinsonHyperlegibleMono-RegularItalic.otf b/fonts/Atkinson/mono/AtkinsonHyperlegibleMono-RegularItalic.otf
new file mode 100644
index 0000000..567aa1f
--- /dev/null
+++ b/fonts/Atkinson/mono/AtkinsonHyperlegibleMono-RegularItalic.otf
Binary files differ
diff --git a/fonts/Atkinson/regular/AtkinsonHyperlegibleNext-Bold.otf b/fonts/Atkinson/regular/AtkinsonHyperlegibleNext-Bold.otf
new file mode 100644
index 0000000..2d10468
--- /dev/null
+++ b/fonts/Atkinson/regular/AtkinsonHyperlegibleNext-Bold.otf
Binary files differ
diff --git a/fonts/Atkinson/regular/AtkinsonHyperlegibleNext-BoldItalic.otf b/fonts/Atkinson/regular/AtkinsonHyperlegibleNext-BoldItalic.otf
new file mode 100644
index 0000000..6de50d5
--- /dev/null
+++ b/fonts/Atkinson/regular/AtkinsonHyperlegibleNext-BoldItalic.otf
Binary files differ
diff --git a/fonts/Atkinson/regular/AtkinsonHyperlegibleNext-Regular.otf b/fonts/Atkinson/regular/AtkinsonHyperlegibleNext-Regular.otf
new file mode 100644
index 0000000..ba345b5
--- /dev/null
+++ b/fonts/Atkinson/regular/AtkinsonHyperlegibleNext-Regular.otf
Binary files differ
diff --git a/fonts/Atkinson/regular/AtkinsonHyperlegibleNext-RegularItalic.otf b/fonts/Atkinson/regular/AtkinsonHyperlegibleNext-RegularItalic.otf
new file mode 100644
index 0000000..49c0897
--- /dev/null
+++ b/fonts/Atkinson/regular/AtkinsonHyperlegibleNext-RegularItalic.otf
Binary files differ
diff --git a/fonts/TypeLightSans/TypeLightSans.otf b/fonts/TypeLightSans/TypeLightSans.otf
new file mode 100644
index 0000000..670e3b7
--- /dev/null
+++ b/fonts/TypeLightSans/TypeLightSans.otf
Binary files differ
diff --git a/fonts/TypeLightSans/info.txt b/fonts/TypeLightSans/info.txt
new file mode 100644
index 0000000..116e91d
--- /dev/null
+++ b/fonts/TypeLightSans/info.txt
@@ -0,0 +1,2 @@
+license: Public Domain
+link: https://www.fontspace.com/type-light-sans-font-f135100 \ No newline at end of file
diff --git a/fonts/UnitBlock/Unitblock.ttf b/fonts/UnitBlock/Unitblock.ttf
new file mode 100644
index 0000000..be3872e
--- /dev/null
+++ b/fonts/UnitBlock/Unitblock.ttf
Binary files differ
diff --git a/fonts/UnitBlock/info.txt b/fonts/UnitBlock/info.txt
new file mode 100644
index 0000000..22e3606
--- /dev/null
+++ b/fonts/UnitBlock/info.txt
@@ -0,0 +1,2 @@
+license: Public Domain
+link: https://www.fontspace.com/unitblock-font-f104834 \ No newline at end of file
diff --git a/include/.gitignore b/include/.gitignore
new file mode 100644
index 0000000..72e8ffc
--- /dev/null
+++ b/include/.gitignore
@@ -0,0 +1 @@
+*
diff --git a/library/.gitignore b/library/.gitignore
new file mode 100644
index 0000000..72e8ffc
--- /dev/null
+++ b/library/.gitignore
@@ -0,0 +1 @@
+*
diff --git a/object/.gitignore b/object/.gitignore
new file mode 100644
index 0000000..72e8ffc
--- /dev/null
+++ b/object/.gitignore
@@ -0,0 +1 @@
+*
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);
+ }
+}