ビルドと実行
ヘッドレスモード
ヘッドレスモードは、ウィンドウ、オーディオデバイス、ゲームパッドなしでゲームを実行します。スクリプトが入力と時計を動かし、スクリーンショットを書き出します。CI でのスモークテスト、ルートがエンディングに到達するかの確認、ビルド間のスクリーンショット比較などの自動テストに使います。
ヘッドレスでの実行
kagari-desktop-runtime [GAME_DIR] --headless --script <FILE> --out <DIR> [--seed <N>] [--data-dir <DIR>]| オプション | 意味 |
|---|---|
--headless | ウィンドウなしで実行します。--script と --out が必要です。 |
--script <FILE> | 入力スクリプト(後述)。 |
--out <DIR> | 出力ディレクトリ。なければ作成します。キャプチャはここに書き出されます。 |
--seed <N> | 新しい物語すべてに使う乱数シード。既定は 1。 |
--data-dir <DIR> | 設定とセーブのディレクトリ。既定は <out>/data。 |
--script、--out、--seed を --headless なしで指定すると使い方の誤り(ステータス 2)です。GAME_DIR はランタイムと同じです。
ヘッドレスモードでも GPU で描画するため、GPU ドライバは必要ですが、ディスプレイサーバーは不要です。ハードウェアの GPU がない環境(多くの CI マシン)では、Mesa の llvmpipe のようなソフトウェアアダプタで動作します。
決定性
ヘッドレスでの実行は再現可能です。同じゲーム、スクリプト、シードからは同じキャプチャが得られます。
| 項目 | ウィンドウあり | ヘッドレス |
|---|---|---|
| 時計 | 実時間 | 0 ms から始まり、wait でのみ進む |
セーブ時刻(local_time) | ローカル時刻 | 常に 2026-01-01 00:00 |
| 新しい物語のシード | システム時計とプロセス ID から | --seed、既定は 1 |
| 設定とセーブ | プラットフォームのデータディレクトリ | --data-dir、既定は <out>/data |
| オーディオ | 再生する | 処理するが再生しない |
| ゲームパッド | 読み取る | なし |
設定とセーブは実行をまたいでデータディレクトリに残ります。毎回まっさらな状態から始める必要がある場合は、それを削除するか、新しい --out を使ってください。
スクリプトの形式
スクリプトは 1 行に 1 コマンドを書いたテキストファイルです。引数は空白で区切ります。空行と、最初の空白でない文字が # の行は読み飛ばされます。コマンドは順に実行されます。
| コマンド | 動作 |
|---|---|
wait MS | 時計を MS ミリ秒進めます。最大 16 ms 刻みで進め、刻みごとにゲームを更新します。 |
key KEY | キーを押して離します。 |
down KEY | キーを押したままにします。 |
up KEY | キーを離します。 |
click X Y | マウスをデザインピクセル(X, Y)に動かし、左ボタンを押して離します。 |
move X Y | マウスをデザインピクセル(X, Y)に動かします。 |
wheel DY | DY ノッチだけスクロールします。DY > 0 は上方向です。 |
capture NAME | 現在のフレームを <out>/NAME.png に書き出し、wrote <path> を表示します。NAME は A-Z a-z 0-9 _ - からなる 1〜64 文字です。 |
expect-crash | この時点でゲームがエラーで停止している必要があります。 |
assert-no-crash | ゲームがまだ動作している必要があります。 |
KEYはstd::system::Keyのバリアント名です。Enter、Escape、Space、Backspace、Tab、Up、Down、Left、Right、PageUp、PageDown、Home、End、Shift、Control、Alt、F1〜F12、A〜Z、Digit0〜Digit9。大文字と小文字は区別されます。- 座標とホイール量は 10 進数(
285、12.5)です。座標はゲームのデザイン解像度で表し、ウィンドウの大きさには依存しません。 - 入力コマンド(
key、down、up、click、move、wheel)は時計を進めません。ゲームは現在の時刻でそれを処理します。アニメーションやテキストを進めるにはwaitを加えてください。 - キャプチャはデザイン解像度の PNG ファイルです。
スクリプト全体はゲームの開始前にパースされます。構文の誤りがあると、script:<line>: <message> というメッセージ(例: script:3: unknown key `space`)を出してステータス 5 で止まります。
エラーとクラッシュ
ゲームがエラーで停止したとき(ゲームがエラーで停止したときを参照):
expect-crashがなければ、次のcapture以外のコマンドでステータス 3 で終了します。最後のコマンドの実行中にエラーが起きた場合もステータス 3 で終了します。expect-crashはエラーを受け入れます。以降のcapture以外のコマンドはすべて無視され、実行はステータス 0 で終わります。captureはエラー画面を書き出します。- ゲームがまだ動作しているときの
expect-crashはスクリプトのエラー(ステータス 5)です。 - エラー後の
assert-no-crashはステータス 3 で終了します。
ゲームが自ら終了した場合(たとえば「終了」ボタンで)、残りのコマンドは飛ばされ、ステータス 0 で終わります。スクリプトの最後でゲームがまだ動作していれば、プレイヤーがウィンドウを閉じたときと同じようにゲームを終了させます。
終了ステータス
| ステータス | 意味 |
|---|---|
| 0 | スクリプトが最後まで実行された(またはゲームが終了した)。 |
| 2 | 使い方の誤り、game.kagari がない、またはゲームを開始できない(不正な .kagari ファイル、このランタイムにないビルトインのインポート、フォントの読み込み失敗。ランタイムを参照)。 |
| 3 | スクリプトが想定していないエラーでゲームが停止した、または assert-no-crash が失敗した。 |
| 4 | GPU の障害。使えるアダプタがない、メモリ不足、デバイスの喪失。 |
| 5 | スクリプトのエラー。スクリプトを読めないかパースできない、expect-crash の時点でゲームが動作中、--out を作成できない、キャプチャを書き出せない。 |
例
example/test_game1 のスモークテストです。タイトル画面を待ってキャプチャし、タイトルの Start ボタンをクリックして、最初の台詞をキャプチャします。
cat > smoke.txt <<'EOF'wait 2000capture title# the title's Start buttonclick 285 265wait 1000capture first-lineassert-no-crashEOFkagari-desktop-runtime example/test_game1/target/v0 --headless --script smoke.txt --out shots --seed 1shots/title.png と shots/first-line.png を書き出し、設定とセーブは shots/data に保存されます。最後にゲームがまだ動作していれば、終了ステータスは 0 です。
最終更新日 2026年10月29日