ビジュアルノベルのためのDSL
を、実は日々妄想している。
個人的にはNScripterみたいな形式が好みだ。テキストが中心と言うか、RDのおんなじノリで好きなのである。吉里吉里も非常に優れたノベルゲームエンジンだと確信してはいるが、いかんせん"タグで挟む"っていうのが非常に好かない性質なので…。
NScripterを使うかとも思うけど、変数とかラベル名とgotoによるフロー管理とか、気にしだすと気になってくるところはあるもので(贅沢な話だけど)。
NScripterとか吉里吉里のマクロ言語としてでもいいから、自分好みのノベルゲーム用スクリプトのアイディアを考えては捨て、考えては捨て…。
今回はその妄想をちょっと書いてみる。
まだテキストをクォーテーションしなきゃいけない点でNScripter的スッキリさが足りない…。
ちなみに元にしているシナリオはisbn:9784777512928ル。
# scene は namespace かトップレベルに属する namespace "Section1" do # scene の定義 scene "start" do text "- シナリオスタート -" text "選択肢を選んでください。" choice [ "選択肢A", "A" ], [ "選択肢B", "Section1:B" ] # 選択肢の表示と行き先 end # 次の scene を相対名で指定している scene "A", :next => "Interval:main" do clear bg "images/bg.jpg" wait 30 fg "images/fg_girl.png" wait 30 text "おはようございます!" 3.times do wait 30 text "・" end wait 30 text "ウェイト中です" wait text "はい!" text "ウェイト終了です。" wait 30 end scene "B", :next => "Interval:main" do clear wait 30 fg "images/fg_girl.png" wait 30 text "こんばんは・・・。" wait 30 text "ウェイト中よ!" wait end # 入れ子にできる。絶対名だと "Section1:Interval" namespace "Interval" do scene "main" do clear choice [ "Aへ", "A" ], [ "Bへ", "B" ], [ "音を鳴らす", "sound" ], [ "終了する", "quit" ] # Section1:Interval:A がないので # 遡って Section1:A を見つける end scene "sound", :next => "main" do sound "sounds/crash.wav" end scene "quit" do quit end end end # エントリポイントとなる scene を絶対名で指定 start "Section1:start"
さてこれをどうするか。
DSL -> DSLコンパイラ -> ASTに -> インタプリタが実行
だと、エラーとか先に見つけられるけど、
DSL -> DSLインタプリタ -> 逐次実行
だと、Rubyの変数機構とか制御構文とかにタダ乗りできる。
scene の中だけ逐次実行にすればいいのかな?
DSL処理系が実行する段まで scene のブロックの評価が遅延されてればRubyのローカル変数機構や制御構文に乗っかれるわけで。
scene 間をわたって使いたい変数は、namespace で宣言できるな。こっちは予め実行されるから。トップレベルでやるとグローバル変数っぽい…
とか思ったけど、Rubyのローカル変数ってファイルスコープだった。Ruby自体のグローバル変数を使わせるのもアレなので、何か用意しないといけないな。
サプルーチンの定義とかは、Rubyのdefをまんま使うよりは、何かAPIを用意して、Procオブジェクトと名前を自力でマップしていくほうがいいかもしれない。napespace との親和性を考えると。
というか scene が引数と返り値のないサブルーチンだなぁ。