Skip to main content

How a game runs

Eggy builds a game package into a runtime for players and a desktop editor for working on the game. Both run the same Game and plugins. The runtime can also target the web, subject to the current platform limits.

The game is the first plugin​

src/main.zig declares pub const Game. A reusable package declares pub const Plugin in src/root.zig. Both are Zig types with optional hooks, components, preferences, and editor declarations. The game runs first, followed by plugins in build-list order.

Plugins are compiled into the game. A package can expose a plugin while using it in its own game, and dependencies share the game's Eggy. There is no runtime plugin discovery or separate inheritance interface for games.

The App belongs to the host​

Each hook receives the current *eggy.App, or an editor context containing it. There is no global current world or player.

App fieldRole
windowWindow adapter; app.window.window is the borrowed SDL window
graphicsGPU device and the main window's swapchain
worldECS world, using eggy.ecs
inputRouted keyboard/mouse state and named input maps for this frame
timeGameplay clocks, delta, and frame count
process_initZig's std.process.Init: arguments, environment, arena, allocator, and I/O

app.process_init remains valid for the run. For example, app.process_init.environ_map.get("MY_GAME_LEVEL") reads an environment variable. The App and plugin instances may move; a hook's pointers are not permanent handles. See Ownership, Play, and reload.

Eggy re-exports libraries through eggy.ecs (Clutch), eggy.math (Eggenvector), eggy.ui (Weeoui), and eggy.vit (Vitellus). Those libraries retain their own APIs. eggy.sdl_adapter.sdl is the SDL3 binding used by the engine.

Startup​

The runtime chooses and loads its startup scene before starting plugins. Preferences and enabled plugins' input maps are registered before init, so initialization can find scene entities and read settings.

Each enabled plugin's init constructs its value and can register ECS systems. Once all plugins have started, Eggy runs the world's Init stages. A failed init unwinds already-started plugins and prevents startup.

Scene selection is a build decision; the configuration reference lists its precedence.

Running frames​

Input reaches UI before gameplay. Weeoui may consume it, then custom uiEvent hooks may consume it before gameplay events. Gameplay polling uses the routed frame state; games must not poll SDL's event queue themselves.

During a running frame, plugin update hooks run before ECS Update systems. Rendering draws the scene, then draw, then gameUi. The supplied draw target and UI context belong to that frame; Eggy owns frame submission.

Gameplay clocks and input edges follow the rules in Input and gameplay time. Hook signatures and dispatch order are listed in Plugin hooks and declarations.

The editor has editing and playing states​

While editing, editorUpdate runs instead of gameplay updates. Play starts gameplay against the scene and runs its systems and events. Pause stops gameplay updates while keeping game UI and drawing available; editor tools can still run.

The editor hosts the game in a shared library, which it can rebuild independently. The editor UI and layout survive a game-library swap, while plugin state restarts. The Build window suspends editor updates and game rendering during the build.

The Play and reload explanation describes what survives, what is restored on Stop, and which values become invalid.

Shutdown and errors​

Started plugins stop in reverse order through deinit, releasing resources they own. The host tears down the App, world, and engine resources.

The runtime treats uncaught hook errors as fatal. The editor reports running game-library hook failures and keeps the editor usable; a failed game initialization prevents that game instance from starting. Recovery within a hook is described in Diagnose and handle errors.