ページ 11

DXライブラリ 地形との衝突判定

Posted: 2014年9月01日(月) 18:42
by Fake
度々申し訳ありません、今回2D横スクロールアクションを作る途中で地形との衝突判定がうまくできませんでした・・・
return 1;で終了するようにプログラムした場合はちゃんと終了するのですが、いざキャラクターをマップチップの上に乗せたり、横からぶつかった場合は進めなくするなどの動作になるとうまく動いてくれません・・・
この場合どうしたらいいのでしょうか?

コード:

#include "DxLib.h"

/************************
変数や関数、構造体の指定
************************/
#define SCREEN_WIDTH	(640)			//画面の横の大きさ
#define SCREEN_HEIGT	(480)			//画面の縦の大きさ
#define MAP_PIXEL_WIDTH	(1280)			//マップの横のピクセル数
#define MAP_PIXEL_HEIGHT (480)			//マップの縦のピクセル数
#define CHIP_SIZE	(32)				//チップサイズ
#define MAP_WIDTH	(MAP_PIXEL_WIDTH / CHIP_SIZE)	//マップの横の大きさ
#define MAP_HEIGHT	(MAP_PIXEL_HEIGHT / CHIP_SIZE)  //マップの縦の大きさ

typedef struct
{
	int x,y,img;
}ch_t;


int chip[4];						//マップチップの指定
int image[6];						//グラフィックハンドルの指定
int PlayerX , PlayerY ;				//プレイヤー変数
int y_prev = 0,y_temp = 0;
int JumpPower ;						//ジャンプ用変数
int CountX = 0;						//アニメーション用カウント変数
int ix = 0,result = 0;				//アニメーション用添字変数
float move = 1.0f;
bool JumpFlag = false;

int Map[15] [40] =					//マップデータ
{
	{2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2},
	{2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2},
	{2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2},
	{2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,3,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2},
	{2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2},
	{2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2},
	{2,2,2,2,2,2,2,2,1,1 , 1,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2},
	{2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2},

	{2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,1,2,2,2 , 2,2,2,2,2,2,2,2,2,2},
	{2,2,2,2,2,2,3,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2},
	{2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,1,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2 , 2,2,2,2,2,2,2,2,2,2},
	{1,1,1,1,1,1,1,1,1,1 , 1,1,1,1,0,1,1,1,1,1 , 1,1,1,1,1,1,1,1,1,1 , 1,1,1,1,1,1,1,1,1,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,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},
};

/*****************
ゲームの基本処理
*****************/
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
						 LPSTR lpCmdLine, int nCmdShow )
{
	int Key ;
	// 移動する前のプレイヤーの位置を保存
	ChangeWindowMode(true);

	if( DxLib_Init() == -1 )	// DXライブラリ初期化処理
	{
		 return -1;				// エラーが起きたら直ちに終了
	}

	
	SetDrawScreen( DX_SCREEN_BACK ) ;		// 描画先画面を裏画面にセット

	// グラフィックのロード
	LoadDivGraph("CharGraph6.png",6,3,2,32,64,image);		//キャラクターの描画
	LoadDivGraph("MapGraph1.png",4,4,1,32,32,chip);			//MAPの描画

	
	PlayerX = 50 ;			// キャラクターの初期データをセット
	PlayerY = 300 ;
	JumpPower = 0 ;

	/********************
	 ここからループ開始
	 *******************/
	while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 )
	{
		
		Key = GetJoypadInputState( DX_INPUT_KEY_PAD1 ) ;	// キー入力取得
		/********
		移動処理
		********/

		if(( Key & PAD_INPUT_RIGHT ) || ( Key & PAD_INPUT_LEFT ))
		{
			move = 1.0f;
		}

		if( Key & PAD_INPUT_RIGHT )// →で右に進む
		{
			PlayerX += (int)4*move ;
		}
		if( Key & PAD_INPUT_LEFT )// ←で左に進む
		{
			PlayerX -= (int)4*move ;	
		}

		/************
		ジャンプ処理
		************/
		if(JumpFlag == true)
		{
			y_temp = PlayerY;
			PlayerY +=(PlayerY-y_prev) + 1;
			y_prev = y_temp;
			if(PlayerY == 360)
				JumpFlag = false;
		}
		if(CheckHitKey(KEY_INPUT_SPACE) == 1 && JumpFlag == false)
		{
			JumpFlag = true;
			y_prev = PlayerY;
			PlayerY = PlayerY-20;
		}
		/******************
		アニメーション処理
		******************/

		if( Key & PAD_INPUT_RIGHT )		//→キーが押されていて、カウントが0より大きい場合
		{								//カウントを0にしてから1ずつ足していく
			if(CountX < 0)
				CountX = 0;
				++CountX;
		}
		if( Key & PAD_INPUT_LEFT )		//←キーが押されていて、カウントが0より小さい場合
		{								//カウントを0にしてから1ずつ引いていく
			if(CountX > 0)
				CountX = 0;
				--CountX;
		}
		
		ix = abs(CountX)%30/10;			//添字用変数にカウント数から添字を求め代入する

		if(CountX > 0)					//添字用変数にキャラの先頭添字番号を足してループ範囲を指定する(右向き)
		{
			ix += 0;
			result = ix;
		}
		else if(CountX < 0)				//添字用変数にキャラの先頭添字番号を足してループ範囲を指定する(左向き)
		{
			ix += 3;
			result = ix;
		}

		if((Key & PAD_INPUT_LEFT) &&(Key & PAD_INPUT_RIGHT))	//何も押してない時はカウント数を0に戻し、初期化
		{
			CountX = 0;
		}
		/********
		ここまで
		********/


		/********
		衝突判定
		********/

		if(Map[PlayerY/32][PlayerX/32+1]==1)	//右の当たり判定
		{
			PlayerX -= (int)4*move ;
		}
		if(Map[PlayerY/32][PlayerX/32-1]==1)	//左の当たり判定
		{
			PlayerX += (int)4*move ;
		}
		if(Map[PlayerY/32-1][PlayerX/32]==1)	//上の当たり判定
		{
			PlayerY += (int)4*move ;
		}
		if(Map[PlayerY/32+1][PlayerX/32]==1)	//下の当たり判定
		{
			PlayerY -= (int)4*move ;
		}



		
		ClearDrawScreen() ;	// 画面を初期化する

		for(int y = 0; y<15; y++)					//マップの描画
		{											//縦15ループ
			for(int x = 0; x < 20; x++)				//横20ループ
			{
				DrawGraph(x * 32, y * 32, chip [Map[y][x]],TRUE);
			}
		}

			DrawGraph( PlayerX , PlayerY , image[result] , TRUE ) ;	// プレイヤーを描画する
		
		ScreenFlip() ;		// 裏画面の内容を表画面に反映させる
	}
