第14章 伸びる豆腐(2)
2006年10月18日
ゲームにおける画面描画処理と云えば、現状DirectXを利用するのが一般的である。
DirectXとはゲーム用APIなどと呼ばれることもあり、その内容はまさにゲームが必要とする機能を全て網羅しているといっても過言ではないだろう。
では、なぜそのようなAPIが必要なのか?
処理速度の高速化が見込めるから?
しかし、満足な速度を得る為には対応したハードウェアが必要になる。
プログラムが簡単になる?
しかし、2ヶ月に一度の頻度でアップデートされるそのAPIの内容を常に把握しつづけるには、それ相応の勤勉を強いられる。
更に次世代のDirectX10に至っては、WindowsVista以前のOSを切り捨てる、とまで云われている。
開発中の商用ゲームにしても、DirectXの大幅なリニューアルにあわせる為に再開発を強いられ、結果、販売時期を大幅に遅らせることになったものもあると聞く。
では何故DirectXなのか?
それを真に理解する為には、Win32APIだけでゲームを作ってみることから始めるべきではないだろうか。
なーんて、もっともらしいことを書いてみたわけだが、実際のところそんな高尚な理由なんて必要でもなんでもなく、本稿が現状でDirectXを取り扱っていない訳は・・・
なんのことはない、新しい情報をどんどん反映していくほどのバイタリティが担当者に無いだけのことである。
もちろん、いずれはDirectXにもチャレンジしていきたいとは企んでいるのだが、いやはや、いつのことになることやら。
とりあえず、前章でなおすと公言した問題点について取組んでいくことにする。
A描画処理の呼び出し方法
前章では関数MainCallBack()のdefaultで呼出した。
しかし、これではメッセージを受取るときにしか呼出されない。
それならば、他に依存しない個所で呼出せば良いのだ。
そこで、こんなのを作ってみた。
まずどこで呼出すことにしたのかと云うと、関数WinMain()の最後尾、メッセージループと呼ばれるwhileループ内にである。
あ、もちろん#include”main_process.h”を忘れずに。
ここは、アプリケーションのタスクが廃棄されるまでずーっとループしている、・・・はずである。
では早速ビルドして実行。
真っ黒なクライアントエリアの適当なところを左クリックしてみよう。
つーっと軌跡を描いて白四角が移動していき、ふむふむ、いい感じに動いてくれている。
しかし、実はこの方法も問題を内包している。
そのひとつを垣間見るために実行中のタスクを確認してみよう。
以下がその様子。
で、一番上にある”010white_box.exe”がビルドしたアプリケーションである。
ごらんのとおり、CPUの使用状況が95になっている。
実は99〜95の間をうろうろしている訳だが、これは困り者だ。
他のアプリケーションの作業時間をごっそり奪ってしまっては、あんまり好ましい動作とは云えない。
しかも、処理内容はお世辞にも高尚と呼べるものではないわけだし。
もちろん、解決の手が無いわけではない。
詳しくは後の章で紹介するが、Win32APIには関数Sleep()ってものがある。
こいつを放り込んでやるのも、まぁ、手ではある。
しかし、メッセージループ内でそれを使うのはあまり賢いとは云えないと思う。
なぜなら、メッセージ処理そのものの速度が影響を受けてしまうからだ。
関数MainCallBack()内で関数SetTimer()を使ってみるのも良いかもしれない。
しかし、これもいまいちすっきりしない。
なにせメッセージ処理は時間にルーズだ。
動きのあるゲームを作ろうとしたとき、あまり向いてないだろう。
そこで、ちょっと背伸びしてマルチスレッド処理に挑戦してみることにした。
マルチスレッド化する為には、どの個所をどのようにスレッド分けするのか、これを明確にしなければならない。
今回の場合は、関数MainTransaction()をまるまる別スレッドにしてみることにした。
ではまず、改良された関数MainTransaction()を見てみよう。
返す型をDWORD型にし、渡す変数をLPVOID型にしている。
これは、Win32APIのルールである。
当然これにあわせて、”main_process.h”も変更しておこう。
また、このスレッドはアプリケーションの稼動中は終了してはならないので、とりあえずwhileループで無限ループ化してしまうことにする。
これはあまりスマートな方法ではないが、メインスレッドである関数WinMain()が終了した時にサブスレッド(ここでは関数MainTransaction)は強制終了する為、見かけ上の問題は無いはずだ。
あと、WM_PAINTメッセージ処理を行わずに、直接、関数BildClientArea()を呼出すことにした。
よって、”main_callback.cpp”内のWM_PAINTメッセージの処理をコメントアウトする。
短期間で何度も書き換えられるような場合は、わざわざ再描画処理を行ってやる必要はないだろう、と考えたからだ。
そして最後にWM_CREATEメッセージ処理の中で関数CreateThread()を使って、関数MainTransaction()を別スレッド化してやれば出来上がりだ。
さて、ここまででなんとなく別スレッド化出来たようなので、ビルドして実行してみよう。
・・・画面は真っ暗なままで、何も表示されない。
もちろん、左クリックしたところで、なんの変化も生まない。
さて実は、まだひとつ遣り残したことがあるわけだが、はたして何処の変更であろうか?
ここまででかなりのページ(?)を使ってしまった為、これは来週までの課題として残しておこう。
ヒントは第11章。
さぁ、みんなで擦ってみてくれたまえ。(偉そうですいません)
|