ページ 11

当たり判定が認識されません。(初学者)

Posted: 2017年4月09日(日) 19:02
by keito94
当たり判定を実装しているつもりなのですが、何故か当たり判定が認識せず、壁を素通りできてしまいます。どうすれば当たり判定が認識してくれるでしょうか?

Mapping.h

コード:

#pragma once
#include "fmfmap.h"
//マップ描画エンジンのオブジェクトクラスを宣言
extern CFmfMap MapObj;
//ビットカウントの宣言。
extern int BitCount;
const int MAP_CELL = 16;
Collision.h

コード:

#pragma once
class CCollision {
	float OffsetL, OffsetU, OffsetR, OffsetD;
	POINT mPt[8];
	int ColType;
public:
	CCollision(POINT pt[], float offset_l, float offset_u, float offset_r, float offset_d, int col_type);
	void Init();
	void GetMove(float* myx, float* myy, float* addx, float* addy);
	POINT CheckMap(int x, int y);
	void GetXPosition(float* myx, float* myy, float* addx, float* addy);
};
Collision.cpp

コード:

#include "Main.h"
#include "Mapping.h"
#include "Collision.h"

CCollision::CCollision(POINT pt[], float offset_l, float offset_u, float offset_r, float offset_d, int col_type)
	: OffsetL(offset_l), OffsetU(offset_u), OffsetR(offset_r), OffsetD(offset_d), ColType(col_type){
	Init();
	for (int i = 0; i < 8; i++)
	{
		mPt[i].x = pt[i].x;
		mPt[i].y = pt[i].y;
	}
}

void CCollision::Init(){
	ZeroMemory(mPt, sizeof(mPt));
}

POINT CCollision::CheckMap(int x, int y){
	POINT pt[] ={	
		{ x + mPt[0].x,	y + mPt[0].y },//左上
		{ x + mPt[1].x,	y + mPt[1].y },//上真ん中
		{ x + mPt[2].x,	y + mPt[2].y },//右上

		{ x + mPt[3].x,	y + mPt[3].y },//左真ん中
		{ x + mPt[4].x,	y + mPt[4].y },//右真ん中

		{ x + mPt[5].x,	y + mPt[5].y },//左下
		{ x + mPt[6].x,	y + mPt[6].y },//下真ん中
		{ x + mPt[7].x,	y + mPt[7].y },//右下
	};

	POINT res = { x, y };
	DWORD cwidth = MapObj.GetChipWidth();
	DWORD cheight = MapObj.GetChipHeight();
	for (int i = 0; i < 8; i++){
		int index = MapObj.GetValue(0, pt[i].x / MAP_CELL, pt[i].y / MAP_CELL);
		int src_x = (index % BitCount) * cwidth;
		int src_y = (index / BitCount) * cheight;
		if(src_x != 0,src_y != 0){
			res.x = pt[i].x / MAP_CELL;//壁の座標を代入
			res.y = pt[i].y / MAP_CELL;
			return res;//壁の座標を返す
		}
	}
	res.x = -1;//ここまで来たら当たっていないということ
	res.y = -1;
	return res;
}

void CCollision::GetXPosition(float* myx, float* myy, float* addx, float* addy) {
	float newx;
	float tempx = *myx;
	float tempaddx = *addx;

	newx = tempx + tempaddx;
	POINT block = CheckMap((int)newx, *myy);
	if (block.x == -1) {
		*myx = newx;
	}
	else {
		if (tempaddx > 0) {
			*myx = (float)((block.x - 1) * 32 + 16 + OffsetR - 0.1f);
		}
		else {
			*myx = (float)((block.x + 1) * 32 + 16 + OffsetL);
		}
		*addx = 0;//当たっているので移動させない。
	}

}

void CCollision::GetMove(float* myx, float* myy, float* addx, float* addy) {
	GetXPosition(myx, myy, addx, addy);
}
Stage.h

コード:

#pragma once
class CStage {
public:
	void Draw();
};
Stage.cpp

コード:

#include "Main.h"
#include "Stage.h"
#include "Mapping.h"
void CStage::Draw() {
	DWORD cwidth = MapObj.GetChipWidth();
	DWORD cheight = MapObj.GetChipHeight();
	for (int y = 0; y < 15; y++) {
		for (int x = 0; x < 20; x++) {
			int src_x, src_y, index;
			index = MapObj.GetValue(0, x, y);
			src_x = (index % BitCount) * cwidth;
			src_y = (index / BitCount) * cheight;
			DrawRectGraph((int)(x*MAP_CELL), (int)(y*MAP_CELL), src_x, src_y, MAP_CELL, MAP_CELL, Game->MapGraph, TRUE, FALSE);
		}
	}
}

