今現在C++とDXライブラリで見下ろしの2Dアクションゲームを作ろうとしているのですが
マップとキャラの当たり判定がよくわからなくて投稿しました。
わかりづらいかもしれないです。すみません。
今現在マップチップの要素が1だったらブロックという風に設定して、
for文でマップチップの配列の要素が1だったら、ブロックのデータ(画像サイズと座標を)を生成して、
そのブロックのデータの二次元配列を作って、それをfor文で調べて、プレイヤーとブロックの四角の当たり判定をこれまたfor文で行って、
プレイヤーの移動予定先が壁ならその進もうとしてるスピードの分だけマイナスをして、進まなくしているのですが、
この方法でやると斜めにぶつかった時に壁伝いに進むことができず、壁とぶつかった時点で左右または上下に動くことができずに
その場で止まってしまいます。
また、キャラのサイズとブロックのサイズが同じなのでブロックとブロックの間をプレイヤーがうまく潜り抜けることができなくて
困っています。プレイヤーの当たり判定を行うときのサイズを小さくしてみたら、入り込めはするものの、角にぶつかっては止まって、ぶつかっては止まっての繰り返しになってもどかしい動きになってしまいます。
そして、壁とぶつかった時に進んだ分だけマイナスするという風にしているので斜めにぶつかった時に少し食い込んでしまい、
そのまま斜め移動を押しっぱなしにすると普通に進むよりスピードが出てしまい壁をすりぬけたりすることがあります。
斜めの移動を横に移動するスピードと同じにする方法もわからず、てんてこまいになっています。
予定では斜めに壁にぶつかっても左右や上下に移動することができて、ぬるぬるとブロックの隙間を潜りぬけられるようにしたいと思っています。こんな感じの当たり判定です
[youtube][/youtube]
恐縮ですが、やり方を教えてください。お願いします。
また現在、ゲームプログラミングの館やそのほかいろんなサイトを見て回っていますが、なかなか自分の実力にあったサイトがなくて
自分なりにそのサイトの解説を見てプログラムをしてみても、惜しいところまではいくんですが結局うまくいかず、現状、質問するしか躓いた時の打開方法がなくて何回も質問するはめになってしまうかもしれないので
なにかいいサイトや教材があったらぜひ教えてください。
よろしくお願いします。
マップとキャラの当たり判定について
Re: マップとキャラの当たり判定について
オフトピック
「思いついただけ」の話なので,信ぴょう性は慎重に判断してください.
そんな話ではダメだと思われる場合には無視していただいて構いません.
そんな話ではダメだと思われる場合には無視していただいて構いません.
「移動前の座標(x0,y0)」と,
「(何も移動を阻害するものが無い場合に)移動後としたい目標地点座標(x1,y1)」
とを結ぶ線分上の,「壁に当たらない」範囲のうち,最も(x1,y1)に近い位置(x',y') を求めれば,
とりあえずそこまでは動いていい.
↓
(※2)
「そのままこれ以上進んだら,どのように壁に当たってしまうのか」という情報から,
残りの移動に関して,目標地点(x1,y1)を修正することができるはず.
例えば,X方向に問題があるなら,目標地点を(x',y1)に修正するとか.
↓
(※3)
(x0,y0) ← (x',y')
(x1,y1) ← 目標地点修正結果
として更新し,(※1)に戻る.(それ以上進めなくなるまで繰り返し.)
…とかだとどうでしょうか.
Re: マップとキャラの当たり判定について
u返信ありがとうございます。
「そのままこれ以上進んだら,どのように壁に当たってしまうのか」とありますが
どのように壁に当たってしまうのかという情報をどういう風に調べれば良いでしょうか?
今現在はxとyの値を調べて、例えば右に移動していている状態で壁に当たったらそのxの移動量を0にする、
上に移動してるときに壁にぶつかったらyの移動量を0にするというやり方をしています。
どういう風にしてどのように壁にぶつかったかという情報を求めますか?
また最も近い位置というのはどういう風に求めればよいでしょうか。
質問ばかりですみません。プログラミングはまだ全然できないのでどういう風に設計すればいいのかわからなくて質問が多くなりました。ごめんなさい。
「そのままこれ以上進んだら,どのように壁に当たってしまうのか」とありますが
どのように壁に当たってしまうのかという情報をどういう風に調べれば良いでしょうか?
今現在はxとyの値を調べて、例えば右に移動していている状態で壁に当たったらそのxの移動量を0にする、
上に移動してるときに壁にぶつかったらyの移動量を0にするというやり方をしています。
どういう風にしてどのように壁にぶつかったかという情報を求めますか?
また最も近い位置というのはどういう風に求めればよいでしょうか。
質問ばかりですみません。プログラミングはまだ全然できないのでどういう風に設計すればいいのかわからなくて質問が多くなりました。ごめんなさい。
Re: マップとキャラの当たり判定について
要するに,
・めり込む直前の位置(キャラクタと壁とが「接触」する位置)まで移動
これで,「移動したい量」のうちの何割かは達成できる
・残りの(未達成である)移動したい量について,接触点の法線方向成分を捨てる
という処理を,「残りの移動したい量」が0になるまで繰り返せばよいのではないか,という.
>最も近い位置というのはどういう風に求めればよいでしょうか。
キャラクタがある方向に移動した結果として何かに「めり込んだ」のであれば,
「移動した方向に」めり込んだ深さだけ,「逆方向に」戻してあげればよいのではないでしょうか.
そうすれば前記(x',y')が求められるように思います.
>どういう風にしてどのように壁にぶつかったかという情報を求めますか?
(x',y')にキャラクタが位置するとき,ブロックとキャラクタが「接している」ことになるわけですが
その接触点の法線方向を「何らかの方法で」決定すればよいかと思います.
例えば…
キャラクタとブロックとが「めり込んでいる」という当たり判定ができているのであれば,
当然ながら,キャラクタの当たり判定領域のうちの「どこ」がブロックにめり込んでいるのか,ということがわかっているはず.
そのめり込んでいる領域中のある1点についての移動した軌跡:移動前の座標と今の(=めり込んでいる時点での)座標とを結ぶ線分
を考え,その軌跡線分とブロックの4辺との交差判定を行うとかすれば,
ブロックのどの辺にキャラクタが当たったのかを推定(近似)できたりしませんか.
・めり込む直前の位置(キャラクタと壁とが「接触」する位置)まで移動
これで,「移動したい量」のうちの何割かは達成できる
・残りの(未達成である)移動したい量について,接触点の法線方向成分を捨てる
という処理を,「残りの移動したい量」が0になるまで繰り返せばよいのではないか,という.
>最も近い位置というのはどういう風に求めればよいでしょうか。
キャラクタがある方向に移動した結果として何かに「めり込んだ」のであれば,
「移動した方向に」めり込んだ深さだけ,「逆方向に」戻してあげればよいのではないでしょうか.
そうすれば前記(x',y')が求められるように思います.
>どういう風にしてどのように壁にぶつかったかという情報を求めますか?
(x',y')にキャラクタが位置するとき,ブロックとキャラクタが「接している」ことになるわけですが
その接触点の法線方向を「何らかの方法で」決定すればよいかと思います.
例えば…
キャラクタとブロックとが「めり込んでいる」という当たり判定ができているのであれば,
当然ながら,キャラクタの当たり判定領域のうちの「どこ」がブロックにめり込んでいるのか,ということがわかっているはず.
そのめり込んでいる領域中のある1点についての移動した軌跡:移動前の座標と今の(=めり込んでいる時点での)座標とを結ぶ線分
を考え,その軌跡線分とブロックの4辺との交差判定を行うとかすれば,
ブロックのどの辺にキャラクタが当たったのかを推定(近似)できたりしませんか.
Re: マップとキャラの当たり判定について
私の場合は
1フレームの処理でx軸とy軸を別々に判定と修正をしています
まずx軸のみ増減させる
すぐに壁の当たり判定をする
当たっていたら
xの加算値が+なら 当たった壁のx値 × 横のブロックサイズ-横のmysize で位置を修正する
xの加算値がーなら (当たった壁のx値+1)× 横のブロックサイズ で位置を修正する
次にy軸のみ増減させる
すぐに壁の当たり判定をする
当たっていたら
yの加算値が+なら 当たった壁のy値 × 縦のブロックサイズ-縦のmysize で位置を修正する
yの加算値がーなら (当たった壁のy値+1)× 縦のブロックサイズ で位置を修正する
こうすれば 斜めにぶつかった時でも壁伝いに進めます めり込みもないです
スピードの分だけマイナスとかもしなくてもいいですよ^^
1フレームの処理でx軸とy軸を別々に判定と修正をしています
まずx軸のみ増減させる
すぐに壁の当たり判定をする
当たっていたら
xの加算値が+なら 当たった壁のx値 × 横のブロックサイズ-横のmysize で位置を修正する
xの加算値がーなら (当たった壁のx値+1)× 横のブロックサイズ で位置を修正する
次にy軸のみ増減させる
すぐに壁の当たり判定をする
当たっていたら
yの加算値が+なら 当たった壁のy値 × 縦のブロックサイズ-縦のmysize で位置を修正する
yの加算値がーなら (当たった壁のy値+1)× 縦のブロックサイズ で位置を修正する
こうすれば 斜めにぶつかった時でも壁伝いに進めます めり込みもないです
スピードの分だけマイナスとかもしなくてもいいですよ^^
Re: マップとキャラの当たり判定について
ちょっと極端な(?)絵ではありますが…
黒矢印の方向に移動しようとした場合,壁に当たった結果としては赤で示したような移動になってほしいのではないかと思いますが,
X座標だけの処理→Y座標だけの処理 という順で処理を行うと,青で描いた移動になってしまいませんか.
また,黒矢印がもっと長ければ,壁をすり抜けてしまうことも有り得そうです.
(そのことが 問題である と言っているわけではないです.)
黒矢印の方向に移動しようとした場合,壁に当たった結果としては赤で示したような移動になってほしいのではないかと思いますが,
X座標だけの処理→Y座標だけの処理 という順で処理を行うと,青で描いた移動になってしまいませんか.
また,黒矢印がもっと長ければ,壁をすり抜けてしまうことも有り得そうです.
(そのことが 問題である と言っているわけではないです.)
Re: マップとキャラの当たり判定について
>黒矢印の方向に移動しようとした場合,壁に当たった結果としては赤で示したような移動になってほしいのではないかと思いますが,
>X座標だけの処理→Y座標だけの処理 という順で処理を行うと,青で描いた移動になってしまいませんか.
>また,黒矢印がもっと長ければ,壁をすり抜けてしまうことも有り得そうです.
確かにusao様の言う通りで 正確 に移動処理をするなら私の方法は問題がありますね
私のやり方は一回の移動量が少ない場合で誤差があまり気にならないゲームなど限定されますね
黒矢印の方向については
一回の移動量が3分の1程度の移動だったら赤で示したような移動になりそうです
移動量が少ない場合でもブロックの角に当たった場合は正確な移動処理にはなりませんが
今回の動画のようなゲームだと気にならないレベルだと思っています
そして、一回の移動量がブロックサイズ以上なら壁をすり抜けてしまうので
一回の移動量をブロックサイズ未満にして複数判定など対処が必要になりますね
ということでかなり限定されますので
もし正確に移動処理をやりたい場合は 遠慮なく私の方法をスルーしてくださいー^^;
>X座標だけの処理→Y座標だけの処理 という順で処理を行うと,青で描いた移動になってしまいませんか.
>また,黒矢印がもっと長ければ,壁をすり抜けてしまうことも有り得そうです.
確かにusao様の言う通りで 正確 に移動処理をするなら私の方法は問題がありますね
私のやり方は一回の移動量が少ない場合で誤差があまり気にならないゲームなど限定されますね
黒矢印の方向については
一回の移動量が3分の1程度の移動だったら赤で示したような移動になりそうです
移動量が少ない場合でもブロックの角に当たった場合は正確な移動処理にはなりませんが
今回の動画のようなゲームだと気にならないレベルだと思っています
そして、一回の移動量がブロックサイズ以上なら壁をすり抜けてしまうので
一回の移動量をブロックサイズ未満にして複数判定など対処が必要になりますね
ということでかなり限定されますので
もし正確に移動処理をやりたい場合は 遠慮なく私の方法をスルーしてくださいー^^;
Re: マップとキャラの当たり判定について
> 私のやり方は一回の移動量が少ない場合で誤差があまり気にならないゲームなど限定されますね
「1回の移動距離が常に十分小さいために 実際上は問題にならない」
ということは かなり多そう(?) だと思います.
別の話ですが,
「移動量が十分に小さい」という前提があれば,例えば,
「ある瞬間に壁にめり込んでいても別にいいじゃないの?」という考え方もできると思います.
ちょこっとだけめり込んでいていようが別に目立たないので,
各時刻において…
・キャラクタが壁にめり込んだ状態になることを許容する
・めり込んでいる場合には,それが解消する方向にいくらか押し戻す力をキャラクタに加える
みたいな処理でも十分かもしれません.
「1回の移動距離が常に十分小さいために 実際上は問題にならない」
ということは かなり多そう(?) だと思います.
別の話ですが,
「移動量が十分に小さい」という前提があれば,例えば,
「ある瞬間に壁にめり込んでいても別にいいじゃないの?」という考え方もできると思います.
ちょこっとだけめり込んでいていようが別に目立たないので,
各時刻において…
・キャラクタが壁にめり込んだ状態になることを許容する
・めり込んでいる場合には,それが解消する方向にいくらか押し戻す力をキャラクタに加える
みたいな処理でも十分かもしれません.