坂道の当たり判定を作っています。

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
アバター
keito94
記事: 264
登録日時: 2年前
連絡を取る:

坂道の当たり判定を作っています。

#1

投稿記事 by keito94 » 2年前

このサイトの関数をベースにして、

コード:

//seg1,2(当たり判定)が線分、outT1,2が線分の内分比、outPosが交点(出力用)
bool CCollision::ColSegments(Segment &seg1, Segment &seg2, float* outT1, float* outT2, Vector2* outPos) {
	Vector2 v = seg2.s - seg1.s;
	float Crs_v1_v2 = Vector2Cross(&seg1.v, &seg2.v);
	if (Crs_v1_v2 == 0.0F) {
		return false;
	}

	float Crs_v_v1 = Vector2Cross(&v, &seg1.v);
	float Crs_v_v2 = Vector2Cross(&v, &seg2.v);

	float t1 = Crs_v_v2 / Crs_v1_v2;
	float t2 = Crs_v_v1 / Crs_v1_v2;

	if (outT1)
		*outT1 = Crs_v_v2 / Crs_v1_v2;
	if (outT2)
		*outT2 = Crs_v_v1 / Crs_v1_v2;

	const float eps = 0.00001f;
	if (t1 + eps < 0 || t1 - eps > 1 || t2 + eps < 0 || t2 - eps > 1) {
		// 交差していない
		return false;
	}
	//出力用。
	if (outPos)
		*outPos = seg1.s + seg1.v * t1;

	return true;
}
坂道の当たり判定を作っています。なんとかそれらしいものはできましたが、上りの部分でガクガクしながら移動してしまいます。
現在考えている線分を使った坂道のアルゴリズムは、
①坂道のブロックがあるかどうかを確認
②坂道の線分を設定
③プレイヤーの線分を設定
④プレイヤーの線分と坂道の線分が交差していたら座標を返す
⑤さきほど返した座標にめり込み防止処理をしたのがプレイヤーの座標。
アルゴリズムは間違っているのかもしれません…。
何かアルゴリズムの改善案や、アルゴリズムの問題点などを上げてくれないのでしょうか?
当たり判定関係のプログラムは以下のとおりです。
ヘッダーファイル

コード:

	//坂道の当たり判定
	POINT CheckSlope(int x, int y,Segment& Slope,int layernum,int slopecond,int addy = 0);
	//坂道のブロックとしての当たり判定。
	POINT CheckSlopeBlock(int x, int y,int layernum,int addy=0);
	//ブロックの左上の点を取る。(坂道用)
	Vector2 GetMatrixPos(float myx, float myy);
	//seg1,2が線分、outT1,2が線分の内分比、outPosが交点(出力用)
	bool ColSegments(Segment &seg1, Segment &seg2, float* outT1 = 0, float* outT2 = 0, Vector2* outPos = 0);
	//横の衝突判定
	void GetXPosition(float* myx, float* myy, float* addx, float* addy);
	//縦の衝突判定
	void GetYPosition(float* myx, float* myy, float* addx, float* addy, int* jcount, bool* gflag);
プログラム(ヘッダーの部分のみ)

コード:

Vector2 CCollision::GetMatrixPos(float myx, float myy) {
	DWORD cwidth = Game->MapData().GetChipWidth();
	DWORD cheight = Game->MapData().GetChipHeight();
	int x = (int)(myx / cwidth);
	int y = (int)(myy / cheight);
	return Vector2((float)x * cwidth, (float)y * cheight);
}
//省略。
POINT CCollision::CheckSlopeBlock(int x, int y, int layernum, int addy) {
	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 = Game->MapData().GetChipWidth();
	DWORD cheight = Game->MapData().GetChipHeight();
	for(int i = 0; i < 8; i++){
		int index = Game->MapData().GetValue(layernum , pt[i].x / cwidth, pt[i].y / cheight);
		int src_x = (index % Game->GetBitCount()) * cwidth;
		int src_y = (index / Game->GetBitCount()) * cheight;
		//坂道の当たり判定がない時は床の当たり判定を行う。
		if (src_x == 0 && src_y == 0) {
			res.x = pt[i].x / cwidth; // 壁の座標を代入
			res.y = pt[i].y / cheight;
			return res; // 壁の座標を返す
		}
	}
	res.x = -1;
	res.y = -1;
	return res;
}

