HSPポータル
サイトマップ お問い合わせ


HSPTV!掲示板


未解決 解決 停止 削除要請

2011
0724
actsアクションの当たった後の処理について15未解決


acts

リンク

2011/7/24(Sun) 21:22:35|NO.40147

アクションゲームの当たり判定は分かるのですが
その後の処理がいまいちわかりません…
1方面の処理だけならうまくいくのですが
2方面以上だとどうしても相殺し合ったりしてうまくいきません
みなさんはどのように処理してますか?
ご教授ください

repeat MAP_HEIGHT ;マップ読み込み hei=cnt repeat MAP_WIDTH wid=cnt if map(wid,hei)==1{ if (( me_x + ME_SIZE_X - 1) >= CHIP_SIZE*wid ) { if ( me_x+ <= (CHIP_SIZE*wid + CHIP_SIZE - 1) ) { if ( (me_y + ME_SIZE_Y - 1) >= CHIP_SIZE*hei ) { if ( me_y <= (CHIP_SIZE*hei + CHIP_SIZE - 1) ) { ;ここに処理をいれる } } } }



この記事に返信する


ORZ

リンク

2011/7/24(Sun) 21:44:09|NO.40148

プログラムの前に自分の中で、日本語に置き換えるとこういう問題はすっきりする。
キャラが右に進んだ時の判定は、xxxかつxxxかつxxxでないときに当たったことにして
逆に左に進んだ時は、yyyかつyyyかつyyyなとき当たったことにしよう、という具合だ。
これをプログラムに置き換えるのがプログラミングという作業になる。

だまされたと思って髪と鉛筆を用意して、日本語を書きなさい。『んなの頭の中でわかってらあぼけ』と
言う言葉が出てくるうちは絶対わかってないし、分かってるならこういうソースは書かない。

あとコメントは入れなさい。ついでにいうと、正しく入れなさい。
これはマップの読み込みじゃなくて、当たり判定の処理じゃないの?



acts

リンク

2011/7/24(Sun) 21:54:40|NO.40149

分かりました。少し頭の中を整理して、したいことと
どうすればそれが可能か紙に書いてみます。
あとマップの読み込みと同時に1つのチップごとに
当たり判定の処理をしています。まずいかな…



backdrop

リンク

2011/7/24(Sun) 22:08:52|NO.40151

>あとマップの読み込みと同時に1つのチップごとに当たり判定の処理をしています。まずいかな…
完全に別々にしたほうがよいです、読み込みは読み込み、当たりは当たりでってしないと遅くなります
第一、ここで識別すると一見まとまるように見えますが実は無駄な処理をやりかねなくなってしまいます



acts

リンク

2011/7/25(Mon) 00:02:01|NO.40166

だめだ…
どなたか少しヒントをください
推測ですがもしかして
壁判定と床判定と天井とか全部別々で処理するのですか?



f(就寝前)

リンク

2011/7/25(Mon) 00:59:38|NO.40171

何がしたいのか今一見えんが
こういう事か?


・自分の現在位置をX,Yとする。

・移動方向を確定。
 移動方向からXYの移動量を決める。これをMX,MYとする。
 たとえば右ならMX=1,MY=0 上ならMX=0,MY=-1等とする。

・現在位置に移動量を加えた位置が障害物なら移動できない。
 X+MX,Y+MYの位置が障害物 -> 移動量MX,MYを0にクリアする。

・実際に現在位置に移動量を加える



ひらまる

リンク

2011/7/26(Tue) 15:52:17|NO.40213

そういやアクションをつくるときにいつも思うのですが、
fさんの例のように移動量が1なら何の問題もなく済みますが、
移動量が実数や大きな値だったとき、
まるが右に4マス動きたいけど2マス目に障害物がある。
◎→■→
 →■→◎
すり抜けないようにするにはどうするか?

移動先まで1ますずつ、全てのマスで判定をする?
でもそれだと処理がかさむ…
◎→■→
 ◎■→

他にも、大きな壁があった場合、
まるが右に4マス動きたいけど、2マス目以降は壁になってる。
◎→■■■
この場合は移動できないってことにしちゃうと、◎は壁に隣接することができない。

めり込んでから壁の外に押し出す方法だと処理がかさむ…
 →■■◎
 →■◎■
 →◎■■
 ◎■■■

線分で判定する場合
まるが右に4マス動きたいけど、2マス目に左向きの法線を持った線分がある。
◎→|→→
まるの移動するベクトルと壁の線分の当たり判定をして、
当たっていた場合、壁の法線方向にまるの大きさの分だけ座標を移動させる。

しかしこの場合、以下のようなブロックとの当たり判定時、
   _
◎→|→|→
    ̄
まるは左右どちらの壁ともぶつかっているから、ぶつかった全ての線分の法線を調べて、
まるの移動後の座標が法線に対して負の高さになっている線分を当たりとする?

でもそれだと、同じ方向を向いた線分が連続している場合にどれとぶつかったのかわからなくなる。
◎→|||→


……アクションゲームの当たり判定ってめちゃくちゃ難しくないですか?
何年もこういった問題で悩んでいて、今でも答えが出ていないのですが……;



木村

リンク

2011/7/26(Tue) 23:59:10|NO.40227

>>ひらまる氏
>線分で判定する場合
>でもそれだと、同じ方向を向いた線分が連続している場合にどれとぶつかったのかわからなくなる。

 現フレームでの時間をt=0、1フレーム後の時間をt=1と置き、各障害物線分との衝突時刻を算出し、衝突時刻が早い順から処理を組み立ててゆけば良いかと。
 actsさんも何か参考が欲しいとおっしゃっていましたので、開発wikiに線分同士の衝突を判定するモジュールとちょっとした解説を置いとておきました。
 皆様の参考になれば幸いです。
http://hspdev-wiki.net/?Math%2F%C0%FE%CA%AC%C6%B1%BB%CE%A4%CE%B8%F8%BA%B9%C8%BD%C4%EA



ひらまる

リンク

2011/7/27(Wed) 00:37:05|NO.40228

>現フレームでの時間をt=0、1フレーム後の時間をt=1と置き
一度の移動量が多く、全ての線分と「同時」に衝突した場合の問題です。
わかりづらくてすみません;

この場合、全ての線分と衝突した座標を求め、
衝突した座標が移動前の座標と一番近い線分が衝突した線分ということになると思いますが、
例によって処理がかさんで……;



skyblue

リンク

2011/7/27(Wed) 07:20:29|NO.40229

>めり込んでから壁の外に押し出す方法だと処理がかさむ
壁の長さを求めて引けばいいのでは?



ひらまる

リンク

2011/7/27(Wed) 15:55:30|NO.40239

>壁の長さを求めて引けばいいのでは?
確かにそうですね。
しかし壁が斜めだったりした場合は、壁にめり込んだ距離の計算が複雑になります。

ここまで書いてふと、1次関数で壁を表すのが軽いのではないかと思いました。
これは使えるかもと思い、適当にスクリプトを組んでみたところ、
逆に垂直な壁を表現するのが難しくなりました;

RPGのようなマスで分けられていれば当たり判定はとても簡単なのですが、
アクションゲームのように実数でなめらかな動きをさせる場合、
どういった判定が最も効率良く精密なのでしょうか……



木村

リンク

2011/7/27(Wed) 17:52:58|NO.40246

>>ひらまる氏
>一度の移動量が多く、全ての線分と「同時」に衝突した場合の問題です。
 いえ、こちらも表現が悪かったようです。申し訳ありません。
 お詫び代わりに、改めて説明いたします。

 まず、現フレーム時の座標を(A,B)、1フレーム後の座標を(C,D)とします。
 前述の参照先の紙芝居1枚目を見れば分かる通り、(A,B)と(C,D)を通る線分はフレーム数tを噛ませて、
>X(t) = (C-A)t+A : Y(t) = (D-B)t+B {0≦t≦1}
と、表す事ができます。
 もう一方の線分も同じようにsを噛ませて表せば、tとsの連立方程式によって交点のX座標とY座標が求まります。

 ここで重要なのが、交点のX座標とY座標が求まる前に、フレーム数に相当するtも求まっていると言う事です。
 このtは何を意味しているかというと、双方の直線が厳密にはtフレーム目に衝突していると言う事を意味しています。
 例えば、前述の参照先の紙芝居の5枚目を例に出せば、t=0.7は0.7フレーム目に衝突、t=2.1は2.1フレーム目に衝突したと言う事になります。
 そして、システム上は0フレーム目から1フレーム目までの衝突だけを抽出して、処理しているわけです。

 このtを利用すれば、同一フレーム内での衝突の優先順位を付ける事ができます。
 処理が重くなる心配もあるでしょうが、tを求める式は引き算10回、掛け算4回、割り算1回だけで済みます。当方の環境下では256回繰り返して、ようやく1ms遅れた程度でした。

 参考までにline a, b, c, dとline e, f, g, hの接点のt(衝突フレーム数)は以下の式となります。(前述の参照先のスクリプトのtの算出法と同一)

t = double((e-g)*(b-f)-(f-h)*(a-e))/((c-a)*(f-h)-(d-b)*(e-g))
 昨日の紙芝居にも少し説明を追加しておいたので、よろしければご覧ください。
http://hspdev-wiki.net/?Math%2F%C0%FE%CA%AC%C6%B1%BB%CE%A4%CE%B8%F8%BA%B9%C8%BD%C4%EA#z2fc9392

>逆に垂直な壁を表現するのが難しくなりました;
 Y=aX+bのような形で処理しているとY軸に平行な直線を定義できません。
 0=aX+bY+cの形であれば、ほぼ全ての直線を定義できます。(ヘボンの公式だったかそんな名前があった気がします)



ひらまる

リンク

2011/7/28(Thu) 02:47:45|NO.40264

んーーーなるほど
紙芝居を参考にスクリプトを組んでみると、確かに正確な線分同士の当たり判定ができました…
ていうかこれって3Dの当たり判定でも使われる方法だったりするかも…?
(昔内積とか法線とか使って当たり判定を作った気がするうろ覚え)

この方法を使う場合、主に2つの問題に悩まされます;
・衝突したときにどういった処理をするか
・キャラクタのサイズをどう反映するか

これについて、以前おちゃっこさんのサイトでも質問したのですが、
みなさんとても真剣に考えてくれたものの、
明確な答えが得られませんでした。

私の場合、
移動先の座標を壁と移動ベクトルの交点(衝突座標)としてしまうと、
そこからさらに壁に向かって移動する場合、
ちょっとした誤差ですり抜けてしまうことがあるので、

移動先座標 = 衝突座標 - キャラクタサイズ * 移動ベクトルの反ベクトル
移動ベクトル = 衝突線分の法線ベクトル

としていますが、プルプルガクガク動いてしっくりきません…;
衝突した場合の処理…思考錯誤しているのですがうまくいきません;
どうしたらきれいに動くのでしょうか……



ひらまる

リンク

2011/7/28(Thu) 02:52:46|NO.40266

Σ思考錯誤ってなんだよっ 頭オカシイ人かよっ(誤字ですみません;



木村

リンク

2011/7/30(Sat) 00:52:22|NO.40291

>>ひらまる氏へ
>プルプルガクガク動いてしっくりきません…;
 最小移動量を定義してみてはいかがでしょうか。移動ベクトルの長さが3未満の場合は、移動処理をしないとすればガクガクブルブルは収まると思います。



GENKI

リンク

2011/7/30(Sat) 02:24:28|NO.40292

> としていますが、プルプルガクガク動いてしっくりきません…;

衝突判定をするときにキャラクタサイズを考慮していないんじゃないでしょうか?
キャラクターの中心(あるいは基点)座標と壁だけ見て判定していませんか?
キャラクターの中心座標を壁ギリギリ触れないところに移動すると、キャラが半分めり込んで見えませんか?さらにゆっくり壁に触れると急に壁から突き放されたり。

見かけより衝突判定用の壁をキャラクタのサイズ分だけ見た目の壁から離しておく(壁を近づける)とキャラクタサイズを考慮する必要がなくなるので壁スリだけと簡単です。
汎用性なくなりますが。



ONION software Copyright 1997-2021(c) All rights reserved.