ゲームライブラリ

ゲーム製作日誌 プログラム編 No.9 「Direct3D9デバイスの作成」

今回は、前回解説して出現させた「ウィンドウフォーム」からDirect3D9デバイスを作成する方法を解説します。


1、デバイスの作成方法

 Direct3D9デバイスの作成手順は以下のとおりになっています。

//Direct3D9デバイスを作成する
Device device; //代入用変数を用意
Direct3D direct3D = new Direct3D(); //Direct3Dインターフェースを作る(おまじない)
PresentParameters pp = new PresentParameters(); //デバイス作成にあたっての設定を容易

...

//上記で設定したパラメータでデバイスを作成
device = new Device(direct3D, 0, DeviceType.Hardware, frm.Handle, CreateFlags.HardwareVertexProcessing, pp);

 ちなみに、このコードは前回配布したソースコードを抜粋したものです。各行について細かく説明をしていきます。

  1.  Direct3Dインターフェースを作成する(おまじない)
    Direct3D direct3D = new Direct3D(); //Direct3Dインターフェースを作る(おまじない)
     SharpDX.Direct3D9名前空間内Direct3Dクラスのインスタンスを作成しておきます。このインスタンスがないと、Direct3D9デバイスが作成できないので必ず作成しておく必要があります。


  2. 描画設定リストを作る
    PresentParameters pp = new PresentParameters(); //デバイス作成にあたっての設定を容易
     Direct3D9デバイスを作成するには、描画設定を予め伝えておかなくてはなりません。そのため、描画設定を格納する変数を用意します。型はそれ専用のPresentParameters(名前空間:SharpDX.Direct3D9)です。

  3. 描画設定(バックバッファ)を設定する
    //バックバッファ関連
    pp.BackBufferCount = 1; //バックバッファを一枚用意
    pp.BackBufferFormat = Format.A8R8G8B8; //バックバッファに保管する色要素はアルファ抜きRGB
    pp.BackBufferWidth = frm.ClientSize.Width; //バックバッファの幅
    pp.BackBufferHeight = frm.ClientSize.Height; //バックバッファの高さ
     バックバッファとは、画面に直接描画するのではなく、代わりにメモリに書き込む機能です。この機能を利用することでCPUの処理とGPUの処理を分離して、全体的な流れの高速化が見込めます。また、メモリに完全に書き込んでから一気に画面に表示するので”ちらつき防止”の意味もあります。
     設定はソースコードを参照してください。バックバッファの大きさは、フォームの大きさを指定してください。

  4. 描画設定(Zバッファ)を設定する
    //Zバッファとステンシルバッファの設定
    pp.AutoDepthStencilFormat = Format.D24X8; //Zバッファに24ビット,ステンシルバッファに8ビットの精度を与える
    pp.EnableAutoDepthStencil = true; //Zバッファとステンシルバッファを有効にする
     Zバッファとは、一度書き込んだポリゴンのピクセルの遠さを記録しておくメモリです。これを有効にしておくと、遠くのものから近くのものにと順序に沿って物体を描画する必要がなくなります。Format.D16もありますが、精度不足に陥ることがよくあるのでD24X8を指定してください。

  5. 描画設定(ウィンドウかフルスクリーンか)を設定する
    //描画ウィンドウの設定
    pp.Windowed = true; //ウィンドウモードで設定
     画面にどのように絵を描画するか設定します。この設定をfalseにするとフルスクリーンモードで描画ができるのですが、今回はウィンドウフォームを用いた描画なので解説しません。

  6. 描画設定(フレーム更新タイミング)を設定する
    //フレーム更新タイミング関連
    pp.PresentationInterval = PresentInterval.Default; //ディスプレイの垂直同期に合わせて更新
     描画した絵をどのタイミングで画面に表示させるか設定します。Defaultでは、ディスプレイの表示更新タイミングに合わせて表示させます。Immediateでは、ディスプレイを待たずに直ちに画面に反映させます。
     このような性質上、ディスプレイの表示周波数によって設定をDefaultにした場合は、FPSがそれを超えることはありません。

  7. 描画設定(アンチエイリアス)を設定する
    //アンチエイリアス設定
    pp.SwapEffect = SwapEffect.Discard;
    pp.MultiSampleType = MultisampleType.None; //アンチエイリアス無効
     描画したポリゴンの縁がピクセル単位にまとめられてギザギザする減少を回避する機能がアンチエイリアスです。サンプルでは無効にしましたが、有効にしたい場合は、
    pp.MultiSampleType = MultisampleType.FourSamples; //アンチエイリアス有効
    などと指定してください。

  8. デバイスを作成する
    //上記で設定したパラメータでデバイスを作成
    device = new Device(direct3D, 0, DeviceType.Hardware, frm.Handle, CreateFlags.HardwareVertexProcessing, pp);
    Direct3Dインターフェースと、フォームのハンドル、描画設定リストを使ってデバイスのコンストラクタを呼び出します。これが完了すれば、Direct3D9デバイスを取得することができ、いよいよ画面への描画が可能になってくるのです。 