POINT CCollision::CheckSlope(int x, int y, Segment& Slope, int layernum,int slopecond,int addy) {
	//当たり判定。
	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 },//右下
	};
	DWORD cwidth = Game->MapData().GetChipWidth();
	DWORD cheight = Game->MapData().GetChipHeight();
	Segment Player;
	switch (slopecond) {
	//1は下の下り坂。
	case 1:
		Player.s = { (float)pt[2].x,(float)pt[2].y };
		Player.v = { (float)pt[5].x,(float)pt[5].y };
		break;
	//2は上の上り坂。
	case 2:
		Player.s = { (float)pt[7].x,(float)pt[7].y };
		Player.v = { (float)pt[0].x,(float)pt[0].y };
		break;
	//3は上の上り坂。
	case 3:
		Player.s = { (float)pt[5].x,(float)pt[5].y };
		Player.v = { (float)pt[2].x,(float)pt[2].y };
		break;
	//0は下の上り坂。(0以外は想定していないのだ。)
	default:
		Player.s = { (float)pt[0].x,(float)pt[0].y };
		Player.v = { (float)pt[7].x,(float)pt[7].y };
		break;
	}
	POINT res;
	//デバッグ用。
	float T1;
	float T2;
	Vector2 Vres;
	if (Slope.s.x >= Player.v.x && Player.v.x < Slope.v.x || Slope.s.x <= Player.v.x && Player.v.x > Slope.v.x) {
		if (ColSegments(Slope,Player,&T1,&T2,&Vres)) {
			res.x = (int)Vres.x;
			res.y = (int)Vres.y;
		}
	}
	//ここまで来たら衝突していないということ。
	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, (int)*myy);
	//X座標が衝突していなかったら。
	if (block.x == -1) {
		*myx = newx;
	}
	//X座標が坂道のレイヤーにいたら。
	else if(block.x == -2){
		int Layer = GetChipLayerNum((int)newx, (int)*myy);
		Segment Slope;
		//スロープの条件分離。
		int SlopeCond;
		switch (Layer) {
		case 2:
			Slope.s = GetMatrixPos(newx, *myy - 16.0f);
			Slope.v = GetMatrixPos(newx + 16.0f, *myy);
			SlopeCond = 0;
			break;
		}
		POINT slopeblock = CheckSlopeBlock((int)newx, (int)*myy, Layer);
		POINT slope = CheckSlope((int)newx, (int)*myy, Slope, Layer,SlopeCond);
		//-2を返したら、ブロックとして扱う。
		if (slope.x == -1) {
			*myx = newx;
		}
		else if (slope.x == -2) {
			//ブロックとしての当たり判定。
			if (tempaddx > 0) {
				*myx = (float)((slopeblock.x - 1) * 16 + 8 + OffsetR - 0.1f);
			}
			else {
				*myx = (float)((slopeblock.x + 1) * 16 + 8 + OffsetL + 0.1f);
			}
			*addx = 0;
		}
		else {
			//めり込み防止をする。
		}
	}
	//ブロックの当たり判定。
	else {
		if (tempaddx > 0) {
			*myx = (float)((block.x - 1) * 16 + 8 + OffsetR - 0.1f);
		}
		else {
			*myx = (float)((block.x + 1) * 16 + 8 + OffsetL + 0.1f);
		}
		*addx = 0;//当たっているので移動させない。
	}
}

