第4章 動作のしくみ
images/04_runtime.png
図4-1: 起動〜ランタイムの流れ
images/04_runtime.pngこの章は主に実行時の挙動を説明します。描画やセーブのプラットフォーム差は 6章(仕様)も確認してください。シナリオの作り方は 制作者向け入門 を参照してください。
4.1 起動時の動作
フェーズ1: エンジン初期化
- 実行ファイルのあるフォルダを基準にする
- 同じフォルダと 1 階層下のフォルダ(
GameDataなど)の*.lafをマウントする - Windows では、前回の起動でタイトルまでに読んだファイル(120 個ほど)を、ウィンドウと DirectX の準備と並行して裏で先読みする(下の「起動時の先読み」)
フェーズ2: 設定読み込み
system/Config.txt(暗号化していればConfig.lsf)を先に 1 回実行 — 保存先、データルート(setDataRoot先の*.lafも追加でマウント)、INI の有無、拡張子、素材フォルダを確定する- 保存先を決める —
SaveDataManagerで移した先(save_redirect.dat)があればそこ、無ければ既存のsystemdata.datを標準の置き場から探す。exe の隣に書き込めなければ AppData へ回す(第3章 3.4) systemdata.datを読み込む(無ければ作る)。config.iniは INI を有効にしたときだけ読む- 画面モード・拡大フィルタなどの設定を反映する
フェーズ3: UI 表示
- 起動ダイアログ(Windows)— 解像度・フィルタの選択。
Config.txtのSystem.setStartupDialog(true)は初回の既定値で、以後はsystemdata.datに保存された利用者の選択(「次回も表示する」)に従う - メインウィンドウを作る(まだ表示しない)
PreInitialize.txt—RunMode.txt(実行モードの決定)→Localization.txt(言語)→ メニューバーとシステムメニューの組み立て- ウィンドウを表示する
data0/startup.txt→Initialize.txt— プラグインの許可一覧(ここでは読み込まない)、Configの再実行、クイック/オートセーブの履歴の登録、検索パス、多言語、イベント CG、マウスジェスチャー、メッセージウィンドウ・メニューバー・選択肢・バックログ・動画・音量・書体の初期化- 中断データ(
Suspend)があれば、ロゴとタイトルを飛ばしてその場面から再開する logo_enhanced.txt→title_enhanced.txt。Debug 実行モードでは、タイトルが出そろったところで開発用の道具(LuminaDebugTools.dll)を読み込む
コマンドライン引数 --start-scenario= を付けて起動すると、ロゴとタイトルを飛ばして指定のシナリオから始めます(第6章)。
プラグインは使う直前に読む(Windows)
DLL は起動時には読み込みません。音は最初に音を鳴らすとき、動画は最初に動画を出すとき(.ogv なら mrutheora.dll も)、アニメやモーションは最初に使うとき、システム情報はそのダイアログを開くときに、エンジンが自動で読み込みます。読み込めるのは許可一覧に載った DLL だけです。かかった時間は lumina_diag.log の [プラグイン] の行に残ります。
起動時の先読み(Windows)
エンジンは、起動からタイトルまでに読んだファイルを覚えておき、次の起動ではウィンドウと DirectX の準備をしている間に裏でそれらを読んでおきます。PC を起動した直後(素材が HDD にあり、OS のファイルの控えが空のとき)の 1 回目の起動が速くなります。
- 記録:
%LOCALAPPDATA%\LUMINA\startup-prefetch\<指紋>.log(指紋は実行ファイルの場所から決まる)。1 回の起動ごとに「タイトルまで何 ms」「先読み何件」が 1 行残る - 初めての起動では記録だけを行い、2 回目から先読みする。効き目は PC を再起動した直後の回の数字で確かめる
ブラウザと Android の起動
- ブラウザ: 最初に WebGPU が使えるかを確かめ、使えなければ理由を画面に出してゲームデータの取得もエンジンの起動もしない。使えれば
GameData/packlist.jsonに載ったパックを 1 本ずつ取得してから起動する(lumina_pre.js) - ブラウザ: アドレスの
?KEY=VALUEを環境変数の代わりに読む - Android: アプリのファイル置き場の
launch.txt(1 行に 1 つKEY=VALUE)を環境変数の代わりに読む - どちらも
PreInitialize.txt→startup.txt→Initialize.txtの流れは Windows と同じ
4.2 ランタイムループ
ゲーム実行中は、おおむね次の処理が繰り返されます。
毎フレームの処理
- 入力ポーリング(ADV 抽象: 文字送り、スキップ、メニュー等。ゲームパッドも受け付ける。第6章 6.10)
- スクリプトエンジン 1 ステップ
- 音声フェード・ムービー更新
- 描画(上限は
Window.setFPSで決める。見本は 60)
4.3 スクリプト実行モデル
システムスクリプト
- 同期実行:
function内のSystem.wait(ms)でブロック - LUMINA Script: 関数やオブジェクトを使う書き方。ファイルの先頭に
// @luminaを書く(旧い目印// @tjsも引き続き使える。functionを使っていれば目印が無くても判別される) - オブジェクト呼び出し:
System.xxx(),Title.addButton(),Movie.play() - 実行モード:
System.isDebugMode()で Debug / Release を見分けられる(決め方はsystem/RunMode.txt)
シナリオスクリプト
- 行単位実行: 1 コマンドずつ処理
- 待機:
wait,click,message(クリック待ち付き) - ラベル:
*label(またはlabel name。名前の後ろにコロンは付けない) - マクロ:
data0/macro/*.txt(暗号化すると.lsf)を読み込んでおき、名前で呼ぶ - 変数:
System.loadScenarioでシナリオを新しく始めるとシナリオ変数は空になる。System.jumpScenarioは変数を保ったまま切り替える
3D
- Scene3D: 3D の場面は専用の描画先に描き、その絵を背景の層へ載せる。
Scene3D.runAction()は、決めた出来事(トリガー・拾う・調べる・倒す・やられる・時間切れなど)が起きるまで操作を受け付けて遊ばせ、出来事の名前を返して戻る(その間メッセージウィンドウは隠れる)。Android / ブラウザでは画面を触って操作する
API の一覧は 第9章、シナリオ命令は 第10章 を参照してください。
4.4 音声の動作
拡張子ごとの再生方法の目安です。プラットフォームによって利用可否が異なります。
| 拡張子 | Windows のバックエンド |
|---|---|
.wav | 標準の音声再生(プラグイン不要) |
.ogg | mruvorbis.dll |
.opus | mruopus.dll |
BGM クロスフェード、SE プール、ボイスダッキングはスクリプト API 経由。
| プラットフォーム | 音声 |
|---|---|
| Windows | WAV は標準。OGG Vorbis/Opus はプラグイン DLL(使う直前に自動で読み込む) |
| Android | OpenSL ES。OGG Vorbis と Opus のみ(復号は本体に内蔵、プラグイン不要)。WAV は再生できない |
| ブラウザ | Web Audio。ブラウザの音声デコード(decodeAudioData。OGG・WAV・MP3 など、ブラウザが読める形式) |
4.5 動画の動作
スクリプトでは拡張子を省いて書き、プラットフォームに合った形式を同じ名前で data8 に並べるのが基本です(例: opening.ogv と opening.mp4)。
| プラットフォーム | 形式と再生のしかた |
|---|---|
| Windows | すべて lmmovie.dll 経由。.ogv は Theora(mrutheora.dll)、mp4 / mov / wmv は Media Foundation、avi / mpg は DirectShow。無圧縮(レベル 0)でパックに入れた動画は、パックからその場で再生する |
| ブラウザ | HTML の <video>。mp4 / m4v / webm を GameData\data8 に素のファイルで置く(パックには入れない)。拡張子を省くと mp4 → webm → 設定の拡張子 → ogv の順に探す |
| Android | MediaCodec(H.264 / HEVC / VP8 / VP9)。mp4 / m4v / webm を APK に無圧縮のまま同梱する。探す順はブラウザと同じ(ogv は飛ばす) |
Windows ではムービーを専用のホストウィンドウへ描画し、オーバーレイ合成できます。
4.6 セーブの動作
セーブの概念は共通ですが、保存先の実体はプラットフォームごとに異なります(第 6 章参照)。
- スロットセーブ:
System.saveData(slot)/System.loadData(slot)、SaveSlotオブジェクト - クイックセーブ/オートセーブ: 履歴の置き場と保持数は
Initialize.txtのSaveSlot.setSeries("quicksave", 1000, 10)/SaveSlot.setSeries("autosave", 1100, 10)で決める(通常のスロットと重ならない番号にする) - 前回の続きから:
QuickResumeオブジェクト(タイトルの「前回の続きから」) - 中断(サスペンド):
Suspendオブジェクト。起動時に中断データがあればそこから再開する - 設定永続化: 起動ダイアログや環境設定の変更 →
systemdata.datへ自動保存 - ロードとシーン戻り: シナリオの位置・変数とともに、背景・立ち絵・イベント CG・BGM・メッセージウィンドウの状態を戻す(Windows・Android・ブラウザで同じ)
保存形式(System.setSaveDataMode):
| モード | 説明 |
|---|---|
""(空文字) | 平文 |
c | AES-GCM で暗号化 |
z | zstd で圧縮(見本の Config.txt はこれ) |
4.7 終了時の動作
System.exit()またはメニュー「終了」- 終了確認ダイアログ(種別: MessageBox / 画像 / rc)。シナリオの途中なら中断して終わることもできる
- フェードアウト(
System.exit(種別, 暗転ms, 待ちms)で指定したとき) systemdata.datへの自動保存- プラグインの解放、各種リソースの後片付け