2008/11/11(火)yieldが使いたい

はてブ数 2008/11/10 19:50 計算機な日記::ソフト作りつーさ

RPGのシナリオスクリプトを、
C#のあるソースファイルのメソッドとして定義し、
C#コンパイラに食わせることを考える。

スクリプトなのだから、スクリプタさんが書く。
文法こそC#だがスクリプトっぽい感覚で書けるように留意する。

RPGなのだから「メッセージを表示してボタン待ち」のような高レベルAPIを用意したい。
スクリプトの実行はそこでブロッキングして、一見処理が止まってるように見せたい。
しかし実際にスレッドまで止めてしまうとゲームが止まってしまう。どうする?

メッセージを表示してボタン待ちをしながら、ゲームの内部処理は止めずに行いたい。
ああ、ブロッキングするAPIの中で内部処理ルーチンを呼べばいいのか。んな無茶な。

マイクロスレッド? コルーチン? ファイバー? ああ、yield があればいいなぁ。
ブロッキングAPIの中ではこれをひたすら呼び出せばいいだけになるんじゃないか?
が、C#のyieldは、列挙に特化しすぎてて、たとえばAPIの中から呼び出すとかできない。

ダメじゃん。ということで あれこれ試行錯誤して void Yield(); 作ってみた。
メインスレッドとスクリプトスレッドを作ってスレッドの実行をフリップフロップ(謎)。
マイクロスレッドみたいに大量のスレッドを実行しようとするわけじゃないから、
スレッド切り替えコストなんてこの際無視を決め込む。

と、こんな感じで書けることになる。

    public void ExecuteHoge()
    {
            Console.WriteLine(" SCRIPT --- スタート ");
            for (int i = 0; i < 4; i++)
            {
                Console.WriteLine(" SCRIPT >> 実行 : " + i);
                if (i  == 2) Sleep(1);
                Yield();
            }
            Console.WriteLine(" SCRIPT --- 終了 ");

    }

ああ、いったいこれのどこがスクリプトなんだというツッコミはおいておく。
一見ちゃんと動いてるようにみえる……が。

20081111051109.png

おいおい、本当にゲームシステムに組み込んで動くのか。
冒険だなぁ。