void CCollision::GetYPosition(float* myx, float* myy, float* addx, float* addy, int* jcount, bool* gflag) {
	float tempaddx = *addx;
	float newy = *myy + *addy;
	POINT block = CheckMap((int)*myx, (int)newy, *addy);
	//Y座標が衝突していなかったら。
	if (block.y == -1) {
		*myy = newy;
		*gflag = false;
	}
	//Y座標が坂道のレイヤーにいたら。
	else if(block.y == -2){
		*addy = 0;
		int Layer = GetChipLayerNum((int)*myx, (int)newy);
		Segment Slope;
		//スロープの条件分離。
		int SlopeCond;
		switch (Layer) {
		case 2:
			Slope.s = GetMatrixPos(*myx, newy - 16.0f);
			Slope.v = GetMatrixPos(*myx + 16.0f, newy);
			SlopeCond = 0;
			break;
		}
		POINT slopeblock = CheckSlopeBlock((int)*myx, (int)newy, Layer);
		POINT slope = CheckSlope((int)*myx, (int)newy, Slope, SlopeCond, Layer);
		//-2を返したら、ブロックとして扱う。
		if (slope.y == -1) {
			*gflag = true;
		}
		else if (slope.y == -2) {
			//ブロックとしての当たり判定。
		}
		else {
			*addy = slope.y;
		}
	}
	//ブロックの当たり判定。
	else {
		if (*addy < 0) {
			*myy = (float)((block.y + 1) * 16 + 8 + OffsetU + 0.1f);
		}
		else {
			*myy = (float)((block.y - 1) * 16 + 8 + OffsetD - 0.1f);
			*jcount = 0;
			*gflag = true;
		}
		*addy = 0;
	}
}
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
keito94
記事: 264
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#2

投稿記事 by keito94 » 2年前

少し誤表記がありました。
GetXPositionとGetYPositionの

コード:

		case 2:
			Slope.s = GetMatrixPos(newx, *myy - 16.0F);
			Slope.v = GetMatrixPos(newx + 16.0F, *myy);
			SlopeCond = 0;
			break;
の部分を

コード:

		case 2:
			Slope.s = GetMatrixPos(newx, *myy + 16.0F);
			Slope.v = GetMatrixPos(newx + 16.0F, *myy);
			SlopeCond = 0;
			break;
になおしてください。
また現在確認されている不具合としては、坂道の当たり判定をしていると、空中にいるとみなされていることです。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#3

投稿記事 by purin52002 » 2年前

正直ソースが多すぎて読むのが面倒です。
不具合が出ていそうな箇所をあぶりだしてほしいです。

そこでデバッグですよ!
いまこそデバッグトレーニングの成果を試すときですよ!

とりあえず坂道のアタリ判定をしているときに空中にいるとみなされる原因を探してみましょう。
  1. 判定している箇所を探す。
  2. 空中にいるとみなす計算を探す。
  3. その計算に使われている変数を探す。
  4. 変数を設定する計算を探す。
を繰り返してください。
いつか「お前、その計算結果はおかしいだろ^p^」となる処理が見つかるはずです。

原因となる処理さえ見つけられればあとは何とかなったりならなかったり、、、
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

アバター
keito94
記事: 264
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#4

投稿記事 by keito94 » 2年前

purin52002さん、いつもお世話になっております。
自分でデバッグして、原因を突き止めてから、自分で症状を改善させましたが、まだ完成ではありません。
なぜなら、このアルゴリズムで、else if(tempaddx != 0)のところへ来ないで、ブロックとして扱われてしまうからです。

コード:

	if (Slope.s.x >= Player.v.x && Player.v.x < Slope.v.x || Slope.s.x <= Player.v.x && Player.v.x > Slope.v.x) {
		if (ColSegments(Slope,Player,&T1,&T2,&Vres)) {
			res.x = (int)x-Vres.x;
			res.y = (int)y-Vres.y;
		}
	}
	else {
		//何故かここへ来る。
		res.x = -2;
		res.y = -2;
		return res;
	}