/****************
ゲームの終了処理
****************/
	DxLib_End() ;				// DXライブラリ使用の終了処理

	return 0 ;					// ソフトの終了
}

Re: DXライブラリ 地形との衝突判定

Posted: 2014年9月02日(火) 11:57
by softya(ソフト屋)
こういうのは感覚的に分かりやすくしないと、なかなかバグが取れません。
当たり判定を可視化してみたので、何処が悪いか考えてみてください。
なお、グラフィックデータを必要とするものは返事がつきづらいので、DrawBoxなどで代用してみてくださいね。

コード:

#include "DxLib.h"

/************************
変数や関数、構造体の指定
************************/
#define SCREEN_WIDTH    (640)           //画面の横の大きさ
#define SCREEN_HEIGT    (480)           //画面の縦の大きさ
#define MAP_PIXEL_WIDTH (1280)          //マップの横のピクセル数
#define MAP_PIXEL_HEIGHT (480)          //マップの縦のピクセル数
#define CHIP_SIZE   (32)                //チップサイズ
#define MAP_WIDTH   (MAP_PIXEL_WIDTH / CHIP_SIZE)   //マップの横の大きさ
#define MAP_HEIGHT  (MAP_PIXEL_HEIGHT / CHIP_SIZE)  //マップの縦の大きさ

typedef struct {
	int x, y, img;
} ch_t;


int chip[4];                        //マップチップの指定
int image[6];                       //グラフィックハンドルの指定
int PlayerX , PlayerY ;             //プレイヤー変数
int y_prev = 0, y_temp = 0;
int JumpPower ;                     //ジャンプ用変数
int CountX = 0;                     //アニメーション用カウント変数
int ix = 0, result = 0;             //アニメーション用添字変数
float move = 1.0f;
bool JumpFlag = false;

