Sample game entry point
sample/main.mojo from the engine repository, verbatim: the entry point of the third-person sample game (ADR-0014). The game itself lives in sample/game/ (components, levels, settings, gameplay) and is built only on public engine APIs.
bash
tools/in_container.sh pixi run sample # windowed: arena level, WASD/Space, Esc for the menu
tools/in_container.sh pixi run sample -- --level sponza # the Khronos atrium with a mesh collider
tools/in_container.sh pixi run sample-headless # offscreen autopilot runsample/main.mojo #
mojo
"""Cinder sample game entry point.
pixi run sample [--headless] [--level arena|sponza] [--autopilot] [--frames N] [--profile]
[--screenshot PATH]
`--headless` renders offscreen (tests, benchmarks); `--frames N` stops after N frames;
`--screenshot PATH` writes the last headless frame as a PNG.
"""
from std.sys import argv
from cinder.app import App, AppConfig, parse_app_args
from cinder.core.image import save_png
from game import SampleGame
def main() raises:
var args = List[String]()
var raw = argv()
for i in range(1, len(raw)):
args.append(String(raw[i]))
var config = AppConfig(String("Cinder sample"), 1280, 720, False)
var rest = parse_app_args(args, config)
var level = String("arena")
var autopilot = False
var max_frames = -1
var screenshot = String()
var verbose = False
var i = 0
while i < len(rest):
if rest[i] == "--level" and i + 1 < len(rest):
level = rest[i + 1]
i += 1
elif rest[i] == "--autopilot":
autopilot = True
elif rest[i] == "--verbose":
verbose = True
elif rest[i] == "--frames" and i + 1 < len(rest):
max_frames = Int(rest[i + 1])
i += 1
elif rest[i] == "--screenshot" and i + 1 < len(rest):
screenshot = rest[i + 1]
i += 1
else:
raise Error(t"unknown argument {rest[i]}")
i += 1
var game = SampleGame(level, autopilot)
game.verbose = verbose
config.render = game.settings.render_settings()
var config_headless = config.headless
var app = App(config^)
var frames = 0
while app.run_frame(game):
frames += 1
if max_frames >= 0 and frames >= max_frames:
break
if screenshot.byte_length() > 0 and config_headless:
save_png(app.lib.ptr(), screenshot, app.read_frame())
print(
t"frames {frames}, collected"
t" {game.collected}/{game.total_collectables}, won {game.won}, gpu"
t" errors {app.gpu_error_count()}"
)
# The game holds physics and audio objects that live in the app: end it first.
game.shutdown(app)
_ = game^
_ = app^