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

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

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

#1

投稿記事 by keito94 » 7年前

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

コード:

//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
登録日時: 7年前
連絡を取る:

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

#2

投稿記事 by keito94 » 7年前

少し誤表記がありました。
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
登録日時: 7年前
連絡を取る:

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

#3

投稿記事 by purin52002 » 7年前

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

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

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

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

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

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

#4

投稿記事 by keito94 » 7年前

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
登録日時: 7年前
連絡を取る:

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

#5

投稿記事 by purin52002 » 7年前

申し訳ないのですが、理解力が人一倍ないので一つ一つ確認していきます^^;
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
登録日時: 7年前
連絡を取る:

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

#6

投稿記事 by keito94 » 7年前

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

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

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

#7

投稿記事 by purin52002 » 7年前

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
登録日時: 7年前
連絡を取る:

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

#8

投稿記事 by keito94 » 7年前

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
登録日時: 7年前
連絡を取る:

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

#9

投稿記事 by purin52002 » 7年前

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
登録日時: 7年前
連絡を取る:

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

#10

投稿記事 by keito94 » 7年前

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

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

コード:

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
登録日時: 7年前
連絡を取る:

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

#11

投稿記事 by purin52002 » 7年前

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

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

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

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

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

#12

投稿記事 by keito94 » 7年前

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

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

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

#13

投稿記事 by purin52002 » 7年前

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

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

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

#14

投稿記事 by keito94 » 7年前

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

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

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

#15

投稿記事 by purin52002 » 7年前

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


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

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

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

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

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

#16

投稿記事 by keito94 » 7年前

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

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

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

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

#17

投稿記事 by purin52002 » 7年前

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
登録日時: 7年前
連絡を取る:

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

#18

投稿記事 by keito94 » 7年前

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

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

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

#19

投稿記事 by purin52002 » 7年前

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

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

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

#20

投稿記事 by keito94 » 7年前

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
登録日時: 7年前
連絡を取る:

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

#21

投稿記事 by keito94 » 7年前

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

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

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

#22

投稿記事 by purin52002 » 7年前

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

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

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

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

#23

投稿記事 by keito94 » 7年前

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

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

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

#24

投稿記事 by purin52002 » 7年前

理解力ががが^p^

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

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

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

#25

投稿記事 by keito94 » 7年前

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

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

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

#26

投稿記事 by purin52002 » 7年前

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

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

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

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

#27

投稿記事 by keito94 » 7年前

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

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

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

#28

投稿記事 by purin52002 » 7年前

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

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

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

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

#29

投稿記事 by keito94 » 7年前

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

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

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

#30

投稿記事 by purin52002 » 7年前

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

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

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

#31

投稿記事 by keito94 » 7年前

違います違います!!
ColSegment自体は正しく動作しています!!
そして、修正が一つ…。
最初のプログラムの177行の部分を、

コード:

POINT slope = CheckSlope((int)*myx, (int)newy, Slope, Layer,SlopeCond);
に修正してください…。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

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

#32

投稿記事 by keito94 » 7年前

あの、ブログ見ましたけど…。
移動後の座標ではなく、現在の座標だったのですか!?
ボクも気づきませんでした…。
すいませんが、現在の座標ベースでの当たり判定のアルゴリズムを教えてくれませんか?
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

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

#33

投稿記事 by purin52002 » 7年前

purin52002 さんが書きました:
purin52002 さんが書きました: 坂道とプレイヤーの線分が交差していたらColSegments関数にtrueを返してほしくて、
でもColSegments関数はfalseを返すし、
これはColSegments関数の不具合ということですか?
keito94 さんが書きました:違います違います!!
ColSegment自体は正しく動作しています!!
ColSegments関数の仕業じゃないとすれば妖怪の仕業、、、?

冗談はさておき、
http://dixq.net/forum/blog.php?u=900&b=6581のISLeさんの投稿を見ると、
GetXPosition周りが怪しいとか、、、。

解決案としましては、
  • GetXPosition関数とかの修正
  • GetXPosition関数を使っている箇所の修正
でしょうか?

どちらの方法が絶対いい!とは言い切れないのでどちらの方法をとるかはkeitoさんが決めて下さい。
(なんかほかにもっといい方法あるかも^p^)
keito94 さんが書きました:あの、ブログ見ましたけど…。
移動後の座標ではなく、現在の座標だったのですか!?
ボクも気づきませんでした…。
すいませんが、現在の座標ベースでの当たり判定のアルゴリズムを教えてくれませんか?
すみませんが元のアルゴリズムも対して理解していないので
こっちに関してはもう、、、「がんば^p^」というしか、、、
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

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

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

#34

投稿記事 by keito94 » 7年前

ブログなどでみなさんがそこまで言うのなら、ソースコードを公開しますので、
サンプルコード.zipのScene.cppとScene.h以外のソースコードをプロジェクトに追加してください。
ブログで聞いた話によると、今のソースコードは色々と改善すべきところがあると思うので、ここで改善案を出していただければ、
それを修正すると思います。
添付ファイル
サンプルコード.zip
(20.73 KiB) ダウンロード数: 452 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

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

#35

投稿記事 by purin52002 » 7年前

坂道に入ると
Run-Time Check Failure #3 - The variable 'SlopeCond' is being used without being initialized.
という例外が出て止まってしまいます@_@
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

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

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

#36

投稿記事 by purin52002 » 7年前

プログラムを動かしてみたところキャラクターが坂道に差し掛かると
キャラが沈んだり、なぜか左右にものすごい勢いで動いたりしました。

何が悪いのかとプログラムを読もうと思ったのですが、いわゆるマジックナンバーが多く正直私レベルだと理解できません。(っていうかしたくない^p^)

出来ればマクロ、enum、定数などに置き換えたほうがいいと思います。

コード:

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,*addx,*addy);
	//Y座標が衝突していなかったら。
	if (block.y == -1) {// -1 is magic number ( mn )
		*myy = newy;
		*gflag = false;
	}
	//Y座標が坂道のレイヤーにいたら。
	else if(block.y == -2){// -2 is mn
		int Layer = GetChipLayerNum((int)*myx, (int)newy);
		Segment Slope;
		//スロープの条件分離。
		int SlopeCond;
		switch (Layer) {
		case 2:
			Slope.s = GetMatrixPos(*myx, newy + 16.0F);// 16 is mn
			Slope.v = GetMatrixPos(*myx + 16.0F, newy);// 16 is mn
			SlopeCond = 0;
			break;
		}
		POINT slopeblock = CheckSlopeBlock((int)*myx, (int)newy, Layer);
		Vector2 slope = CheckSlope((int)*myx, (int)newy, Slope, Layer,SlopeCond);
		//-2を返したら、ブロックとして扱う。
		if (slope.y == -1) {// -1 is mn
			*gflag = true;
			*addy = 0;
		}
		else if (tempaddx != 0 && slope.y != -2) {// -2 is mn
			*gflag = true;
			*myy = slope.y;
		}
		else if (slope.y == -2) {// -2 is mn
			*gflag = true;
			*addy = tempaddx;
			*myy = newy;
		}
	}
	//ブロックの当たり判定。
	else {
		if (*addy < 0) {
			*myy = (float)((block.y + 1) * 16 + 8 + OffsetU + 0.1f);// 16,8,0.1 is mn
		}
		else {
			*myy = (float)((block.y - 1) * 16 + 8 + OffsetD - 0.1f);
			*jcount = 0;
			*gflag = true;
		}
		*addy = 0;
	}
}