2、総括

 今回はDirect3D9デバイスの作成方法と、そのための描画設定リストの設定項目について確認しました。設定項目の中には、解説不足なものも多くあったと思うので、今後それぞれ詳しく解説していきたいと思います。
 次回からはこのDirect3D9デバイスを利用して画面への描画へと進んでいきます。

ゲーム製作日誌 プログラム編 No.8 「描画ウィンドウの表示&サンプル配布」

こんにちは。
今回は、前回確認したDirect3Dによる描画の流れの一つひとつについて掘り下げていきます。

1、サンプルプログラム配布

 今回以降の説明では、前回の内容通りに作成したあるひとつのプログラムのソースコードを参照しながら解説をしていきたいと思います。
 プログラムのソースコードを入手するには、ここのURLを参照してください。
  解説用ソース群URL:https://docs.google.com/uc?authuser=0&id=0B7rzXohtSxChZXpDMUdPeUxFVDQ&export=download

 配布ファイルを展開すると、「Visual Studio 2010」のC#プロジェクトが作成されます。プログラムの内容は、Direct3Dを利用してウィンドウに時間ごとに異なった色を表示するものとなっています。終了キーは[X]です。


2、ウィンドウフォームの表示

  •  Direct3Dを使って描画をするためには、Direct3Dデバイスが必要です。
  •  Direct3Dデバイスを初期化・手に入れるためには、描画先のウィンドウフォームが必要です。
 こういった依存関係があるため、まずは、描画先のウィンドウフォームを出すための手順から解説していくことにします。

 ウィンドウフォームとは、画面中に出てくる窓のことで下の図の白い枠で囲まれた領域のことを言います。Windowsを使ってればわかりますよね?
ClientPosition

 このウィンドウフォームを出現させるための便利な機能がいくつかVisual C#についています。出現させる流れとしては、プロジェクトにウィンドウフォームを作成して、コードにそれを表示させる記述をする、といった流れになっています。

 ・ウィンドウフォームを作成する手順
  1.  「ソリューションエクスプローラ」でプロジェクトを右クリックして「追加」→「Windows フォーム」をクリックする。

  2. 適当な名前(FrmScreen等...)をつけて、「追加」を押す

 これでウィンドウフォームをプロジェクトに作成することができます。作成されたウィンドウフォームは、「ソリューションエクスプローラ」内に表示されてダブルクリックをすることで、編集することができます。

 ゲームで主に必要となってくることは、右上に出てくるボタンの種類やウィンドウサイズの変更が可能かなどでしょう。



 ・ウィンドウフォームを出現させるためのコード

  ここで先ほど配布したコードが登場してきます。Program.cs内の行19からです。配布したコードでも、起動直後にすぐウィンドウフォームを表示しようとしています。


