ページ 11

衝突判定…

Posted: 2013年11月06日(水) 05:42
by 土門
オブジェクトリストからプレイヤーだけを取出し、
障害物の位置が記載されているマップ配列と衝突判定するプログラムで
衝突すると止まる、という処理をさせています。
(障害物の四面、どこから当たったかを判定してしています)

が、障害物の画像とはズレた場所で衝突しています。
衝突処理の部分のプログラムがおかしいということはわかっているのですが、、
悩み、弄り、を繰り返し、もうどこが間違っているのか、よくわからなくなりました。

あたり判定を何度も触ってこられた方なら一目で
間違っている部分がわかるかと思います。
すみませんが、このバカにどこがおかしいのか
教えてやってください。

コード:

リストの頭からケツまで移動するfor文の中です
イテレータは宣言してます

ここでは左側にあるブロックとの衝突判定を記載します。
16×16の障害物画像に対して、左側から主人公がかなりめり込んでからストップしますし、
X軸が少しずらすともう左に通過してしまいます。
どうやら障害物のあたり判定の幅がうまく機能していない様に思います。
障害物はMAPCHIP_SIZE(16)で判定をとっているはずなのに、です。
ちなみに主人公の画像imageサイズは20×20で、
主人公のあたり判定サイズboundsは16×16にしています。

//左側にあるブロックとの判定
if((*it)->プレイヤーである && (*it)->進行方向が左である){
  int j =(int)((*it)->getposX())/MAPCHIP_SIZE;
  int i =(int)((*it)->getposY() + ((*it)->getimage_h() - (*it)->getbounds_h())/2-1)/MAPCHIP_SIZE;

  if(マップ配列[i][j] == 障害物である){
    if( (*it)->getposX() + ((*it)->getimage_w() + (*it)->getbounds_w())/2 > j*MAPCHIP_SIZE &&
      (*it)->getposX() + ((*it)->getimage_w() - (*it)->getbounds_w())/2 < j*MAPCHIP_SIZE + MAPCHIP_SIZE &&
      (*it)->getposY() + ((*it)->getimage_h() + (*it)->getbounds_h())/2 > i*MAPCHIP_SIZE &&
      (*it)->getposY() + ((*it)->getimage_h() - (*it)->getbounds_h())/2 < i*MAPCHIP_SIZE + MAPCHIP_SIZE)
    {
	  //判定後の処理
      (*it)->ストップ!
    }
  }
}

//右側にあるブロック~以下省略

Re: 衝突判定…

Posted: 2013年11月06日(水) 14:41
by 土門
質問、ソースの不備がありましたら
お申し付けください。

ちなみにゲームはシューティングゲームです。
ジャンプとか無く、画面をプレイヤーが縦横無尽に動いてる状態での話です。

一般的な弾と弾、敵とプレイヤーだの、プレイヤーと障害物の矩形衝突判定は簡単です
(どんな状況だろうととにかく当たったら、「当たった」と判断すればいいだけだから)
ですが、当たった方向を考慮して、判定後の処理を書く場合は面倒なことになりますよね?
しかも、ただの障害物として「進めない」処理をしたいだけなのです。
シューティングゲームにおいて、これが面倒でした。

最初は、移動先の座標と旧座標と常に保存している状態にして
衝突したら主人公は旧座標へ戻す方法を考えました。
そうすれば、いちいち当たった側面を考える必要が無いからです。
が、画面が強制スクロールしているのを想定すると、
障害物もスクロールさせるわけです。
すると主人公は押されなければなりませんが、「旧座標に戻す処理」だと
おかしなことになりますよね?
「押される」状態にするには、やはり、プレイヤーの座標に値を加えなければなりません。
というわけで、前にいた場所に戻す、という作戦は使えません。

で、今に至る、という感じです。
ですが、今回の判定の問題自体は、別のところにあると思っています。
矩形衝突判定の場所です。
ここです。

コード:

