横スクロールアクションの衝突判定とイベント

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
taka

横スクロールアクションの衝突判定とイベント

#1

投稿記事 by taka » 13年前

横スクロールアクションの衝突判定で質問させて下さい
言語はobjective-Cです

ブロックの上に、ブロックと同じ大きさの触れたら死亡するイベントを置いているのですが、
ブロックと死亡イベントの間に横から突っ込むと死亡イベントに触れてしまう問題が発生しています



50x50のブロックを基準にゲームを作成しています
右移動時の問題として、お願いします。

右に移動時は、移動先の座標と衝突判定マップを照らしあわせ、
衝突判定あれば、自分の中心座標を
(X:衝突があったブロックの一つ左のブロックのX位置*50+自分のサイズの半分, Y:変わらず)
と補正してきっちりブロックに添うようにしています。
衝突判定マップはブロック単位で衝突か否かを保持しています

これは問題ないように動いています。

衝突判定では、自分の 「右上」「右下」 の位置それぞれで判定するのですが、その2つの座標を
右下は (X:中心X座標+自分のサイズ半分 Y:中心Y座標-自分のサイズ半分)
右上は (X:中心X座標+自分のサイズ半分 Y:中心Y座標+自分のサイズ半分)

として衝突ブロックを確認しようとした所、
衝突判定マップの位置を (座標/50)で取得しているため、自分がピッタリ(0.0)にいたとしても
右下はマップ(0.1) 右上はマップ(1,1) を見に行ってしまいます
(中心座標が(25,25)で、上記の計算をすると右下の座標(0,50) 右上の座標(50,50)となるため)
ちなみに左下はマップ(0,0)、左上はマップ(1,0)です。左下以外、外側を見に行っている状態です
これを修正するため、
右下は (X:中心X座標+自分のサイズ半分 -1 Y:中心Y座標-自分のサイズ半分)
右上は (X:中心X座標+自分のサイズ半分 -1 Y:中心Y座標+自分のサイズ半分 -1)
と、少し小さめに衝突判定をしていました。


そこで問題が発生しています

 ×
 □
 □
--------
×:触れたら死亡イベント
□:ブロック

とある場合、死亡イベントとブロックの間辺りに右向けに突っ込んでも、
衝突判定の後にイベントチェックしているので
通常なら死亡イベントに触れない位置に補正されるので死亡することはありません。

が、上記の通り判定を1ドットずらしてしまっているため、突っ込み方によっては
衝突判定がその1ドット分は許容してしまい、
補正しないから1ドットイベントに触れ、死亡する、というバグが発生してしまっています。

数日取り組んでいますが、一向に実装方法が思いつきません
イベントを一回り小さくする、補正を0.00001 くらいにする、といった逃げ腰な回避方法くらいです。


どうかアドバイスを頂けないでしょうか

ライブラリの都合上、基本的に自機は中心座標で動かします。自分のサイズは取得できます。
よろしくお願いします。

taka

Re: 横スクロールアクションの衝突判定とイベント

#2

投稿記事 by taka » 13年前

ごちゃごちゃしてしまったので、
要点だけ書いておきます


衝突判定のため、自分の右上と右下の座標を取得し、それぞれの座標に対応する衝突マップをチェックしたいが
右上の座標からは今いるマップの右上の番号を、右下の座標からは右隣りの番号を取得してしまう

何が間違っているのだろうか?
自キャラも1ブロックの大きさだが、このままでは1x1ブロックの通路が通れない。

・衝突マップは、1か0が入っており、ブロック単位で作られている。[0][1][0][1][1][0] 等
・衝突マップ番号の取得は、チェック座標/50 で取得している
・自分の右上の座標は、中心座標+自分サイズの半分で計算。
 例えば画面の一番左下にいる場合、中心座標は(25,25)。自分サイズの半分を足して、(25 + 25, 25 + 25) → (50,50)が右上座標とする。
  一番左下なので衝突マップは(0,0)をチェックしたいのだが、でもこれでは50で割ると(1,1)をチェックしにいってしまう
・つまり、自キャラの外側で衝突判定している

・これを解決するため座標の計算のとき、足すのを自分の半分の25ではなく、24を足して (49,49)にしてみた。
 →右上の座標としてはこっちのが正しいと思うが、1ドット分壁にめり込むまで衝突判定・補正をしないので、
 触れることのできない壁の上にあるイベントに触れてしまう


という感じです
解決策を教えてください・・・

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 横スクロールアクションの衝突判定とイベント

#3

投稿記事 by softya(ソフト屋) » 13年前

ブロック単位で当たり判定せずドット座標系で当たり判定してはどうでしょうか?
それなら当たりサイズも自在に調整できます。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka

Re: 横スクロールアクションの衝突判定とイベント

#4

投稿記事 by taka » 13年前

ありがとうございます
しかし、使用しているマップツールがブロック単位でしか出力できないため
できる限りはブロック単位での対応としたいのですが、ドット単位でないと厳しいのでしょうか・・・

違和感があるのは、(0,0)に50ドットの画像をおくと右上は(50,50)となりますが、
(0.0)から(0,50)までを数えると51ありますよね
この辺でズレが出ているのかとも考えているのですが、怪しさはありますか?

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 横スクロールアクションの衝突判定とイベント

#5

投稿記事 by softya(ソフト屋) » 13年前

>違和感があるのは、(0,0)に50ドットの画像をおくと右上は(50,50)となりますが、

なりませんよ。(49,49)です。(0,0)を含むわけですから。
50を足したら隣の画像です。

なので、
>中心座標は(25,25)。自分サイズの半分を足して、(25 + 25, 25 + 25) → (50,50)が右上座標とする。
(25+25-1,25+25-1)が正しい右上(右下?)です。

