C++言語でゲームを作る際の配列の共有について

このQ&Aのポイント
  • 質問者はC++言語でゲームを作っているが、敵のビット(武装)を管理するために配列を共有したいと考えている。
  • 具体的には、CBoss1_ringクラスで生成したCBoss1_bitをCBoss1_ringクラスのs_bit配列に格納し、CBoss1_1_Groupクラスのbit配列でもs_bit配列のCBoss1_bitのメソッドを使用したいという要望を持っている。
  • 質問者はどのように配列の共有を実現すべきか、または別の解決策があるかを知りたいとしている。
回答を見る
  • ベストアンサー

配列の共有

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(); }

質問者が選んだベストアンサー

  • ベストアンサー
  • chie65535
  • ベストアンサー率43% (8524/19373)
回答No.1

CBoss1_ringクラスとCBoss1_1_Groupクラスの両方で共有したいものだけを持つ「基本クラス」を作ります。 つまり、CBoss1_Baseクラスを新たに作り、そのクラスにs_bit配列を持たせ、MoveやDrawメソッドも、このクラスに作ります。 あとは、基本クラスであるCBoss1_Baseクラスから派生させ、上位クラスのCBoss1_ringクラスとCBoss1_1_Groupクラスを作ります。 CBoss1_ringクラスもCBoss1_1_Groupクラスも「自分の元になった、下位の基本クラスであるCBoss1_Baseクラスを使える」ので、CBoss1_Baseクラスを共有する事になります。 例えば、横スクロールシューティングゲームで 自分:上下左右に自由に移動 敵:上下に自由に移動 自分の弾1:右のみ移動 自分の弾2:右に重力引かれて落下 敵の弾:発射地点から自由な方向に直進 となっていたとします。 こういう場合は 全オブジェクト共通のBaseクラスに、座標を持つPosメンバ変数、指定座標に移動させるMoveメソッドを作る 「自分」をBaseクラスから派生させ、キーパッドの入力に従ってMoveメソッドを呼ぶ 「敵」をBaseクラスから派生させ、ランダムで上下どちらかに動くか決めてMoveメソッドを呼ぶ 「自分の弾1」をBaseクラスから派生させ、右に移動するようにMoveメソッドを呼ぶ 「自分の弾2」をBaseクラスから派生させ、右に落下移動するようにMoveメソッドを呼ぶ 「敵の弾」をBaseクラスから派生させ、どの方向に飛ぶかのメンバ変数を追加して、その変数に従って移動するようにMoveメソッドを呼ぶ で、この時「自分の弾は、敵とだけ衝突する」と言うなら、Moveメソッドを呼んだ後に、別のオブジェクトと衝突しているか判定するHit_Checkメソッドを呼べば良いです。 この時「落下する自分の弾2は地面にも衝突する」と言う場合には、「自分の弾2」のクラスにHit_Checkメソッドをオーバーライドして地面衝突判定を追加したHit_Checkメソッドを作ります。 具体的には「基本クラスのHit_Checkメソッドを呼び、衝突してたら結果を持って関数を終了、衝突してなかったら地面と衝突判定して結果を持って関数を終了」という書き方をします。 同じく「敵の弾は自分とだけ衝突する」と言う場合には、Moveメソッドを呼んだ後に、別のオブジェクトと衝突しているか判定するHit_Checkメソッドを呼べば良いです。 派生について簡単に書くと、例えば 基本オブジェクト⇒キャラと弾の2つを派生 キャラオブジェクト⇒自分と敵を派生 弾オブジェクト⇒自分の弾と敵の弾を派生 自分の弾⇒直進弾と落下弾を派生 敵の弾⇒直進弾と誘導弾を派生 のようにします。 基本オブジェクトには「座標変数」とか「座標移動する移動メソッド」とか「表示メソッド」とか「座標を返すメソッド」など、すべてのオブジェクトに共通のものを入れます。 (「座標移動する移動メソッド」以外で座標が書き換わると困るので、座標変数は上位クラスからは見えないプライベート変数にしましょう) キャラオブジェクトには「自分が発射した弾のテーブル」など、敵味方のキャラクターオブジェクトに共通のものを入れます。 このように「共通で使う物は基本クラスにする」と言う書き方をしましょう。 こうすれば「座標を知りたい」のなら、該当オブジェクトの基本クラスの「座標を返すメソッド」を呼ぶだけで済み、該当オブジェクトの種類は一切気にしなくて良いのです。 Windowsのアプリを作る時も、ボタンやエディットボックスやメニューなどの「GUIコントロールオブジェクト」は「座標と大きさなど、どのクラスでも必ず要るもの」を「基本クラス」として定義し、その基本クラスから派生させて、ボタンにはボタンのキャプションを追加、エディットボックスにはエディットテキストを追加する、などのメンバ追加やメソッド追加、メソッドのオーバーライドを行い、さまざまなコントロールオブジェクトを管理します。