マジックナンバーとはソース中にいきなり出てくる意味の分からない数字です。
(0はまあ初期化って意味だろうし直さなくてもいいかなー、と思いました)

数字だけだとややこしいので、名前を付けてやると見やすくなると思います。

コード:

#define SLOPE -1
const int SLOPE -1 ;
enum ChipType { SLOPE = -1 } ;

if( slope.y == SLOPE ) { ... }
のようにすると、他人が見た時や、時間をおいてからソースを見直すときにわかりやすいと思います^^
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

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

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

#37

投稿記事 by keito94 » 7年前

purinさんに言われてマジックナンバーを駆逐し、コメントによる解説を加えたソースを作りました。
引き続き、Scene.cppとScene.h以外をプロジェクトに入れてください。
オフトピック
コメントをたくさん書く…
ボクはそれに賛成ですね。
添付ファイル
サンプルコード.zip
(21.69 KiB) ダウンロード数: 458 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

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

#38

投稿記事 by purin52002 » 7年前

マジックナンバーが定数に置き換えられてて見やすくなっていました^^
ただ(私がconst intって書いたせいかも知らないけど)定数がすべてconst intで定義されていました。
定数は別に整数である必要はなく、比較対象と同じ型にしたほうがいいと思います。

以下修正案

コード:

//collision.cpp
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,*addx,*addy);
	const int OK = -1;
	const int SLOPE = -2;
	//Y座標が衝突していなかったら。
	if (block.y == OK) {
		*myy = newy;
		*gflag = false;
	}
	//Y座標が坂道のレイヤーにいたら。
	else if(block.y == SLOPE){
		//ブロックのレイヤー番号の獲得。
		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);
		//坂道としての当たり判定。
		Vector2 slope = CheckSlope((int)*myx, (int)newy, Slope, Layer,SlopeCond);
		const int SLOPEOK = -1;
		const int BLOCK = -2;
		//-2を返したら、ブロックとして扱う。
		if (slope.y == SLOPEOK) {
			*gflag = true;
			*addy = 0;
		}
		//歩いていた場合は、
		else if (tempaddx != 0 && slope.y != BLOCK) {
			*gflag = true;
			*myy = slope.y;
		}
		else if (slope.y == BLOCK) {
			*gflag = true;
			*addy = tempaddx;
			*myy = newy;
		}
	}
	//ブロックの当たり判定。
	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;
	}
}

22行目:
SlopeCondが初期化されていません。(c++だと多分0で初期化されるけど)
次のswicthで値を代入するならdefaultの状態も作ったほうがいいと思います。

37行目:
slope.yはfloat型、SLOPEOKはint型です。値の比較は型をそろえたほうがいいと思います。
42行目、46行目も同じ。

46行目:
16行目でSLOPEと判定しているのにBLOCKかどうか調べるのはなんででしょうか?

以下ちょっと重要かも?
(addyとmyyがわかっていません。myyがキャラクターのy座標?)

39行目:
坂道にいるときにaddyが0になっている。
坂道に沿ってmyyを変化させなくていいんでしょうか?

44行目:
myyにslope.yを代入してるけど、slopeってSLOPEかBLOCKか判定する変数じゃないんでしょうか?

48行目:
addyにtempaddxを代入してるけど、y成分にx成分を代入していいのでしょうか?(y(x)=xみたいな意味?)

49行目:
myyにnewyを代入していますが、newyは5行目でmyy+addyと定義されており、addyはこの時点ではGRAVかGRAVMAXの値しかとらなさそうなんですけど、これは意図したとおりの計算ですか?
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

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

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

#39

投稿記事 by keito94 » 7年前

myyと言うのはキャラクターの座標です。
addyと言うのは、キャラクターの移動量です。
あと、purinさんのご指摘に従い、Collision.cppを少し修正してみました。(中身に変わりはありません。)
49行目の件はちょっと誤算でしたね…。
オフトピック
ええっ!?Y座標を坂道に合わせて動かせばいいんですか!?
ちょっと甘かったです…。
添付ファイル
Collision.cpp
(10.55 KiB) ダウンロード数: 439 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

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

#40

投稿記事 by purin52002 » 7年前

keito94 さんが書きました:
オフトピック
ええっ!?Y座標を坂道に合わせて動かせばいいんですか!?
ちょっと甘かったです…。
y座標動かさないと坂道のぼれないやないかーいw
でもこれで不具合の原因がわかりましたね^^
移動した座標が坂道だったら、坂道の傾斜に応じてy座標を変化させてやればいいわけですね。
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

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

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

#41

投稿記事 by keito94 » 7年前

Y座標を坂道に合わせて移動させるというのはわかったけど…。坂道移動のアルゴリズムがちょっとよくわからないなぁ…。
お手数ですが、Collision.cppに書かれてある当たり判定のアルゴリズムを残したままでいいので、坂道移動のサンプルコードをくれませんか?
コメントにも書かれてあるように線分の衝突の部分判定のチェックの部分に間違いとかあるのかな…。
ついでにちょっと調べてくれませんか?(以下のように修正してください。)

コード:

Vector2 CCollision::CheckSlope(int x, int y, Segment& Slope, int layernum,int slopecond,float 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;
	}
	Vector2 res = { (float)x,(float)y };
	//デバッグ用。
	float T1;
	float T2;
	Vector2 Vres;
	int PlayerCond;
	//式自体はあっているが…。レイヤーの数値獲得に原因がありそうだ。
	//プレイヤーの終点のX座標が、坂道のX座標の間なら、1。間でないのなら、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) {
		PlayerCond = 1;
	}
	else {
		PlayerCond = 0;
	}
	//衝突した場合は座標に内分を足し、そうでない場合は内分を引く。
	//(間違っているかもしれない…。)
	if (PlayerCond != 0) {
		if (ColSegments(Slope,Player,&T1,&T2,&Vres)) {
			res.x = x-T1;
			res.y = y-T1;
			addy = T1*2;
			return res;
		}
		else {
			res.x = x + T1;
			res.y = y + T1;
			addy = T1*2;
			return res;
		}
	}
	else {
		//なるほど、あり得ない座標を代入したら、レイヤーの数値獲得もおかしくなるわけか…。
		res.x = -2;
		res.y = -2;
		return res;
	}
	//ここまで来たら衝突していないということ。
	res.x = -1;
	res.y = -1;
	return res;
}
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#42

投稿記事 by ISLe » 7年前

とりあえず、他は現状のままでよいので、Vector2.cppの下記の関数を変更してください。
これでやっとまともに坂道判定にとっかかれると思います。

コード:

Vector2& Vector2::operator *=(const float& a)
{
#if 0
	return Vector2(x * a, y * a);
#else
	x *= a;
	y *= a;
	return *this;
#endif
}

Vector2& Vector2::operator /=(const float& a)
{
#if 0
	return Vector2(x / a, y / a);
#else
	x /= a;
	y /= a;
	return *this;
#endif
}

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

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

#43

投稿記事 by keito94 » 7年前

