• ベストアンサー

マップチップの当たり判定の出し方

キャラの座標をposx、posyとして宣言し、キー入力でその値をプラスやマイナスをして動かせるようにし、またマップをint map[16][16]として宣言し、for文でmap[x][y]として回して絵画しているのですが、キャラの移動変数と連動して当たり判定を作ろうとすると、「キャラの移動変数が配列になっていない」というエラーが出ます。 しかし、キャラ座標を配列にする訳にもいかないのでどうすればいいのか困っています。

noname#112042
noname#112042

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

  • ベストアンサー
  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.3

追記。 もし「キャラの座標」と「マップ配列の要素の番号」が1対1に対応していない場合は switch (map[new_posx][new_posy]にある場所のタイプ) { の部分を switch (map[new_posxからmapの要素に対応させる変換式][new_posyからmapの要素に対応させる変換式]にある場所のタイプ) { に変えて下さい。 例えば new_xposが  ~102⇒mapを飛び出すのでNG new_xposが103~113⇒map[0][???] new_xposが114~124⇒map[1][???] new_xposが125~135⇒map[2][???] new_xposが136~146⇒map[3][???] new_xposが147~157⇒map[4][???] new_xposが158~168⇒map[5][???] (以下略) new_xposが268~278⇒map[15][???] new_xposが279~  ⇒mapを飛び出すのでNG のようにに対応しているなら「103を引いて、11で割る」と0~15になります。 なので、上記の例であれば switch (map[((int)new_posx-103)/11][new_posyからmapの要素に対応させる変換式]にある場所のタイプ) { と書けばOKです(もちろん、NG範囲を除外した上で) y方向も、同じように変換式にして下さい。 引いたり(場合によっては足したり)、割ったりする数値は「質問者さんが書いているプログラムに合う数値」に合わせて、適切な値に変えて下さい。

noname#112042
質問者

お礼

丁寧なご回答ありがとうございます。 おかげで当たり判定ができました。 ですが、時々当たり判定が1マス分ずれることがあります。 その点については自分なりにまた努力してみようと思います

その他の回答 (2)

  • chie65536
  • ベストアンサー率41% (2512/6032)
回答No.2

普通は 以下、無限ループ { new_posx = posx; new_posy = posy; キー入力 押したキーで、new_posxかnew_posyを増減する new_posxかnew_posyが、0より小さくなったり15より大きくなったりして、mapから出そうになった場合は、continue;で無限ループの先頭に戻る switch (map[new_posx][new_posy]にある場所のタイプ) { case 歩ける場所:  posx = new_posx;  posy = new_posy;  break; case 壁とかの入れない場所:  break; case 入ったら体力が減る場所:  posx = new_posx;  posy = new_posy;  体力を減らす  体力がまだあるならbreak;  体力が尽きたら、そのまま「case 入ったら死ぬ場所:」の処理を続ける。つまり、break文を書かず、下にあるcase文に突入させる case 入ったら死ぬ場所:  posx = new_posx;  posy = new_posy;  死亡処理  ライフ残があるならbreak;  ライフ残が無いなら、そのまま「case 入ったらゲームオーバーする場所:」の処理を続ける。つまり、break文を書かず、下にあるcase文に突入させる case 入ったらゲームオーバーする場所:  posx = new_posx;  posy = new_posy;  ゲームオーバーの処理  break; } キャラ表示 }/*無限ループ終り*/ と言うような処理をします。

  • dic2008
  • ベストアンサー率53% (7/13)
回答No.1

>「キャラの移動変数が配列になっていない」というエラーが出ます。 とでることには 何かのツールを使用してのエラーでしょうか? それとも独自のシステムでやっているのでしょうか? たとえば1マップのサイズを32x32とすると posx_i = posx / 32; posy_i = posy / 32; と計算し posx_i, posy_i を配列と比較してみてはいかがでしょう? 新しく配列用の変数 posx_i, posy_i ということです

関連するQ&A

  • 敵との当たり判定

    現在VisualC++2008でゲームを製作してるんですが 自分と敵との当たり判定がわかりません。 どのようにすればいいか教えてもらえないでしょうかm(_ _)m #define SCREEN_WIDTH (640) // 画面の横幅 #define SCREEN_HEIGHT (480) // 画面の縦幅 #define CHIP_SIZE (32) // 一つのチップのサイズ #define MAP_WIDTH (SCREEN_WIDTH / CHIP_SIZE) // マップの横幅 #define MAP_HEIGHT (SCREEN_HEIGHT / CHIP_SIZE) // マップの縦幅 #define CHAR_SIZE (30) // プレイヤーのサイズ float PlX, PlY ; // プレイヤーの座標(中心座標) int ActMain( void ) { // プレイヤーの座標を初期化 PlX = 100.0F ; PlY = 1.0F ; // マップ { int i, j ; for( i = 0 ; i < MAP_HEIGHT ; i ++ ) { for( j = 0 ; j < MAP_WIDTH ; j ++ ) { // 1のところだけ描画 if( MapData[i][j] == 1 ) { DrawBox( j * CHIP_SIZE, i * CHIP_SIZE, j * CHIP_SIZE + CHIP_SIZE, i * CHIP_SIZE + CHIP_SIZE, GetColor( 0, 0, 0 ), TRUE ) ; } } } } //プレイヤーの描写 DrawBox( ( int )( PlX - CHAR_SIZE * 0.5F ), ( int )( PlY - CHAR_SIZE * 0.5F ), ( int )( PlX + CHAR_SIZE * 0.5F ) + 1, ( int )( PlY + CHAR_SIZE * 0.5F ) + 1, GetColor( 255, 0, 0 ), TRUE ) ; Cr = GetColor( 255 , 255, 255 ) ; //敵の描写 DrawGraph(teki[0].x,teki[0].y,teki[0].img,TRUE); //初期化 void SYOKIKA(void){ teki[0].x=500; teki[0].y=200; teki[0].img=LoadGraph("red_player.bmp"); //当たり判定をつくったつもりですが反応せず・・・。一応あたったらPlXを0に移動させようとしています。 if(PlX==teki[0].x) PlX=0; if(PlX==teki[0].y) PlX=0; if(PlY==teki[0].x) PlX=0; if(PlY==teki[0].y) PlX=0; がソースです(文字数が足りないのであたり判定に関係ありそうな(敵と自分の座標関連)ところだけ抜きました)今のところ敵、自分、マップ表示や自分の移動などはできているのですが、敵に触れても反応せず、ときおり敵のいないまったく関係のない場所でPlXが0に移動したりしてしまいます ソースみづらくて申し訳ありません。

  • mapの初期化

    こんにちは。 STLのmapについて質問です。 mapで変数を宣言したときに定数初期値を設定したいのですが、どのようにするばよろしいのでしょうか?例えば以下のような感じにしたいのです。 const map<string, int> month = { {"October", 10}, {"November", 11}, {"December", 12} }; 環境はVC2005です。 ご存じでしたら教えていただけないでしょうか?

  • STL mapでアクセス違反

    VC++2005 Express Editionを使用しています。 (Platform SDKを別途インストールしています。) STL mapの変数を宣言すると、その部分でアクセス違反が発生します。 これだけのコードも動きません。 #include <map> using namespace std; int main() { map<int, int> m; m.insert(pair<int, int>(0,10)); return 0; } グローバル宣言するれば、実行直後に止まります。 なにか対策があればよろしくお願いします。

  • 多角形同士の交差の判定

    Javaで用意されている「Polygon」クラスには,「intersects」という矩形との交差判定をするメソッドがありますが,これではなく,多角形(Polygon)同士の交差判定をするメソッドってありますか? あと,初歩的なことかもしれませんが,「Polygon」クラスのx座標とy座標の配列の型は「int」型ですが,これを「double」型で定義したい場合は自作するしかないですよね?

    • ベストアンサー
    • Java
  • C#で壁の当たり判定と自キャラの移動で困っています

    初投稿です。C#のコンソールアプリケーションでゲーム作りをしているC#初心者です。 GraphicsExというフォームを作ってそこに壁を描画するところまではできたのですが、画像を自キャラとして動かせるとよいのですが、できないので今はとりあえず丸を描画して動かしています。 質問なのですが、自キャラを丸で描画して動かすと、壁の当たり判定が分からないので、キャラ(ただの丸ですが)が壁をすり抜けてしまいます。壁にぶつかった時にそれ以上進めないようにするために壁の当たり判定をどなたか教えてほしいです。 あとGraphicsを使っているからか、プログラムがおかしいのか分かりませんが(おそらく後者(汗)キャラの移動はキー入力でやっていて、数秒は意図した通りに移動できるのですが何故かキャラを移動しても、しなくても数秒後にフォームがとまってしまい動かなくなります。どのようにプログラムを記述をするとうまく自キャラの操作をできるのかも教えていただけるとすごく嬉しいです。 重ね重ね恐縮ですが、できればソース付でお願いします。 そもそも、コンソールアプリケーションでゲームを作るべきではない、DirectXを使うべきだ、とかあると加えてアドバイスほしいです。 (ウインドウズフォームもDirectXもあまり詳しくないですが。。。orz) 一応いままでのおおまかなプログラムを載せておきます。長文失礼しました。

  • MAPの配列・・・???!!!

    Mapというものを使うのが初めてなのですが、 よくわからなくなってしまいました。 他のプログラムから、 「MAPの配列で返ってくる」 のですが、このMAPの配列をintひとつ、ストリング2つから 作ろうとしているのですが、できずに困っています。 map[0]=("abc","ABC") map[1]=("def","DEF") map[2]=("ghi","GHI") ・ ・ みたいなイメージなのですが、エラーになります・・・ Map[] hairetu = new HashMap(); これでコンパイルできません。 HelloWorldMap.java:17: 互換性のない型 出現: java.util.HashMap 要求: java.util.Map[] Map[] hairetu = new HashMap(); Map[] hairetu; という宣言だけならできます。 受け渡し先でMapの配列を要求しているのでこのような形が必要なのですが・・・ ちなみにソースを見ると hairetu[i].get(キー) みたいなとり方をしています。

    • ベストアンサー
    • Java
  • 木構造を描写すると重なる

    vectorに入った要素をある順序で木構造で表現しようとしてます。 まず bbについてですがi=0から増えていくごとに0,-1,1,-2,2というようになります。これにより一つ目の子ノードは親ノードのy座標と同じ位置で次はposY(親ノードのY座標)-1*y1*2となり次は反対側にという風に下上下上という風に描写していきます。それを再起呼び出しで繰り返すことで全ての文字を木構造表現しています。 木構造の表現は出来ているのですが問題があります。子ノード同士が同じ座標に描かれます。どういうことかというと同じ親ノードを持つ複数の子ノード(子2、子3とします)同士がさらに複数の子ノード(子4)を持つ時に、子4は子4の子3ノードと重なってしまいます。y座標の決定がbbによって同じ振幅になるからだと思います。 しかし打開策が思いつかないので考えられる方法を教えていただきませんか? 下のプログラム自体はそれほど必要でないと思いますので細かい説明は辞めておきます。 class drawpair{ int bb=0;//子ノードのy座標を決める値 int x1; public drawpair(Graphics g,Vector x,int posX,int posY,Vector causal1){ for(int i=0;i<x.size();++i){ if(i==0){ //親ノードの描写.DrawWordで文字を描写します。 new DrawWord(g,(String)x.elementAt(i),posX,posY); }else{ //y座標を決めるbbの値の設定。 bb +=(int) Math.pow(-1,i)*(i-1); new DrawWord(g,(String)x.elementAt(i),getFontMetrics(f1).stringWidth((String)x.elementAt(0))+posX+50,posY+bb*2*y1); PairNode tes = new PairNode(); x1=tes.nextNode((String)x.elementAt(i),causal1); if(x1!=-1){ new drawpair(g,(Vector) causal.elementAt(x1),getFontMetrics(f1).stringWidth((String)x.elementAt(0))+posX+50,posY+bb*2*y1,causal); } } samplevec.removeAllElements(); } } }

    • ベストアンサー
    • Java
  • 【C#】アクションゲームの地形衝突判定について

     はじめまして、C#でジャンプアクションゲームを製作していて、どうしても解決できないことが出来たので質問させてください。  質問と言うのは、キャラクタとマップとの衝突判定についてです。  テキストベースのマップデータを二次元配列に入れ、それを元にマップを作成し、キャラクタの現在位置の座標を、接触しているマップチップのサイズで割り、その値をマップデータが入っている二次元配列に要素数として入れると、現在接触しているマップデータの位置が割り出せると言うところまではわかり、やってみるとマップと衝突しているように見えるのですが、このマップをスクロールさせると、衝突判定に利用している二次元配列のマップデータがスクロールしない為か、キャラクタを移動させると、マップの段差部分でキャラクタが宙に浮くと言う問題が発生しています。  なら、マップデータも一緒にスクロールさせれば言いと思い、ずっとネットや本などで調べたりして、試してはいるのですが、これと言った解決法が見つかりません。 どなたか、わかる方おりましたらよろしくお願いいたします。

  • 大域変数について

    配列の大域変数externの使いかたがよくわかりません。 BCC Developerを用いて分割コンパイルをしています。 headerファイルにて配列 int map[10][10]; と定義してその配列を他のファイルで使いたい場合は extern int map; ではいけないのでしょうか? あと、headerにて static int * map[10][10] と記述して他のファイルにて extern int *map という記述の仕方は可能なのでしょうか? 大域変数なのにstaticを用いるのはおかしいかとおもいますが… ご教授よろしくお願いします。

  • 当たり判定の処理がわかりません。

    CとDXライブラリでSTGを作っているのですが、あたり判定がわかりません。前、斜め右上、斜め右下の3方向に飛ぶ弾の処理を行いたいのですが、どうすればいいのでしょうか? 画面に出力することはできたのですが、ななめに飛ぶ弾だけ判定できずに困っています。 ―――――――――ソースの一部――――――――――― //拡散する弾 void JitamaMove2(){ //弾の発射 int key = GetJoypadInputState(DX_INPUT_KEY_PAD1); if( (key & PAD_INPUT_A) && (trigger == 0) ) { for( int i = 0; i < 3; i++ ){ if (jitama[i].life == 0){ jitama[i].life = 1; jitama[i].x = jikidata.x+24; jitama[i].y = jikidata.y+8; jitama[i].y1 = jikidata.y+8; jitama[i].y2 = jikidata.y+8; float dy = jikidata.y; float d = sqrt(dy*dy); jitama[i].yobi = dy/d*idouryou[4]*10; break; } } trigger = 20; } if(trigger>0) trigger = trigger - 1; //弾の移動 for(int i=0; i<3; i=i+1){ if(jitama[i].life > 0){ jitama[i].x = jitama[i].x + idouryou[10]; DrawGraph(jitama[i].x, jitama[i].y,*(jitama[i].ghandle), TRUE); float idouy = (float)jitama[i].yobi / 10; jitama[i].y2 = jitama[i].y2 - idouy; DrawGraph(jitama[i].x, jitama[i].y2 - 10, *(jitama[i].ghandle), TRUE); //斜め下に対する弾の描写 jitama[i].y1 = jitama[i].y1 + idouy; DrawGraph(jitama[i].x, jitama[i].y1 + 10, *(jitama[i].ghandle), TRUE); //斜め上に対する弾の描写 //画面外に出たときの処理 if(jitama[i].x>640) jitama[i].life = 0; } } } /*当たり判定を計算する関数*/ int IsAtari(CharaData *a, CharaData *b){ int retval = 0; int ax1 = a->x + (a->image_w - a->bounds_w)/2; int ay1 = a->y + (a->image_h - a->bounds_h)/2; int ax2 = a->x + (a->image_w + a->bounds_w)/2; int ay2 = a->y + (a->image_h + a->bounds_h)/2; int bx1 = b->x + (b->image_w - b->bounds_w)/2; int by1 = b->y + (b->image_h - b->bounds_h)/2; int bx2 = b->x + (b->image_w + b->bounds_w)/2; int by2 = b->y + (b->image_h + b->bounds_h)/2; if( (ax1<bx2) && (bx1<ax2) && (ay1<by2) && (by1<ay2) ){ switch (a->amode){ case A_NORMAL: //キャラ消滅 a->life = 0; break; case A_HARD: //耐久力-1 a->life = a->life -1; break; } switch (b->amode){ case A_NORMAL: //キャラ消滅 b->life = 0; break; case A_HARD: //耐久力-1 b->life = b->life -1; if(b->life > 0) SetHanten(b->x, b->y, b->image_w, b->image_h); break; } if(b->life == 0) SetBakuen(b->x, b->y); retval = 1; } return(retval); } //当たり判定の処理 int AtariHantei(){ for(int i=0; i<50; i=i+1){ if(tekidata[i].life > 0 && tekidata[i].amode != A_GHOST){//A_GHOS・・・判定なし //自機と敵の判定 if(IsAtari(&jikidata, &tekidata[i])==1) return(1); //弾と敵の判定 for(int j=0; j<3; j=j+1){ if(jitama[j].life > 0 && jitama[j].amode != A_GHOST){ IsAtari(&jitama[j], &tekidata[i]); } } } } for( int i = 0; i < 50; i++ ){ if(tekitama[i].life > 0){ if(IsAtari(&jikidata, &tekitama[i]) == 1) return(1); } } return(0); }

専門家に質問してみよう