フリーゲーム・フリーソフトの開発過程を記録していく、TDtechnic公式ブログです。製品はカテゴリの「ダウンロード場」からダウンロードして頂けます。
上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

こんばんは。いやあこんな時期にねえ、まさかの部分の進展がありました。

…当たり判定!

今になって、当たり判定に劇的な改良が施されました。

今までの当たり判定の弱点は、以下の様な状況でした。
collision.jpg
上図のように、鈍角(90°より広い角度)のカドに突っ込むと、ガクガク振動していたのです。同図にも書いてありますが、今までは二枚の壁の打ち消しベクトルを単純に足していたため、足し算の結果である押し返しベクトルがご覧のとおりもとの速度(上図v)よりも大きくなってしまっていたからです。つまり「打ち消す」どころか「跳ね返し」てしまい、それがプレイ時には小刻みな振動として現れていたのです(ちなみに鋭角~直角のカドの場合、打ち消しベクトルがもとの速度を超えることはありませんので無問題です)。

壁とキャラの当たり判定では跳ね返りは考慮しないので、打ち消しベクトルがvより大きくなるのは当然異常でして、これは夏に当たり判定を作った時からわかっていた問題でした。にもかかわらず今まで一切修正されなかったのは、他ならない、

…私の力が及ばなかったからです。

もちろん、今までの間、この修正には何度も挑戦しました。いろんな方法を試しました。ノート端や、大学のホワイトボードに思いつく限りを描き連ねて、考えました。けれどもどの方法も、効果があまりなかったり、振動は止まったが逆にカドから出られなくなるというものだったり、散々な結果でした。正直これにあまりこだわっていてもゲームは進まないので、仕様として諦めて完成に漕ぎ着けるつもりでした。

しかし、私の心を変える言葉に、昨日出会いました。

ゲームプログラマになる前に覚えておきたい技術ゲームプログラマになる前に覚えておきたい技術
(2008/11/15)
平山 尚(株式会社セガ)

商品詳細を見る

上の本は、私が最近趣味で読んでいるものです。技術的な復習と、純粋に楽しむための読書を兼ねています(筆者が面白い!)。
さて、こちらの本の546頁より、引用させていただきます。

…建物の角に突っ込むとキャラクターがガクガク振動するゲームをよく見るが、…(中略)…直す技術力がないのか、直すことに価値を認めないのかは知らないが、ゲームを遊ぶ側から見れば立派な不具合であり、言い訳できるものではあるまい。

図星でした。耳が痛かったです。ここまでやっと完成に近づいてきたつもりなのに、これを直せないままなのは私も悔しかったです。それを、まさにピンポイントで、バグの例として挙げられたものですから、ゾッとしました。
ここまで言われて黙っているわけにはいかないでしょう。私は、本気で、今まで以上に本気で、こいつを直すことに決めました。

結論を言うと、鍵は発想の転換でした。今まではあくまで物理的根拠のある一本の数式を見つけるんだと意気込んでいたのですが、それは諦め、幾らかのif文を含むことを許容して方策を練ったのです。まあ、そうだとしても、どのように分岐するかというのは探らなければならなかったわけですが。では、私の答えを以下に述べましょう。

①最初は問答無用で打ち消し
一つ目の壁は普通に判定します。ただ、打ち消しベクトルはすぐに反映せずに、どこかに保存しておきます。

②二回目以降は壁ズリできるかどうかを判定
二つ目の壁もまずは打ち消しベクトルを求めます。ここで、「一つ目の打ち消しベクトルと速度ベクトルの外積」と「二つ目の打ち消しベクトルと速度ベクトルの外積」を求め、異符号だったら壁ズリ不可、同符号だったら壁ズリ可能と判定できます。これはつまり、「角に向かっている場合」と「角に近い場所だが離れる方向に進んでる場合」という意味になります。詳しくは文字や口で表現しにくいので語りませんが、作図すると実際にこうなります。

③壁ズリできる場合は、より向き合ってる壁の打ち消しベクトルを採用
②で壁ズリできると決まった場合、部分打ち消しベクトルが必要なわけですが、ここでまた二つの足し算とかするとまた振動します(一フレームだけ)。ここでは、二つのうちから適切な法線を選びます。だってこれは「角から離れる場合」なんですから、実際にはズッている方の壁しか判定する必要ないわけですからね。ズッていない方の壁からは離れていっているはずです。ではこれをどう判定するかと言うと、さっき求めた外積を使いまわせます。外積の大きさはsinθに比例しますから、それを求めてsinθの絶対値がより小さい方の壁を選べば、それがズッている方の壁(= より向き合ってる壁 = 法線ベクトルと速度ベクトルの角度が小さい壁)のはずです。結局こちらの壁にしか当たってなかったということにしていいわけですから、その打ち消しベクトルを選びます。

④壁ズリできない場合は、全力で止める
②で壁ズリできないとわかった場合は、もう動かす必要はありません。打ち消しベクトルに(-v)を代入して終わりです。これ以降どのような状況であると分かっても、カドに向かっていっている人がどうにも動きようがないのは変わりませんからね。

⑤万が一、三つ目以降の壁が検出されたら②に戻る
三つ以上の壁に同時にぴったり当たるというのはなかなか無いことなんですが、三つ目以降も同様の処理で大丈夫なはずです。不死女にはそうなり得る地形がないので試していませんが、③で採用された方の壁を一つ目としてまた相応しい壁を選べばいいだけですからね。

⑥最後に、今までの集大成の打ち消しベクトルを速度ベクトルに加算する
ここまで残った打ち消しベクトルで実際に速度を打ち消します。ちなみに、キャラ同士の判定の方はこれを使わなくてもめったに振動しないっぽいので、キャラ同士判定の打ち消しベクトルはまた別に保持しておいてここで一緒に足すのがいいでしょうね。

以上です。これでついに不死女のマップはどの壁も滑らかに壁ズリできるようになりました。
関連記事

[2015/03/16 23:33] | 不死女 -Immortal girl-
|
コメント:
この記事へのコメント:
コメント:を投稿
URL:

パスワード:
非公開コメント: 管理者にだけ表示を許可
 
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。