Re: 当たり判定が認識されません。(初学者)

Posted: 2017年4月09日(日) 19:55
by みけCAT
オフトピック
keito94 さんが書きました:どうすれば当たり判定が認識してくれるでしょうか?
デバッグをして正しいコードに修正すればいいでしょう。 (脊髄反射)

Re: 当たり判定が認識されません。(初学者)

Posted: 2017年4月09日(日) 20:03
by みけCAT
keito94 さんが書きました:

コード:

	for (int i = 0; i < 8; i++){
		int index = MapObj.GetValue(0, pt[i].x / MAP_CELL, pt[i].y / MAP_CELL);
		int src_x = (index % BitCount) * cwidth;
		int src_y = (index / BitCount) * cheight;
		if(src_x != 0,src_y != 0){
			res.x = pt[i].x / MAP_CELL;//壁の座標を代入
			res.y = pt[i].y / MAP_CELL;
			return res;//壁の座標を返す
		}
	}
  • MapObj.GetValueが0, 1, 2程度の小さい値を返す
  • BitCountが16とか32程度の大きな値
と仮定すると、indexもBitCountもint型なので割り算の小数部分は切り捨てられてindex / BitCountは0になり、0にcheightを掛けたsrc_yも0になります。
さらに、条件式src_x != 0,src_y != 0で使用されているコンマ演算子の意味は「左辺を評価してその結果を捨てた後、右辺を評価した値を返す」なので、
src_xの値はチェックされません。
その結果、8回全てこの条件を満たしてsrc_y == 0の場合、当たっていないとみなされるでしょう。
ただし、本当の実装が提示されていないので、この仮定が正しいかはわかりません。

Re: 当たり判定が認識されません。(初学者)

Posted: 2017年4月09日(日) 20:13
by keito94
>>みけCATさん、つまりこういうことですね?

コード:

	for (int i = 0; i < 8; i++){
		int index = MapObj.GetValue(0, pt[i].x / MAP_CELL, pt[i].y / MAP_CELL);
		int src_x = (index % BitCount) * cwidth;
		int src_y = (index / BitCount) * cheight;
		if (src_x != 0 && src_y != 0){
			res.x = pt[i].x / MAP_CELL;//壁の座標を代入
			res.y = pt[i].y / MAP_CELL;
			return res;//壁の座標を返す
		}
	}
Collision.cppの58行目にブレイクポイントをかけてみたところ、常にこんな感じでした。
このバグをどうやって直せばいいのでしょうか?

コード:

-		block	{x=-1 y=-1}	tagPOINT
		x	-1	long
		y	-1	long
		block.x	-1	long


Re: 当たり判定が認識されません。(初学者)

Posted: 2017年4月09日(日) 20:18
by みけCAT
keito94 さんが書きました:>>みけCATさん、つまりこういうことですね?
コンマ演算子を論理AND演算子にしたのはわかりましたが、indexやBitCountの仕様の説明も使い方の変更も無いようですね。
よくわからないので、「こういうこと」とはどういうことか日本語で説明していただけますか?
keito94 さんが書きました:Collision.cppの58行目にブレイクポイントをかけてみたところ、常にこんな感じでした。
このバグをどうやって直せばいいのでしょうか?
まずはCollision.cppの40行目にブレイクポイントをかけて各変数の値をチェックするといいかもしれません。

Re: 当たり判定が認識されません。(初学者)

Posted: 2017年4月09日(日) 20:48
by keito94
みけCAT さんが書きました: コンマ演算子を論理AND演算子にしたのはわかりましたが、indexやBitCountの仕様の説明も使い方の変更も無いようですね。
indexと言うのは、マップチップのパラメータを表す変数です。
BitCountと言うのはマップエディタのパーツのデータ量を表す変数です。
こういうことというのは、AND演算子に変更したということですよ。
みけCATさんに言われたとおりにして、デバックをしたりマップデータの編集を行いつつ、ソースコードを以下のようにしたら治りました。

コード:

POINT res = { x, y };
	DWORD cwidth = MapObj.GetChipWidth();
	DWORD cheight = MapObj.GetChipHeight();
	for (int i = 0; i < 8; i++){
		int index = MapObj.GetValue(1, pt[i].x / MAP_CELL, pt[i].y / MAP_CELL);
		int src_x = (index % BitCount) * cwidth;
		int src_y = (index / BitCount) * cheight;
		if (src_x == 0 && src_y == 0){
			res.x = pt[i].x / MAP_CELL;//壁の座標を代入
			res.y = pt[i].y / MAP_CELL;
			return res;//壁の座標を返す
		}
	}