ISLeさん、ライブラリの欠点のご指摘ありがとうございます!!
少し変更したのをGithubにあげようと思います!!
これが坂道の当たり判定に関係するわけですよね?
修正済みのVector2.cppを使ったサンプルコードをください!!
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#44

投稿記事 by ISLe » 7年前

Vector2.cppを修正してやっとまともにデバッグできる状況になるというだけです。
坂道判定に関しては、ここからスタートですよ。
ご自身で取り組んでください。

keito94 さんが書きました:Collision.cppに書かれてある当たり判定のアルゴリズムを残したままでいいので
わたしはこれを残したままのやり方を知りませんし考えたくもないです。
もっとシンプルに実装する方法を知っていますが、根本的に考え方が異なるのです。
#某所に書いたのはそういうことであってコードが正しいとか正しくないとかいうことではない。

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

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

#45

投稿記事 by keito94 » 7年前

そうか、Collision.cppの当たり判定は間違っていたのか…。
今の言葉でちょっと頭が混乱してしまったので、坂道移動のサンプルコードをくれませんか?
それをもとにソースコードを変更したいと思うので…。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

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

#46

投稿記事 by purin52002 » 7年前

坂道に沿って動くプログラムです。
高校生レベルの数学がわかればわかるはず、、、?
添付ファイル
purin52002.zip
キーボードのaとdで動きます。(windows用)
(8.12 KiB) ダウンロード数: 448 回
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#47

投稿記事 by ISLe » 7年前

keito94 さんが書きました:そうか、Collision.cppの当たり判定は間違っていたのか…。
わたしが違う方法を使うというだけで、間違っているとは言っておりません。

キャラが壁にハマってしまう
わたしが使う方法は既に最初期にお伝えしてます。
壁にめり込んでいるのを補正するなら、ただ壁にめり込んでいるのを補正するだけでいい、というふうなことです。
やり方が違うというだけで、やること自体は変わりません。


keito94さんのいまのコードでは、機能ごとに階層が深く複雑化していく構造です。
機能ごとの依存度が高く、機能の変更や追加が他へ大きく影響するため、そのバランスを取ることに大量の時間を割くことになります。

わたしが使う方法は機能ごとの実装に階層を持たせない方法です。
それだけのことですが、コードの重複が減り応用範囲が広がるので、プラマイの相乗効果で効率として何百倍何千倍もの差が生まれます。


プレイヤーキャラが坂道の上にいる(接している)という状態であれば、背景に坂道があろうかなかろうが、背景に何もなく見た目空中に浮いているようでも、設定した坂道のパラメータで上り下りするように振る舞えばいい。

そして、そこに背景として坂道を合成すれば、その坂道をプレイヤーキャラが上り下りしているように見える。

プレイヤーキャラが坂道の上にいる(接している)という状態は、プレイヤーキャラが持っているものです。
それを自由に制御できるようにする。

プレイヤーキャラが坂道を上り下りする処理と、プレイヤーキャラが背景の坂道と接しているかどうか判定する処理は、まったく関係なく実装できるのです。
最終的に、背景の坂道にプレイヤーキャラが接している場合に、プレイヤーキャラに対して坂道の上にいる(接している)と連絡する処理を加えればよいのです。
そうであれば、最初からプレイヤーキャラが坂道の上にいる(接している)という状態で初期設定して動かしてテストしたり、特定のキーを押したら状態が切り替わるようにしてテストしたりなどシンプルな条件で単体テストを行うことができます。


坂道移動のサンプルコードが手に入ったとして、いまのままコードに継ぎ足していっても効率は悪くなる一方ですよ。
わたしは、わたしとは、やり方が違うと言っているのです。

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

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

#48

投稿記事 by keito94 » 7年前

ISLe さんが書きました: わたしが違う方法を使うというだけで、間違っているとは言っておりません。
ますますわけがわからなくなってしまいました…。(あれで完璧だったつもりなのに…。)
では、あなたが考えてるやり方のほうのサンプルコードを出してください!!
それをもとにして、Collision.cppをプログラムしますから!!
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#49

投稿記事 by ISLe » 7年前

> keito94 さん
わたしの書いた文章をちゃんと読みましたか。
文字をなぞるだけでなく、意味を理解しましたか。

「それをもとにして、Collision.cppをプログラム」する必要があったら、それはもうわたしのやり方ではないのです。
「それをもとにして、Collision.cppをプログラム」できるようなサンプルコードをわたしのやり方で書いたら、もはや何も(あるいはほとんど)変更する必要がないのですから、コードを入れ替える一択しかあり得ません。

理解する気がないと思われるところに、説明を補完する役割としてのサンプルコードを提示する意義を感じませんし、そういうサンプルコードはお望みでありませんよね。

#トピック自体は有意義であって欲しいので、そういう意味では考えておきます。

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

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

#50

投稿記事 by keito94 » 7年前

ISLe さんが書きました: わたしの書いた文章をちゃんと読みましたか。
文字をなぞるだけでなく、意味を理解しましたか。
すいません。さっきの発言はなかったことにしてください…。
軽率かつ思い込みでした…。
あの時はつい、Collision.cppは変える必要ないのかと…。
ISLe さんが書きました:
理解する気がないと思われるところに、説明を補完する役割としてのサンプルコードを提示する意義を感じませんし、そういうサンプルコードはお望みでありませんよね。
そうですよね…。

というわけで、あなたが考えている方の当たり判定のサンプルコードを出してください。
ようやくあなたの発言の意味が飲み込めましたので…。
オフトピック
今となってはあの書き込み、反省しているよ…。
追記:適切なものに直しました。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

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

#51

投稿記事 by keito94 » 7年前

http://dixq.net/fourm/blog.php?u=900&b=6581より
ISLe さんが書きました:そんな基本的なところに気付けないくらいにコードが複雑化している現状がある。
わたしはそれを解決するのが急務だと考えた。
ええっ!?スパゲッティーコードだったんですか今書いていたコード!?
そりゃ解決されないわけだ…。
ISLe さんが書きました: keito94さんはさっさと坂道を実装して終わらせたいと考えている。
であればかみ合うはずがないっすね。
ほんとそれですよ…。今となってはそりゃそうなっちゃうよな…。と反省しています…。

追記:ソース元を出しました。
最後に編集したユーザー keito94 on 2017年6月04日(日) 19:11 [ 編集 1 回目 ]
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

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

#52

投稿記事 by keito94 » 7年前

ISLeさん、言い方が悪かったみたいですね…。
今書いているコードがスパゲッティコードになってるのは認めます。
しかし、どうしても、坂道の当たり判定が、今のしか考えられないので、
あなたが考えている方の当たり判定のサンプルコードを提示してください。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#53

投稿記事 by ISLe » 7年前

ログインしたユーザーしか見ることができない場所に書かれた他人の文章を、ログインせず誰でも見ることができる場所に張り付ける行為。非常識ではないですか?
No.33と違い、No.51は明らかに無断転載でしょう。

このトピックをログインせずに見るひとからしたら、まったく意味不明ですよ。
そういう脈略のないところがコードにも表れているのと違いますか。