//描画フォームを初期化します
FrmScreen frm = new FrmScreen();
frm.ClientSize = new System.Drawing.Size(1280, 720); //フォームサイズは、ClientSizeプロパティで変更
frm.Show(); //フォームを表示しておく

  1.  まずはフォームのインスタンスを作る。
    FrmScreen frm = new FrmScreen();
    こんなコードで実現できます。「FrmScreen」とは、先ほどプロジェクトに作成したウィンドウフォームの名前です。

  2. 表示するフォームの大きさを決める。
    frm.ClientSize = new System.Drawing.Size(1280, 720);
    フォームの大きさ、つまり描画領域の大きさですね。描画解像度とも言いますかね。その解像度を指定しているのがこの行です。フォームのSizeプロパティに代入するのではなく、ClientSizeプロパティに設定してあげてください。
    違いはなにかと申しますと、Sizeプロパティの方はタイトルバーやウィンドウの縁も合わせたウィンドウサイズで、ClientSizeプロパティはそれらを除いた純粋な領域です。自分は最初ここでハマりました...。

  3. ウィンドウを実際に出現させる。
    frm.Show();
    まんまですね。これでウィンドウフォームを画面に出現させることが出来ました。ShowDialog()メソッドの方を呼び出してしまうと、ウィンドウが閉じるまで処理を継続できないので注意してください。


 今回は、描画領域として必要なウィンドウフォームを出現させる方法を解説しました。次回は、そのフォームを元にDirect3D 9デバイスを作成する方法を解説していきます。

ゲーム製作日誌 プログラム編 No.7 「Direct3Dのはじめのはじめ」

こんにちは。
前回までは、プレイヤーが操作するキーボードやマウスの状態をプログラム側で検知する手段として、DirectInputを扱ってきました。

no1-2
以前まで作成していた部分は、ゲームライブラリでいう入力を受け付けるところの「部門1」でした。今回から制作を始めていく機能は、出力の大部分を担う画面への描画機能であります。Direct3D 9という機能を使って描画を実現していこうと思います。


1、SharpDXの準備+ウィンドウの表示

 描画編からは、ウィンドウフォームを扱っていく必要が有るためにプロジェクトに若干の変更を加える必要があります。
 具体的には、「No.3」のプロジェクトの作成を「Windowsフォームアプリケーション」にするだけなのですが、今回はプロジェクトごと配布してしまおうと思います。

  • DirectX 9をインストールしていないPCの場合は、「DirectX End-User Runtimes (June 2010) 」をMicrosoftのページからダウンロードしてインストールしてください。
    ※「DirectX SDK」は、必要に応じてインストールすればよいです
  • SharpDXをダウンロードしたことがない場合は、「SharpDXのページ:http://sharpdx.org/」の「Download」ページの中ほどにある「SharpDX-Full-2.5.0.exe」をダウンロードしてインストールしてください。インストール中のオプションで必ず「SharpDX Runtime Assemblies」は選ぶようにしてください。
  1. VS(Visual Studio)側で「Windows フォームアプリケーション」プロジェクトを作成する
  2. VSのメニューバー中の「プロジェクト」→「参照の追加」をクリックする
  3. 「参照の追加」ダイアログ中の「参照」タブをクリックする
  4. SharpDXの「DirectX11-net40」というフォルダまで行き着く
    ※ 多くの場合、「DirectX11-net40」フォルダは「C:\Program Files (x86)\SharpDX\Bin」にインストールされます。また、スタートメニュー中の「SharpDX」→「SharpDX Runtime Assemblies」→「Bin」と進んでいくことでも見つけられます
  5. 「参照の追加」ダイアログで、そのフォルダ中の「SharpDX.dll」「SharpDX.DirectInput.dll」「SharpDX.Direct3D9.dll」「SharpDX.DirectSound.dll」の4つを選んで「OK」ボタンを押します。
 これでC#でSharpDXを扱えるようになりましたし、フォーム表示についてもできるようになっているはずです。しかし、そのままのコードではフォームが普通に出てなんにも手が出せないので、サンプルを参考にしながらProgram.csの中身を変えてみてください。


