トップページ > 過去ログ > 記事閲覧
異なるクラスへ連続してアクセスするには
名前:レッド 日時: 2008/08/06 08:46

いつもお世話になっております、レッドと申します。 異なるクラスのインスタンスに、どうやって連続して アクセスすればよいのかについて、 今回も皆様のお知恵におすがりに参りました。 現在、プレイヤーキャラ視点のシューティングゲームを作っております。 (FPSって言うらしいですね) ゲーム内のフィールド上に「object」クラスから派生した 「敵その1」クラスや「障害物その4」クラス、 「弾丸」クラスや「ミサイル」クラスなど、 様々な種類のクラスのインスタンスをたくさん配置させようと思っています。 それぞれのインスタンスはプレイヤーとの距離をメンバとして持っていて、 それをもとにプレイヤーの視点から遠くにあるものから順番に 描画していこうと思っております。 しかしそれらのクラスたちはそれぞれ異なるクラスであり、 且つ状況によってインスタンスの数が減ったり増えたりするため、 連続してアクセスし距離順にソートし描画する、 という操作がスムーズにできません。 どのようなテクニックを使えば、 異なるクラスのインスタンスに連続して アクセスしていけるのでしょうか。 ご教授お願いいたします。

Page: 1 |

Re: 異なるクラスへ連続してアクセスするには ( No.1 )
名前: 日時:2008/08/06 14:15