keito94 さんが書きました:ISLeさん、言い方が悪かったみたいですね…。
今書いているコードがスパゲッティコードになってるのは認めます。
しかし、どうしても、坂道の当たり判定が、今のしか考えられないので、
あなたが考えている方の当たり判定のサンプルコードを提示してください。
No.47をちゃんと理解できたなら「あなたが考えている方の当たり判定」なんて言葉が出てくるはずないんですけどね。
keito94さんがいま考えている坂道の当たり判定に注力できるようにするための方法を提案しているのですから。

スパゲッティ状態を改善して、(keito94さんの考えた)坂道の当たり判定をデバッグできるようにしろと言っているのですよ。

No.42,No.44にも、あの時点で、坂道の当たり判定はいまだスタート地点にも立ててないふうのこと書きました。
いまもその状況はまったく変わってない。

シグネチャに“只今デバッグトレーニング中。”とあるのは飾りですか。
真剣さが一切伝わってきませんね。

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

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

#54

投稿記事 by keito94 » 7年前

ISLe さんが書きました:ログインしたユーザーしか見ることができない場所に書かれた他人の文章を、ログインせず誰でも見ることができる場所に張り付ける行為。非常識ではないですか?
すいません、ソースをはっきりさせたいと思います…。

http://dixq.net/forum/blog.php?u=900&b= ... で答えたいと思います

①坂道として判定されたら、坂道の線分を生成する。
②プレイヤーの線分を生成する。
③プレイヤーの線分の終点が、坂道の線分の間であれば、プレイヤーの線分と坂道の線分で線分の当たり判定を行う。
④線分と線分が交差していたらそれは当たったことになる。
⑤当たっていたのなら、プレイヤーの座標と坂道の内分比を引いてそれをプレイヤーの座標にしてめり込み防止を行う。
⑥下りのときは交差されないと思うのでその場合はプレイヤーの座標と坂道の内分比を足してそれをプレイヤーの座標にする。
⑦そして、プレイヤーが坂道を歩いているように見えたら完成。
もしかしたらどこか間違っているのかもしれません…。
回答をお願いします。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

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

#55

投稿記事 by keito94 » 7年前

あと、なんとかスパゲッティコードを解消させてみました…。
Collision.cppのGetMoveを見ればわかると思いますが、坂道にプレイヤーが居るのなら、ブロックとしての当たり判定を中断させ、坂道の当たり判定へ移行します。また、GetSlopeでdefaultのところへ来たらそれはブロックとして判定します。昇り降りは、まだ作っておりません。これから質問の答を参照して作りたいと思います。
添付ファイル
Collision.zip
(3.71 KiB) ダウンロード数: 467 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

アバター
usao
記事: 1889
登録日時: 11年前

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

#56

投稿記事 by usao » 7年前

オフトピック
なんか名前出されたから,ちょっとだけ書くけれども…
(ここにレスしていないということは,ここでのやりとりには参加する意思がないのだ,ということを,せめて理解いただきたいのだが)

>坂道として判定されたら
何が? どうやって? 「坂道として判定」されるのか

> 坂道の線分
> プレイヤーの線分
って何?

> プレイヤーの線分の終点が、坂道の線分の間であれば、
点が線分の間にある って,どういう状態のこと?

等々… それ以降の説明も,書いている本人にはわかるのだろうけど,
そのアルゴリズムについて何も知らない人がその文だけを読んで意味を把握するのは困難に思えます.

あなたが「言うまでもない」と思って省略している事柄は,他者にとっては説明が無いと全くわからない事柄なのかもしれない.
例えば,話の中で唐突に「ブロック」という単語が出てきますが,
その正体についての説明無しに,あなたと他者とで完璧に共通の認識を持てるでしょうか?
(マップのデータを2次元の格子で管理しているのだろうな,という想像くらいは付くかもしれませんが)
ブロックの大きさとプレイヤキャラクタの当たり判定の形や大きさとの関係はどうなのか?ということを知らずに,衝突判定処理の妥当性を話し合えるでしょうか?

#私向けの回答は不要です.

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

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

#57

投稿記事 by keito94 » 7年前

ごめんなさい、わかりにくかったですね…。
①プレイヤーが坂道のところに来たら、坂道のパラメーターを設定します。(坂道の線分を設定する。)
②坂道のパラメーターをもとにプレイヤーのパラメーターを設定します。
(具体的にはSlopeCondというパラメーターで、坂道か天井か、(右方向から見て)上りか下りかをもとにプレイヤーの線分を設定する。)
③プレイヤーの足元の点(プレイヤーの線分の終点が、)が、坂道の開始地点と終了地点の間にいたら(坂道の線分の間にいれば)、プレイヤーの線分と坂道の線分で当たり判定を行います。
④プレイヤーが坂道のところを離れたら、坂道の当たり判定を終了して、四角形の床の当たり判定を行います。
⑤坂道にプレイヤーが衝突していたら、プレイヤーの座標に坂道の内分比を足してめり込み防止をします。
⑥下りの時は、プレイヤーが衝突しないと思うので、プレイヤーの座標に内分比を引いてめり込み防止をします。
⑦そして、プレイヤーが坂道を歩いているように見えたら完成です。
オフトピック
もしかしたらまだまだ、説明不足な点があるかも…。
追記:少し修正しました。
最後に編集したユーザー keito94 on 2017年6月05日(月) 19:18 [ 編集 1 回目 ]
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

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

#58

投稿記事 by keito94 » 7年前

No.57のアルゴリズムをもとにしたソースをCollision.zipに添付します。
追記:http://dixq.net/forum/blog.php?u=900&b=6581でISLeさんに指摘されたので、ColSegmentを分離しました。
添付ファイル
Collision.zip
(4.52 KiB) ダウンロード数: 455 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

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

#59

投稿記事 by purin52002 » 7年前

こんばんは

ソース拝見しました。以前のものよりだいぶ見やすくなったと思います^^
ColSegmentsも分離したとのことで見てみましたが、うーん、、、^^;

ISLeさんに指摘されたとのことですが、おそらくISLeさんは「機能的に」分離してみては?と提案したんじゃないでしょうか?

コード:

void Func(int x, int y) 
{ 
    int add = x + y ;
    printf("%d\n", add) ;
}

int Add(int x, int y) { return x + y ; }
void Print(int num) { printf("%d\n", num) ; }

int main()
{
    Func(1, 2) ;//Func関数の中で計算も表示もしてしまっている
    Print(Add(1, 2) ) ;//Add関数で計算、Print関数で表示している
}
たとえばこのようなコードがあったときに、
  • 表示させたい数字が変わった
  • いろんな数字を表示させたい
となった場合、処理をひとまとめにしてしまっているFunc関数だけでは不便な気がしませんか?
処理を機能ごとに分割すれば、仕様に何か変更があってもソースの変更はほんのわずかで済みます。

keito94さんの場合、単純にColSegmentsを別ファイルに分離しているだけなので見やすくはなったかもしれませんが、処理内容は変わっていないのでISLeさんのいう分離とは違うような気がしました^^;
オフトピック
最初私はColSegments内の処理が間違っているせいで坂道移動ががくがくすると思っていましたが、どうやら原因はVector2のほうにあったようですね。紛らわしいこと言ってしまい申し訳ありません<(_ _)>
c++初心者を自負しています。
質問者さんには今後私にプログラミングを教えてくれるようにやさしく丁寧に教えるつもりです。ぎぶあんどていく^p^
回答者さんには精一杯感謝します。ぎぶおんりー^p^

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

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