elseだと、動いてなくても空中に浮かんでしまう上に、何も動かないので、addxが0以外のときのみY座標も動かないようにしています。その為、

コード:

        else {
            *addy = slope.y;
        }
の部分を

コード:

		else if (tempaddx != 0){
			*gflag = true;
			*myy = slope.y;
		}
に修正してください。
オフトピック
やっぱり、坂道の判定はめんどくさい…。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#5

投稿記事 by purin52002 » 2年前

申し訳ないのですが、理解力が人一倍ないので一つ一つ確認していきます^^;
keito94 さんが書きました:

コード:

	if (Slope.s.x >= Player.v.x && Player.v.x < Slope.v.x || Slope.s.x <= Player.v.x && Player.v.x > Slope.v.x) {
		if (ColSegments(Slope,Player,&T1,&T2,&Vres)) {
			res.x = (int)x-Vres.x;
			res.y = (int)y-Vres.y;
		}
	}
	else {
		//何故かここへ来る。
		res.x = -2;
		res.y = -2;
		return res;
	}
これは最初のプログラムの85行目~の修正ということであってますか?
keito94 さんが書きました:

コード:

        else {
            *addy = slope.y;
        }
の部分を

コード:

		else if (tempaddx != 0){
			*gflag = true;
			*myy = slope.y;
		}
これは185行目~であってますか?


すごい初歩的なことかもしれませんが、キャラクター(?)の座標基準ってどうしていますか?
画像で描画するとして、右下の点を座標基準とした場合はx座標を若干修正する必要がありそうななさそうな、、、
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

アバター
keito94
記事: 264
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#6

投稿記事 by keito94 » 2年前

そうです^^
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#7

投稿記事 by purin52002 » 2年前

keito94 さんが書きました: なぜなら、このアルゴリズムで、else if(tempaddx != 0)のところへ来ないで、ブロックとして扱われてしまうからです。
これは元のプログラム179行目~のことでいいんでしょうか?

コード:

 //-2を返したら、ブロックとして扱う。
        if (slope.y == -1) {
            *gflag = true;
        }
        else if (slope.y == -2) {
            //ブロックとしての当たり判定。
        }
        else {
            *addy = slope.y;
        }
これを修正して

コード:

 //-2を返したら、ブロックとして扱う。
        if (slope.y == -1) {
            *gflag = true;
        }
        else if (slope.y == -2) {
            //ブロックとしての当たり判定。
        }
       else if (tempaddx != 0){
            *gflag = true;
            *myy = slope.y;
        }
となったんですよね?

上記の投稿からすると、「tempaddxが0以外の場合の処理を優先する」のかな?
だとするとelse if の順番を変えてみてはどうでしょう。

コード:

 //-2を返したら、ブロックとして扱う。
        if (slope.y == -1) {
            *gflag = true;
        }
        else if (tempaddx != 0){//こっちが先
            *gflag = true;
            *myy = slope.y;
        }
        else if (slope.y == -2) {
            //ブロックとしての当たり判定。
        }
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

アバター
keito94
記事: 264
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#8

投稿記事 by keito94 » 2年前

purin52002 さんが書きました: だとするとelse if の順番を変えてみてはどうでしょう。
言われたとおりにしてみて見ましたが、Y座標に-2が代入されてしまうバグを発見したので、以下のように修正してみました。

コード:

		else if (tempaddx != 0 && slope.y != -2) {
			*gflag = true;
			*myy = slope.y;
		}
ついでに、GetXPositionの部分に以下の修正を加えました。

コード:

		//-2を返したら、ブロックとして扱う。
		if (slope.x == -1) {
			*myx = newx;
		}
		else if (slope.x == -2) {
			if (tempaddx > 0) {
				*myx = (float)((slopeblock.x - 1) * 16 + 8 + OffsetR - 0.1f);
			}
			else {
				*myx = (float)((slopeblock.x + 1) * 16 + 8 + OffsetL + 0.1f);
			}
			*addx = 0;//当たっているので移動させない。
		}
		else {
			//めり込み防止をする。
			*myx = slope.x;
		}
