二次元配列のマップの当たり判定について

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
big

二次元配列のマップの当たり判定について

#1

投稿記事 by big » 13年前

自分は今アクションゲームを作ろうとしていますが、二次元配列でのマップの当たり判定がうまくいかずに困ってます。
ブロックとブロックの間に(横に)移動しながら落下すると、着地したと同時に勝手に左に移動してしまいます。
そして、上(天井)にあたると強制的に右に移動してジャンプを続けてしまって、
上下の当たり判定と左右の当たり判定の順番を変えたら上の当たり判定は正常になったんですが、今度は横のブロックに当たるとすごい速さでブロックからすり抜けてしまって解決法がわかりません。どうしたらいいですか?以下がサンプルコード(未完成なので動きと当たり判定のみ
のコード)です。

コード:

#include "DxLib.h"

#define MAPSIZE_X	(640)									//横マップサイズの長さ
#define MAPSIZE_Y	(480)									//縦マップサイズの長さ
#define CHIPSIZE	(32)									//一つのブロックサイズ
#define MAP_WIDHT	(MAPSIZE_X/CHIPSIZE)					//横のブロックの数
#define MAP_HEIGHT	(MAPSIZE_Y/CHIPSIZE)					//縦のブロックの数

int mapdate[MAP_HEIGHT][MAP_WIDHT] = {
	{ 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },
	{ 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },
	{ 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },
	{ 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },
	{ 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },

	{ 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },
	{ 0,0,0,0,0, 0,0,0,1,1, 1,1,0,0,0, 0,0,0,0,0 },
	{ 0,0,0,0,1, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },
	{ 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },
	{ 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },

	{ 0,0,0,1,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },
	{ 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },
	{ 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0 },
	{ 1,1,0,0,0, 0,0,1,0,0, 1,1,0,0,0, 0,0,0,0,0 },
	{ 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,0,0,1,1 },
};

int zikiX , zikiY , zikiGraph[7] , jumpP , jumpF , chip , haikei;
int i , j ;

int Key[256];
 