#60

投稿記事 by keito94 » 7年前

もしかして、こうではないのでしょうか?
CheckSlopeの部分で座標と移動量を参照しておくように変更しました。
添付ファイル
Collision.zip
(4.19 KiB) ダウンロード数: 477 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#61

投稿記事 by ISLe » 7年前

わたしがVector2の修正を指摘した時点では、それを適用すると上下動は無くなり、坂道に対する当たり判定そのものがなくなったように動作していました。
最新の状態では、上下動は再び発生しています。
原因が異なるであろうため前とは若干挙動が違います。

プレイヤーの移動処理をCPlayerクラスからCCollisionクラスに丸投げしているところで一気に読む気を削がれるのですが、何とか耐えて坂道関連の処理をひととおり読んでみました。
読んでみましたが理解するのは無理でした。

場所によって、移動先の座標で判定してその結果で移動元の座標を更新していたり、移動先の座標を引数で渡してさらに移動量を加えて使っていたり、当たり判定(の計算部分)が合っていようがまともに動くはずもなく、当たり判定が合っているかどうかなんてどうでもいい気持ちになりました。
まあ読む前に感じてたのと感想としては同じです。
それが確信に変わっただけでした。

そもそもkeito94さんは、いまのコードで平らな面の上を水平に移動できている仕組みを理解しているのでしょうか。

#面倒くさい上に誤魔化しにすぎない移動先判定をやめてしまえばいいのに。

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

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

#62

投稿記事 by keito94 » 7年前

ISLeさんが指摘した、移動先座標での判定の部分を、移動量を足した判定に変更してみました。
CheckMapの部分は、addxかaddyのどちらかが、0でなければ正しく動作しない仕様となってます。
添付ファイル
Collision.zip
(4.21 KiB) ダウンロード数: 511 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#63

投稿記事 by ISLe » 7年前

keito94 さんが書きました:ISLeさんが指摘した、移動先座標での判定の部分を、移動量を足した判定に変更してみました。
CheckMapの部分は、addxかaddyのどちらかが、0でなければ正しく動作しない仕様となってます。
直しているとき、他に、移動量渡してない関数があることに気付きませんでした?

あと、現在座標と移動量のポインタを引数で渡して、当たり判定の結果によって、書き換えたり書き換えなかったりするわけですが、それが3段くらいの入れ子になっているので、書き換えた内容が上書きされるのではないだろうか、とか、移動量を何回も加算してしまわないだろうか、とかのうっかりミスをやらかしてしまっている可能性を考えるとキリがないですよね。
キリがないのでわたしは早々に考えることをやめてしまうのですが、keito94さんはその辺すべて把握されておられるのでしょうか。

マップから坂道の情報を取得するところで、ポインタではない引数を書き換えて、呼び出し元でそれを利用しようとしているところなんかを見ると、引数に対して無頓着なのではないかという気がするんですが。
この場合、書き換えた内容はとうぜん呼び出し元には返らないわけで。

どうしてわざわざ分かりにくくミスしやすくしているのかが、わたしには理解できないところです。

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

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

#64

投稿記事 by keito94 » 7年前

ISLeさん、ご指摘ありがとうございます。
出力する引数は、ポインタをつけろというわけですね…。
あと、入れ子化していた部分を修正しました。
添付ファイル
Collision.zip
(4.37 KiB) ダウンロード数: 505 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

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

#65

投稿記事 by keito94 » 7年前

オフトピック
今の修正で、坂道の壁としての当たり判定も楽にできるかなって…。
今思うとはじめのコードは汚い上に、なんか変な要素満載だったな…。
早くに気づいていれば、良かったなと思うこの頃。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#66

投稿記事 by ISLe » 7年前

keito94 さんが書きました:出力する引数は、ポインタをつけろというわけですね…。
ここは(いまのところ)結果に影響を与えていないので、単に、引数に与えた値(特に現在座標と移動量)の変化を把握していないのではないかという疑問を補強する意味で指摘しました。
そういう意味では今回の変更においても疑問は一切解消されていません。
keito94 さんが書きました:あと、入れ子化していた部分を修正しました。
階層が1段増えましたね。
これを修正というのでしょうか。
わたしには改悪にしか見えませんが。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#67

投稿記事 by ISLe » 7年前

現在位置 p
移動量 a

パターンA

コード:

移動関数() {
 aを生成
 当たり判定と補正を行う関数(p, a) {
  if (p + a がめり込んでいる) {
   pをめり込んでいない位置に補正
   aをリセット
  }
  pにaを加える
 }
}
パターンB

コード:

移動関数() {
 aを生成
 pにaを加える
 当たり判定と補正を行う関数(p) {
  if (p がめり込んでいる) {
   pをめり込んでいない位置に補正
  }
 }
}
パターンA,Bともに結果は同じです。
パターンAは、補正が必要なときに、pをいったん更新するのを避けられます。ただそれだけです。
pを格納する変数が更新されないだけで、計算はしますし、それは当たり判定の対象の数だけ繰り返されます。


純粋に移動だけのテストをしたいと思いました。
なので、それ以外を除外します。

パターンA'

コード:

移動関数() {
 aを生成
}
パターンB'

コード:

移動関数() {
 aを生成
 pにaを加える
}
パターンA'では移動しなくなってしまいました。
パターンAで移動の処理が正しいかテストするためには、当たり判定と補正の処理を(いちいち)調整しなければいけません。
ところが、当たり判定と補正の処理が正しく動作している保証がありません。
どうしたら、移動の処理が正しいか、当たり判定や補正の処理が正しいか、証明できるのでしょう。



パターンBは実際にはこのように変形して使います。

コード:

移動関数() {
 aを生成
 pにaを加える
}
当たり判定と補正を行う関数(p) {
 if (p がめり込んでいる) {
  pをめり込んでいない位置に補正
 }
}
移動するオブジェクトが、自分以外に何が存在するか知っている必要ありません。
知っていたら自分以外のオブジェクトが増えたりしたとき変更に巻き込まれることになるからです。

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

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

#68

投稿記事 by keito94 » 7年前

ISLeさんが考えている当たり判定のアルゴリズムに変えてみました。
addxとaddyを0にしないとまともに動作しません。(このステージでは関係ないんですが…。)
オフトピック
なるほど、こうゆうことだったのか…。
添付ファイル
Collision.zip
(4.12 KiB) ダウンロード数: 471 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#69

投稿記事 by ISLe » 7年前

keito94 さんが書きました:ISLeさんが考えている当たり判定のアルゴリズムに変えてみました。
ずいぶん中途半端に変更したのですね。
これをわたしが考えたと言われるのはかなり抵抗あります。
keito94 さんが書きました:addxとaddyを0にしないとまともに動作しません。(このステージでは関係ないんですが…。)
それはそうでしょうね。
わたしがNo.63で書いた、移動量を何回も加算してしまわないだろうか、と懸念していたことを新たにやらかしてます。
このステージでは関係ない…ほんとうにそうでしょうか。
例えば坂道を登りきる前に坂道の判定が消える、ような気がしますが。