int j =(int)((*it)->getposX())/MAPCHIP_SIZE;
  int i =(int)((*it)->getposY() + ((*it)->getimage_h() - (*it)->getbounds_h())/2-1)/MAPCHIP_SIZE;
 
  if(マップ配列[i][j] == 障害物である){
    if( (*it)->getposX() + ((*it)->getimage_w() + (*it)->getbounds_w())/2 > j*MAPCHIP_SIZE &&
      (*it)->getposX() + ((*it)->getimage_w() - (*it)->getbounds_w())/2 < j*MAPCHIP_SIZE + MAPCHIP_SIZE &&
      (*it)->getposY() + ((*it)->getimage_h() + (*it)->getbounds_h())/2 > i*MAPCHIP_SIZE &&
      (*it)->getposY() + ((*it)->getimage_h() - (*it)->getbounds_h())/2 < i*MAPCHIP_SIZE + MAPCHIP_SIZE)
    {
ネットのシューティング講座ですが、
私が見るかぎり、画像サイズ=あたり判定サイズで書かれたものばかりです。
自分は、画像サイズとあたり判定の範囲が別々のサイズです。
その辺の解説、情報を知りたいのですが、、、無いので自分は自信が持てません。
案の定、失敗していますし。。。

どこが間違っているのか、教えてください。

Re: 衝突判定…

Posted: 2013年11月06日(水) 15:29
by h2so5
画像サイズで判定していないのに衝突判定の処理で画像サイズを使用しているのはおかしいと思います。
座標とあたり判定サイズさえ分かれば判定できるはずですから。

Re: 衝突判定…

Posted: 2013年11月06日(水) 15:47
by 土門
やっとレスついた、、、
ありがとうございます!
h2so5 さんが書きました:画像サイズで判定していないのに衝突判定の処理で画像サイズを使用しているのはおかしいと思います。
ただ、すみません、ちょっとわかりにくいので
もう少し詳しく説明して頂けませんか?
プレイヤーの画像サイズのことを言ってるのですか?
設定したあたり判定を画像の真ん中にもってくるためには、計算に必要だと思うんですけど。

Re: 衝突判定…

Posted: 2013年11月06日(水) 15:57
by h2so5
画像を基準にするから複雑になるんですよ。
プレイヤーの座標を画像の左上ではなくて最初から真ん中で管理すれば衝突判定時に画像サイズは必要ないのですから。

Re: 衝突判定…

Posted: 2013年11月06日(水) 15:58
by usao
「画像と判定は別」という扱いなのに,計算に用いるデータが画像依存というのはどうなんでしょう?
ということだと思います.

ところで,
障害物の有無は16x16のグリッドサイズで設定されているのに対して,
プレイヤはそれとは関係なく(最低でも画素単位で?)移動できる という話なのだと思うのですが,
プレイヤの判定サイズがチップと同じ16x16であれば,
「プレイヤの左側」をチェックするのに 2つのグリッドを見なければならないように思うのですが,違いますか?

コード:

90度回転してるけど… ↑方向が「左」だとして,
  ■■
   □
みたいな状況とか考えると.

Re: 衝突判定…

Posted: 2013年11月06日(水) 16:12
by 土門
>>usaoさん
レスありがとうございます!

>プレイヤの判定サイズがチップと同じ16x16であれば,

あ、すみません、実際はプレイヤのサイズは16×16より大きくなります。
今は仮で作っていまして、そうさせてもらってます。
usao さんが書きました:「画像と判定は別」という扱いなのに,計算に用いるデータが画像依存というのはどうなんでしょう?
"画像に依存した計算になってる"、というのはどういう状態がそういう状態なのか、わかりません。
自分としては、画像のサイズを用いて、あたり判定サイズを画像の真ん中にもってきて
その範囲と、16×16のサイズの障害物とが当たっているかどうか、を矩形衝突判定しているつもりなのですが、、、
画像サイズに依存?

Re: 衝突判定…

Posted: 2013年11月06日(水) 16:24
by 土門
h2so5 さんが書きました:画像を基準にするから複雑になるんですよ。
プレイヤーの座標を画像の左上ではなくて最初から真ん中で管理すれば衝突判定時に画像サイズは必要ないのですから。
おっしゃっていることはわかります。
しかし、おことばですが
プレイヤだけでなく、ゲーム制作において画像座標は左上が基本となっていますし、
自分もさまざまな場面で、左上を基軸に画像の設置場所は構想します。
プレイヤや一部判定を行うオブジェクトに対してだけ、
いちいち座標軸を真ん中で管理する方が自分はちょっと面倒だと感じるのですが。。。
今回の自分の計算方法にはミスがあるとは思いますが、
この計算式もひな形として完成してしまえば、
コリジョンクラスにて判定を行う計算式の中で
画像サイズを利用していること自体はなんの手間もなくなると思うんですが、
この考え方自体、ナンセンスなのでしょうか?
ネットでも左上で管理してるものが大半ですし、
真ん中で管理しない不都合ってあるのでしょうか。
(けして、反論しているのではありません、ただ、座標管理を真ん中にしろと言われたのは初めてですので)

Re: 衝突判定…

Posted: 2013年11月06日(水) 17:55
by usao
>あ、すみません、実際はプレイヤのサイズは16×16より大きくなります。

大きくなるなら なおさら複数のグリッドとのチェックが必要になるように思います.


(繰り返しになっちゃうけど)
「座標を真ん中で持つこと」自体が争点ではなく,
当たり判定の計算に際して,本来関係ないはずの画像サイズが用いられているという点が
指摘されているのだと思います.

「getposX(),getposY()で得られる「何らかの座標」と,
 当たり判定を決めるデータ
 の2つだけで判定処理するべきでしょ,表示の都合とかこの場所では関係ないわけだし」
という.

Re: 衝突判定…

Posted: 2013年11月06日(水) 18:08
by ISLe
土門 さんが書きました:一般的な弾と弾、敵とプレイヤーだの、プレイヤーと障害物の矩形衝突判定は簡単です
(どんな状況だろうととにかく当たったら、「当たった」と判断すればいいだけだから)
ですが、当たった方向を考慮して、判定後の処理を書く場合は面倒なことになりますよね?
しかも、ただの障害物として「進めない」処理をしたいだけなのです。
シューティングゲームにおいて、これが面倒でした。
面倒なことにはなりません。

天の声が「ここまで下がれ」と指示するだけで、実際に下がるのはプレイヤーの仕事にすれば良いのです。
プレイヤーの見た目と当たり判定の相違は、プレイヤーのオブジェクトだけが知っていれば良いしそれ以外が知っている必要はなくむしろ知ってはいけないのです。


とにもかくにもまずは、矩形の端を示す一時変数(left,right,top,bottomとか)にいったん代入するようにしたらコードが分かりやすくなるのではないでしょうか。
幅を引いて2で割るとオフセットが求まると思いますが、幅を足して2で割って何を求めたいのかよく分かりません。

Re: 衝突判定…

Posted: 2013年11月06日(水) 18:59
by ISLe
getposX/getposY関数は、関数名からはそのように見えないが、画像の左上を指していなければならない。
画像の基準となる左上座標は存在するが、当たり判定の左上基準座標は存在せず画像の中心を基準にした配置である。

言ってることとやっていることに矛盾する部分があるし、各数値がそれぞれに依存しているので、一箇所いじればあちこちに影響するでしょう。
いちばんの問題は本人がそれに気付いていなかったり気付いても改める気がない(ように見える)ことだと思います。

Re: 衝突判定…

Posted: 2013年11月06日(水) 21:28
by softya(ソフト屋)
DXライブラリならセンター座標で描画する関数も有るので、センター座標にすることは何ら問題ない気がするんですがダメなのでしょうか。

Re: 衝突判定…

Posted: 2013年11月07日(木) 01:11
by 土門
usaoさん
レスありがとうございます。
usao さんが書きました: 複数のグリッドとのチェックが必要になるように思います.
あー、忘れていました。
自分が今判定を行っているグリッドの先(隣)のグリッドも調べる、
というのを過去に組んだことがありましたが、そういうのを組み込んでるか?
というご指摘でしょうか?なら大丈夫です。
土門 さんが書きました:「getposX(),getposY()で得られる「何らかの座標」と,
当たり判定を決めるデータの2つだけで判定処理するべきでしょ
なるほど、そういうご指摘でいうなら、確かに無駄に情報が多いですね、、
ISLeさんのご指摘内容にもあるように、本来そういうのは
接触判定の計算式の中にぶっこまずに、自分のクラス内で出しておけ、と
そういうことでしょうか?


ISLeさん
レスありがとうございます。
ISLe さんが書きました:天の声が「ここまで下がれ」と指示するだけで、実際に下がるのはプレイヤーの仕事にすれば良いのです。
プレイヤーの見た目と当たり判定の相違は、プレイヤーのオブジェクトだけが知っていれば良いしそれ以外が知っている必要はなくむしろ知ってはいけないのです。
はい、そのつもりです。
あくまでわかりやすくするために、貼付けたソースでは直球で「プレイヤー」と書いてますが
基本的に、すべての結果は一度ゲームマネージャークラスが受け取って、
そこからプレイヤーに命令が行く(渡す)様にしてます。
ということでいいんですよね?
ISLe さんが書きました:矩形の端を示す一時変数(left,right,top,bottomとか)にいったん代入するようにしたらコードが分かりやすくなるのではないでしょうか。
つまり、自分のクラスで当たり判定のサイズなり、当たり判定の左上なり、出しておけってことでしょうか?
ISLe さんが書きました:getposX/getposY関数は、関数名からはそのように見えないが、画像の左上を指していなければならない
しなければならない、というより、それがデフォルトじゃないですか?
ゲーム制作サイトで、正直、見たことないんですが、
「座標管理を中心に合わせときましょう」とか。
それでも自分は少数派なんでしょうか?
副管理人さんも同じご指摘してますけど、とにもかくにも
ゲーム制作においてオブジェクトはセンター座標で管理しないと駄目なんですか?
ISLe さんが書きました:画像の基準となる左上座標は存在するが、当たり判定の左上基準座標は存在せず画像の中心を基準にした配置である。
へりくつでは無く、画像の中で自分が決めた当たり判定エリアがちょうど画像の真ん中だから
当たり判定で計算する時に基準を真ん中にもってくるのは当然だと思うんですが、、、。
それを、「オブジェクトの座標管理自体をセンターに持って来てないこと自体間違いだ」と言われるのは
なんかしっくり来ません。「センターに持って来てたらラクだよ」くらいならわかりますが、
今、皆さんから「センターに持ってこないことは間違ってる」みたいに言われてる気がするんですが。

ISLeさん、質問させてください。
シューティングゲーム制作において、マップ(障害物の位置情報など)はグリッドによる設定で二次元配列に格納、
その二次元配列を利用して、ピクセル移動しているプレイヤとで接触判定するのって普通に「有り」ですよね?
移動しているオブジェクト同士の判定はすぐ出来るのに、
なぜ今、この当たり判定でこんな面倒なことになってるのかがわかりません。
考えるコツをどうか教えてくださいませんか?


softya(ソフト屋) さん
レスありがとうございます。
softya(ソフト屋) さんが書きました:DXライブラリならセンター座標で描画する関数も有るので、センター座標にすることは何ら問題ない気がするんですがダメなのでしょうか。
センター座標にしないことは駄目なんでしょうか?
そう聴こえるんですが。あくまで、やり方のひとつですよね?
リファレンスのグラフィックデータ制御関数類を確認しましたが
センター座標で描画する関数は探せませんでしたが
DrawGraphまで使うのやめろと言われるとは思いませんでした。
では、皆さんは画像サイズと当たり判定サイズが相違状態の場合
わざわざその「センター座標で描画する関数」で描画してるんですね。

Re: 衝突判定…

Posted: 2013年11月07日(木) 01:31
by softya(ソフト屋)
この業界が長いプログラマーはバグが減らすために保持する情報を極力減らしてシンプルに処理できる様に工夫をしているものです。
なので、混乱の原因(バグの元)を減らせる方法があるのにあえて避ける理由がないという話をしているんだと思います。
全体的なコードが増える方よりコードが減る方法を選択すると言うシンプルな選択肢です。

ちなみに中心座標で描画する関数です。
「DXライブラリ置き場 リファレンスページ」
http://homepage2.nifty.com/natupaji/DxL ... html#R3N10
この関数がなくても、中心座標で管理すれば描画時だけ画像サイズがあれば良いので、他の処理では画像サイズを意識する必然性が減るはずです。

みなさんの中心座標を使うという提案を受け入れてもらえない理由は組んだコードを直したくないという点だけだと思うのですが如何でしょうか。それとも、中心座標では出来ないメリットがあるのでしょうか?

【補足】
その方法に固執するメリット、デメリットを考えて頂ければと思います。

Re: 衝突判定…

Posted: 2013年11月07日(木) 02:43
by 土門
softya(ソフト屋)さん
早い回答をありがとうございます。

ちょっと愚痴っぽく聞こえてしまいそうですが
そうでは無いことをご理解下さい。
まあ初心者の叫びです。
softya(ソフト屋) さんが書きました: なので、混乱の原因(バグの元)を減らせる方法があるのにあえて避ける理由がないという話をしているんだと思います。
全体的なコードが増える方よりコードが減る方法を選択すると言うシンプルな選択肢です。
皆さんが言いたいことはわかるんです。
でも、この掲示板の相談内容を見てて、
「センター座標にすべき」、ましてや「DrawGraphは止めて、DrawRotaGraphを使いましょう」とか
見た事無いんですけど?
なんで今、こうもプログラムの否定から入るんだろうかなってのはありますよ。
いや、自分のプログラムがまだつたないのはわかります、素人なんで。
でも、普段ここを見てる分では、皆さん、その素人の相談者の貼付けた回りくどいソースの流れを尊重した上で
ご指摘やアドバイス、(手間であろうに)ソースの修正とかしてくださってるのに
自分の時は運が悪いのか、やり方なり、ソースなり、根底から覆す話になりまして。
もちろん、それでもありがたいんです。親身になって教えてくださる方々もいますし。
何度も言いますけど、中心座標で考えられていないであろうプログラム
(どこにでもある左上のpos情報で処理が流れているプログラム)
は、幾度とこの掲示板で見かけて来ました。
で、それらのトピはこの流れにはなっておりませんでしたね。
なぜ、自分の場合はこうまで勧められるのか、まずそこの説明をされたいですね。
なぜ、自分のケースの場合は、それのほうがいいのか、を。
その具体的な理由を。

DrawRotaGraphを教えてくださり、ありがとうございます。
しかし、レトロゲームの制作をもっとーとしている自分にとって、
かなり不必要な(生涯利用しない)引数ばかりが目立つ関数で
非常に利用する気にならないのですが、中心座標管理で描画するということで
わざわざこれを覚えた方がいいのでしょうか?
正直、毎度描画のたびにこんな数の引数を打つ方が手間に感じそうですが。。。。

>この関数がなくても、中心座標で管理すれば
>描画時だけ画像サイズがあれば良い

描画の時は画像サイズ情報が要るんですか?
DrawGraphの引数に画像サイズは要らないですよね?

>みなさんの中心座標を使うという提案を受け入れてもらえない理由は
>組んだコードを直したくないという点だけだと思うのですが如何でしょうか。

んなわけありませんよ。
断じて「コードを直したくない」という横着な気持ちから
嫌がっているのではありません。
私は、成長出来るなら成長したいと思ってますよ。
ちゃんと教える人がいて、ちゃんと確認出来るサイトがあるなら、いつでも。
ただ、正直言いまして「中心座標で管理する方法を知らない」んです。
まったくやりかたがわからないんです。
やりかたがわからないのを勧められても、出来ません。
今、自分の知識や技術の中でゲームを作っているわけですし、
そこから少し発展する、くらいのものを求められるなら自力でも調べてやれると思いますが、
いきなり、降って沸いたような、考えもしなかった方法を「それをやればいい」と投げ返されても
こちらは「それしか方法がないわけでは無いですよね?」と、なんとか回避して
自分の知識の中で制作しようとするのは当然な考えだと思いませんか?
ひとつの方法しかないわけじゃないのですし。

そもそもですよ、
Aという方法で頑張って、途中障害にぶちあたり相談して来た者に対して、
「Aだと面倒だよ?Bの方法でやれ」と言い捨てて、
解説もアドバイスも無しに消える方もどうかと思いますよね。
まあ
h2so5 さんが書きました:画像を基準にするから複雑になるんですよ。
プレイヤーの座標を画像の左上ではなくて最初から真ん中で管理すれば
のことですけどね。
ハッキリ言って、そっから流れがおかしくなってますから。
複雑なのかもしれないけども、自分はそれでやろうとしていたのだから
その方向でのアドバイスなり、ソースへのご指摘なりするのが本来の相談の流れだと思うんですけど。
いや、もちろん、別の方法を促すのもありですけど、
だったらそのあとの私の[意味が分からないのでもう少し詳しく教えてください]的な書き込みに
耳を傾けてくれても良かったのではないかと思います。

結局、そっからトピの流れは
私のやり方そっちのけで「センター座標にしろ」になりました。
流れを変えた当人はドロンです。
私だって理解したい。
でも「オブジェクトをセンター座標で管理して考える」的な話、
プログラミングの館にありました?ありませんよね?
(自分は興味が無いので3D系のページはまったく見ていませんが)
で、ゲームプログラミングの館や、この掲示板を漁っても参考となるページが無い。
そんな方法を「お前のやり方を止めて、センター座標でやれ」と言われても、
こちらは「え?」となっているわけです。
知らないことをいきなり勧められる、それって、
もう自分にとって、デメリットではありませんか?
そういうことです。
避けてる理由はそれだけです。

まあ、もひとつ言えば、私の今回の衝突判定のやり方は
ゲーム制作のひとつとして、どっかのサイトの講座的なところなどで
覚えた方法(まったく同じとは言いません、自分はミスもしてますし)なんで
「あり得ない方法」ではないはずです。
それをこの掲示板ではここまで否定されるとは思いませんでした。
いや、否定じゃ無いですね。面倒なんでしょうね。
すべては
h2so5 さんが書きました:画像を基準にするから複雑になるんですよ。
の言葉から始まったんですよ。
計算の中に当たり判定や画像のサイズを入れたところで、
複雑っていうほど複雑じゃないですよね。多分、自分の式が間違っているだけなんで。
その間違った部分を教えてほしかった、ただそれだけのために相談したのに
まったく違う流れになりましたね。
「土門」という名前のせいでしょうかね。目立ってしまったんで。
生意気な奴だから意地悪なレスしてやろう、ないしは答えないでおこう、みたいな。
ほうぼうのトピでよく管理人さんは相談者に名前を統一しろとおっしゃいますが、
こういう弊害があるんで同じ質問や同じゲーム制作内での質問ならともかく、
ほんとまったく関連のない新しい相談をするときは別名でもいいと思うんですよ。
相談するにも同じ名前である必要が有る「場合」なんてこちらでも判断付きますよ。
(ガキが荒らしてるんじゃないんですから)
新しい質問は質問で、心機一転で質問させてくださいよ、ほんと。

Re: 衝突判定…

Posted: 2013年11月07日(木) 09:39
by usao
>「座標を真ん中で持つこと」自体が争点ではなく,
>当たり判定の計算に際して,本来関係ないはずの画像サイズが用いられているという点が
>指摘されているのだと思います.

と書いたのですが… 私が捉え方を間違っているのでしょうか.
「座標を中心で管理しなくてはならない」と言われているわけではない と思います.
「中心で管理すれば複雑さが軽減される」と言われているわけで,言い換えれば,
複雑さを緩和する方法の例 として 中心座標を持つ という方法が挙げられているに過ぎないものと思います.

あるデータの座標を,どこで持つか は自由でしょう.
いろいろなやり方が考えられます.
たまたまそれが 画像描画に都合のいい左上座標であっても 実際は構わないわけです.
座標の原点をどこに取るか?といった問題に対して方法は一意に決まらないでしょう.
ただ,ある場所に取れば扱いやすい,扱いにくい, ということはあるはずで,
現状,何かしらのバグがあり,その原因が不明な中で,
処理内容の複雑さを緩和できるならばする というアプローチは有りだとは思いますよ.
(より扱いやすい,見通しの良い ものはデバッグもよりしやすい というか.)


で,それはそれとして質問内容はあくまでも「衝突の判定がうまくいっていない」なので,
「現状のコードの状態に対して問題点を指摘してくれ」という希望を出すことは
質問者側の立場から言えばもっともな話かと思います.
で,「座標をどこにとるか」の話とは関係ない部分で
「一つのグリッドだけで判定してていいんですか?」という問いかけ(のようなもの)をしてみているのですが,
その点が本当に大丈夫なのかどうかがはっきりしません.
少なくとも提示したコードでは, プレイヤvs一つのグリッド でしか判定が行われないように見えます.
例えばプレイヤが縦方向に4グリッド分のサイズを持っていて,それが左方向に動いたならば
少なくとも,プレイヤ矩形の左側の辺を含むグリッド4個との間で判定を行わねばならないと思うのですが,
現在問題となっている現象の原因とこのこととは無関係だと考えてよいのでしょうか.
オフトピック
>名前
土門さんの昔の質問時に,「私はこの件にこれ以上関わるのを控えます」という旨の宣言?をしましたが,
今回の質問は過去のそれとは別物だと捉え,普通に関わっています.
そこらへんのことは大丈夫です.

Re: 衝突判定…

Posted: 2013年11月07日(木) 09:55
by usao
あと,↑の話に関連して,このコード部分でのiとjの導出方法が気になります.

コード:

int j =(int)((*it)->getposX())/MAPCHIP_SIZE;
int i =(int)((*it)->getposY() + ((*it)->getimage_h() - (*it)->getbounds_h())/2-1)/MAPCHIP_SIZE;
・Y方向については「プレイヤの中心」に対応するグリッドの座標を求めている
・X方向については「左移動時だから」ということで,「プレイヤの左側辺」に対応するグリッド座標を求めている?
のかな,と漠然と思うのですが,これだと

・前述のとおり,やはり1個のグリッド (j,i) としか判定してないのでは?
・ここで使うべき「プレイヤの左側辺」とは,画像の左側辺ではなくて,衝突判定矩形の左側辺 であるべきでは?

…と思うのですが,どうなんでしょう?
オフトピック
あと,どうでもいいかもしれませんが

コード:

const int CenterX = (*it)->getposX() + (*it)->getimage_w()/2;
const int CenterY = (*it)->getposY() +  (*it)->getimage_h()/2;
const int bound_rx = (*it)->getbounds_w()/2;
const int bound_ry = (*it)->getbounds_h()/2;
const int ChipTop = i*MAPCHIP_SIZE;
...
とか書くと,判定計算の箇所が見やすいかもしれませんね.
(計算の回数も減る?)

Re: 衝突判定…

Posted: 2013年11月07日(木) 09:56
by softya(ソフト屋)
>「土門」という名前のせいでしょうかね。目立ってしまったんで。
別段目立つ名前ではないですよ。考え過ぎだと思います。
どちらかというと強固に中心座標に対して反応したので目立ったと感じです。
これは、ご自身にとってメリットの有ることなのだろうか・・・。と言う疑問ですね私の場合。

あと中心座標の話になったのは、左上座標で管理しているからコードがややこしくなり、そのためにバグに遭遇しているのでは?と言う話だと思います。
そうですね。実際にはゲームにより管理すると便利な座標というのは存在します。大抵の2Dゲームなら、画像の下側の中心がゲームとして作りやすくなります。シューティングだと、それこそ中心座標が便利です。
コードを見ると、計算が多くやたら読みづらいので、みなさんこの面倒を直したほうが良いんじゃと思われたんだと思います。

ちなみに、龍神録はキャラクターたちを中心座標で管理しています。
なので書いていないかもしれませんが、中心座標で管理するプログラムはこの掲示板では多発しているはずです。

バグの修正については後で回答しますが usaoさんの言われることが正しいかと思います。検証してから回答しますね。

Re: 衝突判定…

Posted: 2013年11月07日(木) 18:36
by softya(ソフト屋)
検証してみました。意図がよく分からないところが結構あります。
getboundsって画像中心からの当たり範囲を得る関数ではないのでしょうか?

※マークは問題が有ると思われる点。コードを見てみると中心座標で管理したほうが楽そうだと私も思いますよ。
意図がよく分からない計算が有るので解説をお願いします。図に書いてもらったほうが分かりやすいかもです。

コード:

//左側にあるブロックとの判定
if((*it)->プレイヤーである && (*it)->進行方向が左である){
	分かりやすく変数を作って考えます。
	int plx = (*it)->getposX(); ← 左側
	int pcy = (*it)->getposY() + ((*it)->getimage_h() - (*it)->getbounds_h())/2-1; ← 中心? いや、bounds次第では下側に偏ります。※
	int mx = plx / MAPCHIP_SIZE;
	int my = pcy / MAPCHIP_SIZE;
	中心だと仮定して、左側中心が障害物に食い込むまで当たり判定は起こらない。ここですでに問題がある気がします。※
	if(マップ配列[my][mx] == 障害物である){
		(*it)->getposX() + ((*it)->getimage_w() + (*it)->getbounds_w())/2 左端座標+画像幅+当たり範囲の幅の半分 → 画像の幅を超えて当たり判定があります。※
		(*it)->getposX() + ((*it)->getimage_w() - (*it)->getbounds_w())/2 左端座標+画像幅-当たり範囲の幅の半分 → 画像の真ん中に当たり判定があります。※
		(*it)->getposY() + ((*it)->getimage_h() + (*it)->getbounds_h())/2 上端座標+画像高+当たり範囲の高さの半分 → 画像の高さ超えて当たり判定があります。※
		(*it)->getposY() + ((*it)->getimage_h() - (*it)->getbounds_h())/2 上端座標+画像高-当たり範囲の高さの半分 → 画像の真ん中に当たり判定があります。※
	}
}
私の受けたコードの印象を絵にすると、青がキャラクタの画像、赤が当たり範囲です。
当たり判定イメージ.png
当たり判定イメージ.png (2.29 KiB) 閲覧数: 13002 回
【補足】
で結局、書いてある通り私もソースコードを検証した結果で中心座標で処理したほうが良いと言う結論になりました。そのほうがプログラムがシンプルになるのでメリットが多数あります。
回答している人は全て、ゲーム業界で無いにしてもプログラミングのプロばかりなので的はずれなコメントをしているわけではないとご理解ください。

Re: 衝突判定…

Posted: 2013年11月08日(金) 00:37
by ISLe
いちおう断っておくとわたしは中心座標で管理したほうが良いとは言っていません。
どこでも良いです。
どこでも良いのに関係のない要素に依存しているのが問題だというのがわたしの言い分です。
土門 さんが書きました:つまり、自分のクラスで当たり判定のサイズなり、当たり判定の左上なり、出しておけってことでしょうか?
要するにそういうことです。
当たり判定するときは、当たり判定の矩形というかたちで表現すればコードは読みやすくなります。
関係のない情報は隠されるので(土門さんにとって)余計なことに口出しされることもなくなるでしょう。

わたしの投稿でスルーされた部分ですが、反対側のオフセットが求まることが分かりました。
式を変形してまとめるのもけっこうですが、ひと目で分かりにくくなるのはどうかと思います。
ひと目で分かるようにコードを書けば、勘違いや検証を何度も繰り返して時間を無駄にすることを防ぐことができます。

Re: 衝突判定…

Posted: 2013年11月08日(金) 01:21
by 土門
softya(ソフト屋) さん
まずは、私のために時間をとって検証してくださり、
ありがとうございます。
そして、すみません、
softya(ソフト屋) さんに自分も検証して説明しようと思ったら
式がおかしかった、つまりはsoftya(ソフト屋) さんの言うとおり
当たり判定の場所が無茶苦茶だったことがわかりました。
とりあえず、式は訂正させてください(解説もしときますね。

まず、
(*it)->getposX() + ((*it)->getimage_w()/2) - ((*it)->getbounds_w()/2)
オブジェクトのX座標に画像横幅の半分を足して真ん中を出して、
そこに当たり判定横幅の半分を引くことにより
『当たり判定矩形の左端のX座標』を割り出します。

(*it)->getposX() + ((*it)->getimage_w()/2) + ((*it)->getbounds_w()/2)
オブジェクトのX座標に画像横幅の半分を足して真ん中を出して、
そこに当たり判定横幅の半部を足すことにより
『当たり判定矩形の右端のX座標』を割り出します。

(*it)->getposY() + ((*it)->getimage_h()/2) - ((*it)->getbounds_h()/2)
オブジェクトのY座標に画像縦幅の半分を足して真ん中を出して、
そこに当たり判定の縦幅の半分を引くことにより
『当たり判定矩形の上端のY座標』を割り出します。

(*it)->getposY() + ((*it)->getimage_h()/2) + ((*it)->getbounds_h()/2)
オブジェクトのY座標に画像縦幅の半分を足して真ん中を出して、
そこに当たり判定の縦幅の半分を足すことにより
『当たり判定矩形の下端のY座標』を割り出します。

これで、それぞれのXY座標を組み合わせることにより、
当たり判定の矩形が求められますよね?
それをRectAとして、同じように求めたオブジェクトRectBがあるとして
そのふたつの衝突判定を行えば、本来の私の言っている通りの
オブジェクトで設定した当たり判定同士の衝突判定が行える、、、
そうなりませんか?
画像も用意しました。当たり判定は画像サイズより小さく設定するので
画像がめり込むのは問題無いのです。
そもそも、画像の枠ギリギリまで必ずキャラ絵が来ているわけでもないでしょう?
その場合は当たり判定サイズを絵に合わせる、至極当然のことです。
http://dl6.getuploader.com/g/9%7Cnikoman/177/000.jpg

このトピを立てた時には、これらの式の内容を間違えてました。
softya(ソフト屋) さんのおかげで判明しました。
で、もし、上記の式でちゃんと求められることをsoftya(ソフト屋) さんが認めるとしたなら
それが正解であり、私はその正解をこのトピで誰かから修正、ご指摘なり、受けたかったと。
そういうことです。最初から。
何度も言いますが、最終的にsoftya(ソフト屋) さんがそのご指摘をしてくださった、
ということですから。
本当にありがとうございます。

>getboundsって画像中心からの当たり範囲を得る関数ではないのでしょうか?

いえ、中心からではありません。
上記の利用方法通り、想定した当たり判定の矩形の高さと横幅です。
softya(ソフト屋) さんが書きました:コードを見てみると中心座標で管理したほうが楽そうだと私も思いますよ。
意図がよく分からない計算が有るので解説をお願いします。
解説しました。これでこちらの意図はわかって頂けましたよね?
どうでしょうか。
例えば、これらの式自体がもうちゃんと成り立っているなら、
あとは各オブジェクトのクラスにて
当たり判定のサイズを個別に決めてやればいいだけです。
面倒もクソもありませんね?
ダラダラ書いていようが式はひとつだけです、
コリジョン関数として使うだけですから。

さて、それでもsoftya(ソフト屋)さんは
softya(ソフト屋) さんが書きました:中心座標で管理したほうが
プログラムがシンプルになるのでメリットが多数あります。
と言いますか?
意地悪で聞いてるわけではありません。
自分にはまだ"中心座標で管理"のイメージが湧いてないので
その多数のメリット、というのをぜひお聴かせ願いたいです。

Re: 衝突判定…

Posted: 2013年11月08日(金) 01:34
by 土門
ISLeさん
ISLe さんが書きました:わたしは中心座標で管理したほうが良いとは言っていません。
どこでも良いです。
はい、ISLeさんは言ってません。
そうですよ、どこでも良いですよね?
なぜセンター座標センター座標という言葉が
飛び交ったのでしょう。
ISLe さんが書きました: 反対側のオフセットが求まることが分かりました。
さすがです。
あのミスまみれの式から
こちらのしたかったことを読み取って頂いたわけですよね?

そういうことなんですよ。

要は、h2so5氏が最初パッ見で私の式を複雑だと感じ、
その式の内容も読まずに
別の案を投げる様なレスしたから、こんなややこしいことになったと。
そういうことですよね?

式は先ほど、修正しました。ISLeさんも確認して頂ければと思います。
これで、ISLeさんのご指摘通り、各クラスで当たり判定の矩形座標を出して
それ用の変数にでも入れといてコリジョン関数で利用すれば、
完全に問題無い状態ですよね??

Re: 衝突判定…

Posted: 2013年11月08日(金) 01:53
by ISLe
usaoさんの指摘は、真横じゃなくて縦にズレてたらどうなの?ってことです。
上端しか判定してなかったら、下半分に引っ掛かるブロックはすり抜けてしまいますよね。
訂正したという式もサイズによっては誤差があるくらいで何も変わってませんしね。

この式だと当たり判定を画像の中心にしか配置できないと書いたように、少なくともわたしは最初からgetbounds_*の意味は分かってましたよ。


ブロックごとにピクセル単位で比較するのは、ブロック単位でループを回す場合の当たり判定処理(を行うサンプルコードによく見られるパターン)です。

プレイヤーの位置からマップ座標を求める場合は、矩形が重なる範囲を求めて、その範囲でループを回す必要があります。
左に移動する場合、左辺の線分と重なるブロックだけでも良いですが。
わたしのブログでタイルマップの描画モジュール(Javaですが)を公開してますが、上記のようにして見える部分だけを処理しています。
公開したのはそういう処理をしているコードを見たことがないからです。
#ちなみにそのコードは左上基準です。

なにもかもちゃんぽんなのがいけないのです。
いろんな指摘を食らうのはとにもかくにもコードが読みにくいせいです。
自業自得です。

Re: 衝突判定…

Posted: 2013年11月08日(金) 01:57
by ISLe
土門 さんが書きました:これで、ISLeさんのご指摘通り、各クラスで当たり判定の矩形座標を出して
それ用の変数にでも入れといてコリジョン関数で利用すれば、
完全に問題無い状態ですよね??
問題はあります。
先に書いたとおり根本的に間違ってます。

コードが読みにくいせいで、それが分かるまでにこれだけの時間を要してしまいました。

Re: 衝突判定…

Posted: 2013年11月08日(金) 09:35
by usao
「複雑」とか「面倒」とかいうのはまぁ最終的には主観でしょうし,
ご自身がそう思われないのであれば,こちらとしては実際 *わりとどうでもいい* ので,
それよりも以下について明確にしてほしいところです.

(1)式を修正したとのことですが,どこを見ればそれがわかるのでしょう?
 NO.1, No.2あたりのコードが修正されたのでしょうか.
 具体的に何が変わったのですか?
 元がどうなってて,それをどうしたのか というのが読み取れる形にしておかないと
 話がわからなくなってしまいます.

 式について解説されたようですが,それは元の式について? 修正後の式について?
 #元の式の状態でも その説明通りの2つの矩形の判定になっていたように思うのですが…?
 
(2)で,何かが修正した結果として,「問題は解決された」のでしょうか?

(3)私の指摘点が華麗にスルーされていますね.
 当該指摘が本件とは全く関係ないのであれば
 そうであればそうだと再度言っていただければ良いのですが.
  (別に個人的にはスルーされようが構わないのですが,ここでのルール的には一言でも答えるべきかと.)

Re: 衝突判定…

Posted: 2013年11月08日(金) 14:50
by 土門
usaoさん
usao さんが書きました: 私の指摘点が華麗にスルーされていますね.
すみません、usaoさんのご指摘については検証、解説可能な状態にした後に
レスしようと思ってました。
usaoさんの指摘する、プレイヤーがブロックとずれたときの話ですが
自分は過去にグリッド設定のブロックの連続した並びを
プレイヤーがスムーズになぞれるプログラムを組んだことがありまして、練習で。
(スーパーマリオのブロックや床をグリッド設定で表示〜そこをプレイヤーが動く的な感じです)、
その時に、まさに最初usaoさんがご指摘するような状況に落ち入り、
それを打開した経歴がありました。
その上で、今回のプログラムを作っているつもりです。
(途中で相談内容のような状態になったので、
今回はまだそこまでゲーム制作を進めていませんでしたが)
本来ならば、usaoさんのご指摘の問題には対処出来ているプログラムが出来るはずなのです。
が、usaoさんにそれを突っ込まれたので「?」となりました。
作っているプログラムはそれを打開する箇所がちゃんと盛り込まれていくはずですが、
もしかしたらジャンプの概念があるアクションゲームの場合と
今回の上下左右を移動出来るシューティングゲームとの場合で
修正しなければならない箇所があるわけですが、
自分はまだそこまで進めていなかったので、
今回の一部のソース(見せたのは左面を調べる式だけですし)を見せただけの状態では
usaoさんからそう判断されてしまうのかな、とか。
そういうのもあったんでちょっと自分で確認しようと思ったのです。

で、私にとって今回のusaoさんへの本題ですが
usao さんが書きました:(1)式を修正したとのことですが,どこを見ればそれがわかるのでしょう?
NO.1, No.2あたりのコードが修正されたのでしょうか.
具体的に何が変わったのですか?
とりあえず、最後に書いた式を見て言ってるんでしょうか?
2013年11月08日(金) 01:21の私の書き込んだ式です。
これがトピ最初の内容と同じに見えるんでしょうか?

まず、式を見ただけで、どこの部分の式かはピンと来ますよね?
あなた程の方なら。
確かに「ぱっと見」は同じに見えなくもないので
(でも同じに見えるなら尚更どこの式はわかりますよね)
どこの式かわかったら目視で比較し、違う箇所わかりますよね?
それが修正した箇所ですよ。
しかも、「修正した」と銘打ってから式を書いてますから
わざわざ「修正前の式」までそこに書く必要有りますかね?
私よりも何倍も熟練された方ならすぐ書いた式がどの場所の式の話かわかるはずで、
そうすると確認も比較も容易なはずです。
それをわざわざあなたほどの方が「話がわからなくなった」とか言いますか。
私のレスを読まずに「修正」ってところだけに反応してレスしてる感じなんですけど。
比較が出来れば、その結果が変わることもわかるはずです。
まあダラダラと長いので読み飛ばしたい気持ちはわかりますので説明します。
要は、トピ立て最初に書いている私の接触判定の式だと、
当たり判定の矩形の位置がこちらの意図する場所に出てくれていなかった。
それはソフト屋さんの画像つきの検証でわかったと(自分でも検証した。
で、本来求めていたのは、画像サイズ内にちゃんと収まってくれる当たり判定の矩形であり、
自分は画像の中心にそれ(当たり判定の矩形)がくるように設定するのが目的だった。
(私の用意した画像を見れば、本当は真ん中にしたかったのもわかると思います)
ずれたのは式のせいだった。なので式を修正した。
新しい式は最後に書いた式です。2013年11月08日(金) 01:21の私の書き込みの中。

結果が同じ、みたいなことusaoさん言ってますけど、
画像サイズに対して設定される当たり判定矩形の位置が違うでしょ?
式でわかりませんか?あなたほどの方が。
ああ、自分が当たり判定を真ん中にしたいってのを汲み取って
センター座標の方がラクだろ、と言ってたわけでもないんですね。

ただ、結果は同じ、とおっしゃってるのは頂けなくはないですか?
あなたほどの方が。
確かに当たり判定の矩形は出ますが、前者の式と後者の式では
矩形の出る位置が違うはずです。
4+8÷2 と (4+8)÷2とで答えは違いますよね?
算出される値が変わるのに、一緒だと言われても困ります。
usao さんが書きました: 元がどうなってて,それをどうしたのか というのが読み取れる形にしておかないと
話がわからなくなってしまいます.
新たに書いた式とその説明分と画像まで用意したのに
新しく書いた式がどの場所の式の話で、
以前の式とどこが違ってて、結果なにが変わるのか、
わからなかったのでしょうか、あなたほどの方が。
(本当ならもひとつ、その結果から土門がなにを望んでいたのか
読み取ってほしいところだけども、それはさすがに都合よ過ぎですから)
usao さんが書きました: 何かが修正した結果として,「問題は解決された」のでしょうか?
今回修正されたのは、
コリジョン判定の時にはじき出す当たり判定の矩形の位置です。

というか、これだけ確認させてください。
矩形の位置、私の言う通り、変わりますよね?
というのもusaoさんは、今回どこが変わったの?同じだと
なにも変わっていない的なことを言い放ってます。
usaoさんが正しいのでしょうか。
私が間違っているのでしょうか?(修正した式が)

で、解決についてはソフト屋さんのレス待ちです。
自分の修正した式で、
「わけのわからないところに当たり判定が設定されている、
なにをしたいのかわからない式」では無くなったはずです。
その自分のレスに対しての返事を待っています。
こちらの意図を理解してもらえたはずで、
それをわかった上で、まだ、センター座標の方が、と言うのであれば
私にも考えがありますので。

Re: 衝突判定…

Posted: 2013年11月08日(金) 17:24
by usao
ごめん,よくわからないのだけど…

私は,最初に示されたコードの状態で既に,画像と判定枠との関係が
>2013年11月08日(金) 01:21
であなたが示した画像(の左側の絵)のようになっているのではないかと思っていました.

最初の式
(*it)->getposX() + ( (*it)->getimage_w() + (*it)->getbounds_w() )/2
修正されたという式
(*it)->getposX() + ( (*it)->getimage_w()/2 ) + ( (*it)->getbounds_w()/2 )

私には /2 が展開されただけに見えるのです.

>4+8÷2 と (4+8)÷2
という関係ではなくて
(4+8)/2 → 4/2 + 8/2
という変化にみえる.(まぁ演算順が変わったので,結果が同値になるとは言わないけど…)

修正後に対する説明 と, 最初のコード との間で
並び順が異なっているようではありますが,ひょっとして修正とはそっちのことなんでしょうか.

まぁ,実際に当事者側が修正になったとおっしゃられているのだから修正されたのでしょうから,
私が「変わってなくね?」と言い続ける意味はないですし
ここまで感情的に反応されながらコード検証する趣味はないので,
残念ながら今回も私はこれ以上はやめときますかね…
オフトピック
私が何か見落としているか勘違いしているのかもしれませんし,
そうであれば「すいません,気づきませんでした」とか「完全に勘違いしていました」とか謝りますが,
回答側に誤りがあったとして,それに対しての言われようがここまでだと普通は関わりたくなくなるんじゃないでしょうか.
自分の名前のせいでどうだ とか気にされていたようですが,
「ああ,この人には 何か間違った回答をしてしまったらこのような仕打ちを受けるのだな」とか思われたら
それこそ次回に響くように思うのですが.

Re: 衝突判定…

Posted: 2013年11月08日(金) 17:58
by usao
No.17の
>・Y方向については「プレイヤの中心」に対応するグリッドの座標を求めている
については私が勘違いしていました.
失礼しました.

最後に,一応私の想像を書いておきます.

コード:

int j =(int)((*it)->getposX())/MAPCHIP_SIZE;  //←これがまちがい
 ↓
int j =(int)((*it)->getposX() + ( (*it)->getimage_w() - (*it)->getbounds_w())/2 )/MAPCHIP_SIZE;  //iの導出と同じようにする

//iについては,本来は複数グリッド対応をされているらしいので,実際の記述は不明.
int i =(int)((*it)->getposY() + ((*it)->getimage_h() - (*it)->getbounds_h())/2-1)/MAPCHIP_SIZE;  //※-1の意図は不明

Re: 衝突判定…

Posted: 2013年11月08日(金) 18:03
by ISLe
ISLe さんが書きました:訂正したという式もサイズによっては誤差があるくらいで何も変わってませんしね。
わたしもこう書きましたがスルーされたようです。

Re: 衝突判定…

Posted: 2013年11月08日(金) 18:15
by 土門
usaoさん
別に感情的になってません。
声をあらげてませんよね?
文字数が多いだけですよ。

あと、usaoさんの気分を害したなら謝ります。
すみませんでした。

ただ、重箱の隅を突かれてる気になるんですが。
確かに、あなたの言う展開しただけのものもあります。
四つありますから、式が。
ただ、明らかにおかしかったものが混じっていたわけです。
だから全部を修正しただけです。わかりやすく。
その式が展開されただけじゃない?って式だけ持って来て
攻撃してくるのは、どうかなと思うんですけど。
かといって、退散されても困ります。
私はあなたに喧嘩を売ったわけでも、
あなたの気分を害させるつもりで言ったわけでも無いからです。
あなたほどの、というのは皮肉でもなんでもなく、
ほんとにそう思うから何度も言っただけです。
それがなんかしらそちらの気分を害したならすみませんでした。

ただ、
>私は,最初に示されたコードの状態で既に,画像と判定枠との関係が
>あなたが示した画像(の左側の絵)のようになっているのではないかと思っていました.

この勘違いが今回の元凶ではないでしょうか。
あなたは最初から画像の状態が出来ていると思った。
だからあとから私が画像の状態ができた式を出したところで
「だから?」となった。
だったら私も今はあなたのその反応が理解出来ます。
でも、勘違いされたのはusaoさんですよ。
私はこのソースのおかしい部分を指摘してほしいと提示したので
この部分の式はすでに正しいなどと
確認無しで信用されても正直困ります。バカなんで。

あと、今となっては遅かれ早かれですが
土門を名乗った過去のトピから毎度荒れてますんで
土門というコテでは
そのあなたのいうレッテルはすでに貼られているわけです。
もちろん、荒れずに済む場合もあります。
荒れる場合もあります。
どちらに原因があれにせよ、荒れることがあります。
自分が未熟ですから。
「なんで俺が言うことをスルーしてんの?」とか
「そのやりかたが悪い。あのやり方すればいいよ。あとは自分で調べてねバイバーイ」などと
言われたときの対処は正直、難しいですよ。
突っ込む方にも少し配慮が足りないとは思わないのでしょうか?
他人のトピでもよく思いますよ、それは。

ただ、答える方々は善意のみで行っている。
それは相談者から見れば大変ありがたいことで
偉そうなこと言える身分ではございません。
でも、だからといって、切り捨てごめんがまかり通るとも思いません。

とりあえず、自分たち相談者が立場が低いのは事実ですので
荒れたり、気分を害させてしまったならば
私は謝ります。そういうつもりは無いので。
usaoさん、すみませんでした。

Re: 衝突判定…

Posted: 2013年11月08日(金) 18:31
by usao
>四つありますから、式が。
>ただ、明らかにおかしかったものが混じっていたわけです。

4つともコピペしてきて見比べていたのですが,気づくことができません.
4つのうちのどれが おかしかったもの だったのでしょうか.

コード:

//修正前(No.1より)
(*it)->getposX() + ((*it)->getimage_w() + (*it)->getbounds_w())/2    //(1)
(*it)->getposX() + ((*it)->getimage_w() - (*it)->getbounds_w())/2    //(2)
(*it)->getposY() + ((*it)->getimage_h() + (*it)->getbounds_h())/2    //(3)
(*it)->getposY() + ((*it)->getimage_h() - (*it)->getbounds_h())/2    //(4)

//修正後
(*it)->getposX() + ((*it)->getimage_w()/2) - ((*it)->getbounds_w()/2)    //(2)の/2を展開したもの
(*it)->getposX() + ((*it)->getimage_w()/2) + ((*it)->getbounds_w()/2)    //(1)の〃
(*it)->getposY() + ((*it)->getimage_h()/2) - ((*it)->getbounds_h()/2)    //(4)の〃
(*it)->getposY() + ((*it)->getimage_h()/2) + ((*it)->getbounds_h()/2)    //(3)の〃

Re: 衝突判定…

Posted: 2013年11月08日(金) 18:38
by 土門
usaoさん
すみません、用事があるので時間がないです。
あとでレスしますが、今ひとつだけ質問させてください。

変わって無いというのであれば
最初からNo: 19のソフト屋さんの画像のようにはならない、と
言うわけでいいですか?
つまり、ソフト屋さんが間違っている、と。
書いてる通り、前者の式では
ソフト屋さんは画像サイズに対して、当たり判定の場所はが
そのようになると言ってますが。

Re: 衝突判定…

Posted: 2013年11月08日(金) 18:41
by 土門
あ、スタートの位置の修正版を俺が書いてないからか

Re: 衝突判定…

Posted: 2013年11月08日(金) 18:54
by ISLe
土門 さんが書きました:ただ、
>私は,最初に示されたコードの状態で既に,画像と判定枠との関係が
>あなたが示した画像(の左側の絵)のようになっているのではないかと思っていました.

この勘違いが今回の元凶ではないでしょうか。
あなたは最初から画像の状態が出来ていると思った。
だからあとから私が画像の状態ができた式を出したところで
「だから?」となった。
だったら私も今はあなたのその反応が理解出来ます。
でも、勘違いされたのはusaoさんですよ。
私はこのソースのおかしい部分を指摘してほしいと提示したので
この部分の式はすでに正しいなどと
確認無しで信用されても正直困ります。バカなんで。
usaoさんは勘違いなどしていません。
最初から土門さんの画像の状態はできています。

わたしが問題点はそこではないと繰り返し指摘しているのをスルーするのはなぜですか?

Re: 衝突判定…

Posted: 2013年11月08日(金) 18:55
by usao
>私は,最初に示されたコードの状態で既に,画像と判定枠との関係が
>>2013年11月08日(金) 01:21
>であなたが示した画像(の左側の絵)のようになっているのではないかと思っていました.

と書いていますから
私はそう思っている,ということです.ソフト屋さんとは意見が異なる状況ですね.

ただ,私は「コードを見て」そう思っているだけです.
コードを実際に走らせて値を見て検証しているわけではありません.
(そもそも走らせることができる状況でコードが示されていませんし.)

それに対して,
あなたは実際に変数の値を確認した結果を踏まえて
私の言っていることを否定しているはずですから,その純然たる事実を持って否定すればよいわけであって
そもそも その質問を私に投げかける{意味,必要性}がわかりません.
「実際の値がこうなっているので,それは違っています」と一言言えばよいでしょうに.

Re: 衝突判定…

Posted: 2013年11月08日(金) 19:01
by ISLe
一時変数を使っていれば、コードは見やすくなるし、softyaさんの勘違いにもすぐ気が付いたと思うんですけどね。
コードが見やすければそもそもsoftyaさんが勘違いすることもなかったはず。

Re: 衝突判定…

Posted: 2013年11月08日(金) 21:48
by softya(ソフト屋)
かなりレスが長くなっているので誤解することも多そうですので細かいコメントを控えますが、当たり判定の状態が画面に表示されればバグの状態も確認できますので、これをやってみてください。DrawBoxで判定している4頂点を結んだBOXを表示させるだけです。まだ完全には直っていない?ですよね。

こちらでは全体のコードやデータがないと実験できないプログラムですので、誤解とか勘違いとかの余地は当然増えます。関数の戻り値がどういう値なのかも勘なので勘違いしている可能性があります。No: 19でも書いた通り「意図がよく分からないところが結構あります」と言うコードなのです。
なので、かも知れないは書けてもバグの特定は土門さん任せになります。

で、中心座標の件は保持座標を中心座標にしたらいちいち中心座標を計算で求めなくて良いので計算式がスッキリすると思ったので中心座標にしたほうが良いと提案させていただいた次第です。中心座標を計算しているのは間違いないようなので。それが全体的にコード量を減らすことに繋がるなら採用すべきだと私は思った訳です。

【補足】
私の回答待ちですって事になっている件については、ここだけのコードでは判断できません。
当たり判定全部のコードがちゃんとしていたら正しいかもしれませんが、これだけでの判断は不能です。ブラックボックスの部分が多すぎるからです。
本人が正しいと思っていても正しいとは限りません。そう考えるのがデバッグの鉄則ですので、そうとしか答えられません。

ともかく計算式が長いのでデバッグしづらいと思います。
コードの見渡しも悪いので私以外にも提案されるている一時変数に代入して計算することをおすすめします。

Re: 衝突判定…

Posted: 2013年11月09日(土) 07:59
by へにっくす
とりあえず今までの話をまとめると、以下の画像のようなイメージかな。
20131109_dixq_net_t14121_1.png
まとめ。
土門さんの当たり判定の出し方はいいのですが、それだと画像のサイズと当たり判定のサイズを常に使用するよね?だから煩雑になる。
中心座標を予め求めておけば、当たり判定の矩形を出すときは、画像のサイズを用いなくて済みますよね?という話だと思うんですけど。
いっしょにやるんでなく、別々に計算してみてはどうでしょう?

そうすれば、あとは当たり判定のサイズと、マップサイズと一致するんだから、
土門 さんが書きました:私が見るかぎり、画像サイズ=あたり判定サイズで書かれたものばかりです。
に適用することができるよね?

Re: 衝突判定…

Posted: 2013年11月09日(土) 11:39
by usao
現在採られてる方法の上での問題現象の解決 を望まれているのだと思いますので,
現状の方法が
 他者には煩雑に見えたり,違う方法の方が良いのではないかと思われたり,
 あるいは根本的に間違っているのではないかと捉えられたりすること
については この際,どうでもいいこととして脇においておくことにしたとして……

何かしらの修正作業が行われたのですから,まず現在最も情報をいただきたい事柄は
「それで 直ったのかまだなのか? まだだとしたらどういった状況の変化なり改善があったのか?」 という点です.
私のNO.25の書き込みで言えば,(2)の項目ですね.
(1)と(3)についてはまぁお答えいただいているのですが,最も肝心な点が不明.


[追記]
ソフト屋さんもおっしゃっていますが,プレイヤの衝突判定矩形と共に,
チェック対象となっているグリッド(i,j)の16x16領域矩形も同時に描画するようにして
実際に動かしてみれば 何が起こっているのかがわかるのではないでしょうか.