コンテンツへ
#123
by keito94 » 6年前
ISLe さんが書きました:ブロックとキャラの当たり判定を書き直す必要がある、ということですよ。 keito94さんは、そこで使うべき方法を既に知っています。 RECT型の当たり判定について こんどは返信がもらえるように頑張りましょう。 坂道の実装までまだまだ遠いので、新たにトピたてて仕切り直したほうが良いかもしれません。
#122
by ISLe » 6年前
#121
#120
#119
ISLe さんが書きました: 場所はCCollision::CheckMapで合ってると書いたのに。
ISLe さんが書きました: 前提から外れたことを同じやり方でやろうとしたらどうなりますかね。
#118
keito94 さんが書きました:もしかしてめり込み防止の部分ですか?
#117
ISLe さんが書きました: “坂道を実装するには邪魔になりそうな前提条件”は、たぶんkeito94さんが完璧だと思っているところ、にありますよ。
#116
#115
keito94 さんが書きました:(今のコードでは)左へ上へ行ってしまうバグが起きてしまうことです。
keito94 さんが書きました:その問題というのは、CheckMapや、マップチップを確認する部分にあります。
#114
ISLe さんが書きました: 分かっているなら、どこがどうして問題なのか、説明して見せてください。
#113
#112
ISLe さんが書きました: むしろ、坂道を実装するには邪魔になりそうな前提条件は排除していきたいが。
#111
keito94 さんが書きました:ですが、地上に着地せずにめり込んで左に移動してしまいます。
#110
keito94 さんが書きました:現在考えているのは、衝突したら一ブロックずらした座標で判定するということです。 (キャラの座標が中央基準なので…。) ですが、地上に着地せずにめり込んで左に移動してしまいます。
keito94 さんが書きました:左右の判定は一応完成しました。
#109
#108
keito94 さんが書きました:ISLeさんのご指摘を受けて、ブロックの単位ではなく、座標で判定して見るようにしてみました。
コード:
int bpos = block.x * 16; int brpos = bpos + 32; int blpos = bpos - 32; bool Debug = true; if (brpos < *myx) { *myx = (float)((block.x - 1) * 16 + 8 + OffsetR - 0.1f); } if (blpos > *myx) { *myx = (float)((block.x + 1) * 16 + 8 + OffsetL + 0.1f); }
int bpos = block.y * 16; int bbpos = bpos - 8; int btpos = bpos + 8; bool Debug = true; if (bbpos < *myy) { *myy = (float)((block.y - 1) * 16 + 8 + OffsetD - 0.1f); *jcount = 0; *gflag = true; } if (btpos > *myy) { *myy = (float)((block.y + 1) * 16 + 8 + OffsetU + 0.1f); }
keito94 さんが書きました:でも、また新たなバグが発生してしまいました…。 実行すると、着地せずに画面外に落下します。
#107
#106
keito94 さんが書きました:正確には当たり判定のコード自体は完成していたのですが、
if (block.x < *myx) { *myx = (float)((block.x - 1) * 16 + 8 + OffsetR - 0.1f); }
keito94 さんが書きました:なかなか理想通りの動きになりません…。 どうしたら、理想通りの動き(地上にいるときだけGroundFlagがtrueになったまま)になるのでしょうか?
#105
#104
#103
ISLe さんが書きました:No.67に書きました。 CPlayer::Moveから除けたいのは、あたり判定(を直接呼び出している)部分。 カオス過ぎていますぐそれはできないので、少しずつ改善しようとしているところ、ことごとく先回りして改善の芽を潰す。 ある意味keito94さんの才能かもしれませんね。
keito94 さんが書きました:No.81の当たり判定のアルゴリズムの左右の当たり判定の部分は完成したのですが、 上下の当たり判定で、めり込んで左の壁まで行ってしまいます。
#102
ISLe さんが書きました: 正に舌の根の乾かぬうちにってやつですね。
ISLe さんが書きました: CPlayer::Moveから除けたいのは、あたり判定(を直接呼び出している)部分。
ISLe さんが書きました: 現状、座標補正によって、当たり判定の範囲外に移動するため、フレームごとにCPlayer::GroundFlagのオン/オフが繰り返される状況。 キャラの足元にブロックがあるあいだ、CPlayer::GroundFlagがオンのまま維持されて欲しい。
#101
#100
keito94 さんが書きました:後、重力の部分を分割してみました。
keito94 さんが書きました:ごめんなさい、座標をずらす部分をむやみにいじってしまいました… No.81の当たり判定のアルゴリズムの左右の当たり判定の部分は完成したのですが、 上下の当たり判定で、めり込んで左の壁まで行ってしまいます。 後、重力の部分を分割してみました。
#99
ISLe さんが書きました: タイルのサイズは16ピクセルであるのに、-8~8という範囲(=17ピクセル)を使って重要な判定をしている。
#98
#97
#96
keito94 さんが書きました:壁に当たった時、キャラをずらすアルゴリズムの例を上げてくれますか。
keito94 さんが書きました:とりあえず、No.81で言われた方法にしてみました。 現在確認されているバグは、 着地すると、キャラがぴょんぴょん跳ねる。 左の壁に衝突すると、キャラが上に上がる。 となります。
#95
#94
keito94 さんが書きました:なん…だと…。地上にいるというのは振る舞いだけだったのか…。
ISLe さんが書きました:今度こそ取り除かれたのではないのでしょうか?
#93
ISLe さんが書きました: キャラが地面にめり込むと地面に触れないぎりぎりの位置に座標補正されます。 次のフレームで、それは地上に立っていることになるのでしょうか。
ISLe さんが書きました: 前に一度CCollision::GetMoveからも取り除かれたのに、今は復活してますね。
#92
keito94 さんが書きました:現在は移動量に依存していた部分を取り除いたところです。
keito94 さんが書きました:CPlayer::GroundFlagはそれが真になっていると、地上にいるかのように振る舞うフラグです。(混乱を招く回答すいません…。)
#91
#90
ISLe さんが書きました: 移動量撤廃の方針を続けるならこのトピで続ければよいのでは。
#89
#88
#87
#86
#85
ISLe さんが書きました: コードを上から下になぞるだけでなく、実際に動いているときの流れを意識してください。
#84
#83
#82
ISLe さんが書きました: #むしろ無限ループを楽しんでください。
ISLe さんが書きました: 移動量を使わないでどうやって判定するのか?といういちばんのキモを質問しないのですね。 やっとここまで問題点をピンポイントであぶり出せたのに。
ISLe さんが書きました: 間違った理解でコードをいじるからおかしなことになるのと違いますか。
#81
#80
#79
#78
#77
keito94 さんが書きました:CCollisionと言うのは当たり判定の処理を行うクラスです。
keito94 さんが書きました:CPlayer::GroundFlagと言うのは、キャラが地上に居るかどうかを管理する変数です。 CPlayerで移動処理をして、CCollisionで当たり判定をチェックします。 ジャンプした、もしくは空中にいる時はGroundFlagが偽になります。 地上にいる時はGroundFlagが真になります。 GroundFlagが真になっている時は落下を行わないはずです。 これで間違いないですよね?
keito94 さんが書きました:あと、質問用のソースコードをリポジトリに上げてみました。
keito94 さんが書きました:追記:今のコードで確認されている不具合は、左の当たり判定と、右の当たり判定が同時に出ていることと、落下を全くしないことと坂道を登りきると、 キャラが消えてしまうことです。
#76
#75
ISLe さんが書きました:No.47で書いたように、プレイヤーキャラは、地面に着いているから落下しない、のでなく、(プレイヤーキャラ自身が)落下する状態でないから落下しない、ようにすれば落下しなくなります。 そういう目的に使える情報は既にCPlayerクラスにありますよね。
#74
ISLe さんが書きました: (プレイヤーキャラ自身が)落下する状態でないから落下しない
#73
keito94 さんが書きました:僕の頭の中のコードでは、どう頑張っても、めり込み補正の部分とY座標の部分で移動量に頼ってしまいます。 なので、移動量に頼らないめり込み防止のサンプルコードをください。
keito94 さんが書きました:なお、今上げたコードでは、常に落下しているので、最終的にはキャラが画面外に移動します。
#72
#71
#70
#69
keito94 さんが書きました:ISLeさんが考えている当たり判定のアルゴリズムに変えてみました。
keito94 さんが書きました:addxとaddyを0にしないとまともに動作しません。(このステージでは関係ないんですが…。)
#68
#67
移動関数() { aを生成 当たり判定と補正を行う関数(p, a) { if (p + a がめり込んでいる) { pをめり込んでいない位置に補正 aをリセット } pにaを加える } }
移動関数() { aを生成 pにaを加える 当たり判定と補正を行う関数(p) { if (p がめり込んでいる) { pをめり込んでいない位置に補正 } } }
移動関数() { aを生成 }
移動関数() { aを生成 pにaを加える }
移動関数() { aを生成 pにaを加える } 当たり判定と補正を行う関数(p) { if (p がめり込んでいる) { pをめり込んでいない位置に補正 } }
#66
keito94 さんが書きました:出力する引数は、ポインタをつけろというわけですね…。
keito94 さんが書きました:あと、入れ子化していた部分を修正しました。
#65
#64
#63
keito94 さんが書きました:ISLeさんが指摘した、移動先座標での判定の部分を、移動量を足した判定に変更してみました。 CheckMapの部分は、addxかaddyのどちらかが、0でなければ正しく動作しない仕様となってます。
#62
#61
#60
#59
by purin52002 » 6年前
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関数で表示している }
#58
#57
#56
by usao » 6年前
#55
#54
ISLe さんが書きました:ログインしたユーザーしか見ることができない場所に書かれた他人の文章を、ログインせず誰でも見ることができる場所に張り付ける行為。非常識ではないですか?
#53
keito94 さんが書きました:ISLeさん、言い方が悪かったみたいですね…。 今書いているコードがスパゲッティコードになってるのは認めます。 しかし、どうしても、坂道の当たり判定が、今のしか考えられないので、 あなたが考えている方の当たり判定のサンプルコードを提示してください。
#52
#51
ISLe さんが書きました:そんな基本的なところに気付けないくらいにコードが複雑化している現状がある。 わたしはそれを解決するのが急務だと考えた。
ISLe さんが書きました: keito94さんはさっさと坂道を実装して終わらせたいと考えている。 であればかみ合うはずがないっすね。
#50
by keito94 » 7年前
ISLe さんが書きました: わたしの書いた文章をちゃんと読みましたか。 文字をなぞるだけでなく、意味を理解しましたか。
ISLe さんが書きました:> 理解する気がないと思われるところに、説明を補完する役割としてのサンプルコードを提示する意義を感じませんし、そういうサンプルコードはお望みでありませんよね。
#49
by ISLe » 7年前
#48
ISLe さんが書きました: わたしが違う方法を使うというだけで、間違っているとは言っておりません。
#47
keito94 さんが書きました:そうか、Collision.cppの当たり判定は間違っていたのか…。
#46
by purin52002 » 7年前
#45
#44
keito94 さんが書きました:Collision.cppに書かれてある当たり判定のアルゴリズムを残したままでいいので
#43
#42
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 }
#41
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; }
#40
keito94 さんが書きました: オフトピックええっ!?Y座標を坂道に合わせて動かせばいいんですか!? ちょっと甘かったです…。
#39
#38
//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; } }
#37
#36
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; } }
#define SLOPE -1 const int SLOPE -1 ; enum ChipType { SLOPE = -1 } ; if( slope.y == SLOPE ) { ... }
#35
#34
#33
purin52002 さんが書きました:purin52002 さんが書きました: 坂道とプレイヤーの線分が交差していたらColSegments関数にtrueを返してほしくて、 でもColSegments関数はfalseを返すし、 これはColSegments関数の不具合ということですか? keito94 さんが書きました:違います違います!! ColSegment自体は正しく動作しています!!
purin52002 さんが書きました:purin52002 さんが書きました: 坂道とプレイヤーの線分が交差していたらColSegments関数にtrueを返してほしくて、 でもColSegments関数はfalseを返すし、 これはColSegments関数の不具合ということですか?
purin52002 さんが書きました: 坂道とプレイヤーの線分が交差していたらColSegments関数にtrueを返してほしくて、 でもColSegments関数はfalseを返すし、
keito94 さんが書きました:違います違います!! ColSegment自体は正しく動作しています!!
keito94 さんが書きました:あの、ブログ見ましたけど…。 移動後の座標ではなく、現在の座標だったのですか!? ボクも気づきませんでした…。 すいませんが、現在の座標ベースでの当たり判定のアルゴリズムを教えてくれませんか?
#32
#31
POINT slope = CheckSlope((int)*myx, (int)newy, Slope, Layer,SlopeCond);
#30
#29
#28
#27
#26
keito94 さんが書きました:purin52002 さんが書きました: これは、真になるであろうパラメータを与えても真にならないということですか? そ、そういうことではなくてですね…。 坂道のブロックにいると判定されているときに何故か真にならないということです。
purin52002 さんが書きました: これは、真になるであろうパラメータを与えても真にならないということですか?
purin52002 さんが書きました:理解力ががが^p^ 坂道ブロックにいるときは真と判定してほしいのに、真と判定されない。 という不具合だと思ったのですが違うのですか?
#25
#24
ページトップ