XNAにおける3Dゲーム描画設計 (任意の描画を行う)
4/5に引き続き、今回は「タスク毎に任意の描画を行う設計」について説明したいと思います。
いままでの描画の説明はモデル、スプライト共々「タスク内に内包される1つの描画データ(モデルであったり、スプライトであったり)を汎用的に描画する」といった「1タスクに1描画データ」というものでした。
しかし、場合により「1タスクに複数描画データ」もしくは「1タスクに複雑な描画方法」といった場合が必要になることもあり、汎用的に設計したもののみでは表現が不足する場合もあります。
そこで「描画のオーバーライド」という設計をフレームワークに盛り込み、これを用いて任意の描画を実現する方法を説明します。
説明には例のごとく、サンプルソースを元にしたいと思います。
ちなみに、前回挙げたサンプルから設計を一部変更した部分があるので、サンプルを挙げ直したいと思います。(^^ゞ
(ブログのネタとして即興でプログラミングしているので、今後も後戻りが多そうです… が、それは趣味でやっているので「それもアリ」ということでwww)
■ サンプルソース(2008.04.11.zip)

サンプルソースでこの設計を実現しているのはエネルギーメータータスククラス(EnergyGageTask)の所で、上述の説明でいうと「1タスクに複数描画データ」「1タスクに複雑な描画方法」の両方の考え方を持っています。「1タスクに複数の描画データを持ち、複雑な描画を行う」という感じです。
そして、まずは処理イメージを挙げるので、概要を把握できるようにします。
(前回の描画イメージとの変更も兼ねています)

ここでポイントとなるのは、図でいう所の赤点線が関連する、
・エネルギーメータータスクの2段上の基底クラスとなる「キャラクタータスククラス(CharacterTask)」
・エネルギーメータータスクの1段上の基底クラスとなるスプライトタスククラス(SpriteCharacterTask)
の「Draw関数」
・エネルギーメータータスククラスの「Draw関数」
といった3個所となります。
以降に各ポイントの説明をしたいと思います。
【キャラクタータスククラスの描画関数】
キャラクタータスククラスは、画面に表示されるオブジェクトの抽象的なクラスとなります。
画面に表示されるオブジェクトというのは、3Dモデルでも2Dスプライトでも何でも良く、「とにかく画面に表示されるオブジェクト」というポリシーを持ちます。
「画面に表示される」ということから、どのようなデータをどのように描画する実現方法なのかは、派生先、もしくは描画を行うクラスに任せるとして、「絶対に描画される」として設計されています。これを踏まえてキャラクタータスククラスにはDrawという関数が用意されています。描画方法は派生先で考えるので、中身は空の実装となります。
【スプライトタスククラスの描画関数】
キャラクタータスククラスから派生しているスプライトタスククラスはDraw関数をオーバーライドして、スプライトを表現するための描画を実現します。
スプライトタスククラスにはスプライト情報である、m_textureを用いて描画を行います。
描画自体は、描画管理であるDrawManagerクラスにある関数DrawSpriteを用いて、これにm_textureを渡して描画を行います。
この描画設計の考えはモデルタスククラス(ModelCharacterTask)も同様で、描画するデータがモデル情報(m_model)であり、描画を実際に行う関数はDrawManagerクラスのDrawModelを呼び出して行います。
【エネルギーメータータスククラスの描画関数】
スプライトタスククラスから派生しているエネルギーメータータスククラス(EnergyGateTask)は、スプライトタスククラスにあるm_texture(これには1枠分のメーターゲージビットマップが1つ)を用いずに、自分のメンバにあるm_imageEnergyとm_imageEnergyGage(どちらもTexture2Dクラス)に対して、コンストラクタでビットマップを読み込んでいます。
次にDraw関数をオーバーライドして、独自の描画を行っています。
このクラスは1枠100のエネルギーゲージを最大1000としたエネルギー量を描画しており、とりあえずエネルギーを1000に初期化しておいて、ゲージを10回、満タンのエネルギーを10枠分を画面左上座標(16,8)の位置から右に向って描画しています。
◇ ◇ ◇
このように共通の描画処理は基底クラスにまとめておき、任意の描画を行いたい場合は派生させてオーバーライドする…といった、よくみかける実装ではありますが、これを実現しています。
サンプルソースの設計ではDrawManager.Drawの中でモデルとスプライトの描画ルーチンが分れていますが、これはスプライトはバッチで描画するのがXNAの仕様という理由からそのようにしています。しかし、描画用配列を一つにしてしまっているので、各描画テーブルを走査する際には、中身をわざわざ判定しているので、将来はモデル用とスプライト用に別々の描画用管理リストを用意しても良いかと思っています。
いままでの描画の説明はモデル、スプライト共々「タスク内に内包される1つの描画データ(モデルであったり、スプライトであったり)を汎用的に描画する」といった「1タスクに1描画データ」というものでした。
しかし、場合により「1タスクに複数描画データ」もしくは「1タスクに複雑な描画方法」といった場合が必要になることもあり、汎用的に設計したもののみでは表現が不足する場合もあります。
そこで「描画のオーバーライド」という設計をフレームワークに盛り込み、これを用いて任意の描画を実現する方法を説明します。
説明には例のごとく、サンプルソースを元にしたいと思います。
ちなみに、前回挙げたサンプルから設計を一部変更した部分があるので、サンプルを挙げ直したいと思います。(^^ゞ
(ブログのネタとして即興でプログラミングしているので、今後も後戻りが多そうです… が、それは趣味でやっているので「それもアリ」ということでwww)
■ サンプルソース(2008.04.11.zip)

サンプルソースでこの設計を実現しているのはエネルギーメータータスククラス(EnergyGageTask)の所で、上述の説明でいうと「1タスクに複数描画データ」「1タスクに複雑な描画方法」の両方の考え方を持っています。「1タスクに複数の描画データを持ち、複雑な描画を行う」という感じです。
そして、まずは処理イメージを挙げるので、概要を把握できるようにします。
(前回の描画イメージとの変更も兼ねています)

ここでポイントとなるのは、図でいう所の赤点線が関連する、
・エネルギーメータータスクの2段上の基底クラスとなる「キャラクタータスククラス(CharacterTask)」
・エネルギーメータータスクの1段上の基底クラスとなるスプライトタスククラス(SpriteCharacterTask)
の「Draw関数」
・エネルギーメータータスククラスの「Draw関数」
といった3個所となります。
以降に各ポイントの説明をしたいと思います。
【キャラクタータスククラスの描画関数】
キャラクタータスククラスは、画面に表示されるオブジェクトの抽象的なクラスとなります。
画面に表示されるオブジェクトというのは、3Dモデルでも2Dスプライトでも何でも良く、「とにかく画面に表示されるオブジェクト」というポリシーを持ちます。
「画面に表示される」ということから、どのようなデータをどのように描画する実現方法なのかは、派生先、もしくは描画を行うクラスに任せるとして、「絶対に描画される」として設計されています。これを踏まえてキャラクタータスククラスにはDrawという関数が用意されています。描画方法は派生先で考えるので、中身は空の実装となります。
【スプライトタスククラスの描画関数】
キャラクタータスククラスから派生しているスプライトタスククラスはDraw関数をオーバーライドして、スプライトを表現するための描画を実現します。
スプライトタスククラスにはスプライト情報である、m_textureを用いて描画を行います。
描画自体は、描画管理であるDrawManagerクラスにある関数DrawSpriteを用いて、これにm_textureを渡して描画を行います。
この描画設計の考えはモデルタスククラス(ModelCharacterTask)も同様で、描画するデータがモデル情報(m_model)であり、描画を実際に行う関数はDrawManagerクラスのDrawModelを呼び出して行います。
【エネルギーメータータスククラスの描画関数】
スプライトタスククラスから派生しているエネルギーメータータスククラス(EnergyGateTask)は、スプライトタスククラスにあるm_texture(これには1枠分のメーターゲージビットマップが1つ)を用いずに、自分のメンバにあるm_imageEnergyとm_imageEnergyGage(どちらもTexture2Dクラス)に対して、コンストラクタでビットマップを読み込んでいます。
次にDraw関数をオーバーライドして、独自の描画を行っています。
このクラスは1枠100のエネルギーゲージを最大1000としたエネルギー量を描画しており、とりあえずエネルギーを1000に初期化しておいて、ゲージを10回、満タンのエネルギーを10枠分を画面左上座標(16,8)の位置から右に向って描画しています。
◇ ◇ ◇
このように共通の描画処理は基底クラスにまとめておき、任意の描画を行いたい場合は派生させてオーバーライドする…といった、よくみかける実装ではありますが、これを実現しています。
サンプルソースの設計ではDrawManager.Drawの中でモデルとスプライトの描画ルーチンが分れていますが、これはスプライトはバッチで描画するのがXNAの仕様という理由からそのようにしています。しかし、描画用配列を一つにしてしまっているので、各描画テーブルを走査する際には、中身をわざわざ判定しているので、将来はモデル用とスプライト用に別々の描画用管理リストを用意しても良いかと思っています。
XNAにおける3Dゲーム描画設計 (スプライトの描画)
4/1に引き続き、Texture2Dクラスの描画を今回より説明して行きたいと思います。
…とその前に、実は以前公開した2008.03.23.zipのサンプルだと説明の順序が難かしくなることが分ったので、これとは別にスプライトの情報を描画するためのクラスを追加したので、このクラスを用いてスプライトの描画を説明して行きたいと思います。
(エネルギーメータの描画は今後説明予定だった「描画のオーバーライド」という設計をしており、これはスプライトの描画説明を終らせてからが良いと判断しました)
■ サンプルソース(2008.04.05.zip)

Fig.実行画面(背景を黒くしました)
さて、今回サンプルに追加したスプライトのクラスはLogoTaskというもので、以下のビットマップをロゴとして読み込みます。

次にロゴのスプライトを作成したということで、これを描画する処理に焦点を当てて行きたいと思います。
まず、LogoTaskクラスが、TaskManagerクラスに登録された時点で、このクラスの内部に保持している描画リストm_drawManagerに登録されます。
このm_drawManagerは、DrawManagerクラスに参照され、XNAのフレームワークである描画イベントSampleGame.Drawの呼び出しタイミングによりDrawManagerクラスのDraw関数が呼び出されます。

DrawManagerクラスの中では、モデルとスプライトの描画処理が順に実行され、スプライトの描画はDrawManager.DrawSprite関数にて実現されています。
この中処理はモデル描画の場合に類似して、
1.登録されているモデルキャラクタークラスの選別
2.スプライト情報の描画
の順で処理しています。以下に各々を説明します。
【1.登録されているモデルキャラクタークラスの選別】
登録されているタスクを描画するためのループを行っており、その際描画対象がスプライトキャラクタータスク(SpriteCharacterTask)クラスのみ描画を行うように判定しています。対象となったタスクは、ここから更にDrawManager.DrawSprite関数にスプライト情報や表示座標を引き渡され、この中でスプライトの描画を行います。
留意点として、この選別のループ前と後に、SpriteTool.m_sprite.Beginと、SpriteTool.m_sprite.Endを呼び出しています。
m_spriteは前回説明したSpriteBatchというクラスで、XNAのスプライト描画を司る仕組みを持ちます。
具体的には、Begin~End内にスプライトをXNAのクラスで描画を行われると、グラフィックに転送する処理を溜めこんで、一括で描画するという機構のためこのような処理となっています。
このため「一括=Batch」という用語が用いられています。
【2.モデル情報の描画】
DrawManager.DrawSprite関数では引数に渡されたビットマップ情報(Texture2D)や座標情報、色情報を用いて描画を行います。
これらの情報があれば描画は至極単純で、
SpriteBatch.Draw(ビットマップ情報, 画面に描画を行う座標, ビットマップ内の描画を行う座標, 色)
で描画できます。
(他にもオーバーロードされた引数があるので、より細かい描画方法が実現できます)
ここで紹介したパラメータの色ですが、これはビットマップにかけ合わせる色情報となります。
SpriteCharacterTaskクラスでは初期設定が白になっており、そのままのカラー情報で色をかけ合わせるということになっています。
また、このカラー情報は半透明であるアルファ情報を持つので、
例えばこの色のパラメータを"new Color(0, 255, 255, 128)"とした場合、白色だったロゴが水色の半透明(ロゴの水色に対して背景の黒の半透明なので、暗い水色)になります。
また、本サンプルでは、この描画の直前に「スケーリング」ということを行っていますが、これはゲーム画面の大きさを変化させるゲームを作成する場合の考慮となります。
(Xbox 360で実行することを前提としている人からすれば比較的ナンセンスな話ではありますが…)
2Dスプライトの描画座標系は3Dの実現方法と違い、スケーリングを行なわなければならない(と私は思っていのですが、XNAのフレームワークで実現できるのであれば、どなたか御教授お願い致します…)ので、この処理を行っています。
現時点のサンプルソースでは起動パラメータ等で画面のサイズを変化できるようにしていませんが、将来これを改良する場合には、ウィンドウのサイズ(こちらがパラメータで可変)と実際のゲーム画面のサイズ(こちらは設計の時点で不変)を決定して、これを元にスケーリングできるようになります。
現時点のサンプルはXNAが生成する、800x600のサイズのウィンドウ=ゲーム画面として、Globalクラスに設定してあります。これを変化させるとゲーム画面サイズが設定できるようになります。(例えば、Global.m_screenNormalSizeを1024x768に設定すと、ウィンドウ内を800x600の大きさ前提で表示していたロゴが1024x768の画面位置として表示されます)
◇ ◇ ◇
モデルの描画程、難解ではないと言われているスプライト描画ですが、それでも色々と知っておくことが多いとは思います。
これでSpriteCharacterTaskクラス内に単純なm_textureを1枚だけ持つものの描画が行えました。
次回はエネルギーメータのビットマップの様な、SpriteCharacterTaskクラス内に1枚だけのビットマップを任意な描画の仕方で描画する(サンプルではメーターを繰り返し10回描画する等)設計を紹介したいと思います。
…とその前に、実は以前公開した2008.03.23.zipのサンプルだと説明の順序が難かしくなることが分ったので、これとは別にスプライトの情報を描画するためのクラスを追加したので、このクラスを用いてスプライトの描画を説明して行きたいと思います。
(エネルギーメータの描画は今後説明予定だった「描画のオーバーライド」という設計をしており、これはスプライトの描画説明を終らせてからが良いと判断しました)
■ サンプルソース(2008.04.05.zip)

Fig.実行画面(背景を黒くしました)
さて、今回サンプルに追加したスプライトのクラスはLogoTaskというもので、以下のビットマップをロゴとして読み込みます。

次にロゴのスプライトを作成したということで、これを描画する処理に焦点を当てて行きたいと思います。
まず、LogoTaskクラスが、TaskManagerクラスに登録された時点で、このクラスの内部に保持している描画リストm_drawManagerに登録されます。
このm_drawManagerは、DrawManagerクラスに参照され、XNAのフレームワークである描画イベントSampleGame.Drawの呼び出しタイミングによりDrawManagerクラスのDraw関数が呼び出されます。

DrawManagerクラスの中では、モデルとスプライトの描画処理が順に実行され、スプライトの描画はDrawManager.DrawSprite関数にて実現されています。
この中処理はモデル描画の場合に類似して、
1.登録されているモデルキャラクタークラスの選別
2.スプライト情報の描画
の順で処理しています。以下に各々を説明します。
【1.登録されているモデルキャラクタークラスの選別】
登録されているタスクを描画するためのループを行っており、その際描画対象がスプライトキャラクタータスク(SpriteCharacterTask)クラスのみ描画を行うように判定しています。対象となったタスクは、ここから更にDrawManager.DrawSprite関数にスプライト情報や表示座標を引き渡され、この中でスプライトの描画を行います。
留意点として、この選別のループ前と後に、SpriteTool.m_sprite.Beginと、SpriteTool.m_sprite.Endを呼び出しています。
m_spriteは前回説明したSpriteBatchというクラスで、XNAのスプライト描画を司る仕組みを持ちます。
具体的には、Begin~End内にスプライトをXNAのクラスで描画を行われると、グラフィックに転送する処理を溜めこんで、一括で描画するという機構のためこのような処理となっています。
このため「一括=Batch」という用語が用いられています。
【2.モデル情報の描画】
DrawManager.DrawSprite関数では引数に渡されたビットマップ情報(Texture2D)や座標情報、色情報を用いて描画を行います。
これらの情報があれば描画は至極単純で、
SpriteBatch.Draw(ビットマップ情報, 画面に描画を行う座標, ビットマップ内の描画を行う座標, 色)
で描画できます。
(他にもオーバーロードされた引数があるので、より細かい描画方法が実現できます)
ここで紹介したパラメータの色ですが、これはビットマップにかけ合わせる色情報となります。
SpriteCharacterTaskクラスでは初期設定が白になっており、そのままのカラー情報で色をかけ合わせるということになっています。
また、このカラー情報は半透明であるアルファ情報を持つので、
例えばこの色のパラメータを"new Color(0, 255, 255, 128)"とした場合、白色だったロゴが水色の半透明(ロゴの水色に対して背景の黒の半透明なので、暗い水色)になります。
また、本サンプルでは、この描画の直前に「スケーリング」ということを行っていますが、これはゲーム画面の大きさを変化させるゲームを作成する場合の考慮となります。
(Xbox 360で実行することを前提としている人からすれば比較的ナンセンスな話ではありますが…)
2Dスプライトの描画座標系は3Dの実現方法と違い、スケーリングを行なわなければならない(と私は思っていのですが、XNAのフレームワークで実現できるのであれば、どなたか御教授お願い致します…)ので、この処理を行っています。
現時点のサンプルソースでは起動パラメータ等で画面のサイズを変化できるようにしていませんが、将来これを改良する場合には、ウィンドウのサイズ(こちらがパラメータで可変)と実際のゲーム画面のサイズ(こちらは設計の時点で不変)を決定して、これを元にスケーリングできるようになります。
現時点のサンプルはXNAが生成する、800x600のサイズのウィンドウ=ゲーム画面として、Globalクラスに設定してあります。これを変化させるとゲーム画面サイズが設定できるようになります。(例えば、Global.m_screenNormalSizeを1024x768に設定すと、ウィンドウ内を800x600の大きさ前提で表示していたロゴが1024x768の画面位置として表示されます)
◇ ◇ ◇
モデルの描画程、難解ではないと言われているスプライト描画ですが、それでも色々と知っておくことが多いとは思います。
これでSpriteCharacterTaskクラス内に単純なm_textureを1枚だけ持つものの描画が行えました。
次回はエネルギーメータのビットマップの様な、SpriteCharacterTaskクラス内に1枚だけのビットマップを任意な描画の仕方で描画する(サンプルではメーターを繰り返し10回描画する等)設計を紹介したいと思います。
XNAにおける3Dゲーム描画設計 (ビットマップを読み込む)
3/30に引き続き、Texture2Dクラスにビットマップ情報を読み込む処理を説明します。
前回はSpriteToolというクラスを作成して、これのLoad関数にて引数のアセット名に対応するビットマップを読み込むことができる説明を行いました。
SpriteToolクラスはモデル操作クラスであるModelToolの設計同様、XNAのContentManagerクラスを内包したstaticクラスとなり、これにLoadSprite関数というのを実装しています。SpriteToolクラスはプログラム開始時に初期化として、ContentManagerクラスを設定して、その後からプログラム内のツールとしてスプライトの操作を提供するポリシーを持ちます。
(GlobalクラスのInitialize関数内で初期化を行っています)
また、この初期化の際にXNAのスプライト描画を司るSpriteBatchというクラスを生成しています。これは描画の際(DrawManager.DrawSprite関数)に用いられます。
SpriteCharacterTaskクラスは、このツールクラスを用いてビットマップを読み込み、戻り値のTexture2Dクラスをメンバのm_textureに設定できます。

次回はこのTexture2Dクラスを用いた描画について説明したいと思います。
前回はSpriteToolというクラスを作成して、これのLoad関数にて引数のアセット名に対応するビットマップを読み込むことができる説明を行いました。
SpriteToolクラスはモデル操作クラスであるModelToolの設計同様、XNAのContentManagerクラスを内包したstaticクラスとなり、これにLoadSprite関数というのを実装しています。SpriteToolクラスはプログラム開始時に初期化として、ContentManagerクラスを設定して、その後からプログラム内のツールとしてスプライトの操作を提供するポリシーを持ちます。
(GlobalクラスのInitialize関数内で初期化を行っています)
また、この初期化の際にXNAのスプライト描画を司るSpriteBatchというクラスを生成しています。これは描画の際(DrawManager.DrawSprite関数)に用いられます。
SpriteCharacterTaskクラスは、このツールクラスを用いてビットマップを読み込み、戻り値のTexture2Dクラスをメンバのm_textureに設定できます。

次回はこのTexture2Dクラスを用いた描画について説明したいと思います。
XNAにおける3Dゲーム描画設計 (Visual C#+XNAプロジェクトにスプライト用ビットマップファイルを登録する)
3/23に引き続き、Texture2Dクラスにスプライト情報となるビットマップファイルを登録する手順を説明します。
XNAにおいて、スプライトとなるビットマップファイルはWindowsでは一般的な「.BMP/.JPG/.PNG」等が読み込むことができ、これらを登録することになります。
(他にも、Direct Drawなどでお馴染の.DDSや昔から存在する.TGAなどもあります)
このビットマップファイルの登録はモデルファイル同様、ソリューションエクスプローラーにアセットとして登録することができます。
サンプルソースでは"Sprite"というフォルダを作成し、この下にエネルギーメーターのビットマップ"EnergyGage.png"をアセット"EnergyGage"として登録しています。
[エネルギーメータのビットマップ]

[ソリューションエクスプローラーに登録]

スプライトのビットマップにおける留意点としては「マゼンダ色(R:255,G:0,B:255)が透過属性」として認識されます。これにより、スプライトの抜きの部分を実現することが可能となります(逆に言えば、マゼンダ色は使用できないということになります)。
これはXNAのデフォルトコンテンツライブラリの仕様のようです。(Windows上はWindows 3.1のVideo for Windows時代からクロマキー=マゼンダみたいな文化がありますね)
このため、JPEGのようなカラー情報が曖昧になるファイルフォーマットは抜きの処理を行うのは向いていないことになるので注意が必要となります。
このようにアセット名を登録することにより、Texture2Dクラスがこの名前でアクセスできるようになります。
アセット名を用いてのビットマップの読み込みはモデル同様、至極簡単で、
Texture2D = ContentManager.Load("アセット名");
というだけでTexture2Dにビットマップ情報が設定できます。
サンプルソースでは上述のコードをモデル情報の読み込みの時同様に、SpriteToolというクラスを作成しています。
XNAにおいて、スプライトとなるビットマップファイルはWindowsでは一般的な「.BMP/.JPG/.PNG」等が読み込むことができ、これらを登録することになります。
(他にも、Direct Drawなどでお馴染の.DDSや昔から存在する.TGAなどもあります)
このビットマップファイルの登録はモデルファイル同様、ソリューションエクスプローラーにアセットとして登録することができます。
サンプルソースでは"Sprite"というフォルダを作成し、この下にエネルギーメーターのビットマップ"EnergyGage.png"をアセット"EnergyGage"として登録しています。
[エネルギーメータのビットマップ]

[ソリューションエクスプローラーに登録]

スプライトのビットマップにおける留意点としては「マゼンダ色(R:255,G:0,B:255)が透過属性」として認識されます。これにより、スプライトの抜きの部分を実現することが可能となります(逆に言えば、マゼンダ色は使用できないということになります)。
これはXNAのデフォルトコンテンツライブラリの仕様のようです。(Windows上はWindows 3.1のVideo for Windows時代からクロマキー=マゼンダみたいな文化がありますね)
このため、JPEGのようなカラー情報が曖昧になるファイルフォーマットは抜きの処理を行うのは向いていないことになるので注意が必要となります。
このようにアセット名を登録することにより、Texture2Dクラスがこの名前でアクセスできるようになります。
アセット名を用いてのビットマップの読み込みはモデル同様、至極簡単で、
Texture2D = ContentManager.Load
というだけでTexture2Dにビットマップ情報が設定できます。
サンプルソースでは上述のコードをモデル情報の読み込みの時同様に、SpriteToolというクラスを作成しています。
XNAにおける3Dゲーム描画設計 (スプライト描画情報を持たせる)
前回まで3Dモデル情報の描画を行う説明をしてきましたが、今回から2D情報をスプライトとして描画する説明を行います。
3Dゲームにてスプライトの表現というと、奥行がないもの(常に手前に表示されるもの)ということで、ステータス情報や文字情報が主な表示情報となることが多いと思われます。ここでは従来のサンプルにコードを追記編集して、自機のエネルギーメーターの表示といったサンプルを挙げて説明して行こうと思います。
■サンプルソース (2008.03.23.zip)

Fig.実行画面

Fig.サンプルソースのデータ構成
◇ ◇ ◇
モデルキャラクタータスククラスを設計した際は、このクラス内にモデル情報を保持しましたが、今回はスプライト情報を持つクラスとして、スプライトキャラクタータスククラスを設計します(至極単純な発想ですね)。
サンプルソース上では「SpriteCharacterTask.cs」がその実装例として実装しています。
XNA上でスプライトを実現するには、Texture2Dクラスを用いれば容易に実現が行え、この情報に対して描画を行えば、画面にスプライト(ビットマップ)が描画できます。モデルキャラクタータスククラスの時同様、スプライトキャラクタータスククラスには、このTexture2Dクラスをメンバ(m_texture)として保持し、このスプライトを描画するための座標(m_drawRect)を内包しています。
ここで、スプライトとテクスチャーの用語が混合しているので、本ブログではどのように考えているかというと、
[スプライト]
昔ながらの2Dゲームにて表現される、平面のビットマップオブジェクト(物体としての定義が強いです)。
[テクスチャー]
3Dのモデルに貼り付けるビットマップデータ(要素としての定義が強いです)。
という感じで表現します。
XNA上のスプライト情報はTexture2Dというクラスの考え方を持っていても、描画の際にはSpriteBatchというクラスを用いた「スプライト」という用語を用います。
3Dモデル表示をメインとしたゲームを作成する場合、(設計次第ではありますが)スプライトの情報というのは、基本的にステータス情報の表示等が主で、ゲーム上の自機や弾等の衝突が行われるようなオブジェクトとしては実装されません。これは基本的にスプライトには奥行情報が無いためで、3次元キャラクターと2次元キャラクターでは同じ次元で存在させて衝突させることが、困難とされているためです。
(これを実現した場合、大抵3次元座標の方が2次元座標の情報に合せる表現が多々見受けられます。例としては3Dの表現をしている2Dタイプのシューティングゲームなどがその例となっています)
本サンプルの設計では、2Dはあくまでステータス情報のみという考えで設計しています。
次回からはこれを踏まえて、描画の設計について説明して行きたいと思います。
◇ ◇ ◇
ちなみに上述の例の逆応用で、2次元ビットマップを3次元空間で表現する方法があり、これは「ビルボード」と呼ばれる手法となります。古くからはFPSでDOOMが、RPGではゼノギアス等がこのような処理を行っているように見受けられます。ポリゴン描画のオーベーヘッドに比べ、高速で処理できますし、アニメ調のキャラクターを表現するゲーム設計には有効な手法と思います。
3Dゲームにてスプライトの表現というと、奥行がないもの(常に手前に表示されるもの)ということで、ステータス情報や文字情報が主な表示情報となることが多いと思われます。ここでは従来のサンプルにコードを追記編集して、自機のエネルギーメーターの表示といったサンプルを挙げて説明して行こうと思います。
■サンプルソース (2008.03.23.zip)

Fig.実行画面

Fig.サンプルソースのデータ構成
◇ ◇ ◇
モデルキャラクタータスククラスを設計した際は、このクラス内にモデル情報を保持しましたが、今回はスプライト情報を持つクラスとして、スプライトキャラクタータスククラスを設計します(至極単純な発想ですね)。
サンプルソース上では「SpriteCharacterTask.cs」がその実装例として実装しています。
XNA上でスプライトを実現するには、Texture2Dクラスを用いれば容易に実現が行え、この情報に対して描画を行えば、画面にスプライト(ビットマップ)が描画できます。モデルキャラクタータスククラスの時同様、スプライトキャラクタータスククラスには、このTexture2Dクラスをメンバ(m_texture)として保持し、このスプライトを描画するための座標(m_drawRect)を内包しています。
ここで、スプライトとテクスチャーの用語が混合しているので、本ブログではどのように考えているかというと、
[スプライト]
昔ながらの2Dゲームにて表現される、平面のビットマップオブジェクト(物体としての定義が強いです)。
[テクスチャー]
3Dのモデルに貼り付けるビットマップデータ(要素としての定義が強いです)。
という感じで表現します。
XNA上のスプライト情報はTexture2Dというクラスの考え方を持っていても、描画の際にはSpriteBatchというクラスを用いた「スプライト」という用語を用います。
3Dモデル表示をメインとしたゲームを作成する場合、(設計次第ではありますが)スプライトの情報というのは、基本的にステータス情報の表示等が主で、ゲーム上の自機や弾等の衝突が行われるようなオブジェクトとしては実装されません。これは基本的にスプライトには奥行情報が無いためで、3次元キャラクターと2次元キャラクターでは同じ次元で存在させて衝突させることが、困難とされているためです。
(これを実現した場合、大抵3次元座標の方が2次元座標の情報に合せる表現が多々見受けられます。例としては3Dの表現をしている2Dタイプのシューティングゲームなどがその例となっています)
本サンプルの設計では、2Dはあくまでステータス情報のみという考えで設計しています。
次回からはこれを踏まえて、描画の設計について説明して行きたいと思います。
◇ ◇ ◇
ちなみに上述の例の逆応用で、2次元ビットマップを3次元空間で表現する方法があり、これは「ビルボード」と呼ばれる手法となります。古くからはFPSでDOOMが、RPGではゼノギアス等がこのような処理を行っているように見受けられます。ポリゴン描画のオーベーヘッドに比べ、高速で処理できますし、アニメ調のキャラクターを表現するゲーム設計には有効な手法と思います。