ページ 1 / 1
RECT型を使ってのめり込み防止の実装について。
Posted: 2017年6月25日(日) 19:59
by keito94
C++初心者です。
http://dixq.net/forum/viewtopic.php?f=3 ... 1の言うことに従って、
RECT型で当たり判定を実装していますが、当たり判定の部分は実装できました。
めり込み防止の部分となるとどうも考えがつきません。
今現在僕が考えているルーチンは、
①プレイヤーが衝突したら、地面の座標を返す。
②地面の座標とプレイヤーの座標を比較する。
③めり込んでいたら、プレイヤーをずらして当たる前にまで戻す。
なのですが…。
RECT型の当たり判定で、地面の座標を新しく作る予定の当たり判定プログラムに教える方法がわかりません。
どうすればいいのでしょうか?
それを教える方法が完成すれば後は楽にできるんです。
添付してあるコードは一部のみなので、単体では動きません。
Re: RECT型を使ってのめり込み防止の実装について。
Posted: 2017年6月26日(月) 17:41
by ISLe
keito94 さんが書きました:RECT型で当たり判定を実装していますが、当たり判定の部分は実装できました。
ここは、敵キャラとの当たり判定だけにRECT使っています。
いまやろうとしているのは、ブロックとの当たり判定にRECTを導入しようということではないのでしょうかね。
そのまんま引っ張ってきて、無意味だ無駄だってやりとりを何度も繰り返すばかり。
コード理解しようとしてくださいよ。
オフトピック
そもそもネットに転がってるサンプルコードがなあ。
Re: RECT型を使ってのめり込み防止の実装について。
Posted: 2017年6月26日(月) 18:12
by keito94
ごめんなさい…。
RECTは敵キャラとの当たり判定でしたか…。
でも、ルーチンはそのままなんですが、効率が良くて汎用性のあるブロック当たり判定がどうしても思いつかないんです…。
衝突したブロックの座標を返すサンプルコードをくれませんか…。
ISLe さんが書きました:
コード理解しようとしてくださいよ。
わかりました…。
Re: RECT型を使ってのめり込み防止の実装について。
Posted: 2017年6月26日(月) 18:44
by ISLe
keito94 さんが書きました:効率が良くて汎用性のあるブロック当たり判定がどうしても思いつかないんです…。
衝突したブロックの座標を返すサンプルコードをくれませんか…。
いますぐやるべきは、CCollision::CheckMap関数にある、キャラとブロックの当たり判定をRECT構造体を使うように書き換えること。
いまは動作そのものは変えなくていい。むしろ変えてはいけない。
衝突したブロックの座標云々はRECT構造体使って衝突したブロックが分かるようにできてから。
言っちゃあなんですが、効率が良いとか汎用性があるとか、keito94さんに判断できるんですか?
Re: RECT型を使ってのめり込み防止の実装について。
Posted: 2017年6月26日(月) 21:00
by keito94
ISLeさんに言われてRECT構造体に書き換えてみたのですがバグだらけです。
なにか、アドバイスはないのでしょうか?
Re: RECT型を使ってのめり込み防止の実装について。
Posted: 2017年6月27日(火) 17:22
by ISLe
keito94 さんが書きました:ISLeさんに言われてRECT構造体に書き換えてみたのですがバグだらけです。
なにか、アドバイスはないのでしょうか?
バグだらけなのはわたしの責任なんですか?
何か書いても、書いた内容を理解する気はないように見えるし、無関係なところも含めてあちこちテキトーにいじくり回して問題を増やすし、さらにはその責任を押し付けられるのでは、何も書きたくないすなあ。
No.1に添付してるRectCollision.cppとか、大元からめちゃくちゃいじくり回してるけど、No.5ではわざわざIntersectRect関数とは別に関数作ってたりするし、ほんとにコードいじくり回すだけで理解してないんだなって思います。
#もちろん理解した上で使わないという選択肢はある。
コードいじくり回す時間を、コードを理解する時間に回して欲しい。
CCollision::CheckMap関数には、もうひとつ別の大きな問題があるんだけど、keito94さんが自力でそれに気付くのは無理かな。
RECT構造体使って、点でなく形での当たり判定を想像したら、それに気付くと期待するのだけど、想像しないから。
それと、いま気づいたんですが…
keito94 さんが書きました:③めり込んでいたら、プレイヤーをずらして当たる前にまで戻す。
「当たる前にまで戻す」?
また方針転換ですか?
あるいは、そもそもRECT構造体を使う理由を理解してないってことでしょうか。
Re: RECT型を使ってのめり込み防止の実装について。
Posted: 2017年6月27日(火) 17:57
by keito94
ISLe さんが書きました:
また方針転換ですか?
ごめんなさい…。
ブロックに当たったら当たる前の座標に戻すでしたね…。
頭のなかで勘違いしてしまいました…。
後、添付しているソースコードでは、左の当たり判定の部分は実装されたのですが、右の当たり判定の部分がバグっているようです。
Re: RECT型を使ってのめり込み防止の実装について。
Posted: 2017年6月27日(火) 18:15
by keito94
http://dixq.net/forum/blog.php?u=2409&b=6635
これを読んで下さい。
今のコードはどうせバグバグ祭りだと思いますので…。
理由はそこに書かれてあると思います。
Re: RECT型を使ってのめり込み防止の実装について。
Posted: 2017年6月27日(火) 18:35
by たいちう
プログラムを書けないのは仕方ないが、
せめて最後にISLeさんにお詫びやお礼は書けないのだろうか。
Re: RECT型を使ってのめり込み防止の実装について。
Posted: 2017年6月27日(火) 19:04
by usao
オフトピック
問題点は プログラミング言語の種類 とは違うところにあると思うのですが…
理解して → 書く
言語の種類が問題になるのは後者の側の作業.
問題点が前者側にあるのなら,言語を変えても改善しないのではないかと危惧します.
Re: RECT型を使ってのめり込み防止の実装について。
Posted: 2017年6月27日(火) 19:08
by keito94
ISLeさん、今まで色々ご迷惑をかけてごめんなさい…。
でも、C言語の素質がないことをようやく知りました…。
では、ありがとうございました!!
Re: RECT型を使ってのめり込み防止の実装について。
Posted: 2017年6月28日(水) 16:28
by ISLe
keito94 さんが書きました:ブロックに当たったら当たる前の座標に戻すでしたね…。
頭のなかで勘違いしてしまいました…。
いやいや、さらに酷くなってますよ。
A.「当たったら」とは
当たっていない状態から当たっている状態への『変化』
B.「当たっている」とは
その時点で当たっているという『状態』
AとBの違いが分からないですかねえ。
状態×変化のAは、状態だけのBより複雑になるのは明らか。
わたしはずっと「めり込みの補正」と表現してますよ。
Pythonを学んでこのような日本語のニュアンスの違いが分かるようになるといいですね。
Re: RECT型を使ってのめり込み防止の実装について。
Posted: 2017年6月28日(水) 16:54
by ISLe
オフトピック
やたらサンプルコードよこせ言ってたけど、うちのブログは参考にならんかったかな。
まあ、2010年の記事だしJavaだし。
実験要素山盛りなのでそのままコピペはよろしくないから、せめて自力で見付けられるくらい意欲ある人でないとな。
Re: RECT型を使ってのめり込み防止の実装について。
Posted: 2017年6月28日(水) 16:58
by NNN
やや雑談な書き込みです
前の方の質問でことごとくズレた受け取り方をするので
デバッグ頑張れという形の認識になっただけマシかなと思っていましたが
最近のスレの流れを見ると残念な形になってますね
感覚的にはアクションゲームを作るには圧倒的に技術不足で
オセロや五目並べレベルの簡易ゲームを作るべきなのでは?という感じ。
下積みって大事だな〜と思いました
Re: RECT型を使ってのめり込み防止の実装について。
Posted: 2017年6月29日(木) 18:40
by ISLe
CCollision::CheckMapを改造。
戻り値のRECTは、矩形ではなく、各方向に何ピクセルめり込んでいるかを表す。
rcMoverは、CMoverクラスから直接持ってきたいところだが、引数周りを変えると変更点が多くなりすぎるので先送りとする。
コード:
RECT CCollision::CheckMap(int x, int y) {
RECT rcMover = {
x + mPt[0].x,
y + mPt[0].y,
x + mPt[7].x + 1,
y + mPt[7].y + 1,
};
RECT rc, rcResult;
CopyRect(&rcResult, &rcMover);
DWORD w_map = Game->MapData().GetMapWidth();
DWORD h_map = Game->MapData().GetMapHeight();
DWORD w_chip = Game->MapData().GetChipWidth();
DWORD h_chip = Game->MapData().GetChipHeight();
//レイヤー1が四角形床。
for (DWORD y_map = 0; y_map < h_map; y_map++) {
for (DWORD x_map = 0; x_map < w_map; x_map++) {
int index = Game->MapData().GetValue(1, x_map, y_map);
#if 0
//斜め床の判定。
int indexslope = GetChipLayerNum(x, y);
int src_x = (index % Game->GetBitCount()) * cwidth;
int src_y = (index / Game->GetBitCount()) * cheight;
//坂道の当たり判定があるのなら、-2を返す。
if (indexslope != 0) {
//res.x = -2;
//res.y = -2;
return res;
}
#endif
if (index == 0) {
// 四角いブロック
RECT rcBlock = { x_map*w_chip, y_map*h_chip, (x_map + 1)*w_chip, (y_map + 1)*h_chip };
if (IntersectRect(&rc, &rcMover, &rcBlock)) {
// めり込んでいる分だけ領域を削る
if (rc.left == rcMover.left) { // 左寄り
if (rc.right > rcResult.left) rcResult.left = rc.right;
}
if (rc.top == rcMover.top) { // 上寄り
if (rc.bottom > rcResult.top) rcResult.top = rc.bottom;
}
if (rc.right == rcMover.right) { // 右寄り
if (rc.left < rcResult.right) rcResult.right = rc.left;
}
if (rc.bottom == rcMover.bottom) { // 下寄り
if (rc.top < rcResult.bottom) rcResult.bottom = rc.top;
}
}
}
}
}
// めり込んでいる量に変換
rcResult.left -= rcMover.left;
rcResult.top -= rcMover.top;
rcResult.right = rcMover.right - rcResult.right;
rcResult.bottom = rcMover.bottom - rcResult.bottom;
return rcResult;
}