int GetHitKeyStateAll_2(int GetHitKeyStateAll_InputKey[]){
    char GetHitKeyStateAll_Key[256];
    GetHitKeyStateAll( GetHitKeyStateAll_Key );
    for(int i=0;i<256;i++){
        if(GetHitKeyStateAll_Key[i]==1) GetHitKeyStateAll_InputKey[i]++;
        else                            GetHitKeyStateAll_InputKey[i]=0;
    }
    return 0;
}
 
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,LPSTR lpCmdLine, int nCmdShow ){
    ChangeWindowMode(TRUE);//ウィンドウモード
    if(DxLib_Init() == -1 || SetDrawScreen( DX_SCREEN_BACK )!=0) return -1;//初期化と裏画面化

	//自機の保存と初期化
	LoadDivGraph("zikiA.png",7,7,1,32,32,zikiGraph);
	chip = LoadGraph("CHIP1.png");
	haikei = LoadGraph("haikei.bmp");
	zikiX = 126;
	zikiY = 415;
	jumpP = 0;
	jumpF = 0;

    while(ProcessMessage()==0 && ClearDrawScreen()==0 && GetHitKeyStateAll_2(Key)==0 && Key[KEY_INPUT_ESCAPE]==0){
          //↑メッセージ処理          ↑画面をクリア           ↑入力状態を保存       ↑ESCが押されていない
		//背景の描画
		DrawGraph(0,0,haikei, FALSE);
		
		//マップ描画
		for( i = 0 ; i < MAP_HEIGHT ; i++ )
			for( j = 0 ; j < MAP_WIDHT ; j++ )
				if(mapdate[i][j] == 1)
					DrawGraph( j*32 , i*32 , chip , FALSE);
		
		//ジャンプ中か否か
		if(mapdate[(zikiY+32)/32][zikiX/32] != 0
			||mapdate[(zikiY+32)/32][(zikiX+16)/32] != 0
			||mapdate[(zikiY+32)/32][(zikiX+32)/32] != 0){
			jumpF = 0;
			jumpP = 0;
		}else{
			jumpF = 1;
		}
		
		//ジャンプの処理
		if( Key[KEY_INPUT_Z] == 1 && jumpF == 0 )jumpP = 20;

		//落下処理
		zikiY -= jumpP;
		jumpP -= 1;
		if(jumpP == -10)jumpP = -10;

		//自機の操作
		if( Key[KEY_INPUT_LEFT] != 0){//左キーを押して壁がなかったら座標を-5する
			if(mapdate[zikiY/32][zikiX/32] == 0
				||mapdate[(zikiY+32)][zikiX/32] == 0)
			zikiX -= 5;
		}
		if( Key[KEY_INPUT_RIGHT] != 0){//右キーを押して壁がなかったら座標を+5する
			if(mapdate[zikiY/32][(zikiX+32)/32] == 0
				||mapdate[(zikiY+32)/32][(zikiX+32)/32] == 0)
			zikiX += 5;
		}
		//左の壁の当たり判定
		if(mapdate[zikiY/32][zikiX/32] == 1
			||mapdate[(zikiY+16)/32][zikiX/32] == 1
			||mapdate[(zikiY-1)/32][zikiX/32] == 1){
				zikiX = ((zikiX+33)/32)*32;
		}
		//右の壁の当たり判定
		if(mapdate[zikiY/32][(zikiX+31)/32] == 1
			||mapdate[(zikiY+31)/32][(zikiX+31)/32] == 1){
				zikiX = ((zikiX+33)/32)*32-32;
		}
		//上(天井)の当たり判定
		if(jumpF == 0 || jumpF == 1){
			if(mapdate[zikiY/32][zikiX/32] == 1 
				||mapdate[zikiY/32][(zikiX+31)/32] == 1){
				zikiY = (zikiY/32+1)*32;
				jumpP = 0;
			}
		}
		//床の当たり判定
		if(jumpF == 0 || jumpF == 1){
			if(mapdate[(zikiY+32-1)/32][zikiX/32] == 1
				||mapdate[zikiY/32][(zikiX+31)/32] == 1){
				zikiY = ((zikiY+33)/32)*32-32;
				jumpF = 0;
			}
		}
		//落下中に判定する
		if(jumpF == 1 && jumpP > 0){
			if(mapdate[(zikiY+33)/32][zikiX/32] == 1
				||mapdate[(zikiY+33)/32][(zikiX+32)/32] == 1){
				jumpP = 0;
				jumpF = 0;
			}
		}

		
		//自機描画
		DrawGraph(zikiX,zikiY,zikiGraph[1],TRUE);


        ScreenFlip();
    }
 
    DxLib_End();
    return 0;
}

box
記事: 2002
登録日時: 14年前

Re: 二次元配列のマップの当たり判定について

#2

投稿記事 by box » 13年前

big さんが書きました:

コード:

		//上(天井)の当たり判定
		if(jumpF == 0 || jumpF == 1){
		}
		//床の当たり判定
		if(jumpF == 0 || jumpF == 1){
		}
変数の意味がわからないので何ともいえませんが、何となく、
どちらかのif文はjumpPの値を使うのではないか、と思っています。
的外れなコメントでしたらすみません。

ところで、幅の英語表記は
WIDTH
です。
WIDHT
ではありません。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

big

Re: 二次元配列のマップの当たり判定について

#3

投稿記事 by big » 13年前

boxさん御回答ありがとうございます。boxさんの言ったとこと

コード:

if(mapdate[zikiY/32][zikiX/32] == 1
            ||mapdate[(zikiY+16)/32][zikiX/32] == 1
            ||mapdate[(zikiY-1)/32][zikiX/32] == 1){
                zikiX = ((zikiX+33)/32)*32;
        }
この部分に修正を加えたところ上の判定が正常になりました!ありがとうございます。あとは地面に自キャラが着いていて横のブロックに当たると、自キャラの下のブロックにめり込みすごい勢いで左に行ってしまうところです。これはどうしたらめり込まないようにできますか?

big

Re: 二次元配列のマップの当たり判定について

#4

投稿記事 by big » 13年前

判定の順番を 床 ⇒ 上(天井) ⇒ 左 ⇒ 右 (左と右はどの順番でも大丈夫でした)に変えたら直りました! 解答してくれた方ありがとうございました!

閉鎖

“C言語何でも質問掲示板” へ戻る