Demo 1

Demo1 は、DGCScreen の使い方を示している。これを見ると、使用の際には難しい設定が必要なようにも感じるが、何のことは無い。DGCScreen Component をフォームに配置するだけでよい。必要な設定はすべて DGCScreen Component がやってくれるし、プロパティもデフォルトの設定で十分である。ここら辺は DGC の、そして Delphi の優秀さの現われであろう。

試しに新しいアプリケーションを作成し、 DGCScreen Component を置いてみるとよい。そして実行・・・おっとその前にやることがあった。

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
  if Key = #27 then Close;
end;
これは、フォームの OnKeyPress イベントである。これが無いと平和に終了することが出来なくなるから、けして忘れてはいけない。しかしそれでも忘れてしまった人は、Win 95 は Alt+Tab でアプリケーションを切り替えられるので、いったんアプリを最小化しておき、強制終了させるとよい。Delphi の開発環境から実行した場合は、実行-プログラムの終了を選べば良い。

通常の DirectX アプリケーションでは ESC キーで終了できるものが多いが、これもそのため。この機能は DGCScreen についていてもいいと思うのだが、さほど面倒でもないので良しとしよう。なお、フォームのイベントの書き方が分からない人は、この先を読んでもつまらないと思うので、まず Delphi のプログラムの勉強から始められるとよい。

うまく実行できたらぱっと画面が切り替わり、何も無い状態になると思う。それもそのはず、何も描いていないのだからしょうがない。もちろん、デモプログラムはその辺のことは考えてあるので、この後何をすれば良いのかを見てみよう。

procedure TForm1.DGCScreen1Initialize(Sender: TObject);
フォーム上にある DGCScreen Component をクリックして、オブジェクトインスペクタのイベントのページを見てほしい。 DGCScreen Component には4つのイベントが定義されている。OnInitialize イベントは、Direct Draw の準備が終わってから呼び出されるので、この時点ですでに画面は切り替わっている。デモプログラムではここでいくつかの作業をしているが、どれも特に必要ではない。よって、説明は後回しにすることにする。(おいおい)

procedure TForm1.FormKeyPress(Sender: TObject; var Key: Char);
begin
     //If the escape key is pressed fade the palette out and
     //Close the demo
     if Key = #27 then
     begin
          DGCScreen1.FadePaletteOut(100);    // 注目!!
          Close;
     end;
end;
このイベントがなぜ必要かは先ほど説明したが、何がなんでも必要なわけではない。ただ、もし自分の作ったゲームをより多くの人に遊んでもらいたいのであれば、これは書いておいた方が良い。

さて、新しい命令が出てきたことに気がついたであろうか。さりげなくコメントが書いてあるが、これは何?

  DGCScreen1.FadePaletteOut(100);
すでにデモプログラムを実行した人なら分かるかもしれないが、プログラムを終了する際に画面がフェイドアウトしたはずである。100 と書いてあるのはフェイドアウトに要する時間を指定しているのだが、FadePaletteOut のヘルプには具体的な時間の単位は書いてなかった。前に見たような気がするのだが、β5には書いてあるのかもしれない。まあ、私の腹時計で大体1秒ぐらいである。お手軽な割にかっちょいいということで、これも書いておいた方がいいだろう。つまり、Demo1 の OnKeyPress は、最初にアプリケーションを作成する際には必ずコピーしておくことにすると良い。或いは、OnKeyPress を書いた状態でリポジトリに登録しても良い。

procedure TForm1.DGCScreen1Paint(Sender: TObject);
begin
     //The paint event should only be called when surfaces are lost. This
     //can be caused when application switching with ALT+TAB.
     DrawFrame;
     DGCScreen1.Flip;
end;
デモプログラムと順番が前後するが、先にこちらを説明しておく。ここで大事なのは、次の命令である。

  DGCScreen1.Flip;
ふりっぷ?

あなたはなぜ DirectX を使いたいと思ったろうか。速度が早いから?それとも画面が奇麗だから? でもそれ以外にも、Direct Draw を使う重要な利点の一つに「2つの画面を切り替えながら使える」というのがある。ちょっと DGCScreen Component のプロパティを見てみると、BackBaffers という項目があるのが分かると思う。ここに「2」となっているのは、実は2画面を使えるようにしているのである。通常はこのプロパティは変更しないで使うことになる。2画面ある利点は、「書き込み途中の画面が表示されないので、遅いマシンでも画面がちらつかない」ということである。そしてこの Flip というメソッドは、その2つの画面を手動で切り替えるためにある。

