14. サンプルゲーム『灯送りの夜』
1.0.4 から、最初から最後まで遊べる短編のノベルゲームが入っています。 スタートからエンディング、エピローグまで、選択肢・フラグ・複数の結末がそろった形を、シナリオを読みながら確かめられます。
配布物の
SampleGame\lumina.exe
を起動します(1 周 15〜20 分くらい)。 説明は
SampleGame\はじめにお読みください.txt
、変数の一覧と分岐図は
SampleGame\フラグと分岐.txt
にあります。
14.1 ばらのファイルで置いてある理由
このサンプルは、作品を作るときの参考にするためのものです。シナリオ(
.txt
)も絵も音も、パック(
.laf
)にせず、そのままフォルダに置いてあります。
lumina.exe
は自分の隣の
GameData
を読むので、NovelAuthor の「新規作成」で作ったフォルダと同じ並びです。
14.2 シナリオの分け方
ファイル(
GameData\data0\scenario
)
|
中身 | 見てほしい書き方 |
|---|---|---|
nv_prologue.txt |
序章 |
変数の初期化・選択肢・ファイルをまたぐ
jump
|
nv_ch1.txt |
第一章 |
イベント CG・シーン鑑賞・
gosub
・選択肢の中の選択肢
|
nv_ch2.txt |
第二章 | 回数を数えるくり返し・行った場所を選択肢から消す |
nv_ch3.txt |
第三章 | 印で変わる会話・演出の組み合わせ・全画面の文章 |
nv_ch4.txt |
第四章 | 印の組み合わせで分ける・周回で増える選択肢 |
nv_end_*.txt |
結末 4 本 | ベース+差分の CG・入口が複数ある結末 |
nv_epilogue.txt |
エピローグ | 結末ごとの書き分け・周回の記録・エンドロール |
分岐は「印を残して合流する」形にしてあります。選択のたびに話を分けたままにすると、シナリオの量がすぐに増えるためです。
シーン鑑賞の曲:
シーン鑑賞は
*scene_ID
のラベルから始まるので、ラベルより前の
bgm
・
seloop
は通りません。範囲の前から鳴らしている曲は、鑑賞のときだけ通る行で鳴らします(
nv_ch1.txt
の
*scene_nv_pier
)。ふつうに遊ぶときは
jump
でその行を飛ばすと、鳴っている曲が頭に戻りません。
seloop
は
scene_end
の前に
stopse
で止めます。
14.3 周回の記録の受け渡し
setsysflag
で書いた値はどのセーブにも共通で残りますが、シナリオの
if
からは読めません。このサンプルでは次の形で受け渡しています。
-
エピローグが
setsysflag nv_end_1 1のように書く -
次の周回の序章が
sysscript NvRecordを呼ぶ(System.getSystemFlagで読み、GameState.setで入れる) -
序章が
gs_get nv_seen_all nv_seen_allでシナリオの変数へ受け取る
タイトルでは同じ値を
System.getSystemFlag
で読み、見た結末の数だけ灯を出しています(
system/title_enhanced.txt
)。
14.4 直して試す
SampleGame
を丸ごとコピーして、コピーの
.txt
を直し、
lumina.exe
を起動し直します。開発中は
.txt
で動くので、すぐ結果を見られます。
.lsf
は配布のときに使う物で、
Tools\ScriptEncryptor
で作り直します。
NovelAuthor で
灯送りの夜.lnp
を開くと、フローチャートで全体を見ながら編集できます。
14.5 デバッグモードで動かす
このサンプルには
GameData\data0\system\DevMode.txt
があるので、起動するだけでデバッグモードになります。窓の題に
[Debug Mode | FPS]
が出て、窓のメニューに「デバッグ」が増えます。
- 「デバッグ」→「デバッグツール」→「スクリプトデバッガ」で、いま読んでいるファイルと行を見られます。
- 「シナリオジャンパー」には、ファイルとラベルの一覧が出ます。
-
ショートカットは
Shift+D(ツールの一覧)、Shift+F1から(各ツール)です。
変数の値を確かめるとき:
「デバッグ」→「デバッグツール」→「フラグインスペクタ」(
Shift+F3
)に、変数の名前と今の値の一覧が出ます。
setvar
・
addvar
の変数(
nv_nagi
など)は ScenarioFlag のタブ、
setsysflag
などの共通の値は SystemFlag のタブに
sysflag.名前
の形で出ます。窓を開いている間はシナリオの命令が進むたびに更新され、変わった物に ★ が付きます。変わった順は履歴のタブで見られます(窓を閉じている間の変化は履歴に入りません)。値は窓から書き換えられます。スクリプトデバッガの Variables のタブにも同じ値がまとめて出ます。
gs_set
・
gs_add
の値(GameState)は GameState のタブに出て、ミニゲームの実行中も更新されます(文字の値は
""
で囲んで出ます。Variables には
gs.名前
の形で整数だけが出ます)。
配布するとき:
DevMode.txt
はプレイヤーに渡す物に入れません。入っていると、プレイヤーの画面にデバッグのメニューが出て、ログのファイルもできます。ReleaseBuilder でリリース版を作ると自動で外れます。手で配るときは自分で外してください。
GameData\.author
の鍵は全員が持っている「見本の鍵」です。自分の作品は NovelAuthor の「新規作成」で作り、鍵も作品ごとのものを使ってください。
14.6 タイトルをムービーのように動かす
タイトルは動画を流しているのではありません。止まった背景の上に、透明の地に「光だけ」「霧だけ」を描いた絵を何枚も重ね、それぞれをゆっくり動かしています。書いてある場所は
system/NvTitleFilm.txt
(短いファイルです)。
Title.addImage("nvt.mist", "data1/title/nvt_mist_far", -360, 350, 2000, 210, "back");
Title.setImageMotion("nvt.mist", 300, 6, 140000, 26, 50, 37000, 0, 0, 2500);
Title.setImageMotion
の引数
|
意味 |
|---|---|
| id |
Title.addImage
で置いた名前
|
| 揺れ横・揺れ縦・揺れ ms | 揺れの幅と 1 周の時間。横は sin、縦は cos で楕円を描く。時間が 0 なら揺らさない |
| 濃さ下・濃さ上・明滅 ms | 0〜100 の濃さと、下と上を行き来する時間。時間が 0 なら濃さ上のまま |
| ずれ ms(省略可) | 時刻のずれ。同じ周期の絵がそろって動かないようにする |
| 加算(省略可) | 1 で加算合成(光の絵)、0 で通常の合成(霧・雲) |
| 出る ms(省略可) | いまからこの時間で濃くなる。0 ですぐ |
- 動きは時刻だけで決まるので、毎コマのスクリプトは要りません。演出の間もボタンを押せます。
-
飾りは
Title.clearButtonsで一緒に消えます。コンフィグやセーブの画面へ絵が残らず、タイトルへ戻るたびに置き直しても二重になりません。 - 環境設定の「システムアニメーション」を OFF にしたプレイヤーには、止まった絵として見えます。
-
重ねる順は足した順です。右の帯と題字は最後に足して、動く層の上に出しています。背景は
bg_title(全部を合成した絵)ではなくbg_title_base(背景だけ)にします。 -
火の粉は今までどおり
Particle.playAsset(data0/particle/nv_ember.json)です。粒は動く層の下に出ます。 -
Android とブラウザでは
System.getVarInt("sys.platform")(0=Windows・1=ブラウザ・2=Android)を見て、枚数と粒の数を減らしています。 -
見た結末の数だけ湖の灯が増えます(
NvtLanterns)。結末 4 を見ると灯台に灯がともります。 -
題字の縦書きは絵に焼いてあります。「ー」「、」「。」は横書きの字を縦に並べるだけでは形も位置も正しくならないので、縦書き用の字形で描いています(
gen_novelsample_art.pyのVerticalText。書体名の頭に@を付けた Windows の GDI)。
14.7 エンドロールをムービーのように流す
後ろの映像は
system/NvRollFilm.txt
、文字と飛ばす操作は今までの
StaffRoll
(
system/StaffRoll.txt
)です。動画のファイルは使っていません。
-
FX.beginBatch()の中で、場面も灯も全部「何ミリ秒後に出て、どう動いて、いつ消えるか」を予約する - 曲を鳴らす
-
FX.endBatch()で映像の 0 秒を決め、すぐStaffRoll.run()で文字を流す -
途中で飛ばされたら、黒い絵を
FX.imageで重ねて暗くし、FX.clearAll()で片付ける
FX.image("nvf.lake", "data2/nv_lake", 0, 0, 1280, 720);
FX.anim("nvf.lake", 3000, 11100, 900, 3, 0); // 出る ms, 保つ ms, 消える ms, 緩急, 待つ ms
FX.transform("nvf.lake", 1.0, 1.08, 0, -14, 15000, 0, 0); // 拡大元, 拡大先, 動く横, 動く縦, 動く ms, 緩急, 待つ ms
FX.setSmooth("nvf.lake", 1); // ゆっくりの動きが段付きに見えないようにする
-
FX は実時間で進むので、
StaffRoll.run()の間スクリプトが止まっていても、重い環境でも、曲と場面がずれません。 -
StaffRoll.setSceneVisible(1)を書くと、背景の絵を置かないとき下の場面が見えます(書かないと Android とブラウザでは黒で塗ります)。 - FX は作った順に重なります。次の場面を後から作ると、前の場面の上へ現れます。文字(帯)は FX のさらに上です。
-
曲の長さは
Sound.getBgmDurationMs()で取ります。ブラウザは曲を解き終えてから鳴らすので、それまで 0 を返します。鳴らした直後に使うときは、0 の間は待ちます(StaffRoll.txtのsrWaitBgmDuration)。待つ間に映像を始めないので、読み込みが遅くても曲とずれません。 -
帯が流れ終わる時刻は曲に合わせて決められます。
StaffRoll.txtのSR_END_MARGINの注釈に計算があります。曲nv_endingは 1 小節 3 秒なので、場面は 12 秒ごとに変えています。 -
明るい場面でも文字が読めるように、帯の絵には文字の周りに暗いにじみを敷いてあります(
gen_novelsample_art.pyのFilmArt.with_shade)。 - 灯の位置や大きさは、乱数ではなく掛け算の余りで作っています。毎回同じ映像になるので、確かめやすくなります。
素材はすべて
Tool\01_Development\gen_novelsample_art.py
の計算で作りました(
--only film
)。自分の作品では、霧や光の絵を差し替えるだけで同じ動きを使えます。