これで、坂道の当たり判定らしきものはできましたが、線分の当たり判定で坂道を作っているのに、
未だに、-2が代入(ブロックとして判定)されたままで、上り坂の判定がカクカクしたままです。
どうすれば、ブロックとして判定されず、坂道として判定されるのでしょうか?
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#9

投稿記事 by purin52002 » 2年前

slope.xに-2が代入されてしまうということはslopeに値を代入するCheckSlope関数がうまく動いていないんだとおもいます。
keito94 さんが書きました: 自分でデバッグして、原因を突き止めてから、自分で症状を改善させましたが、まだ完成ではありません。
なぜなら、このアルゴリズムで、else if(tempaddx != 0)のところへ来ないで、ブロックとして扱われてしまうからです。

コード:

	if (Slope.s.x >= Player.v.x && Player.v.x < Slope.v.x || Slope.s.x <= Player.v.x && Player.v.x > Slope.v.x) {
		if (ColSegments(Slope,Player,&T1,&T2,&Vres)) {
			res.x = (int)x-Vres.x;
			res.y = (int)y-Vres.y;
		}
	}
	else {
		//何故かここへ来る。
		res.x = -2;
		res.y = -2;
		return res;
	}
おそらくこの部分だと思うのですが、ここら辺はデバッグしてみましたか?

Slope.s.x >= Player.v.x && Player.v.x < Slope.v.x || Slope.s.x <= Player.v.x && Player.v.x > Slope.v.x

この式で判定が行われているので
この式があっているか、
これらの変数に値を代入している部分はあっているかを確認してみましょう。
オフトピック
条件式が長いのは見づらいし予期せぬエラーの原因になったりします。
変数に代入してそれを比較するか、関数にまとめてしまってはどうでしょう?
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

アバター
keito94
記事: 264
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#10

投稿記事 by keito94 » 2年前

デバッグ用に条件式を変数に代入して、それを比較する方式にしてみたところ、式に間違いはないようです。
ですが、レイヤーの数値を獲得する部分に原因があるようです。

最初のプログラムから抜粋。

コード:

int CCollision::GetChipLayerNum(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 },//右下
	};
	DWORD cwidth = Game->MapData().GetChipWidth();
	DWORD cheight = Game->MapData().GetChipHeight();
	//for文で処理を行っているのは、当たり判定のレイヤー数が増えるかもしれないから。
	for (int i = 0; i <= MaxLayerNum; i++) {
		for (int j = 0; j < 8; j++) {
			int index = Game->MapData().GetValue(i + 2, pt[j].x / cwidth, pt[j].y / cheight);
			int src_x = (index % Game->GetBitCount()) * cwidth;
			int src_y = (index / Game->GetBitCount()) * cheight;
			//もしレイヤ番号に、衝突していたら。
			if (src_x == 0 && src_y == 0) {
				//レイヤー番号を返す。
				return i + 2;
			}
		}
	}
	//念のため。
	return 0;
}
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#11

投稿記事 by purin52002 » 2年前

最初のプログラムが見つけられませんでした^p^

このGetChipLayerNum関数に不具合があるということですよね?
値を返すのが25,30行目で、不具合が起きそうなところはsrc_x、src_yの部分ですね。

計算式が間違っているか、計算に使っているindexの値がおかしいかですね。
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

アバター
keito94
記事: 264
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#12

投稿記事 by keito94 » 2年前

デバッグして調べてみたところ、purinさんが指摘した部分に間違いはないどころか、
GetChipLayerNumが上り坂を示す25行が実行された後に30行が実行されているのを確認しました。
あと、GetChipLayerNumを最初のプログラムに追加してみてください。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#13

