Brackets game_tick() with skele_clock_tick_begin/end and the sleep-to-hit-tick-rate call with skele_clock_idle_begin/end.
scaffold
scaffold is a minimal starter template for building a game on top of skele and stk. It is not an engine of its own, it is the smallest working skeleton that wires the two together: a fixed-timestep game loop, hot-reload polling, and three build targets (software client, OpenGL client, headless server) sharing one game module.
Copy this repository to bootstrap a new game and start filling in src/game.c.
Key Features
- Three binaries from one game module: software client, OpenGL client, and headless server, all calling the same
game_init/game_tick/game_shutdowncontract - Fixed-timestep accumulator loop wired to
skele_tick_ns, correct across variable frame times stkhot-reload wired in from the start, polled every loop iteration- Static or dynamic linking against skele/stk via
LINK_TYPE - Cross-platform build (Linux, BSD, macOS, Windows, Raspberry Pi 5 GL auto-detect)
Quick Start
Building
# Unix (Linux/BSD/macOS)
./build.sh debug release
# Windows
build.bat debug release
Builds three binaries into bin/{debug,release}:
<game>_client- software rendering client<game>_glclient- OpenGL client<game>_server- headless server, no video/input linked
Set LINK_TYPE=dynamic (default static) to link against shared libskele/libstk instead:
./build.sh LINK_TYPE=dynamic debug release
Running
./build.sh run # software client
./build.sh run_gl # OpenGL client
Installation
./build.sh install
Installs to /usr on Linux, /usr/local on BSD/macOS by default. Use PREFIX to customize:
./build.sh PREFIX=$HOME/.local install
Usage
Starting a New Game
- Rename
GAME_NAMEinconfig.mk(used to name the built binaries). - Implement
game_init,game_tick, andgame_shutdowninsrc/game.c. - Add any additional source files to
GAME_SRCSinconfig.mk, they are compiled into all three binaries.
The Game Contract (include/game.h)
uint8_t game_init(void); /* return 0 to abort startup */
void game_tick(void); /* called once per simulation tick */
void game_shutdown(void); /* called once on exit */
This is the entire surface a game needs to implement. Rendering, input, windowing, and hot-reload are all handled by the client main.c files calling into skele/stk, not by the game module itself.
Client Loop (software and GL)
Both src/client/main.c and src/gl_client/main.c follow the same pattern: init clock and signal handling, set up stk, init skele, init the game, then run a fixed-timestep accumulator loop polling input and stk each frame before presenting. They are kept as separate files so each can diverge independently as you add renderer-specific setup (window flags, GL context options, and so on) without one client's changes leaking into the other.
Server Loop
src/server/main.c runs the same accumulator pattern without any video/input calls, calling only stk_poll() and game_tick() each iteration, then sleeping out the remainder of the tick.
Project Status
Very early. This is a starter template, not a finished project. game.c ships as an empty stub (game_init returns success, game_tick/game_shutdown do nothing). No automated tests.
License
BSD 3-Clause License
Contributing
Contributions welcome! Please ensure code follows C99 standard and works across all supported platforms.