• ベストアンサー
※ ChatGPTを利用し、要約された質問です(原文:DirextX9.0を使用した2Dゲームにおけるデータ設計)

DirextX9.0を使用した2Dゲームにおけるデータ設計

clsdi99の回答

  • clsdi99
  • ベストアンサー率63% (31/49)
回答No.3

そうですね。スプライトの一元管理も必要ですね。 前回はそこまで書かなくて申し訳ありませんでした。 merutyさんが提示しているclass CPlayer のメンバにスプライトのリスト とありますが、これはスプライトクラスのインスタンスをお考えですか? 私は、ここにスプライトを識別できるハンドルのようなものをリスト化することを考えていました。 例えば CSpriteManager というスプライト管理クラスがあり、各キャラクタクラスは、インスタンス生成時に、CSpriteManagerからxxパターンのスプライトハンドルを取得する感じになるのではないかと。 こうすることによって、リソースとしては、CSpriteManagerが一元管理し、描画に使用したい各場所でそのハンドルを用いで描画してあげればよいかと思います。 背景(マップ)などの描画も同じ感じで、できると思いますが如何でしょうか? 注意点としては、一元管理とはどのようなものを想定するかです。 私の考えでは、あくまでリソース管理としての「管理」であって、そのスプライトを描画するかしないか?という管理は含んでいません。 この管理は一元的にやろうと思えばできますが、折角オブジェクト指向でキャラクタオブジェクトを作成しているので、描画するかしないかなどの管理はキャラクタが行うべきかなと思います。 余談ですが、こーいう話はすごく楽しいです。^^

meruty
質問者

お礼