int Map[15] [40] = {                //マップデータ
	{2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
	{2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
	{2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
	{2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 3, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
	{2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
	{2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
	{2, 2, 2, 2, 2, 2, 2, 2, 1, 1 , 1, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
	{2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},

	{2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 1, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
	{2, 2, 2, 2, 2, 2, 3, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
	{2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 1, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2 , 2, 2, 2, 2, 2, 2, 2, 2, 2, 2},
	{1, 1, 1, 1, 1, 1, 1, 1, 1, 1 , 1, 1, 1, 1, 0, 1, 1, 1, 1, 1 , 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 , 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, 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},
};

/*****************
ゲームの基本処理
*****************/
int WINAPI WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
                    LPSTR lpCmdLine, int nCmdShow ) {
	int Key ;
	// 移動する前のプレイヤーの位置を保存
	ChangeWindowMode( true );

	if( DxLib_Init() == -1 ) {  // DXライブラリ初期化処理
		return -1;             // エラーが起きたら直ちに終了
	}


	SetDrawScreen( DX_SCREEN_BACK ) ;       // 描画先画面を裏画面にセット

	// グラフィックのロード
	LoadDivGraph( "CharGraph6.png", 6, 3, 2, 32, 64, image ); //キャラクターの描画
	LoadDivGraph( "MapGraph1.png", 4, 4, 1, 32, 32, chip ); //MAPの描画


	PlayerX = 50 ;          // キャラクターの初期データをセット
	PlayerY = 300 ;
	JumpPower = 0 ;

	/********************
	 ここからループ開始
	 *******************/
	while( ProcessMessage() == 0 && CheckHitKey( KEY_INPUT_ESCAPE ) == 0 ) {

		Key = GetJoypadInputState( DX_INPUT_KEY_PAD1 ) ;    // キー入力取得
		/********
		移動処理
		********/

		if( ( Key & PAD_INPUT_RIGHT ) || ( Key & PAD_INPUT_LEFT ) ) {
			move = 1.0f;
		}

		if( Key & PAD_INPUT_RIGHT ) { // →で右に進む
			PlayerX += ( int )4 * move ;
		}
		if( Key & PAD_INPUT_LEFT ) { // ←で左に進む
			PlayerX -= ( int )4 * move ;
		}

		/************
		ジャンプ処理
		************/
		if( JumpFlag == true ) {
			y_temp = PlayerY;
			PlayerY += ( PlayerY - y_prev ) + 1;
			y_prev = y_temp;
			if( PlayerY == 360 )
				JumpFlag = false;
		}
		if( CheckHitKey( KEY_INPUT_SPACE ) == 1 && JumpFlag == false ) {
			JumpFlag = true;
			y_prev = PlayerY;
			PlayerY = PlayerY - 20;
		}
		/******************
		アニメーション処理
		******************/

		if( Key & PAD_INPUT_RIGHT ) {   //→キーが押されていて、カウントが0より大きい場合
			//カウントを0にしてから1ずつ足していく
			if( CountX < 0 )
				CountX = 0;
			++CountX;
		}
		if( Key & PAD_INPUT_LEFT ) {    //←キーが押されていて、カウントが0より小さい場合
			//カウントを0にしてから1ずつ引いていく
			if( CountX > 0 )
				CountX = 0;
			--CountX;
		}

		ix = abs( CountX ) % 30 / 10;   //添字用変数にカウント数から添字を求め代入する

		if( CountX > 0 ) {              //添字用変数にキャラの先頭添字番号を足してループ範囲を指定する(右向き)
			ix += 0;
			result = ix;
		} else if( CountX < 0 ) {       //添字用変数にキャラの先頭添字番号を足してループ範囲を指定する(左向き)
			ix += 3;
			result = ix;
		}

		if( ( Key & PAD_INPUT_LEFT ) && ( Key & PAD_INPUT_RIGHT ) ) { //何も押してない時はカウント数を0に戻し、初期化
			CountX = 0;
		}
		/********
		ここまで
		********/

		ClearDrawScreen() ; // 画面を初期化する

		for( int y = 0; y < 15; y++ ) {             //マップの描画
			//縦15ループ
			for( int x = 0; x < 20; x++ ) {         //横20ループ
				DrawGraph( x * 32, y * 32, chip [Map[y][x]], TRUE );
				if( Map[y][x] == 1 ) {
					DrawBox( x*32, y*32, x*32+32, y*32+32, GetColor(255,255,255), TRUE );
				} else if( Map[y][x] == 2 ) {
				//	DrawBox( x*32, y*32, x*32+32, y*32+32, GetColor(255,0,0), TRUE );
				}
			}
		}

		/********
		衝突判定
		********/

		if( Map[PlayerY / 32][PlayerX / 32 + 1] == 1 ) { //右の当たり判定
			int posX = PlayerX + 32;
			int posY = PlayerY;
			DrawBox( posX, posY, posX+32, posY+32, GetColor(255,0,0), FALSE );
			PlayerX -= ( int )4 * move ;
		}
		if( Map[PlayerY / 32][PlayerX / 32 - 1] == 1 ) { //左の当たり判定
			int posX = PlayerX - 32;
			int posY = PlayerY;
			DrawBox( posX, posY, posX+32, posY+32, GetColor(255,0,0), FALSE );
			PlayerX += ( int )4 * move ;
		}
		if( Map[PlayerY / 32 - 1][PlayerX / 32] == 1 ) { //上の当たり判定
			int posX = PlayerX;
			int posY = PlayerY - 32 ;
			DrawBox( posX, posY, posX+32, posY+32, GetColor(255,0,0), FALSE );
			PlayerY += ( int )4 * move ;
		}
		if( Map[PlayerY / 32 + 1][PlayerX / 32] == 1 ) { //下の当たり判定
			int posX = PlayerX;
			int posY = PlayerY + 32 ;
			DrawBox( posX, posY, posX+32, posY+32, GetColor(255,0,0), FALSE );
			PlayerY -= ( int )4 * move ;
		}





		DrawGraph( PlayerX , PlayerY , image[result] , TRUE ) ; // プレイヤーを描画する
		DrawBox( PlayerX, PlayerY, PlayerX+32, PlayerY+32, GetColor(0,0,255), TRUE );

		ScreenFlip() ;      // 裏画面の内容を表画面に反映させる
	}
	/****************
	ゲームの終了処理
	****************/
	DxLib_End() ;               // DXライブラリ使用の終了処理

	return 0 ;                  // ソフトの終了
}