2、Direct3D 9の流れ

 これからは、Direct3D 9を利用して画面にいろいろ書いていくわけですが、その前に描画するために必要な流れを説明していきます。
  1. 描画用のウィンドウを用意する
     描画した内容を画面に出す領域が必要です。当面は、System.Windows.Forms名前空間にあるFormクラスを使ってウィンドウを用意していきます。

  2. 描画デバイス(SharpDX.Direct3D9.Device)を作成する
     描画デバイスというのは、Direct3D 9の中核を司るクラスでこれを通じて画面に描画したり画像を読み込んだりしていきます。今後は単にDeviceと書いていきます。

  3. 描画するために必要なリソースを読み込み・作成する
     Deviceを通して、描画したい絵や写真をファイルから読み込んだり、CGモデルを読み込んだりします。

  4. 描画開始をDeviceに通知する
     描画を始める前にDeviceに知らせておく必要があります。Device.BeginScene()メソッドを使います。

  5. 描画をしていく
     Deviceに描画命令を送って画面に描画をしていきます。ところでDirect3D 9は、三角ポリゴン(頂点を3つつないで作った三角面)しか描画単位を持たないため、すべての描画命令は「このポリゴンを描け!」といったものになります。

  6. 描画終了をDeviceに通知して画面に反映させる
     「5.」で描いていたポリゴンたちを、画面に反映させます。その際には、Device.EndScene()とDevice.Present()を順に呼びます。

  7. 今までに取得したリソースすべてとDeviceを開放する
     「3.」で読み込んだリソースの多くは、グラフィックボードのメモリに格納されるため必要がなくなった時点で開放してあげる必要があります。

 ざっとこんなものでしょうか。これらがマスターできれば、画面に色んな物を書いていくことができます。

 
 今回はこんなかんじで終わりにします。次回以降で、一つ一つの詳しい説明をしていきます。実践編は、もうちょっとあとになるかもね。

ゲーム製作日誌 プログラム編 No.6-1 「マウスの入力検知の実装」

こんにちは。お久しぶりです。
前回は、プログラムでプレイヤーが操作するマウスの状態を検知する方法を解説しました。今回はそれをどのようにライブラリに組み込むかを模索していきます。


1、組み込み方について考える要素

 キーボード回と同様、まずはマウスの入力検知機能にどんな特徴が必要かを考えます。
 1点を除いて、前回と全く同じです。
 
  • 判定はある周期のタイミングで一気に行い、ライブラリ使用者にはその周期内の判定記録を教えてあげればよい

     マウスをものすごく短い時間内にカチカチ出来る人はいません。ですからマウス状態を調べる作業を頻繁に行う必要はないです。決められた一定の周期に沿って取得しておけば十分です。


  • ゲームライブラリはひとつでよい、ふたつもいらない

      判定をする人は、一人でよいです。そんな時に便利なのがシングルトンパターンであることは前回説明しました。

  • クラスと関わるのは、更新タイミングとキーの状態取得時のみ

     このキー判定クラスが、利用者と関わる必要があるのは大きく分けて二回です。更新タイミングとキーの状態取得時のみです。しかし、ここではクリック状態とカーソル位置を別々に受け取れるようにして3つの関数を用意することにします。
     希望に応じて、カーソルが範囲内にあるか判定する関数を用意してみるのも良いかもしれません。
    ///<summary>
    一定周期が経過しキーボード状態を取得するタイミング
    </summary>
    void Update();

    ///<summary>
    マウスカーソルを取得。
    </summary>
    void GetCursor(out int x, out int y);

    ///<summary>
    ボタンがクリックされているか取得。(返り値:ボタンが押されているか)
    </summary>
    bool IsPressed(int button);

2、絶対座標ではなくフォーム座標

 Windows APIで入手できたマウスカーソル座標とは、画面全体の中での座標でした。実際ゲームを作ってみるとその画面座標というものがいかに意味を成さないわかります。
 ゲームは、絵が表示されるウィンドウの上をポチポチクリックして進めていくものなので、画面全体での座標だけ知ってても全く使えないのです。その絵が表示されてるウィンドウから見たカーソル位置を知る必要があります。
 画面全体のカーソル座標からウィンドウ上のカーソル座標を計算するには、ウィンドウフォームのPointToClient()メソッドを使ってあげます。チョー簡単ですね。ここのところは、サンプルにも入れておいたので気になる方はそちらを参照ください。

ClientPosition



3、サンプルプログラム

 今回の内容を元にサンプルプログラムを作ってみました。詳細はこちらを御覧ください。

 次回からは、ゲームライブラリの描画部にいよいよ入っていこうかなと思っています。(予定)


ゲーム製作日誌 プログラム編 No.6-2 サンプルプログラム