【補足】よく分からなかったら2x2ドットの隣のブロックを計算するとか図に描けるように単純化してみてください。


>しかし、使用しているマップツールがブロック単位でしか出力できないため
>できる限りはブロック単位での対応としたいのですが、ドット単位でないと厳しいのでしょうか・・・

ブロック単位は表示の問題だけですから当たりの座標系はドットに変換して行えば良いだけだと思いますが。
【補足】
マップはブロックそのまま、イベントだけドット判定って方法もありでしょうね。
それとも上の話で問題解決でしょうか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka

Re: 横スクロールアクションの衝突判定とイベント

#6

投稿記事 by taka » 13年前

ああ、すみません
画像を置くと、ではなくと足すと、でした

(0,0)に画像をおくと右上は(49,49)なのに
0 にその画像サイズを足すと 50 になるのが引っかかっていまして

>(25+25-1,25+25-1)が正しい右上(右下?)です。

やはりその分の補正が必要なのですね、ありがとうございます


>ブロック単位は表示の問題だけですから当たりの座標系はドットに変換して行えば良いだけだと思いますが
例えばマップ上で(0,2)の位置に衝突ブロックがある場合、
BLOCK = 50 として
(0 x BLOCK , 2 x BLOCK) から w:BLOCK h:BLOCK の範囲が当たりブロック
これを画面分、又は自分の周囲行う、という感じでしょうか?
ちょっとやってみようと思います


すみません、ちなみに、はじめの考え方のどこが間違っているのでしょうか・・・?
中心座標+サイズの半分だと、50になり、隣のブロックをチェックしてしまう。
だから中心座標+サイズの半分-1 とすれば 49 になり正しい位置を確認できる。が、
そうするとブロックと同サイズでブロックと縦に並んで配置されているイベントに、壁にめり込みながら触れれてしまう

ぴったり自機の座標毎で判断できれば、衝突が発生して押し戻されるのでイベントに触れないのにと。
自機より1ドット小さめに衝突判定してしまっています。

これの理由付けして頂けないでしょうか?
長々とすみません

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 横スクロールアクションの衝突判定とイベント

#7

投稿記事 by softya(ソフト屋) » 13年前

taka さんが書きました: すみません、ちなみに、はじめの考え方のどこが間違っているのでしょうか・・・?
中心座標+サイズの半分だと、50になり、隣のブロックをチェックしてしまう。
だから中心座標+サイズの半分-1 とすれば 49 になり正しい位置を確認できる。が、
そうするとブロックと同サイズでブロックと縦に並んで配置されているイベントに、壁にめり込みながら触れれてしまう

ぴったり自機の座標毎で判断できれば、衝突が発生して押し戻されるのでイベントに触れないのにと。
自機より1ドット小さめに衝突判定してしまっています。

これの理由付けして頂けないでしょうか?
長々とすみません
プログラムがどうなっているか分からないですが、壁と同じ大きさであるのなら上で書いたように大きさを足す時に25-1すれば触れていないはずです。[すこし訂正]
もし有るとしたら壁に触れて座標補正する前にイベントをチェックしてしまっている可能性ぐらいでしょうか。
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

taka

Re: 横スクロールアクションの衝突判定とイベント

#8

投稿記事 by taka » 13年前

イベントのチェックは最後の最後で行なっているので・・・
やはりどこかおかしいんでしょうね

if (右キーが押されたら){
 ・右にちょっと移動
 if ( [衝突判定:[getMapCellUR]] || [衝突判定:[getMapCellUD]]){
  ・補正処理
 }  
}
  
としていまして、衝突判定の関数は、セルの座標を渡せば1か0が帰ってきます

座標からマップ座標に変換する処理に問題があると思うのですが、

getMapCellUR{
return ((int)((self.point.x + self.contentSize.width*0.5) - CL_MARGIN) / BLOCK,
(int)((self.point.y + self.contentSize.height*0.5) - CL_MARGIN) / BLOCK);
}

CL_MARGIN = 0.5
BLOCK = 25

としています。(ブロックのサイズがさっきと違うのは、実行時に表示が二倍になるためです。ややこしくてすみません)

こうすると、マップで (2,0)(2,1)にブロック、(2,2)にイベントがある場合、
自分の座標Xは75(2ブロック目の真ん中)までしか進めないはずが、75.9まで進めます。76にならないと衝突が発生しません
75を超えるとイベントに触れてまうので困っています。

どこか怪しい所はありますか・・・?
すみません、お願いします

taka

Re: 横スクロールアクションの衝突判定とイベント

#9

投稿記事 by taka » 13年前

すみません、最後ですが、ブロックのサイズが混ざってしまいました。
1ブロック25だとして

自分の座標Xは37.5(2ブロック目の真ん中)までしか進めないはずが、37.9まで進めます。38にならないと衝突が発生しません

と訂正します。

アバター
softya(ソフト屋)
副管理人
記事: 11677
登録日時: 15年前
住所: 東海地方
連絡を取る:

Re: 横スクロールアクションの衝突判定とイベント

#10

投稿記事 by softya(ソフト屋) » 13年前

37(75?)になると何故イベントが発生するんでしょうか?
右座標の件をちゃんとしていればイベントが発生しないはずでは?
イベントの当たり判定もgetMapCellURを使っているのですか?
by softya(ソフト屋) 方針:私は仕組み・考え方を理解して欲しいので直接的なコードを回答することはまれですので、すぐコードがほしい方はその旨をご明記下さい。私以外の方と交代したいと思います(代わりの方がいる保証は出来かねます)。

閉鎖

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