GalaxyEggbertGame
The application host: one XNA Game that owns every subsystem, runs the phases and the fixed 60 Hz tick, and draws each frame.
Location
| Header | src/GalaxyEggbertCNA/GalaxyEggbertGame.hpp |
|---|---|
| Sources |
GalaxyEggbertGame.cpp (input capture, cheats, vehicles, death and pickup resolution, music),
GalaxyEggbertGameUpdate.cpp (Update, UpdateTick and its stages),
GalaxyEggbertGameDraw.cpp (Draw, DrawFrame, overlays, captures),
GalaxyEggbertGameScene.cpp (BuildSceneFrame: what the 3D world draws),
GalaxyEggbertGameLoad.cpp (LoadContent, world presentation),
GalaxyEggbertGameMissions.cpp (missions, phases, editor and galaxy worlds, autoplay steps),
GalaxyEggbertGameDemo.cpp (resume log, main-menu demos, recordings) — all in src/GalaxyEggbertCNA/.
Shared file-local helpers: GameHelpers.hpp, GameInternal.hpp. Entry point: main.cpp. |
| Namespace | GalaxyEggbert::CNA |
| Base class | Microsoft::Xna::Framework::Game (CNA) |
| Engine dependency | Yes: CNA (graphics, audio, input, windowing) and cna-engine (Camera, debug drawing). This is the only class tree that is allowed to know about the platform. |
Until 2026-11-09 nearly all of this lived in one GalaxyEggbertGame.cpp of about 8 400 lines; it was then split by topic into the seven files above (a refactor only). Older pages called the class GalaxyEggbertCnaGame.
Purpose
GalaxyEggbertGame is the glue between the engine-independent game code and CNA. It loads the content, owns the
world (WorldRuntime), Blupi (BlupiController), the objects'
rules (InteractionSystem), the renderers, the HUD, sound, menus, save data and the editor,
and calls them in a fixed order once per 1/60 s step. It decides which phase the game is in (menus, Play, Pause,
Win, Lost, Setup, Resume, Editor) and applies the state changes that cross subsystem boundaries: the events
InteractionSystem and BlupiController report are turned here into deaths, camera shakes, sounds,
HUD updates and mission changes.
Collaborators
Uses
- Simulation: WorldRuntime, BlupiController, InteractionSystem, HubDoors,
ChaseCameraYaw,CameraShake. - Presentation: TileAtlas, TerrainRenderer, WorldRenderer (fed a
SceneFrame),ObjectModelTable,EffectParticles,PostProcess,UltraFinish, Hud, Sound. - Input and UI: InputPad,
ControlInput,GamepadInput,FocusNavigator,ScreenKeyboard,EditorDeviceControls. - Persistence and tooling: SaveData, ResumeLog, DemoReplay, Autoplay, WorldEditor, CustomWorldStorage functions.
Used by
src/GalaxyEggbertCNA/main.cpponly: it picks the player's folder, creates one instance, applies the command-line flags and callsRun().
Key members
The public interface is small: the XNA overrides plus the start-up switches that main.cpp sets before
Run(). The rest of the header (about 1 500 lines) is private state and helpers; the table names a selection of
both, verified against GalaxyEggbertGame.hpp as of 2026-11-10.
| Member | Signature | What it does |
|---|---|---|
LoadContent | void LoadContent() override | Loads sprite sheets, the tile atlas, sounds, the 3D model libraries in avatars3d/ (Blupi, objects, BigDecor shapes), and creates the HUD, pad, editor and renderers. Falls back to first person when no Blupi model loads. |
Update | void Update(GameTime& gameTime) override | One fixed 1/60 s step: resume replay, demo playback, one-time start modes, autoplay, CaptureInput(), UpdateTick(), then appends the tick's input to the resume log and to a demo being recorded. |
Draw | void Draw(const GameTime& gameTime) override | Calls DrawFrame(). |
OnDeactivated | void OnDeactivated(System::Object*, const System::EventArgs&) override | Focus lost: stops a demo; in Play writes the resume log (to a temporary file, then renamed), otherwise deletes it. |
OnExiting | void OnExiting(System::Object*, const System::EventArgs&) override | Finishes a demo recording and deletes the resume file (a clean exit leaves nothing to resume). |
EnableStartMission | void EnableStartMission(int missionNumber) noexcept | --mission N: skip the menus and start mission N in Play. |
EnableStartSpawn | void EnableStartSpawn(float x, float y, float z, float yawDegrees) noexcept | --spawn x,y,z[,yaw]: place Blupi at a raw-grid position instead of the world's spawn. |
EnableGalaxyStart | void EnableGalaxyStart() noexcept | --galaxy: --mission N is a mission of the selected player's own galaxy. |
EnableAutoplay | bool EnableAutoplay(const std::string& scriptPath) | --autoplay: a QA script plays instead of the keyboard; false when the script cannot be read or parsed. |
AutoplayExitCode | int AutoplayExitCode() const noexcept | The process exit code main.cpp returns (0 when a script or demo verification passed). |
EnableDemoRecording, EnableDemoVerify | void EnableDemoRecording(const std::string& path, int maxTicks, const std::string& title)void EnableDemoVerify(const std::string& path) | --record-demo / --verify-demo: record a mission as a .gdemo, or replay one silently and compare its end state. |
EnableGoldenCaptureMode, EnableGoldenTraceMode | void ...() noexcept | --golden-capture / --golden-capture-trace: load world 999, run fixed ticks, write golden_frame_NNNN.png or golden_trace.txt, exit. |
UpdateTick (private) | void UpdateTick() | The tick: help overlay, fades, UpdateTickScreens (every phase's input), title scene, then in Play WorldRuntime::Update and UpdateTickWorld. |
LoadMission (private) | void LoadMission(int missionNumber, const std::string* validatedBytes = nullptr) | Reads worlds3d/worldNNN.vwr (or the galaxy's world), rebuilds the presentation, applies hub doors, resets InteractionSystem (keeping lives) with a fresh seed, places Blupi and arms the resume log. |
SetPhase (private) | void SetPhase(GamePhase next, bool bypassFade = false) noexcept | Changes phase (with the original's fade unless bypassed); ends demos and the resume recording when leaving Play for a menu, Win, Lost or the editor. |
DrawFrame (private) | void DrawFrame() | Builds the SceneFrame, renders shadows and the world through WorldRenderer (with the effect passes the level asks for), then DrawOverlay (HUD, menus, editor) and DrawFrameCaptures. |
ApplyCheat, ApplyTypedCheat (private) | void ApplyCheat(int cheatNumber)void ApplyTypedCheat(InputPad::TypedCheat cheat) | The nine cheats of the hidden menu (F12 or the ten-tap gesture) and the typed cheat words recognised by InputPad. |
OpenMissionInEditor, LeaveMissionEditor (private) | void ...() | The xnjttjpo hand-off: open the world being played in the editor, and return to the mission from its start. |
Phases
The phase is a GalaxyEggbert::Def::GamePhase (include/GalaxyEggbert/Def/GamePhase.hpp), the original's
enum plus one value: None, First, Wait, Init (main menu and player select),
Play, Pause, Lost, Win, Trial, MainSetup,
PlaySetup, Resume, Ranking and Editor (Galaxy Eggbert's own). Trial and
Ranking exist for numbering only; nothing switches to them. Menus are drawn and hit-tested by
InputPad in the original's 640 × 480 layout; the title scene (worlds3d/title.vwr)
plays behind the menu and the editor's slot list.
How it is used
The tick in Play
UpdateTickWorld (in GalaxyEggbertGameUpdate.cpp) runs the simulation in this order: terrain animation,
input to steering, BlupiController::Step and its events (sounds, landing, teleports), actions
(UpdateTickActions: switches, dynamite, vehicles), crate pushing, InteractionSystem::Update, terrain
patching (RefreshTerrainMeshIfChanged), voyages, then UpdateTickEvents (shakes, Lost, Win) and
UpdateTickCamera. A simulation speed factor (F5/F6, Tab) scales simDt; the tick itself stays 1/60 s.
See Game Loop for the full walk-through.
const float simDt = dt * GameSpeedFactor(gameSpeed_);
worldRuntime_.Update(simDt);
if (terrainRenderer_ && UpdateTickWorld(dt, simDt, padPlayInput, inputPadClaimedMouse))
{
return; // the world left (a mission over, the bye) or a phase took over
}
Loading a mission
LoadMission(n) reads the world's bytes once and passes the same bytes to
WorldRuntime::LoadFromVwrStream and to ResumeLog::HashBytes, so the resume log records exactly the
world that was played. AdaptHubDoors applies the hub rules (HubDoors) and can choose
where Blupi arrives; in the main hub he starts beside the sign of the last world he played. PlaceBlupi gives Blupi the crate cells and calls
BlupiController::SettleOnGround, so walking starts on the first tick. If the file is missing or invalid the
current mission stays.
Command-line flags (parsed in main.cpp)
| Flag | Effect |
|---|---|
--user DIR | The player's folder (else GALAXY_USER_DIR, else the system's user data folder). |
--mission N, --galaxy, --spawn x,y,z[,yaw] | Start a mission directly (development and QA, not a player feature). |
--autoplay <script> | Play the mission by an autoplay script, write autoplay_trace.txt. |
--record-demo <file>, --demo-ticks N, --demo-title <text>, --verify-demo <file> | Record or verify a main-menu demo (tools/record_demo.sh, tools/verify_demos.sh). |
--golden-capture, --golden-capture-trace | Deterministic screenshots or movement trace of world 999 for tests/golden/. |
Demos, resume and the editor hand-off
- Resume. Every Play tick's input record is appended to a ResumeLog; on focus loss it is
written, on a clean exit deleted. Continue replays it from the mission start (
ReplayBatch). - Demos.
StartDemo/UpdateDemoreplay a.gdemothrough the same simulation; the player's profile, settings and resume file are frozen during a demo and restored after it. See DemoReplay and Demos & Recordings. - Editor. The main menu's Editor button calls
WorldEditor::EnterBrowserand switches toGamePhase::Editor; Play-Test runsLoadCustomWorldForPlayTest, and Win, Lost and Back return to the editor. Typingxnjttjpoin Play callsOpenMissionInEditoron the world being played (campaign saves keep a backup of the shipped file). The menu's Galaxy button callsStartGalaxy, which opens the editor's galaxy screen when the player has no main hub yet. See 3D World Editor and Your Own Galaxy.
Rules and invariants
- Platform code stays here. Android asset copying (
AndroidAssets.cpp), Emscripten storage and the executable hash for the resume log's build identity live insrc/GalaxyEggbertCNA/; the game and editor layers below do not know which platform they run on. - Determinism. The tick is a fixed 1/60 s; randomness comes from
InteractionSystem's generator, seeded per mission and recorded in the resume log and demos. Wall-clock time paces frames and drives the menu's demo idle timer and on-screen notices, never the simulation. Golden files, autoplay, resume and demos all depend on this. - Cross-system state changes happen here.
InteractionSystemreports events and requests; the host applies what needs Blupi, the camera, the HUD or the phase. - Some long comments in the header describe states that no longer exist (the class comment still speaks of an invisible collision-only Blupi). Trust the code.
Tests
No ctest unit test constructs the host. It is covered by end-to-end checks that run the real executable:
VerifyDemoReplays(ctest, needsxvfb-run;tools/verify_demos.sh): replays every shipped demo with--verify-demoand fails when one ends differently.- Golden frames and trace (
tools/verify_golden_frames.sh,tools/verify_golden_trace.sh): byte comparisons againsttests/golden/; manual, need a display. - Autoplay playthroughs (
tools/autoplay.sh,tools/autoplay_all.sh) and live QA step files (tools/qa_live.sh).
See Testing.