もしかして中途半端なのは、CCollision::GetMoveにある落下に関する移動量の処理をどこに移動したらいいか分からなかった(あるいは移動させるのが面倒だった)から、その前後を適当に誤魔化したのでしょうか。

CCollisionから移動量を完全に排除しようという意志が感じられないですね。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#70

投稿記事 by ISLe » 7年前

あと、(いまのところ)削らなくていいものまで削ってますね。

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

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

#71

投稿記事 by keito94 » 7年前

僕の頭の中のコードでは、どう頑張っても、めり込み補正の部分とY座標の部分で移動量に頼ってしまいます。
なので、移動量に頼らないめり込み防止のサンプルコードをください。
なお、今上げたコードでは、常に落下しているので、最終的にはキャラが画面外に移動します。
添付ファイル
Collision.zip
(5.36 KiB) ダウンロード数: 451 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

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

#72

投稿記事 by keito94 » 7年前

オフトピック
やっぱり自分でプログラムするのっていいもんなんだな…。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#73

投稿記事 by ISLe » 7年前

keito94 さんが書きました:僕の頭の中のコードでは、どう頑張っても、めり込み補正の部分とY座標の部分で移動量に頼ってしまいます。
なので、移動量に頼らないめり込み防止のサンプルコードをください。
いちいち頭で考えなくても、引数の宣言からaddx,addyをまるまる取り除けば、変更が必要な部分はコンパイラが教えてくれますよ。
keito94 さんが書きました:なお、今上げたコードでは、常に落下しているので、最終的にはキャラが画面外に移動します。
常に落下してしまうのはどうしてなのか、というところに頭を使いましょうよ。

No.47で書いたように、プレイヤーキャラは、地面に着いているから落下しない、のでなく、(プレイヤーキャラ自身が)落下する状態でないから落下しない、ようにすれば落下しなくなります。
そういう目的に使える情報は既にCPlayerクラスにありますよね。

No.70に書いた、削らなくていいところというのは、その情報を書き換えている部分なので、ここでも新たにバグを仕込んでいるというわけです。
きちんと(物理的に)切り分けないとこういうことが頻繁に起きてキリがないのです。

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

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

#74

投稿記事 by keito94 » 7年前

ISLe さんが書きました: (プレイヤーキャラ自身が)落下する状態でないから落下しない
それを自分なりに実装してみたのですが、今度はキャラが落下しません。
ジャンプすらできません。何か落下する状態を管理する部分にバグが有るようなのですがそれはどこなのでしょうか?
オフトピック
やっぱりプログラムって大変…。
添付ファイル
Collision.zip
(5.5 KiB) ダウンロード数: 500 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#75

投稿記事 by ISLe » 7年前

そもそもCCollisionクラスって何なんですか?
クラスの役割りを説明できますか?
説明できないのにただいじくり回しているだけならキリがないのでやめましょう。
ISLe さんが書きました:No.47で書いたように、プレイヤーキャラは、地面に着いているから落下しない、のでなく、(プレイヤーキャラ自身が)落下する状態でないから落下しない、ようにすれば落下しなくなります。
そういう目的に使える情報は既にCPlayerクラスにありますよね。
CPlayer::GroundFlagってありますよね。
CPlayer::GroundFlagって何ですか?
これも役割りを説明できますか?

CCollisionのアウトプットとして、地面に突き上げられてるという情報を得る方法を作るというのであれば分かります。
CCollisionクラスにAirFlagというメンバを追加して、CPlayerがCCollisionを監視しなければならない依存関係を新たに作る意味が分かりません。

それと、新たにバグを仕込みましたねって伝えましたよね。
仕込んだところを直してほしい、というかただコードを元に戻せばいいだけなのですが…
どこが変わったか見れば一目瞭然だと思うんですが。
#GitHubとか何のためにあるのだろう

トピを見直しているようすが見られないところから、自分で考える気がないように見えます。

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

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

#76

投稿記事 by keito94 » 7年前

>>ISLeさん
簡単に説明します。
CCollisionと言うのは当たり判定の処理を行うクラスです。
CPlayer::GroundFlagと言うのは、キャラが地上に居るかどうかを管理する変数です。
CPlayerで移動処理をして、CCollisionで当たり判定をチェックします。
ジャンプした、もしくは空中にいる時はGroundFlagが偽になります。
地上にいる時はGroundFlagが真になります。
GroundFlagが真になっている時は落下を行わないはずです。
これで間違いないですよね?
あと、質問用のソースコードをリポジトリに上げてみました。
プロジェクトにこのコードを追加してください。
こちらです。
オフトピック
変にいじると大変なことになるのね…。
追記:今のコードで確認されている不具合は、左の当たり判定と、右の当たり判定が同時に出ていることと、落下を全くしないことと坂道を登りきると、
キャラが消えてしまうことです。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#77

投稿記事 by ISLe » 7年前

keito94 さんが書きました:CCollisionと言うのは当たり判定の処理を行うクラスです。
それはCCollisionの説明になっていませんね。
CPlayerも当たり判定の処理をしてますよね。CCollisionのメソッドを呼び出しているから。
もっと言えば、このプログラム自体も当たり判定の処理をしてますよね。
そんな中でCCollisionの役割りとは何なんですか?

それを説明できないから何でもかんでもCCollisionでやろうとしてCCollisionがないと動かないコードになってしまうのでしょう。

keito94 さんが書きました:CPlayer::GroundFlagと言うのは、キャラが地上に居るかどうかを管理する変数です。
CPlayerで移動処理をして、CCollisionで当たり判定をチェックします。
ジャンプした、もしくは空中にいる時はGroundFlagが偽になります。
地上にいる時はGroundFlagが真になります。
GroundFlagが真になっている時は落下を行わないはずです。
これで間違いないですよね?
CPlayer::Moveにはキャラが空中にいてもGroundFlagを真にするコードがありますよ。
keito94さん自身が最近追加したコードですよね。
説明と矛盾してますよ。
この説明は聞かれたから考えたものなのですか?

keito94 さんが書きました:あと、質問用のソースコードをリポジトリに上げてみました。
GitHub云々書いたのは、バージョン管理ソフトを利用すれば変更の取り消しとか楽になると思ったからです。
まあ、公開レポジトリなんかだとコンパイルエラーがある段階でリビジョン上げるのは良くないのでしょうかね。
オフトピック
わたしは、今回ので例えるとaddy,addx削った時点でレポジトリ更新してコメントにきちんと目的を書き、コンパイルエラーを潰すためであればそれはそれでリビジョンを消費するといった感じに、作業過程を細かく記録します。
そういう使い方だとGitHubは大げさなので、Subversionでローカルレポジトリ作ってやってますけどね。
リポジトリとしてはひどいものだけど、開発の過程を見る・知る資料として有用である気がしてます。
keito94 さんが書きました:追記:今のコードで確認されている不具合は、左の当たり判定と、右の当たり判定が同時に出ていることと、落下を全くしないことと坂道を登りきると、
キャラが消えてしまうことです。
あとジャンプボタン押してもジャンプしませんね。

キャラが消えてしまうというのは、画面の右端のブロックに触れた時点で座標補正されて画面の右側の外に消えるということですかね。
こちらで確認してみた限りでは坂道を登りきるだけでは消えないみたいですが。
ブレークポイント使ったりトレース実行したり、変数の値をウォッチしたりというデバッグはしていないのでしょうか。