ところで、このイベントは DGCScreen Component の OnPaint に書かれている。このイベントは、Alt+Tab などで画面が切り替わってしまい、また Direct Draw の画面に戻ってきたときに発生する。現在のバージョンの DGC(β6)では、全画面モードしかサポートしていないため、それ以外の場所でこのイベントが発生することはない。つまり、これも「どうしても必要」なわけではないが、あった方がいいのである。

procedure TForm1.DrawFrame;
var
   n: Integer;
begin
     with DGCScreen1.Back.Canvas do
     begin

       :
       :
       :
       :

          Release; //This must be called to release the device context.
     end;
end;
さて、いよいよ肝心のアプリケーションの中身を覗いてみる。このプログラムでは、DrawFrame がそれに当たる。このデモプログラムの中で唯一イベントハンドラではなく、自分で定義したプロシージャである。

   with DGCScreen1.Back.Canvas do
これから DGCScreen に書き込むことになるわけだが、この時に Delphi の Canvas が使える。したがって、LineTo や TextOut などのメソッドで、簡単に画面に書き込むことができるようになっている。それはいいとして、「Back」って何だろう?

Direct Draw では2画面を切り替えて使えることを説明したが、その2画面とは、「今、ディスプレイに見えている画面」と「同じ大きさの見えない画面」の二つである。一般には前者を「プライマリーサーフェイス」といい、後者を「バックバッファサーフェイス」と言う。「見えている方」に書き込んだのでは、書いている途中が見えてしまって意味が無いので、「バックバッファサーフェイス」に書き込むことになる。「バックバッファサーフェイス」である Back は DGCScreen の TDGCSurface クラスのプロパティであり、TDGCSurface は TCanvas クラスのプロパティを持っているので、Canvas が使えるのである。

難しいことは実際のプログラミングでは関係ない。用はこれを真似して Back の Canvas に描き込めば良いだけである。描き込んだら Flip で画面を切り替える。そしてまた・・・はて? 次はどこに描くのか? プライマリ? バックバッファ?

もちろんバックバッファに描く。画面を切り替えた後は、今まで「プライマリーサーフェイス」だったところが「バックバッファサーフェイス」に、「バックバッファサーフェイス」だったところが「プライマリーサーフェイス」になる。したがって常にバックバッファサーフェイスに描き込むことになる。

  Release; //This must be called to release the device context.
さて、実際に書き込んでいる部分の説明はしない。もし知りたければ、Delphi のヘルプ&マニュアルを見れば、日本語で書いてある。しかし TDGCSurface の TCanvas クラスは、通常の Canvas プロパティと異なる点が一つだけある。それが Release メソッドである。ヘルプには、「Canvas を使い終わったら必ず呼び出さないと、Windows がハングるよ」と書いてある。これを防ぐためにも、常に

  with DGCScreen1.Back.Canvas do begin
    some canvas method
    Release; //This must be called to release the device context.
  end;
の形で使った方が良い。

さて、このデモプログラム中で説明していない命令が後一つある。OnInitialize で呼び出されている、

  DGCScreen1.FadePaletteIn(100);
この命令である。なんだか見たままだが、FadePaletteOut の逆、フェードインを行う。もちろん、すでにフェードアウトされた状態でないと意味が無い。

procedure TForm1.DGCScreen1Initialize(Sender: TObject);
begin
     //Draw stuff on the hidden surface
     DrawFrame;

     //Quickly fade palette to black
     DGCScreen1.FadePaletteOut(1);

     //Flip the hidden surface with the visible one so you can
     //see it on the screen - but you can't see it yet cause the
     //palette is still black???
     DGCScreen1.Flip;

     //Finally Smoothly fade the palette in
     DGCScreen1.FadePaletteIn(100);
end;
このイベントでは、まず DrauFrame でバックバッファサーフェイスに画面を描画し(まだ見えていない)、次に FadePaletteOut でフェードアウト(元々見えない上に、さらに見えなくなる)、描画した画面をプライマリサーフェイスに切り替え(まだ見えない)、FadePaletteIn でフェードイン(やっと見えた)させている。

以上で、Demo1 プログラムの説明を終わる。DGC を使えば、Delphi から DirectX を使うのは簡単であることが、解っていただけたであろうか?

もどる