フリーゲーム・フリーソフトの開発過程を記録していく、TDtechnic公式ブログです。製品はカテゴリの「ダウンロード場」からダウンロードして頂けます。
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

 今日は。蒼き狗と紅き狐さん、及びROMられている皆様、いつもご覧頂き有難う御座います。私は今テスト期間ですが、蒼き狗と紅き狐さんも同様ですかね。共に頑張りましょう。
 さて、今回は先日少し話しましたタスクシステムの話です。これは処理を次から次へと生成、実行、削除して動かすというものです。各タスクは一コマ一回、一気に実行されますから、容易に擬似並列処理が表現出来るわけです。本当に、タスクシステムによる恩恵は計り知れません。これを解りやすく解説されていた「シューティングゲーム プログラミング(Softbank Creative 様)」に感謝感謝です。

シューティングゲーム プログラミングシューティングゲーム プログラミング
(2006/09/28)
松浦 健一郎、司 ゆき 他

商品詳細を見る


 ですがね。何もかもタスクにしていったらですね。

…わかりにくい。

私は状態から機能からすべてタスクにしました。最初は良かったのですが、そのうち並列処理では却って困る事が出て来ました。例えばRPGでメッセージが表示されている所を想像して下さい。その時キャラクターは操作できるべきでしょうか?否。また、タスクが生成が決まったら基本的に一回で生成されますが、同じ様にメッセージで考えると、メッセージは一気に生成されて良いでしょうか?否。一つずつ、順番に生成されなければなりません。この様に、タスク同士の相性が影響してくる状況が生まれて来ました。
 結局強引に、タスクを止めたり特定のタスクの後にタスクを追加したりするシステムを作って解決したんですよ。ですがね。こんなの絶対おかしいよ。プログラミングってこういうものか?ひたすら引数を変えてタスク生成をするのが、プログラミングか?イベントドリブンみたいに、ループ前提の処理ばかりを書くのが、プログラミングか?
 そりゃあ部分的には要るでしょう。例えばループ中にいちいち画像表示のコードなんか書いてられませんよ。画像ってもんは「表示」したらずっと見えてて然るべきです。「表示」ってそういう意味だと思います。Wolf RPG エディター(お世話になりました)や、なでしこ(ちょっと齧りました)みたいな超高級言語では実際そうなってます。本来ループで行うのは、アニメーションとか、入力の受付と処理とかだけですよね。こういう時の画像表示コードなどは、自動でループされるようにするのが自然な実装だと思います。これはタスクシステムの適所ですよね。
 ですが、誰かさんみたいにメインの処理すらタスクにすると、非常に不自然なプログラミングになります。書いた処理は繰り返されるのが当然になってしまいますから、逆に順次実行させるのが難しくなります。ゲームの実際の動作である「あれをして、これをして、ここでこの関数を呼んで、ここでループして…」という表現がソースコード上では全然使えず、わかりにくいです。
 これは前からジレンマでした。私は本流の動作に即したソースを書きたい。でも本流と関係ないコードを分離できる点ではタスクシステムも捨てがたい。じゃあどうするか。

…共存だ。

 よくばりパックで行けばいいんです。何故今迄気付かなかった。タスクシステムを置いたまま、本流の処理を普通の関数にしました。そして本流がタスクを生成し、必要と有らばタスクを参照・操作する。毎フレームでタスクの実行を呼び出す、というルールさえ守ればループも自由に作れる。なんということでしょう。
 タスクシステム本位主義から脱却して一つだけ困ったことがあります。それはプログラムの終了です。ゲームの処理として終了するのは簡単ですが、問題はバツボタンとかでいきなり終了させられた場合です。プレステとかと違ってPCゲームの場合大抵のプレイヤーはバツボタン(中級者ならAlt+F4)で終了できて当然と思ってますからね。タスクシステムならタスクのループを止めれば抜けられましたが、順次実行にすると処理の階層が奥まってしまって簡単には抜けられません。抜けないとウィンドウだけがなくなって処理を続ける幽霊プロセスになってしまいますが、階層が深まるたびに返り値をチェックするのも面倒ですし、例外で一気に抜けるのも気持ち悪いです。どうしたかというと、先ほどの「必ずタスクを呼び出す」ルールのように、ループを作るときのルールをもう一つ(自分の中で)決めました。それは「必ずウィンドウの存在をチェックする」というルールです。全てのwhile文でこれを適用します。すると、或る時点でウィンドウが閉じられれば、全てのループがスキップされます。途中にループじゃない処理が有れば実行してしまいますが、ループをしなければ入力も出力も出来ないため実質的には何も出来ません。そのうち全ての関数を抜けて勝手に終了する筈です。この実装もうまくいきました。因みにおまけとして、記憶ではバツボタンやAlt+F4をされた時に「強制終了しますか?」というお手製ダイアログを表示するコードを挟みました。記憶はオートセーブではないので、誤ってデータが失われるのを防ぐ為です。後、「強制終了」という表現をしたのは、私が本来ゲームというのは途中で終了される方がおかしいと考えているからです。今回そういう終わり方が出来るようにしたのはWindowsでは当たり前だ(と思われている)からであって、本当はきちんとタイトル画面から終了して欲しいのです。イベントドリブンでもないのだから呼び出しと終了は一対一で対応していなければならないというのに(C#では大分楽ですが…)、私に言わせればバツボタンで終了する事などgoto以上の禁忌です。
 そういえば、誤って繋がりで話が変わりますが、今回はDirectXの復旧コードをちゃんと書いたので、ゲーム中に誤ってフルスクリーン解除をしたりしても戻れる様になりました。他にもDirectXの初期化コードもきちんと各種確認をするようにし、フォントサイズすら機種依存だと判明してからは実際にサイズを測って使用するようにしたので、ある意味どんな環境でも正しく起動できる自信があります。某安倍首相ではありませんが、TDtechnicの誇りを「一文字」にするとすれば――それは…「互換性」ですかね。
 なんだかんだ書きましたけど、「普通の」ゲームの作り方を全く知らずに書いてるんですね。まあタスクシステムはその一つでしょうが、でもそればかりでも破綻しましたし。私は言語の仕様書にある使い方を参考に、ゲームというものを表現する上で自分でしっくりきた方法を採用しているだけです。世の中には現に沢山のゲームが有りますが、ああいうのは一体どんな実装を礎としているのでしょうかね。知りたくてたまりません。調べても簡単には出ませんし。
関連記事

[2013/06/03 15:51] | 記憶
|
コメント:
この記事へのコメント:
コメント:を投稿
URL:

パスワード:
非公開コメント: 管理者にだけ表示を許可
 
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。