投稿記事 by purin52002 » 2年前

keito94 さんが書きました: GetChipLayerNumが上り坂を示す25行が実行された後に30行が実行されているのを確認しました。
return i+2 ; のあとにreturn 0 ; が呼ばれたってことですかね?
returnのあとにreturnが呼ばれたことがないのでわからないのですが、その場合どのような値が出力されるのでしょうか?(i+2?それとも0?)
purin52002 さんが書きました: 計算式が間違っているか、計算に使っているindexの値がおかしいかですね。
keito94 さんが書きました:デバッグして調べてみたところ、purinさんが指摘した部分に間違いはないどころか、
となると何が不具合の原因かちょっとわたしではわからないですね、、、^^;
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

アバター
keito94
記事: 264
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#14

投稿記事 by keito94 » 2年前

i+2が出力されたままつもりが、0が出力されてしまうということです。
おそらく原因はブロックとしての当たり判定にあると思われます。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#15

投稿記事 by purin52002 » 2年前

日本語力が低いのでできるだけわかりやすい文章でお願いします^p^;


「ブロックとしての当たり判定」というのがなんなのかわかりませんが、19行目の

int index = Game->MapData().GetValue(i + 2, pt[j].x / cwidth, pt[j].y / cheight);

で正しい値が取得できているでしょうか?
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

アバター
keito94
記事: 264
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#16

投稿記事 by keito94 » 2年前

i+2を出力した方のindexを調べてみたところ、正しい値が獲得できています。
purin52002 さんが書きました: 日本語力が低いのでできるだけわかりやすい文章でお願いします^p^;
ちょっとわかりにくかったですね…。
i+2を出力した後に、坂道のブロックにいるときにはi+2が出力されるはずなのに、何故か0を出力してしまう不具合というのが確認されました。

そして、return 0の部分では、indexの値が獲得されていないのがわかりました。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#17

投稿記事 by purin52002 » 2年前

keito94 さんが書きました: i+2を出力した後に、坂道のブロックにいるときにはi+2が出力されるはずなのに、何故か0を出力してしまう不具合というのが確認されました。
これは坂道ブロックに入った瞬間に0を出力するということですか?
それとも坂道ブロックに入った瞬間はi+2、そのご0が出力されるということですか?

keito94 さんが書きました: そして、return 0の部分では、indexの値が獲得されていないのがわかりました。
仮にreturn 0 ;にブレークポイントをつけてindexをウォッチしたなら、スコープを抜けているので値を見ることができません。
それとももしかしてreturn 0 ;を返す場合のindexの値が不定になるということだったり、、、?
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

アバター
keito94
記事: 264
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#18

投稿記事 by keito94 » 2年前

purin52002 さんが書きました: 坂道ブロックに入った瞬間はi+2、そのご0が出力されるということですか?
その通りです。
仮にreturn 0 ;にブレークポイントをつけてindexをウォッチしたなら、スコープを抜けているので値を見ることができません。
それとももしかしてreturn 0 ;を返す場合のindexの値が不定になるということだったり、、、?
そりゃそうでしたか…。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#19

投稿記事 by purin52002 » 2年前

坂道に入った瞬間だけ正しい値が出力されるとしたら、
  • 坂道判定で座標が修正される。->修正された座標では坂道判定にならない
  • 坂道判定に座標以外のパラメータが使われている。->一定時間以上いたら正しい値を返さない、一度だけ正しい値を返す。など(んなわけないか)
  • 小人さんが意地悪している^p^
これぐらいが私の思い付く原因ですね、、、
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

アバター
keito94
記事: 264
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#20

投稿記事 by keito94 » 2年前

purin52002 さんが書きました: 坂道判定で座標が修正される。->修正された座標では坂道判定にならない
その通りです!!
座標を代入させてみたら確かにありえない値を代入してました!!
どうやら交点ではなく、内分を出力させればいいようですが…。

