2.背景を表示してみよう!

この、解説は、SAMPLE01を基に行っています。
まずは、SAMPLE01( DX7SMP01.lzh VB5以降用ソース&EXE)をダウンロードし
て下さい。

では最初に、Form_Load イベントで呼び出されている、pInitDx から、見て行
きましょう。

まず、'goDX'というパブリックな変数に、DirectX を使用するうえでかかすこ
との出来ない、DirectX7オブジェクトを設定します。'goDX'は、ソースの最上
部(General Declarations)にて、宣言されています。(フォーム内でパブリッ
ク)


Set goDX = New DirectX7 ' DirextXオブジェクト生成


'goDX' に DirectX7オブジェクト が 設定されたかどうか確かめるため、この
直後に、


Debug.Print goDX.TickCount


と書いてみてください。イミディエント・ウインドウに、なにか数字の羅列が
表示されましたか?
このプロパティは、Windowsが立ち上がってからの時間を、1msec(1/1000秒)
で、返します。(ゲームのテンポを一定にする為にWaitをかけたりするのに使
えそうですね。)

続いて、2次元の画像を表示するのに使用される、DirectDrawオブジェクトを
作成しましょう。(マイクロソフトは、DirectDrawを、ビデオカードを表すオ
ブジェクトだと表現しています。恐らく、2枚のビデオカードを所有する場合
は、それぞれにDirectDrawを宣言してコントロールするのでしょう。その場合、
下記の""のところに、それぞれのカードのGUID・固有番号を設定するようです。)


Set goDD = goDX.DirectDrawCreate("") ' DirectDrawオブジェクト生成


やはり、フォーム内でパブリックの'goDD'に、DirectDrawオブジェクトを生成
・設定しました。

次に、この'goDD'に、VBで確保されているWinodow Handle(Winodows上の全
てのアプリケーションに割り当てられる、点呼番号だと思ってください。)を
設定し、通常の大きさのWindowで、表示することを教えてあげます。


' 通常WindowでDDrawを作成
Call goDD.SetCooperativeLevel(Me.hWnd, DDSCL_NORMAL)


このとき、DDSCL_NORMALの代わりに、DDSCL_FULLSCREENを設定すると、フルス
クリーンでの表示となりますが、多少、表示等の手順等に違いがあるため、ま
ずは、デバッグのしやすい、通常のWinodowsで、DirectX に慣れる事をお勧め
します。

さて、DirectDrawという土台の作成が終わりましたので、今度は、Surface の
作成に取り掛かりましょう。
Surface とは、訳すと、"面"や"表面"という意味ですが、そのまま、画面に表
示されたり、一時的に、グラフィックを置いておく為の四角の領域だと考えて
ください。
Surface は、任意の大きさで、複数作成することが出来ます。ただし、当然、
領域が広く、数が多くなるほど、メモリ(通常は、ビデオカード上の、VRAM)
を消費しますので、物理的な制限がありますし、当然、その制限は各マシンで
異なります。
自分が作成したゲームを、より多くの人に遊んでほしいと考えるならば、あま
り、むちゃな使い方は、しない方が良いでしょう。)


ここで、ちょっとSurface の一般的な呼び方について記しておきます。
実際に画面に表示される(あるいは、されている) Surface を、Primary Sur
face、表示されていない、主に裏で作業用に使用される Surface を Back Sur
face(あるいは、Back Buffer )、主に、キャラクタ等のグラフィックを保持
しておく為に使用される Surface を Off-Screen Surface と呼びます。

このうち、Back Surfaceは、ゲームの作り方によっては、作成しなかったり、
逆に、複数作成する場合もあります。

また、Primary Surface という呼び方は、常に、現在表示されている Surface
を指す、相対的な名称ですので、注意してください。(現在、Back Surfaceで
あるSurface を、表示するように指示すれば、それが、Primary Surface にな
り、今まで表示されていた Surface は、Back Surface と呼ばれる。)
これは、オブジェクトの参照でも同じ事が言えるのですが(表示する Surface
を切り替えれば、オブジェクトが指す Surfaceも入れ替わる。)、今は、まだ、
無理に理解する必要はありません。「ふ〜ん、そういうものなんだぁ」と、気
楽に聞き流して下さい。
また、このような切り替えが起こるのは、フルスクリーンモードの時です。
実際に、サンプルを作成していくうちに、自然と理解できると思います。


それでは、画面に表示するために絶対必要な、Primary Surface を作成しまし
ょう。
このとき、'DDSURFACEDESC2'という型で宣言されているオブジェクトに、Surf
ace の細かい設定をしていくのですが、難しい事は抜きにして、最初はサンプ
ルの程度の設定だけで、かまいません。


'この、DESCオブジェクトで、作成するサーフェィスの設定をする
goDDSfdPm.lFlags = DDSD_CAPS

'Primary Surfaceである事を設定
goDDSfdPm.ddsCaps.lCaps = DDSCAPS_PRIMARYSURFACE

'Primary Surfaceを生成し、goDDPSfにセットする
Set goDDPmSf = goDD.CreateSurface(goDDSfdPm)