こんにちは。
 この記事では、ゲーム製作日誌 プログラム編 No.6「マウスの入力検知部分の実装」で考えたマウス判定処理のゲームライブラリへの組み込み方法を実現したソースコード例を紹介します。No.3で扱った、SharpDXの導入が前提になっています。
 今回のプログラムは、No.4のサンプルプログラムの状態更新部分を少し書き換えただけです。

/////////////////////////////////////////////////
//
// マウス入力判定機能クラス
//
// Author. ウマモサク
/////////////////////////////////////////////////

using SharpDX.DirectInput;
using System.Runtime.InteropServices;

class MouseInterface{
#region API連携
//GetCursorPosで現在座標を取得
[DllImport("user32.dll")]
private static extern void GetCursorPos(
ref tagPOINT lpPoint
);

//現在座標が入る構造体
public struct tagPOINT
{
public UInt32 x;
public UInt32 y;
}
#endregion

//シングルトン
private static MouseInterface instance;
public static MouseInterface Instance
{
get
{
return instance;
}
}
private static bool initialized=false;
public static void Initialize()
{
if (initialized)
return;

initialized = true;
instance = new MouseInterface();
}
public static void Dispose()
{
if (initialized)
{
instance.DisposeDevice();
instance = null;
initialized = false;
}
}

protected MouseInterface()
{
this.InitializeDevice();
}

private DirectInput directInput;
private Mouse device;

private MouseState buttonState;
private tagPOINT cursorState;

//描画フォーム
private System.Windows.Forms.Form screenForm;
public void SetScreenForm(System.Windows.Forms.Form form)
{
screenForm = form;
}

public void InitializeDevice()
{
directInput = new DirectInput();

//マウスが存在しない場合への対処
Guid keyboardGuid = Guid.Empty;
foreach (var g in directInput.GetDevices(DeviceType.Mouse, DeviceEnumerationFlags.AllDevices))
{
keyboardGuid = g.InstanceGuid;
}

if (keyboardGuid == Guid.Empty)
{
throw new Exception("マウスが見つかりません");
}

//デバイスを生成してマウス状態の取得を開始
device = new Mouse(directInput);
device.Acquire();

buttonState = device.GetCurrentState();
}

public void DisposeDevice()
{
device.Dispose();
directInput.Dispose();
}

public void Update()
{
buttonState = device.GetCurrentState();
cursorState = new tagPOINT();
GetCursorPos(ref cursorState);

//カーソル位置をフォーム座標に変換する
if (screenForm != null)
{
System.Drawing.Point p = new System.Drawing.Point((int)cursorState.x,(int)cursorState.y);
p = screenForm.PointToClient(p);
cursorState.x = (uint)p.X; cursorState.y = (uint)p.Y;
}
}

public bool IsPressed(int button)
{
return buttonState.Buttons[button];
}

public void GetCursor(out int x, out int y)
{
x = (int)cursorState.x;
y = (int)cursorState.y;
}
}


 以上が、ライブラリ部分です。このライブラリは、ゲーム起動時に以下のコードで初期化します。MouseInterfaceクラスの実体を作成するのです。

MouseInterface.Initialize();


 その後、一定周期で以下のコードを呼び出します。ゲームでは通常、メインループという一定周期で処理をする仕組みを持っているため、その中に記述すればOKです。

MouseInterface.Update();


 実際にボタン押下状況を取得するときは、以下の関数呼び出しの返り値から判断します。左ボダンの判定を例に挙げます。

MouseInterface.IsPressed(0)

 
 マウスカーソルの座標を取得するには、以下の関数呼び出しの引数郡から判断します。

int cursorX,cursorY;
MouseInterface.GetCursor(out cursorX,out cursorY);

 ゲーム終了時には、作成した実体を消去してデバイスを開放する必要があります。
twitterはこちら
ニコ生放送します
ギャラリー
  • ウマモサク
  • ウマモサク
  • ウマモサク
  • 3/17 制作記録
  • 3/17 制作記録
  • C91告知
  • C91告知
  • C91告知
  • C91告知
アクセスカウンター
  • 今日:
  • 昨日:
  • 累計:

  • ライブドアブログ