クラスの設計に関して私はあまり精通していない為 最近少し興味を持っていたのですが、 面白そうなので少し考えてみました。 諸所おかしなところがありますが、基本的には その人の好みの問題でもあると思うので 細かいところは自分変えて見てください。 今回は多重継承を使っていますが、 オブジェクトの関係はあまり考えていません。 使えればいいって感じでこうしたほうが良い ってのもあると思いますが。。。 #短くする為に多少見難くなっています #全角スペースは半角かタブに変換してください。 一番のミソはvectorに抽象クラスを登録させる ところです。(C++では基本かも。) これにより、その基本クラスを継承するクラスは このリストに登録できるようになり、 さらに、純粋仮想関数での実装をオーバーライド させ分けるようにしています。 #include <math.h> #include <stdio.h> #include <algorithm> #include <vector> //配置オブジェクト class ObjectPointBase {   int m_nPointX;   int m_nPointY;  public:   int m_nDistance;   ObjectPointBase() : m_nDistance(0), m_nPointX(0), m_nPointY(0){}   virtual ~ObjectPointBase(){}   //整数未満切捨ての距離   int CalcDistance( ObjectPointBase & Player ){    m_nDistance = sqrt((m_nPointX-Player.m_nPointX)*(m_nPointX-Player.m_nPointX))+sqrt((m_nPointY-Player.m_nPointY)*(m_nPointY-Player.m_nPointY));    printf( "Distance = %d\n", m_nDistance );    return m_nDistance;   }   void SetPoint( int X, int Y ){ m_nPointX = X; m_nPointY = Y; }  private:   // コピーコンストラクタ/代入演算子は無効   ObjectPointBase(const ObjectPointBase& other);   ObjectPointBase& operator=(const ObjectPointBase& other); }; // 距離ソート用の大小比較関数 bool LessDistance( const ObjectPointBase* lhs, const ObjectPointBase* rhs ) {  return lhs->m_nDistance < rhs->m_nDistance; } //敵オブジェクト基本クラス class EnemyObjectBase : public ObjectPointBase {  int m_nMaxHP;  int m_nNowHP;  int m_nItemID;  public:   EnemyObjectBase(){}   virtual ~EnemyObjectBase(){}   virtual void Shot() = 0;  private:   // コピーコンストラクタ/代入演算子は無効   EnemyObjectBase(const EnemyObjectBase& other);   EnemyObjectBase& operator=(const EnemyObjectBase& other); }; //障害物オブジェクト基本クラス class ItemObjectBase : public ObjectPointBase {  int m_ItemID;  int m_Count;  int m_Break;  public:   ItemObjectBase(){}   virtual ~ItemObjectBase(){}   virtual void test() = 0;  private:   // コピーコンストラクタ/代入演算子は無効   ItemObjectBase(const ItemObjectBase& other);   ItemObjectBase& operator=(const ItemObjectBase& other); }; //プレイヤオブジェクト class PlayerObject : public ObjectPointBase {  public:   PlayerObject(){}   virtual ~PlayerObject(){} }; //Enemy1の動作を決定する派生クラス class Enemy1 : public EnemyObjectBase {  int m_nColor;  int m_nGraphicHandle;  public:   Enemy1(){}   virtual ~Enemy1(){}   void Shot(){ printf( "Enemy1のShot!\n" ); } }; //Enemy2の動作を決定する派生クラス class Enemy2 : public EnemyObjectBase {  int m_nColor;  int m_nGraphicHandle;  public:   Enemy2(){}   virtual ~Enemy2(){}   void Shot(){ printf( "Enemy2のShot!\n" ); } }; //item3の動作を決定する派生クラス class Item3 : public ItemObjectBase {  int m_nColor;  int m_nGraphicHandle;  public:   Item3(){}   virtual ~Item3(){}   void test(){ printf( "Item3のtest\n" ); } }; //item4の動作を決定する派生クラス class Item4 : public ItemObjectBase {  int m_nColor;  int m_nGraphicHandle;  public:   Item4(){}   virtual ~Item4(){}   void test(){ printf( "Item4のtest\n" ); } }; //配置オブジェクトを管理する配列型 typedef std::vector<ObjectPointBase*> StageObjectList; typedef std::vector<ObjectPointBase*>::iterator Object; //障害物、アイテムを管理する配列型 typedef std::vector<ItemObjectBase*> ItemObjectList; typedef std::vector<ItemObjectBase*>::iterator Item; //敵パターンを管理する配列型 typedef std::vector<EnemyObjectBase*> EnemyObjectList; typedef std::vector<EnemyObjectBase*>::iterator Enemy; static StageObjectList ObjectList; static EnemyObjectList EnemyList; static ItemObjectList ItemList; int main( void ) {  int i;  Object itObject;  PlayerObject Player;  Enemy itEnemy;  Enemy1 enemy1, enemy2;  Enemy2 enemy3;  Item3 item1;  Item4 item2;  //配置位置決定  enemy1.SetPoint( 200, 100 );  enemy2.SetPoint( 600, 500 );  enemy3.SetPoint( 400, 50 );  item1.SetPoint( 300, 500 );  item2.SetPoint( 550, 640 );  //敵を登録  EnemyList.push_back(&enemy1);  EnemyList.push_back(&enemy2);  EnemyList.push_back(&enemy3);  //アイテム・障害物を登録  ItemList.push_back(&item1);  ItemList.push_back(&item2);  //配置オブジェクトに登録  ObjectList.push_back(&enemy1);  ObjectList.push_back(&enemy2);  ObjectList.push_back(&enemy3);  ObjectList.push_back(&item1);  ObjectList.push_back(&item2);  //プレイヤに対する配置オブジェクトすべての距離を計算する  Player.SetPoint( 10, 20 );  for ( itObject = ObjectList.begin(); itObject!=ObjectList.end(); itObject++ ){   (*itObject)->CalcDistance( Player );  }  //距離について近い順にソートを行う  std::sort( ObjectList.begin(), ObjectList.end(), LessDistance );  for ( i = 0; i < 10 ; i++ ){   //プレイヤまでの距離を計算する為位置を更新する   Player.SetPoint( 100 + (i*40), 200 + (i*40));   //敵に関連する処理を呼び出し距離を計算させる   for( itEnemy = EnemyList.begin(); itEnemy != EnemyList.end(); itEnemy++ ){    (*itEnemy)->CalcDistance( Player );   }   //距離について近い順にソートを行う   std::sort( EnemyList.begin(), EnemyList.end(), LessDistance );   //ソートした結果から近い順になっているはずなのでショットの処理を実行する   for( itEnemy = EnemyList.begin(); itEnemy != EnemyList.end(); itEnemy++ ){    printf( "プレイヤまでの距離:%d(500未満で攻撃する)\n", (*itEnemy)->m_nDistance );    if ( (*itEnemy)->m_nDistance < 500 ){     (*itEnemy)->Shot();    }   }  }  return 0; }
Re: 異なるクラスへ連続してアクセスするには ( No.2 )
名前:レッド 日時:2008/08/07 10:30

>通さん ご返信まことにありがとうございます! お教えいただいた方法を試してみましたところ、 見事に異なるクラスでも連続してアクセスすることができました。 スーパークラスの型のポインタをサブクラスが 利用できるということを恥ずかしながら存じ上げませんでした・・・。 本当にありがとうございます。

Page: 1 |