質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.46%
C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Q&A

解決済

1回答

1387閲覧

2Dアクションゲームで空中の当たり判定でめり込み量の補正アルゴリズムが知りたい

退会済みユーザー

退会済みユーザー

総合スコア0

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

0グッド

0クリップ

投稿2020/02/21 02:28

点と線の交差判定を使って当たり判定のコードです。このコードは地面に居る時は正方形の下側のX軸判定を無効かすることによって左右に動いた時地面の一番端に補正されないようにしています。

困っているのは空中でp->isGround == false の時に壁とぶつかった時にどっちの軸に補正するかどうかの処理のアルゴリズムの実装に困っています。
提示画像Aの時にY軸が上昇中かまたは下降中でXが左右に動いているときX軸だけ修正したい。
提示画像のBの時 Y軸が修正中でXが移動しているかしていないときにY軸だけ修正したい
提示画像Cの時にX軸が移動してるかしないときでもy軸だけ修正したい。

この三つのアルゴリズムを実装したいです。一つずつは作れますが条件分岐するときにA,B,Cもすべて同じ方向を向く時がるため方向を使った修正は無理だと考えお手上げです。

イメージ説明

/*地面に着いているときの処理*/ if(p->isGround == true){ float Fix_x_up = -1; float Fix_x_down = -1; float Fix_y_left = -1; float Fix_y_right = -1; /* X 軸 */ Position now_x_up(p->pos->x + ((p->CELL / 2) - 1), p->pos->y); Position future_x_up((p->pos->x + ((p->CELL / 2) - 1)) + offset_x, p->pos->y); Position now_x_down(p->pos->x + ((p->CELL / 2) - 1), (p->pos->y + (p->CELL - 1))); Position future_x_down((p->pos->x + ((p->CELL / 2) - 1)) + offset_x, (p->pos->y + (p->CELL - 1))); DrawFormatString(400, 400, GetColor(255, 255, 255), "Collisition",true); int r = cross_pos(&Result, now_x_up, future_x_up, Position((mp->get_X() + mp->size_width) + ( (mp->size_width / 2) - 1), mp->get_Y() + mp->size_height), Position((mp->get_X() + mp->size_width) + ((mp->size_width / 2) - 1), (mp->get_Y() + mp->size_height ) - 1 )); if( r != 0) { NoCol_x = false; DrawFormatString(400, 400, GetColor(255, 255, 255), "now_x_up", true); if(p->speed->x > 0){ Fix_x_up = Result->x - ( (p->CELL - 1) + (p->CELL /2) ); }else if(p->speed->x < 0) { Fix_x_up = Result->x + (p->CELL / 2) + 1; } delete(Result); Result = NULL; } /* r = cross_pos(&Result, now_x_down, future_x_down,Position((mp->get_X() + mp->size_width) + ((mp->size_width / 2) - 1), mp->get_Y() + mp->size_height), Position((mp->get_X() + mp->size_width) + ((mp->size_width / 2) - 1), (mp->get_Y() + mp->size_height) - 1)); if (r != 0) { NoCol_x = false; DrawFormatString(400, 500, GetColor(255, 255, 255), "now_x_down", true); if (p->speed->x > 0) { Fix_x_down = Result->x - ((p->CELL - 1) + (p->CELL / 2)); //Fix_x_down = now_x_down.x; }else if (p->speed->x < 0) { Fix_x_down = Result->x + (p->CELL / 2) + 1; //Fix_x_down = now_x_down.x; } delete(Result); Result = NULL; } /* /*X 補正*/ if (Fix_x_up != -1 || Fix_x_down != -1) { if (p->speed->x > 0)/*右*/ { if (Fix_x_up == -1) { p->pos->x = Fix_x_down; } else if(Fix_x_down == -1) { p->pos->x = Fix_x_up; } else { if (Fix_x_up < Fix_x_down) { p->pos->x = Fix_x_up; } else { p->pos->x = Fix_x_down; } } } else if (p->speed->x < 0)/*左*/ { if (Fix_x_up == -1) { p->pos->x = Fix_x_down; } else if (Fix_x_down == -1) { p->pos->x = Fix_x_up; } else { if (Fix_x_up < Fix_x_down) { p->pos->x = Fix_x_down; } else { p->pos->x = Fix_x_up; } } } } /*********************************************** Y軸 *************************************************************************************/ /* Y 軸 値設定*/ Position now_y_left(p->pos->x, p->pos->y + ((p->CELL / 2) - 1)); Position future_y_left(p->pos->x, (p->pos->y + (p->CELL / 2) - 1) + offset_y); Position now_y_right(p->pos->x + (p->CELL - 1), p->pos->y + ((p->CELL / 2) - 1)); Position future_y_right(p->pos->x + (p->CELL - 1), (p->pos->y + (p->CELL / 2) - 1) + offset_y); ofs << "left: " <<future_y_left.y << std::endl; ofs << "right: " <<future_y_right.y << std::endl; r = cross_pos(&Result,now_y_left,future_y_left, Position(mp->get_X(), mp->get_Y() + (mp->size_height / 2) - 1), Position(mp->get_X() + ((mp->size_width) - 1), mp->get_Y() + (mp->size_height / 2) - 1)); if(r != 0) { NoCol_y = false; DrawFormatString(350, 600, GetColor(255, 255, 255), "now_y_left", true); // ofs<<"y_col left"<<std::endl; /*落下*/ if (p->speed->y > 0) { Fix_y_left = (Result->y - ((p->CELL) + ((p->CELL / 2)) - 1)); //ofs << Fix_y_left->y << std::endl; // p->speed->y = 0; /* 補正座標がおかしくなってる書き間違てた。 */ p->isGround = true; p->isJump = false; } /*ジャンプ*/ else if (p->speed->y < 0) { //p->speed->y = 0; Fix_y_left = (Result->y + (p->CELL / 2) + 1); ofs<<Fix_y_left<<std::endl; } delete(Result); Result = NULL; } r = cross_pos(&Result, now_y_right, future_y_right, Position(mp->get_X(), mp->get_Y() + (mp->size_height / 2) - 1), Position(mp->get_X() + (mp->size_width - 1), mp->get_Y() + (mp->size_height / 2) - 1)); if (r != 0) { // ofs << "y_col right" << std::endl; NoCol_y = false; DrawFormatString(350, 300, GetColor(255, 255, 255), "now_y_right", true); /*ジャンプ*/ if(p->speed->y < 0) { Fix_y_right = (Result->y + (p->CELL / 2) + 1); ofs << Fix_y_right << std::endl; // p->speed->y = 0; /*落下*/ }else if (p->speed->y > 0) { // p->speed->y = 0; Fix_y_right = (Result->y - ((p->CELL) + ((p->CELL / 2)) - 1)); p->isGround = true; p->isJump = false; // ofs << Fix_y_right->y << std::endl; } } /* Y 補正 */ if(Fix_y_left != -1 || Fix_y_right != -1) { /*落下*/ if(p->speed->y > 0){ p->speed->y = 0; ofs<<"GGG"<<std::endl; if(Fix_y_left == -1) { p->pos->y = Fix_y_right; }else if(Fix_y_right == -1) { p->pos->y = Fix_y_left; }else{ if(Fix_y_left < Fix_y_right) { p->pos->y = Fix_y_left; }else{ p->pos->y = Fix_y_right; } } /*ジャンプ */ }else if (p->speed->y < 0) { p->speed->y = 0; if (Fix_y_left == -1) { p->pos->y = Fix_y_right; } else if (Fix_y_right == -1) { p->pos->y = Fix_y_left; } else { if (Fix_y_left < Fix_y_right) { p->pos->y = Fix_y_right; } else { p->pos->y = Fix_y_left; } } } } }else if(p->isGround == false )/*空中で上からぶつかった時*/ { /* NOTE */ }

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

似たような質問内容でたびたび回答依頼なるものが届くのですが,
本件,何度か回答として書いた話の内容ならば,
A,B,Cを場合分けとか考える必要もなく適用可能なのではないのか?と思っているのですが,どうなんでしょうか?
この(リンク先の)内容では何かがダメなのでしょうか?

投稿2020/02/21 02:48

fana

総合スコア11708

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

fana

2020/02/21 02:51

もしも,過去の同内容(に外野からは見える)質問において,他の方の回答内容を採用された結果が現在の状態,といったことなのであれば,回答依頼はそちらの方に飛ばさないと,現状コードを土台とした改善策みたいなのは得られにくいのではないかと思います. 少なくとも私個人は「この回答のリンクで示した話でやれるだろう」という考えでいるわけですので…
退会済みユーザー

退会済みユーザー

2020/02/21 03:02 編集

リンク先を確認しました失礼しました。しかし移動中でY軸が上か下に動いているときにY軸だけ補正するにはどうしたらいいのでしょうか?例を上がると 天井や地面に左右に移動しながらの時です。Y軸だけを修正したいです。
fana

2020/02/21 03:06

> 移動中でY軸が上か下に動いているときにY軸だけ補正する というのは,この質問の図で言えばBやCの状況を指しているのでしょうか? この回答内容の話では,所望移動量のうちの衝突面の法線方向成分を除去するという処理になります.なので,例えば ・図中Bの矩形が「左下側から右上側に動こうとした結果(ジャンプか何かして)」なのであれば,右方向への移動量は減じられることなく,矩形の上辺が黒い壁の底辺に触れる位置にY座標が修正される結果となるでしょう. ・図中Cが「単純に地面の上を左右に移動しようとしている状況において,重力の影響を加味した結果」だとすれば,やはり左右への移動量は殺されることなく,矩形の可変が黒い地面(?)の上辺に接する位置に修正される結果となるでしょう. (…と,思っているのですが.)
fana

2020/02/21 03:18

繰り返しっぽくなりますが… 私は上記のように思って(思い込んで)いるわけですので,その内容に対して 「いやいや,それだとこういう状況でこうなるからダメだろ」とか 「そもそも欲しい結果というのが,その話で得られる結果とは異なるのだが?」みたいな話が展開されない限りは,「私との間の話は」現状よりも進展しないのではないかと思います. また,あなたが今現在実装している処理内容とは相容れない内容なのであれば,そもそもこの回答内容に沿う話を何かしら続けること自体に意味もない(あなたの現状に対しては利が無い)ことになります. (「お前の言うことは1つの話としてはわからんでもないが,それはそれ,今の実装を捨てるわけにもいかないのだ」みたいなのは普通にあるでしょうから) なので,毎度回答依頼枠の無駄遣い(確か個数制限がありますよね)になってしまっていないのかを危惧しています.
fana

2020/02/24 02:19

「好意」は無いと思うのですが,一応コメントは書いておきました. まず,アルゴリズムのバグなのか実装のバグなのかを切り分けるところから始められるとよいのではないかと思います. (他者から見たら)未知のアルゴリズムを大量のifとelseでもって実装したコードのどこの部分がバグであってそれをどう直せば良いのか?といったところを突き止める所まで他者に頼るのは至極困難であろうと思います.
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.46%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問