最初に、'DDSD_CAPS' という値を、設定してますが、これななんでしょう?
ヘルプを引くと、"The ddsCaps member is valid.(ddsCapsを有効)"???。
はい、ちんぷんかんぷんですね(^^;。
今の時点では、理解出来なくても結構です。さらに、高度な設定が出てきたと
きに、見ていきましょう。

重要なのは、 その次、DDSCAPS_PRIMARYSURFACE を設定していますね。
この値を設定する事によって、作成される Surface は、Primary Surfaceとな
ります。実際に、次の行で、'goDDPmSf'に、Primary Surface を作成・設定し
ています。


次に、背景のグラフィックを読み込み、保持しておく Off-Screen Surface を
作成しましょう。


'この、DESCオブジェクトで、作成するサーフェィスの設定をする
goDDSfdOs.lFlags = DDSD_CAPS

'Off-Screen の Plain Surfaceである事を設定
goDDSfdOs.ddsCaps.lCaps = DDSCAPS_OFFSCREENPLAIN

'Off-Screen を作成し、BMPを設定
Set goDDOsSf = goDD.CreateSurfaceFromFile("cup.bmp", goDDSfdOs)


今度は、lCapsへの設定が、DDSCAPS_OFFSCREENPLAIN になっています。
これで、作成される Surface は Off−Screen Surface となります。
また、次の行で Surface を作成する再に、BMPファイルから、生成しています。
このような作成の仕方をすると、作成される Surface(この場合は、'goDDOsS
f' )は、参照されているBMPと、大きさ、パレット、色数等が、自動的に同じ
になります。
(この時、参照される BMPファイルが無いと、当然、エラーとなりますので、
注意して下さい。)


最後に、Clipper 領域を作成・設定して、初期化は終わりです。
この Clipper 領域は、サンプルの注釈でも書いていますが、グラフィック等
を転送する際の、有効な枠を設定するものだと、考えてください。実際には、
もうちょっと別の使い方もあるのですが、通常の今は、特に簡単に考えてもら
えれば、問題ありません。


'Clipper 領域を設定する。実際には、転送先のWindow(サンプルの場合は、
'Picture Box)からはみださないようにする設定と思えば良い。(同時に、
'再描画する領域でもある)
Set goDDClip = goDD.CreateClipper(0)

'作成した Clipper 領域を、Picture Box に関連付ける。
goDDClip.SetHWnd picStage.hWnd

'Clipper 領域を、Primary Surfaceに設定する。
goDDPmSf.SetClipper goDDClip

ここでは、フォーム上に貼り付けてある、Picture Box ('picStage')の大きさ
を、領域として設定しています。


さぁ、やっと、これで、”表示する場所”と、”表示するもの”が出来ました。
だいぶ、ややこしく感じた方もおられるかもしれませんが、ここまでは、どん
なアプリケーションや、ゲームでも、だいたい共通の部分なので、常套句とし
て覚えておけばいいでしょう。

では、次に、実際に、背景を表示してみましょう。

背景の表示は、pBltPicture というプロシージャでおこなっています。
(サンプルでは、Picture Box の Paint イベント、つまり、Windows から、
Picture Box を(再)描画しなよ!という、呼びかけがあった時に、表示処理
をしています。)


まず、最初に、


Dim tRect1 As RECT ' Rect は、四角の4角のポイントを保持する。
Dim tRect2 As RECT ' 要は、ある四角の領域とポジションを表している。


という、RECTという型の構造体変数を、宣言しています。
この、RECTという型は、なんのことはない、Left, Top, Right, Bottomとい
う、四角の4つの角のポイントを持っているだけです。(正確には、対角に
位置する2ポイントの座標ですが。)これは、Windows でプログラムを組ん
でいれば、嫌でも目にする値です。Windowsの全ての基本は、Window と呼ば
れている、四角なんですから当たり前ですね。(関係ないけど、誰もが考え
る次世代Windowsの構想の一つに、奥行きを加味した3DのGUIがあるらしい
けど、その時は、奥行き移動のためのホイールを追加した、デュアルホイー
ルのマウスとか、出るのだろうか(笑)?)

そうして、この、tRect1 に、転送先の領域の大きさ、つまり、Picture Box
の大きさセットします。


'Picture Box の大きさを tRect1 に取得
Call goDX.GetWindowRect(picStage.hWnd, tRect1)


内部では、恐らくたんに、Picture Box の Left, Top, Right, Bottom の値を、
tRect1のそれに移しているだけのはずです。(それでも、コードがすっきりす
るのは、気持ちのいいものです。)

次に、背景用が保持されている Surface ('goDDSfdOs')の大きさを、Rect2に
設定してやります。


' tRect2 背景用サーフェィスの大きさを設定(Left と Top は、0なので、
' Bottom に高さを、Right に 幅を設定すると背景サーフェィスの大きさに
' なる)
tRect2.Bottom = goDDSfdOs.lHeight
tRect2.Right = goDDSfdOs.lWidth


で、いよいよ、背景の表示です。ところで、DirectX 上では、よく、表示では
なく、転送という言葉が使用されます。これは、例えば、次に説明する'Blt'
等は、実際には、グラフィックのデータを転送しているだけで、"表示"をして
いるわけではないからです。
転送している先が、たまたま表示される Surface つまり、Primary Surfaceだ
から、画面に表示されるだけの話なのです。
ここら辺は、混乱しやすいところなので、よく、頭の中を整理しておいて下さ
い。


' Primary Surface に、背景用サーフェィスのグラフィックを転送
tRet = goDDPmSf.Blt(tRect1, goDDOsSf, tRect2, DDBLT_WAIT)


上記、Bltで、転送を行っているわけですが、実際には、ゲームを作成されて
いる方にはお馴染みのWinodows APIのStretchBlt とやっている事は同じです。
ただしその転送を、VRAM上で、しかもビデオカードがで受け持つことで、Dire
ctXの売りである高速性が、引き出されているのです。(StretchBltより、REC
T が使用されている分、すっきりしていて見やすいですね。)


どうでしょう?なんとなく理解できたでしょうか?
理解が出来たら、まずは、サンプルを色々と改造してみてください。
(とはいっても、まだ、このサンプルじゃぁ、変更出来るところもほとんどな
いですが・・・。)


次の章では、背景に重ね合わせて、キャラクタを表示する方法を解説します。


< 戻る / RETURN >