それらの不具合は全部No.71のあとからNo.74までのあいだに発生したものですよね。
keito94さん自身が仕込んだもので、環境依存等で勝手に生まれたバグではない。
いちいち頭使って考えなくても、コードの差異を見れば原因の特定は難しくないと思うんですけどね。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#78

投稿記事 by ISLe » 7年前

オフトピック
クラスやメンバなどの役割りを決め、その役割り通りに且つ役割りを発揮できるように構成を考え、それらを繰り返し練っていく、というのがプログラミングの本質であると思う。
コーディングは、それのアウトプットに過ぎない。
いきなりコーディングという場合でも、過程においてのコーディングは思考を補助する役割りであると思う。

役割りを考えず、役割りに基づいてコードを書いていないのであれば、それはプログラミングではない。
プログラミング言語を使ったラクガキだ。

ラクガキだから楽しいというのはあるかもしれない。
であればラクガキを楽しめばいい。

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

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

#79

投稿記事 by keito94 » 7年前

新たなバグを発見しました。地上にいる時は、Y座標の移動量を0にしようとしているつもりなのですが、
ブレークポイント無しで実行するとソースコードに書いてあるバグが発生して、地面にめり込んだ状態になります。
原因はどこにあるのでしょうか?また仕込んだのではないのでしょうか?
添付ファイル
Collision.zip
(5.55 KiB) ダウンロード数: 505 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#80

投稿記事 by ISLe » 7年前

No.76のkeito94さんが書いたCPlayer::GroundFlagの説明は正しいのでしょうか。
間違った理解でコードをいじるからおかしなことになるのと違いますか。
そもそも、コードに「~となるはず」なんてコメントありえません。
引き算のつもりで足し算書いたのをPCが忖度して直してくれるはずもない。

- + - + -

引数の移動量が復活してますね。
ここにきて、移動量撤廃の方針をひっくり返しますか。

移動量を使わないでどうやって判定するのか?といういちばんのキモを質問しないのですね。
やっとここまで問題点をピンポイントであぶり出せたのに。

いや、別にいいんですよ。
どういう方針を選ぶかはkeito94さんの自由ですから。
ただ、そちらを選ぶのなら、わたしはもうサポートできません(しません)。

画面右外に消えてしまう原因を見付けて、直したのでしょう。
わたしが提案する方針よりも、最初に見付けたサンプルコードのやり方を優先した。

それだと坂道の実装でうまくないからこのトピができたのではないかと思うのですが…
少なくともこのトピの内容を一からやり直すことは確定ですね。
絶対不可能というわけではないと思うので、無限ループにならないように、頑張ってください。
#むしろ無限ループを楽しんでください。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#81

投稿記事 by ISLe » 7年前

オフトピック
いちおう移動量を使わない方法を書いておきます。

めり込んでいる対象のブロックは分かっているので、ブロックの座標とキャラの座標を比較して、どちらにずらしたほうが良いか決定します。

移動量で決めると、例えばトンネル状のマップを抜けるとき、うっかりジャンプして天井ブロックに触れると、一気に入り口まで戻されるという現象が発生します。

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

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

#82

投稿記事 by keito94 » 7年前

ISLe さんが書きました: #むしろ無限ループを楽しんでください。
それはやだやだ!!!
ISLe さんが書きました: 移動量を使わないでどうやって判定するのか?といういちばんのキモを質問しないのですね。
やっとここまで問題点をピンポイントであぶり出せたのに。
ごめんなさい、その質問をしようと思っていたところでした…。
ISLe さんが書きました: 間違った理解でコードをいじるからおかしなことになるのと違いますか。
ごめんなさい、ちゃんとソースコードをしっかり読んでからやりたいと思います…。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#83

投稿記事 by ISLe » 7年前

オフトピック
そろそろXとYで関数を分ける必要もない段階まできてたわけだけども。
そうなると、
めり込みを許容して押し戻すマリオ(ブラザーズ)タイプ

めり込みを許容せず一気に移動のロックマンタイプ
を選択する余地も生まれるのだけども。

マリオ(ブラザーズ)タイプ、ロックマンタイプってのはわたしが勝手に分類して言ってるだけだけども。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#84

投稿記事 by ISLe » 7年前

keito94さんは、CPlayer::GroundFlagが真のとき、地上に立っている状態と説明しました。

CPlayer::GroundFlagが真のとき、キャラは地上に立っているように振る舞います。
そこでは、実際にキャラが地上に居るかどうかは関係ありません。

キャラが地面にめり込むと地面に触れないぎりぎりの位置に座標補正されます。
次のフレームで、それは地上に立っていることになるのでしょうか。


コードを上から下になぞるだけでなく、実際に動いているときの流れを意識してください。

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

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

#85

投稿記事 by keito94 » 7年前

ISLe さんが書きました: コードを上から下になぞるだけでなく、実際に動いているときの流れを意識してください。
はーい、わかりました。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

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

#86

投稿記事 by keito94 » 7年前

http://dixq.net/forum/viewtopic.php?f=3&t=19267
一からトピックをやり直してみました。
これ以降のめり込みなどに関する質問はここに書き込んでください。
この件は一応解決とさせていただきます。
最後に編集したユーザー keito94 on 2017年6月13日(火) 18:17 [ 編集 1 回目 ]
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#87

投稿記事 by ISLe » 7年前

移動量撤廃の方針を続けるならこのトピで続ければよいのでは。

移動量を使うなら、元の木阿弥だという意味ですよ。
同じことの繰り返し。
新しいトピを立てても同じ内容のトピができるだけだと思うけども。

そもそもkeito94さんがこのトピを読み直しているようすが見えない。

わたしがkeito94さんのアップロードしたソースコードを過去の分も全部保存して、返信する都度、比較してここが変わったあそこが変わった、また同じことしてるだの、というふうなことをしているわけだけども。

別に、わたしが苦労しているのを分かれだとか、何かを押し付けようというつもりはないよ。

最低限そのくらいしないと内容を理解できないだろってこと。

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

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

#88

投稿記事 by keito94 » 7年前

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

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

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

#89

投稿記事 by keito94 » 7年前

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

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

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

#90

投稿記事 by keito94 » 7年前

ISLe さんが書きました: 移動量撤廃の方針を続けるならこのトピで続ければよいのでは。
ごめんなさい、解決を撤回させてください。この方針を続けようと思います。
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

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

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

#91

投稿記事 by keito94 » 7年前

ちなみに、これが現在のコードです。
現在は移動量に依存していた部分を取り除いたところです。実行しても、落下状態にあるので、めり込んでしまいます。
CPlayer::GroundFlagはそれが真になっていると、地上にいるかのように振る舞うフラグです。(混乱を招く回答すいません…。)
添付ファイル
Collision.zip
(5.4 KiB) ダウンロード数: 402 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#92

投稿記事 by ISLe » 7年前

keito94 さんが書きました:現在は移動量に依存していた部分を取り除いたところです。
前に一度CCollision::GetMoveからも取り除かれたのに、今は復活してますね。
keito94 さんが書きました:CPlayer::GroundFlagはそれが真になっていると、地上にいるかのように振る舞うフラグです。(混乱を招く回答すいません…。)
それはわたしがNo.84で書いた表現をなぞっているだけですね。