コード:

	//式自体はあっているが…。レイヤーの数値獲得に原因がありそうだ。
	if (Slope.s.x >= Player.v.x && Player.v.x < Slope.v.x || Slope.s.x <= Player.v.x && Player.v.x > Slope.v.x) {
		PlayerCond = 1;
	}
	else {
		PlayerCond = 0;
	}

	if (PlayerCond != 0) {
		if (ColSegments(Slope,Player,&T1,&T2,&Vres)) {
			res.x = (int)x-T1;
			res.y = (int)y-T1;
			return res;
		}
	}
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
keito94
記事: 264
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#21

投稿記事 by keito94 » 2年前

座標に内分を引かせて、型を適切なものしたのですが、(CheckSlopeの部分をVector2にしてください)
何故か線分の判定が真になりません。坂道のブロックに入った瞬間だけ、i+2になる症状が全く改善しないんですよ…。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#22

投稿記事 by purin52002 » 2年前

線分の判定が真にならない。
これは、真になるであろうパラメータを与えても真にならないということですか?

だとすると(私は線分判定のアルゴリズムがよくわかっていないので)お手上げです^^;
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

アバター
keito94
記事: 264
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#23

投稿記事 by keito94 » 2年前

purin52002 さんが書きました: これは、真になるであろうパラメータを与えても真にならないということですか?
そ、そういうことではなくてですね…。
坂道のブロックにいると判定されているときに何故か真にならないということです。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#24

投稿記事 by purin52002 » 2年前

理解力ががが^p^

坂道ブロックにいるときは真と判定してほしいのに、真と判定されない。
という不具合だと思ったのですが違うのですか?
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

アバター
keito94
記事: 264
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#25

投稿記事 by keito94 » 2年前

そうです。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#26

投稿記事 by purin52002 » 2年前

keito94 さんが書きました:
purin52002 さんが書きました: これは、真になるであろうパラメータを与えても真にならないということですか?
そ、そういうことではなくてですね…。
坂道のブロックにいると判定されているときに何故か真にならないということです。
purin52002 さんが書きました:理解力ががが^p^

坂道ブロックにいるときは真と判定してほしいのに、真と判定されない。
という不具合だと思ったのですが違うのですか?
理解力がががががが^p^p^
ちょっと状況がわからなくなってしまったので詳しく説明してもらってもいいですか?
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

アバター
keito94
記事: 264
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#27

投稿記事 by keito94 » 2年前

簡単に説明すると、
  • ①坂道のブロックにプレイヤーが入る。(ここはOK)
  • ②坂道のブロックの種類を識別する。(i+2を返す部分)
  • ③坂道の線分とプレイヤーの線分が設定される。
  • ④坂道の線分が、プレイヤーの線分の終点の間なら、線分の判定を行い、線分と衝突していたら、めり込み防止をした座標を返す。
  • ⑤…はずだったのだが、④が誤作動を起こし、その巻き添えで②も誤作動を起こし、普通のブロックとして判定されてしまう。
でしょうか?
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#28

投稿記事 by purin52002 » 2年前

線分と線分が交差していたらtrueを返すのがColSegments関数で、
坂道とプレイヤーの線分が交差していたらColSegments関数にtrueを返してほしくて、
でもColSegments関数はfalseを返すし、
そのせいでブロック判定もうまくいかない。

ということですか?
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

アバター
keito94
記事: 264
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#29

投稿記事 by keito94 » 2年前

そういうことです!!
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
purin52002
記事: 235
登録日時: 2年前
連絡を取る:

Re: 坂道の当たり判定を作っています。

#30

投稿記事 by purin52002 » 2年前

purin52002 さんが書きました: 坂道とプレイヤーの線分が交差していたらColSegments関数にtrueを返してほしくて、
でもColSegments関数はfalseを返すし、
これはColSegments関数の不具合ということですか?
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

返信

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