>class CPlayer のメンバにスプライトのリストとありますが >これはスプライトクラスのインスタンスをお考えですか? はい。ただし、スプライトクラスは画像付きテクスチャーのポインタを持つにすぎず、リソースを所有しているのはそのスプライトが使用されるシーン(オープニング・タイトル画面・ゲーム本編・エンディング等)クラスです。 アドバイスを参考に、キャラクタクラスにスプライトのハンドル(識別子(ID))を持たせることを検討してみました。 C●●Scene : public CBaseScene{  シーン固有の画像が読込まれたテクスチャー[n];//(※)  CSpriteManager* pSM;  シーン固有のキー処理();  シーン固有の描画処理();  シーン固有の移動処理(); } 例えばタイトル画面でスタートボタンを押すとゲーム本編シーンのインスタンスが生成され、背景要素(32*32のマップチップ)・プレイヤー(パターン分)・敵(敵の種類×パターン分)等の画像をテクスチャーに読込みます(※)。この時点でメモリ上へのリソース確保は完了。 続いてスプライトのインスタンスを生成します。スプライトにはテクスチャー[n]配列のうち該当する画像が入っている配列要素[i]のポインタと、その画像の描画範囲を持たせます。1つの画像ファイルに複数パターン(または複数種類)の画像が含まれるため、テクスチャ:スプライト=1:Nとなります。生成したインスタンスはスプライト管理CSpriteMangerに識別子(ID)付きで登録します。 続いて自機等キャラクターのインスタンスを生成し、このキャラクタにスプライトの識別子(ID)を登録します。 CPlayer::AddSpriteHandle(HANDLE hSprite){  this->ハンドルのリスト->Add(hSprite); } C●●Scene::Move(){  //スプライトアニメーション  CSprite* pSprite;  pSprite = pSM->GetSprite(pPlayer->GetSpriteHandle(0));  pSprite->SetPosition(...);//座標更新  pSprite->SetRect(...);//描画範囲更新 } C●●Scene::Draw(){  // ハンドルを指定してCSpriteManagerに描画を任せる。  pSM->DrawSprite(pPlayer->GetSpriteHandle(0));  ・・・ } 最後に、シーンのデストラクタでテクスチャー(※)のリソースが解放され、次のシーンに遷移。 如何でしょうか?

関連するQ&A

  • ID3DXSprite::Drawメソッドに関して質問です。

    ID3DXSprite::Drawメソッドに関して質問です。 ID3DXSprite::Drawメソッドの第3引数でスプライトの 中心を識別する座標を指定できますが、 この座標を画像の様に中心にセットします(単に2で除算するだけですが)。 スプライト上では中心を(0,0)と扱うので、仮にこのスプライトを 左上にあわせて描画するとします。 なお、スプライトのサイズと、ウィンドウのクライアントサイズは 完全に一致しているとします。 単純に中心までの幅はX、中心までの高さはXとなりますので、 スプライトをX、Y分だけ右下にずらせば 問題なく描画されるかと思っていたのですが、 何故か画像内の結果上の様に地味に左上に描画されてしまいます。 そこで画像内の結果下の様にそれぞれにさらに0.5pixlずらして描画しますと これは想像どおりの位置で描画されます。 インターネットで調べるとテクスチャの描画の際には0.5pixl云々という記述が あるのですが、この場合でも0.5pixlのずれを意識する必要があるのでしょうか? それとも私自身、根本的に座標の求め方に問題があるのでしょうか? どうか、ご指摘お願いします。

  • DirectXのSpriteについて

    現在DirectXを使ってプログラムを書いています。 スプライトを使って画像を描画しようと思ったのですが、 LPD3DXSPRITE pSprite;//スプライト LPDIRECT3DTEXTURE9 texture;//適当な画像 pSprite->Begin( 0 ); pSprite->Draw( texture, 0,0,0,0xffffffff ); pSprite->End(); というように使って画像を描画するようですが、これを見ると pSpriteはアプリケーション内に1つ存在すればいいような気がするのですが複数用意する意味はあるのでしょうか? 教えてください。

  • 描画について

    今DirectXでゲームを作ろうとしてるものですが、描画しようと思い打ったのですが位置が思い通りにならない(描画が範囲を下回っている)描画されなくて困っています。ソースはこれです。 HRESULT Render(void) { g_pD3DDevice->Clear(0, NULL,NULL, D3DCOLOR_XRGB(0, 255, 255), 1.0f, 0); // シーンの描画開始 if (SUCCEEDED(g_pD3DDevice->BeginScene())) { // スプライトの描画開始(アルファ・ブレンディング有効&デバイス状態を保存も復元もしない) pSprite->Begin(D3DXSPRITE_ALPHABLEND | D3DXSPRITE_DONOTSAVESTATE); // シーンの描画(2D画像の描画) RECT SrcRect = { 0,0,640,480 }; // テクスチャ内でスプライトに使う範囲(0,0)-(512,64) D3DXVECTOR3 Center(320,240,0); // スプライト内の中心の位置(256,32,0) D3DXVECTOR3 Position(320,240,0); // スプライトを表示する位置(0,0,0)+(320,240,0) static int alpha=0; pSprite->Draw(pTexture.m_texture, // スプライトに使うテクスチャ &SrcRect, // 描画範囲 &Center, // スプライト内の中心の位置 &Position, // スプライトを表示する位置 D3DCOLOR_ARGB(alpha>255?511-alpha:alpha,255,255,255)); //alpha++; alpha &= 0x1FF; //pTexture.m_colorKey); // スプライトの描画終了 pSprite->End(); // シーンの描画終了 g_pD3DDevice->EndScene(); } // シーンの表示 return g_pD3DDevice->Present(NULL, NULL, NULL, NULL); }どうしたらきちんとした位置に描画できるのでしょうか。

  • __interfaceに定義するメソッドについて教えてください!

    __interfaceに定義するメソッドについて教えてください! 描画エンジン(engine.dll)を作成しているのですが、アプリ(App.exe)からは呼んで欲しくないメソッドをインターフェイスに定義する必要があり困っています。具体的には、以下のDrawメソッドになります。 // 形状インターフェイス[engine.dll] __interface IShape { bool Draw(); // ★CRenderクラスから呼ばれる bool SetPos( int x, int y ); }; // 描画クラス[engine.dll] class CRender { bool DrawShape( IShape* pShape ); // pShape->Draw();をする }; // アプリ[App.exe] CRender* pRender = new CRender(); IShape* pShape = new CPolygon(); pShape->SetPos(100, 100); pRender->DrawShape( pShape ); DrawメソッドはCRenderが呼ぶメソッドなので、アプリには公開しなくてもよいメソッドになっています。公開する必要がないので、隠蔽するのが正しいと思っていますが、良い案がございましたらご助言ください。

  • ○×ゲーム

    ○×ゲーム ○×ゲームをつくろうとしてるのですがどうプログラムを組んでいいのか分りません。ポインタとクラスを使って作りたいのですがどなたか教えていただけないでしょうか。 途中までのプログラムを載せておきます。ここからどうすればいいのか教えてください。 #include<iostream> #include<cstdlib> #include<ctime> #define NON 0 #define MARU 1 #define BATU 2 #define MAX_HEIGHT 3 #define MAX_WIDTH 3 using namespace std; int g_mas[MAX_WIDTH][MAX_HEIGHT]; class Game{ public: void Clear(); void Player(int *width, int *height); bool Draw(); } void Game::Clear() { for(int width=0; width<MAX_WIDTH; width++) { for(int height=0; height<MAX_HEIGHT; height++) { g_mas[MAX_WIDTH][MAX_HEIGHT] = NON; } } } void Game::Player(int width, int height) { } bool Game::Draw() { for(int width=0; i<MAX_WIDTH; width++) { for(int height=0; i<MAX_HEIGHT; height++) { if(g_mas[MAX_WIDTH][MAX_HEIGHT] == NON) { return 0; //引分けじゃない時、0を返す } } } return 1; //引分けだった時、1を返す } int main() { int width, height; Game g; g.Clear(); srand((unsigned int)time(NULL)); }

  • DIRECTXのスプライト描画で質問です

    いつもお世話になってます。 DIRECTX9.0、VC++6.0を使っています。 DIRECTXでLPDIRECT3DTEXTURE9(テクスチャ)とLPD3DXSPRITE(スプライト)を使って描画しています。 ですが、テクスチャの縦と横のサイズが256*256を超えたものが正常に表示できません。 色々調べてみると、縦と横のピクセル数が2の乗数以外の中途半端なサイズのテクスチャは、キリの良いサイズに変換されるみたいですが、一応縦横共に2の乗数のテクスチャなのにうまく表示できません。 例:768*512ピクセルのTGA形式のファイル 大きな画像ファイルを表示する方法はないでしょうか? どうぞ宜しくお願いします。

  • クラスメソッドのみのクラスのオブジェクト生成は不可??

    あるテキストのjavaの問題です。 public class Draw{   static void pixel(int x,int y){     /*座標(x、y)に点を描画*/   }   static void line(int x1,int y1,int x2,int y2){     /*座標(x1、y1)~(x2、y2)に線を引く*/   } } で、これを実行するための以下のようなクラス public class TestDraw{ <ここに入力> } という問題なのですが2つまでは絞れたのですが、 (1) public static void main(String args[]){   Draw d = new Draw().line(10,10,20,30); } ↑× (2) public static void main(String args[]){   Draw.line(10,10,20,30); } ↑○ (2)はlineメソッドがstaticメソッドだからオブジェクト生成しなくても良い、ということなんですが (1)も正解のような気がするのですが・・・ 解説によると「lineはvoidなのでnew Draw().line(10,10,20,30);とすれば正解、とあります。 どうもいまいち理解できません。 クラスメソッドはオブジェクト生成しなくとも良い→オブジェクト生成できない ということなのでしょうか? それからちなみに、public classって2つ記述できないんではありませんでしたか?

    • ベストアンサー
    • Java
  • ダブルポインタの参照方法について

    いつも参考にさせていただいております。 C++初心者です。初歩的なことかとは思いますが、ご教授願います。 ポインタリストを引数にもつメソッドを作成しています。 この時にリストからイテレータを取り出しているのですが、ポインタからさらにポインタを 取り出しているのでダブルポインタ?になるみたいなのですが、取り出したクラスのメンバ関数の 参照方法がわかりません。->で参照するとビルドした時にコンパイルエラーが発生します。 基本的なことだとは思いますが、ご教授お願い致します。 下記サンプルコード class test { public: test(void); virtual ~test(void); TCHAR* WINAPI GetName(); void WINAPI SetName(const TCHAR* value); } BOOL WINAPI test::test(list<test *> testlist) { list<test *>::iterator itTest = testlist.begin(); while(itTest != searchCondition.end()) { itTest ← ここでGetNameを参照したい } }

  • 配列の共有

    C++言語でゲームを作っているのですが どうしても分からない部分があるので質問させてください 敵のビット(武装の方です)を管理するために、CBoss1_ringクラスとCBoss1_1_Groupクラスで 配列を共有しようと考えたのですが、うまくいきません 理想としては、CBoss1_ringクラスで生成したCBoss1_bitを、 CBoss1_ringクラスのs_bit配列に格納し、 CBoss1_1_Groupクラスのbit配列で、 CBoss1_ringクラスが持っている、s_bit配列のCBoss1_bitのMoveやDrawメソッドを使用したいのですが(本当に分かりづらくてすみません) そもそもこの設計自体が間違いなのか、方法や手段が間違いなのか、もう何が間違いなのか分かりません。 より良い手段や、打開策など、無いものでしょうか。 よろしくお願いします。 以下ソース CEnemyBoss,CEnemyBossは共通した変数やメソッドを持たせています class CBoss1_bit : public CEnemyBoss_St1_1 { public: CBoss1_bit(double inx,double iny); bool Move(); void Draw(); }; //-------- class CBoss1_ring : public CEnemyBoss_St1_1 { CBoss1_bit* s_bit[5]; public: CBoss1_ring(double inx,double iny, CBoss1_bit& bits); bool Move();//ビットを生成する動作をここにいれる void Draw();//ringの描写 }; CBoss1_ring::CBoss1_ring(double inx,double iny,CBoss1_bit& bits) {  //↑適当なステータス設定をここより上で行う↑  *s_bit = &bits; //Groupクラスのbitをringクラスで共有したい  //↑ここでの処理がうまくいかない  //参照を使ってみていますが、もうよく分かりません } bool CBoss1_ring::Move() { //一定間隔タイミングでbitを生成しs_bit[i]に格納する(座標は適当です) for(int i=0;i<5;i++)   s_bit[i] = new CBoss1_bit(GetRand(480)+160,GetRand(600)); return true; } //--------- class CBoss1_1_Group : public CEnemyBoss { CBoss1_bit* bit[5];//ビットパーツ CBoss1_ring* ring;//ビットの生成を管理するパーツ public: bool Move();//全インスタンスの移動処理を行う void Draw();//全インスタンスの描画処理を行う }; CBoss1_1_Group::CBoss1_1_Group(double inx,double iny) { //各オブジェクトの生成を行う     //とりあえず生成してみている… for(int i=0;i<5;i++) bit[i] = new CBoss1_bit(-60,-60);          /*bitの配列を渡して、ringクラスのs_bit配列と    bit配列で同じ中身?を共有したい*/ ring = new CBoss1_ring(inx,iny-220,**bit); } bool CBoss1_1_Group::Move() { for(int i=0;i<5;i++) if(bit[i])bit[i]->Move(); if(ring)ring->Move(); return true; } void CBoss1_1_Group::Draw() { for(int i=0;i<5;i++) if(bit[i])bit[i]->Draw(); if(ring)ring->Draw(); }

  • DirectX png画像でx軸回転について

    D3DXCreateTextureFromFile関数でpng画像を読み込んで、LPD3DXSPRITEのスプライト機能で描画しています。 float rad += 0.005f;という感じでラジアン値を変えつつ回転の様子を調べているのですが、どうも予想通りに動いてくれません。 D3DXMatrixRotationZでz軸回転させると、一定間隔でくるくる回ってくれて、これは予想通りです。 しかしD3DXMatrixRotationXでx軸回転させようとすると、一瞬で画像が縮んでしばらく消えてから、また一瞬の内に伸びて縮んでしばらく消える、という事の繰り返しになります。 なぜx軸(y軸もですけど)の時だと、上手く回転してくれないのでしょう? そして、どのように値を与えれば、一定間隔でくるくる回ってくれるようになるのでしょうか? どうかよろしくお願いします。