No.84では、それに対する問題の指摘も同時にしているのですが、理解できませんでしたか?
No.85を見たら理解しようという気概を感じられませんけどね。



画面右端のブロックに触れると右外に消えてしまう問題については、さらに前のNo.81で既に書いてます。
keito94さんが方針変更されると思ったのでオフトピになってますが。

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

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

#93

投稿記事 by keito94 » 7年前

ISLe さんが書きました: キャラが地面にめり込むと地面に触れないぎりぎりの位置に座標補正されます。
次のフレームで、それは地上に立っていることになるのでしょうか。
なん…だと…。地上にいるというのは振る舞いだけだったのか…。
ISLe さんが書きました: 前に一度CCollision::GetMoveからも取り除かれたのに、今は復活してますね。
今度こそ取り除かれたのではないのでしょうか?
添付ファイル
Collision.zip
(5.38 KiB) ダウンロード数: 403 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#94

投稿記事 by ISLe » 7年前

keito94 さんが書きました:なん…だと…。地上にいるというのは振る舞いだけだったのか…。
『CPlayerは』『CPlayer::GroundFlagによってのみ』振る舞いを変えることでCPlayerの独立性が高まります。
CPlayer::GroundFlagの変化とは無関係になるので、キャラの挙動と、ブロックのあたり判定それぞれ別々にデバッグが可能になる。

という内容のことをNo.47で書いているんですけどね。
当時は理解できなかったとしても今は理解できるかもしれない。
何回も読み直して理解しようという気はないのでしょうか。

あと、バグの原因の特定も容易になる。
挙動の変化がおかしいならCPlayer::GroundFlagを書き換えている場所を探せばいい。
#CCollisionが直接書き換えているから問題をややこしくしているけども、まあそこは後回しでいい。


ISLe さんが書きました:今度こそ取り除かれたのではないのでしょうか?
余計なことをしなければ、No.74で達成できていたのに。



で、次にやるべきことは既に示されている(No.81,92)わけですが?

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

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

#95

投稿記事 by keito94 » 7年前

とりあえず、No.81で言われた方法にしてみました。
現在確認されているバグは、
  • 着地すると、キャラがぴょんぴょん跳ねる。
  • 左の壁に衝突すると、キャラが上に上がる。
となります。
壁に当たった時、キャラをずらすアルゴリズムの例を上げてくれますか。
添付ファイル
Collision.zip
(5.42 KiB) ダウンロード数: 424 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#96

投稿記事 by ISLe » 7年前

keito94 さんが書きました:壁に当たった時、キャラをずらすアルゴリズムの例を上げてくれますか。
これはつまり…
CCollision::GetXPosition関数にある(あった)
*myx = (float)((block.x - 1) * 16 + 8 + OffsetR - 0.1f);
*myx = (float)((block.x + 1) * 16 + 8 + OffsetL + 0.1f);
とか
CCollision::GetYPosition関数にある(あった)
*myy = (float)((block.y + 1) * 16 + 8 + OffsetU + 0.1f);
*myy = (float)((block.y - 1) * 16 + 8 + OffsetD - 0.1f);
という文がそれであるということを認識する気もないっていう意味ですかね。
認識すらする気がないのにどうやったら、例をあげて示すことができるんですかね。
これ(↑)がそれですよ、ってのはkeito94さんが望む例ではないですよね。
これは何かの哲学ですかね。

keito94 さんが書きました:とりあえず、No.81で言われた方法にしてみました。
現在確認されているバグは、
  • 着地すると、キャラがぴょんぴょん跳ねる。
  • 左の壁に衝突すると、キャラが上に上がる。
となります。
というわけで、No.81で言った方法になってない(不十分)です。

既存のコードを理解すればそのバグは直せるはずですが。



keito94さんは、いつになったらプログラミングやデバッグを始めるつもりなんですか?
無意味で無関係なコードがまた復活してたり、認識してないはずのコードがテキトーに変更されてますけど。

コードの切り貼りしたいだけなら、結果がどうあれ、その状況を楽しめばいいんじゃないでしょうか。
そういうことなら、他人に正解(?)を求めるのは楽しみ方として間違っていると思います。
巻き込まないでください。
オフトピック
同じことを3回繰り返したら、もはやサンプルとしての価値もない。

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

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

#97

投稿記事 by keito94 » 7年前

ごめんなさい、座標をずらす部分をむやみにいじってしまいました…
No.81の当たり判定のアルゴリズムの左右の当たり判定の部分は完成したのですが、
上下の当たり判定で、めり込んで左の壁まで行ってしまいます。
後、重力の部分を分割してみました。
添付ファイル
Collision.zip
(5.45 KiB) ダウンロード数: 441 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#98

投稿記事 by ISLe » 7年前

オフトピック
現時点で気になることを書き残しておきます。

CCollision::GetXPosition関数などで、キャラ座標はピクセル単位でブロックはタイル単位と異なる座標系が混在しており、さらにキャラ座標は中心が基準となっているところに、さらにx,yなど数値をバラバラにやり取りしているため混乱に拍車をかけている。

タイルのサイズは16ピクセルであるのに、-8~8という範囲(=17ピクセル)を使って重要な判定をしている。

座標およびサイズ情報と当たり判定メソッド(のプロトタイプ)を持つCMoverクラスがあるのに、どうしてそれを使わないのだろうか。
CPlayerはCMoverを継承しているのに、どうしてわざわざ情報をバラバラにして引数に渡すのだろうか。

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

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

#99

投稿記事 by keito94 » 7年前

ISLe さんが書きました: タイルのサイズは16ピクセルであるのに、-8~8という範囲(=17ピクセル)を使って重要な判定をしている。
今の発言を受けて、当たり判定のサイズを変更してみました。
添付ファイル
Collision.zip
(5.45 KiB) ダウンロード数: 473 回
デバッグは投げ捨てるものではない。
今までの質問でこれは学んだこと。
質問する時は、必ずちゃんと調べた上に問題をもとにした仕様書を作ってから質問すること。
仕様書の大切さを改めて思い知った…。

ISLe
記事: 2650
登録日時: 14年前
連絡を取る:

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

#100

投稿記事 by ISLe » 7年前

keito94 さんが書きました:後、重力の部分を分割してみました。
これ、何か目的があるんですよね。
コードに手を加えるというのは、バグを生む可能性を含みます。
プログラムを台無しにするのと引き換えにしてもいいくらい意味のあることなんでしょうね。
ちょっと分からないので説明していただけませんか。


もし、万が一、意味もなくやったのだとしたら…
(※下線加筆)
keito94 さんが書きました:ごめんなさい、座標をずらす部分をむやみにいじってしまいました…
No.81の当たり判定のアルゴリズムの左右の当たり判定の部分は完成したのですが、
上下の当たり判定で、めり込んで左の壁まで行ってしまいます。
後、重力の部分を分割してみました。
正に舌の根の乾かぬうちにってやつですね。


No.67に書きました。
CPlayer::Moveから除けたいのは、あたり判定(を直接呼び出している)部分。

カオス過ぎていますぐそれはできないので、少しずつ改善しようとしているところ、ことごとく先回りして改善の芽を潰す。
ある意味keito94さんの才能かもしれませんね。

返信

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