Build & run¶
This page assumes Raylib is already installed on your system. Otherwise, compilation will fail at link time.
Compiling¶
The GUI is built with GNU Make from the gui/ directory:
The output is the build/zappy_gui binary (gui/Makefile:12). The Makefile
exposes the usual targets:
| Target | Effect |
|---|---|
make (all) |
Builds build/zappy_gui |
make clean |
Removes object files (build/obj) |
make fclean |
clean + removes the binary |
make re |
fclean then all |
The compiler is g++ with -Wall -Wextra -std=c++17 (gui/Makefile:1), with the
header directories src/core, src/network, src/renderer, src/world,
src/player (gui/Makefile:4). Nine translation units are compiled
(gui/Makefile:15); gui/raylib/Window.cpp is deliberately excluded (dead
code).
Root wrapper¶
The repository's root Makefile builds the three components (gui, ai, server)
and generates a small ./zappy_gui script at the root (Makefile:11):
This wrapper simply does cd gui/build/ then exec ./zappy_gui "$@"
(Makefile:13). It exists so the binary finds its assets — see
Asset resolution below.
Running¶
Command-line options¶
Argument parsing happens in gui/src/core/main.cpp:22:
| Option | Meaning | Details |
|---|---|---|
-h <host> |
Server address | Required: if empty, usage + exit |
-p <port> |
Server port | Default 4242; must be > 0 |
Although -p has a default value (4242, gui/src/core/main.cpp:20), -h does
not: launching without -h prints Usage: <argv0> -p port -h machine and exits
with failure (gui/src/core/main.cpp:46). Both options are therefore effectively
required in practice. An unknown argument, or a non-numeric port (Invalid port
value), also causes a failure exit (gui/src/core/main.cpp:34).
The GRAPHIC handshake¶
As soon as the connection is established, the GUI announces itself as a graphical
client by sending GRAPHIC\n (gui/src/core/main.cpp:55):
In response, the server pours out the world state (map size, tiles, teams, players, eggs…) that the MessageParser decodes. The full exchange is documented in GUI ↔ Server protocol.
Deliberate detail: the socket is opened BEFORE InitWindow¶
The order of operations in main is not incidental (gui/src/core/main.cpp:52):
NetworkClient net;
net.connect(host, port); // (1) socket opened
net.send("GRAPHIC\n"); // (2) handshake
// ...
InitWindow(WINDOW_W, WINDOW_H, WINDOW_T); // (3) window + textures
renderer.loadAssets("assets"); // (4) ~1000+ PNG files
The connection is made before InitWindow and asset loading on purpose.
loadAssets opens and reads over a thousand textures, consuming many file
descriptors. By connecting the socket first, we guarantee it gets a stable
descriptor, with no risk of colliding with an internal Raylib fopen happening late
in an already crowded descriptor table.
Asset resolution¶
The binary locates its assets/ folder flexibly, via resolveAssetsBase
(gui/src/renderer/Renderer3D.cpp:25). It probes for a witness file
(/animation/walk/1.png) at several levels:
static const char* kProbe = "/animation/walk/1.png";
if (FileExists((assetsDir + kProbe).c_str())) return assetsDir; // ./assets
if (FileExists(("../" + assetsDir + kProbe)...)) return "../" + assetsDir; // ../assets
if (FileExists(("../../" + assetsDir + kProbe)...))return "../../" + ...; // ../../assets
That is why the GUI is typically run from gui/build/: the assets are then at
../assets. This is exactly what the root wrapper does (cd gui/build/ then exec),
and the reason that cd exists.
# "Manual" launch equivalent to the wrapper
cd gui/build
./zappy_gui -h 127.0.0.1 -p 4242 # finds ../assets
If the sprites do not appear
A GUI launched from a directory where none of the three path variants point to
the assets falls back to the raw assetsDir, and the animations do not load.
Run it from gui/build/ (or via ./zappy_gui at the root).
Next step¶
Once connected and showing the map, on to rendering: see Graphics rendering for the main loop, the camera and the controls.