WINDAGE ENGINE v1.0.0
Contents

Docs / Start

The sample game

WindageSample is a complete, deliberately dull first-person game that ships in the engine's repository and is built against the engine's public API only. It exists to prove that someone who did not write the engine can build with it, and it is the best place to see how any feature is meant to be used.

The courtyard, drawn by the sample
The courtyard level.

What is in it

The game is a fetch quest: touch every marked crate before the clock runs out. Around that it carries everything a small game needs:

Run it

swift run WindageSample

No Xcode project, scheme or signing. The window opens on the engine's splash; any key skips it and still does what it was pressed for. The console prints which level file it loaded.

Once the editor has saved, its copy lives in Application Support and shadows the file in the repository, so editing courtyard.json appears to do nothing. The console line says so, and ⌘⌫ in the editor throws the copy away.

Controls

The movement keys come from the player's bindings, so the on-screen hints are read from them rather than typed in. These are the defaults:

KeyDoes
W A S Dmove
Left Shiftsprint
Spacejump
Ccrouch (slide when sprinting)
click / Esccapture / release the mouse
Osettings
Ppause
Rrestart the run
Nnext level
Mcycle tone mapping: clamp, Reinhard, ACES
Tabin and out of the editor

With a controller connected, the left stick moves, the right stick looks and the menu button opens settings.

In the editor: aim and click (or Space) to pick, arrows move, Q/E up and down, A/D turn, -/= scale, B copy, ⌫ delete, L lamp on and off, [ ] lamp height, , . lamp brightness, T choose a kind, I add one where the crosshair meets the ground, ⌘S save, ⌘Z undo, ⌘R redo, ⌘⌫ revert to the shipped level.

Environment variables

The sample reads its options from the environment, so a check or a screenshot can be repeated exactly.

VariableEffect
WINDAGE_SAMPLE_LEVEL=1start on that level: 0 courtyard, 1 ruins
WINDAGE_SAMPLE_CAMERA=x,y,z,yaw,pitchstart the camera there (degrees) and fly instead of walk
WINDAGE_SAMPLE_WALK="d:0.7 w:1.0 wait:1"play a script of keys and seconds through the keyboard's own path; yaw: and pitch: turn the view
WINDAGE_SAMPLE_RATE=60simulation steps per second; default 120
WINDAGE_SAMPLE_CHECK=1run as a check: no window shown, no keyboard, no sound, saves of its own
WINDAGE_SAMPLE_FRAME=<path>draw one frame to a PNG and quit
WINDAGE_SAMPLE_SPLASH=1 or 0show or hide the splash; by default it is off in a check or a frame
WINDAGE_SAMPLE_SILENT=1run with no audio engine at all
WINDAGE_SAMPLE_FPS=1print frames and steps per second, and the longest wait between steps
WINDAGE_SAMPLE_CHARACTER=/path/Nameload a rig from Name.usdc, its clips from Name_*.usdc beside it
WINDAGE_SAMPLE_MEASURE_AUDIO=1render the brazier's crackle offline, print its level at distances, quit

A scripted walk prints where the feet ended each segment, which is what Tools/walks.py checks against its records. See walks and frames.

How the code is split

The sample is three targets, and this is the shape the engine recommends for any game:

TargetHolds
WindageSampleCorethe logic that needs no window: SampleRun (the clock, objectives, pause, win and lose, the save format), SampleLevel (which level files exist and where an edited copy lives), SampleRubble, and the level files themselves
WindageSampleCoreTeststests against the core, run by swift test with nothing launched
WindageSamplethe app: main.swift (window, view, renderer) and SampleGame, the GameLoop that draws, plays sound and turns keys into calls on the core

A win condition, a clock, a pause and a save fail quietly, and none of them need a drawable, so in the core they run in swift test in milliseconds. The split has paid for itself: parallel tests found SampleRun keeping progress in one shared static store. The store is injected now, which is also what save slots need.

SampleRun.step also returns what happened as a value instead of calling back, so nothing mutates the run mid-step.

To start your own, see Your first game.