関連するQ&A

  • javaの配列

    javaの配列なんですが、配列の全要素一気にメソッドを実行させることができますか? 例えば、 Turtle[] hm = new Turtle[3]; for(int i = 0; i < 3; i++){ hm[i] = new Turtle(); } と配列を生成し、fd(int s)←[sピクセル前進]というメソッドを配列の全部の要素を順番ごとにではなく全部同時に実行させたい場合、コードはどのように書けばよいのでしょうか?

    • ベストアンサー
    • Java
  • newで個別に生成した配列にNULLを代入しても大丈夫か

    C++にて要素数が不定の配列のクラスをnewで生成します。 このとき、newで一度に全ての配列を生成するとメモリをかなり取るので、 指定された要素番号のみを生成したいのでダブルポインタにし、 全体を生成してから個別にクラスを生成することで、 思い通りの処理ができるようになりました。 (生成する番号は0→1→2みたいな順列ではないため) しかし、ここで1つ問題が発生しました。 まずは以下にそのソースを示します。 ----------------------------- class CHOGE {   int a; public:   CHOGE(){ a=999; }   void print(){ cout<<a<<endl; } }; ----------------------------- void main(){   CHOGE **p = new CHOGE*[3];   if( p[0] != NULL ){ // ←条件を通過してしまう     cout << "ほげ~" << endl; // ←表示される     //p[0]->print(); // ←当然エラー   }   p[0] = new CHOGE();   p[0]->print(); // ←OK   delete p[0];   p[0] = NULL;   delete [] p;   p = NULL; } ----------------------------- 上記は3個の要素の配列を生成してから、 個別に0番目の要素のインスタンスを生成しています。 しかし、上記main関数の3行目では、 インスタンスはまだ生成していなにもかかわらず NULLチェックを通り過ぎてしまいます。 そこで上記main関数の2行目に  for(int i=0; i<3; i++) p[i] = NULL; という処理を入れると期待通りに動いてくれるのですが、 どうも引っかかるといいますか、何かの情報を消してしまったり やってはいけないことをやってそうで、不安なのです・・・。 上記のようなとき、NULLを代入しても大丈夫なのでしょうか?

  • 計算後に配列の中身が入れ替わってしまう

    内容を見ていただき、ありがとうございます。私は現在Cを勉強中で、練習の一環として次のようなプログラムを作っていました。 このプログラムは、2つのグループの人数をキーボードから入力して、それぞれのグループの割合を表示するというものです。そこで私の書いたソースは以下の通りです。 /****************** #include<stdio.h> main(){ double score[2]; int i = 0; double sum; ++i; printf("グループ%dの人数:",i); scanf("%lf",&score[i]); ++i; printf("グループ%dの人数:",i); scanf("%lf",&score[i]); sum = score[1] + score[2]; score[1] = score[1] / sum *100; score[2] = score[2] / sum *100; printf("人数の割合は\nグループ1 グループ2\n"); printf("%9.1lf%%%9.1lf%%",score[1],score[2]); return 0; } ***************/ ソースを見る限り、それぞれのグループの割合が表示されるはずだと思ったのですが、これを実行するとグループ2の割合が常に100%になってしまいます。検証してみますと、16行目の sum = score[1] + score[2]; のあとでscore[2]の人数がsumと入れ替わっているようです。この原因は、配列を0から始めなかったことと関係があるのではないかと思い、末尾のプログラムのように配列の開始番号を0からにすると狙い通りに作動しました。 しかし、未だに何故このような動きになるのかがわかりません。このような事態をどのように表現して良いのかもわかりませんので、検索もできませんでした。 そこで、どなたかこの現象についてご存知の方がいらっしゃいましたら、ご教授願えないでしょうか。よろしくお願いいたします。 /********************* #include<stdio.h> main(){ double score[2]; int i = 0; double sum; printf("グループ%dの人数:",i+1); scanf("%lf",&score[i]); ++i; printf("グループ%dの人数:",i+1); scanf("%lf",&score[i]); ++i; sum = score[0] + score[1]; score[0] = score[0] / sum *100; score[1] = score[1] / sum *100; printf("人数の割合は\nグループ1 グループ2\n"); printf("%9.1lf%%%9.1lf%%",score[0],score[1]); return 0; } ***********/

  • 共有できない

    この度タブレットPCを買ったのですがすでに持っているノートパソコンとデータを共有したいと思いホームグループというのを設定したのですが タブレットPCからノートパソコンのフォルダにアクセスしようとすると接続が見つからないとか電源やデバイスどうたらと書いてあるメッセージがでます ですがどちらも電源が入っておりLANにも繋がってます どうすれば共有できますか? 一応パソコンの機種を書いておきます ノートパソコン TOSHIBA T451/46DR win7、64bit Intel i5 セキュリティESET タブレットPC acer W500S win7、32bit セキュリティ、マカフィー LANは同じところを使ってます たぶんbitの違いのせいかと思っています 詳しいご回答よろしくお願いします。

  • 【MATLAB】任意の多次元配列からの配列の抽出

    ベクトルvから複数の要素を抽出し,新しいベクトルuを生成する方法には,以下のようにインデックスを指定する方法があります. idx = [3 10 15 28]; u = v(idx); この方法を拡張し,以下のようにN次元配列Aのi次元目のインデックスを指定することで複数の配列を抽出し,新しい配列Bを得ようと考えています. idx = [3 10 15 28]; B = A(:,:, ・・・ ,:,idx,:, ・・・ ,:,:); Aの次元Nはi以上の任意の値で,iは予め指定された値である場合, 配列Bを得る方法はございますでしょうか. 現在,私は以下のような方法で計算しておりますが,コマンド「eval」を用いて力技でしのいでいる感じで,最適な方法が他にあるのでは,と考えております. N = length(size(A)); idx = [3 10 15 28]; i = 3; buf = 'A('; for s = 1:N if s == i buf = [buf 'idx']; else buf = [buf ':']; end if s < N buf = [buf ',']; end end buf = [buf ')']; B = eval(buf);

  • プログラミング初心者です。プログラミングについてなのですが、32ビット

    プログラミング初心者です。プログラミングについてなのですが、32ビット長のものを一度8ビット長の配列に格納し、また32ビット長のものに戻したいのですが、以下のプログラムに間違っているところはあるでしょうか。うまくいかなくて困っています。よろしくお願いします。    a:32bit長  b[4]:8bit長 // 32bit→8bit /////// for(i=0;i<4;i++){ b[i] = a%256; a = a/256; } // 8bit→32bit ///////  a = b[0]+b[1]*256+b[2]*256*256+b[3]*256*256*256;

  • クラス型配列のコピー

    いつもお世話になっています。 クラス型配列のコピーについてなのですが、 普通の配列だと //コピー元配列 String[] str1 = {"str1","str2","str3" }; //コピー先配列 String[] str2 = new String[2]; //指定分だけ、配列内データをコピー System.arraycopy(str1,0,str2,0,2); //表示 for(int s=0;s<2;s++ ) { System.out.println(str2[s]); } といった形式で、コピーできますが、 これがクラス型の場合可能でしょうか? サンプル例として、 public class SampleFormBean { private String sampleName; private int number; public void setSampleName(String sampleName) { this.sampleName = sampleName; } public String getSampleName() { return sampleName; } public void setNumber(int number) { this.number = number; } public int getNumber() { return number; } } というクラスがあった場合で、 実行するソースは、 //SampleFormBeanクラス型配列 SampleFormBean [] sampleS = SampleFormBean Sample[3]; //SampleFormBeanクラスインスタンスの生成 SampleFormBean sample = new SampleFormBean (); //データの設定 sample.setSampleName("test1"); sample.setNumber(0); sampleS[0] = sample; sample.setSampleName("test2"); sample.setNumber(1); sampleS[1] = sample; sample.setSampleName("test3"); sample.setNumber(2); sampleS[2] = sample; という感じになります。 また、for()なら、ディープコピーとして可能ですが、 これ以外に何か手段はあったりするのでしょうか? 宜しくお願いします。

    • ベストアンサー
    • Java
  • ActionScript3.0(アクションスクリプト3.0)でMovieClipインスタンスを配列で生成する方法

    よろしくお願いいたします。 アクションスクリプト3.0において、あるMovieClipクラスから複数のMovieClipインスタンスを作り、それぞれを独立して制御させたい時に、 インスタンスを生成する際、配列でしようとしたのですがエラーとなりうまくいきません。 var my_mc[i]:MovieClip = new MC(); 上記の宣言を繰り返し処理により複数インスタンス生成をしようと思っていました。 MovieClipインスタンスを配列で生成する場合は別の方法があるのでしょうか?それともそもそもできないのでしょうか? また、MovieClipインスタンスをそれぞれ独立して制御させたい場合、別の方法などありますでしょうか? 以上、間違った表現等あるかもしれませんが、よろしくお願いいたします。

    • ベストアンサー
    • Flash
  • Excelのメモリ(配列)の上限は2Gではないのか

    こんにちは、 現在ExcelのVBAで大量に配列を必要なマクロを作成しています。 その為、計算量が増えるとどうしても、 メモリ不足というエラーが発生してしまい困っています。 そこで、現在使っているExcelがどれだけの配列とメモリを使用できるのか 下記コードを使用してテストしてみました。 そうすると、下記のような値の時メモリ不足というエラーが発生してマクロが終了しました (下図参照) ・メモリ(プライベートワーキングセット)  :1249716 K (約1G?) ・String型配列数(各要素"01,02,03,04,05,06") :約28000000(2800万個) 私の知識では、32bitアプリケーションのメモリの上限は2Gだと聞いています。 ですが、実際にはその半分しか使われていません。 そこで質問となるのですが ・32bitアプリケーションの上限が2Gと言われているのはプラベートワーキングセットの値のことではないのか? ・32bit版Excelを使用して、これ以上のメモリ(配列)を使用することは可能か ・可能であれば、その方法はどんな方法か? 以上のことについてお聞きしたいと思っております。 上のどれか一つでもいいです。知っていることがあれば教えてください。 補足となりますが、テストしたPCの簡単な環境を下に記載して置きます。 どのPCでも上記結果とほぼ変わりはありませんでした。 PC1 Windows7 32bit メモリ 4G Excel2013(32bit) PC2 Windows7 64bit メモリ 8G Excel2010(32bit) 以下は使用したプログラムコードです --------------------------------------------------------------- Public Sub 配列上限取得計算() On Error GoTo ErrEnd Dim i As Long Const kankaku As Long = 1000000 Dim Moji As String Moji = "01,02,03,04" Dim ans() As String ReDim ans(1 To kankaku) As String i = 1 Do If i Mod kankaku = 0 Then ReDim Preserve ans(1 To i + kankaku) As String End If ans(i) = Moji i = i + 1 Loop Erase ans Exit Sub ErrEnd: MsgBox Err.Description & vbCrLf & "これ以上の配列を設定できません。" & vbCrLf & "上限は" & i & "です。" Erase ans Err.Clear End Sub

  • 多次元配列のソートがうまくいかない

    多次元配列のソートがうまくいかない 質問失礼します. 以下のような,String型,int型,double型の混在した多次元配列([3][3]の配列)をソートするプログラムを作成しました. このプログラムでは3番目の項目でソートを行っています. 問題点なのですが, 3番目の項目がdouble型の一桁(例えばarray[1][2]が2.0)ならばうまくソートできるのですが, 一つを2桁(例えばarray[1][2]を10.0)にすると何故か先頭の数(10.0の場合1)を基準にソートされてしまっているようです・・・ 配列へのデータの入れ方が間違っているのでしょうか? 原因がはっきりわからず困っているのですが, わかる方いましたらよろしくお願いします. public class Sort_test { /** * @param args */ public static void main(String[] args) { // TODO 自動生成されたメソッド・スタブ String[][] array = new String[3][3]; array[ 0 ][ 0 ] = "A"; array[ 0 ][ 1 ] = 2001+""; array[ 0 ][ 2 ] = 9.0+""; array[ 1 ][ 0 ] = "B"; array[ 1 ][ 1 ] = 1001+""; array[ 1 ][ 2 ] = 2.0+""; array[ 2 ][ 0 ] = "C"; array[ 2 ][ 1 ] = 3001+""; array[ 2 ][ 2 ] = 6.0+""; TheComparator comparator = new TheComparator(); // 3番目の項目でソートするように設定 comparator.setIndex( 2 ); // ソート実施 Arrays.sort( array, comparator ); dump(array); } public static void dump( String[][] array ) { for ( int i = 0;i < array.length;i++ ) { for ( int j = 0; j < array[ i ].length;j++ ) { System.out.print( "\t" + array[ i ][ j ] ); } System.out.println(); } } } //多次元配列ソート用クラス class TheComparator implements Comparator { /** ソート対象のカラムの位置 */ private int index = 0; /** ソートするためのカラム位置をセット */ public void setIndex( int index ) { this.index = index; } public int compare( Object a, Object b ) { String[] strA = ( String[] ) a; String[] strB = ( String[] ) b; return ( strA[ index ].compareTo( strB[ index ] ) ); } }

    • ベストアンサー
    • Java

専門家に質問してみよう