ひさしぶりの投稿ですじゃ。
最近めっきりと日記を書く機会が減っておりましたが、ここ1ヶ月くらいは
プログラムの方を進めてました。え?そんな変わってないって?苦笑
具体的には壁沿い移動、パーティ歩き、それと新しくキャラクターの
位置にスプライトを表示できるようにしてみました!
実質的には壁沿い移動にほとんど時間がかかってしまいましたね…。
ようやく壁抜けしない壁沿い移動を実装できて、色々と反省するべき点が
多かったので以下に少しまとめてみたいと思います。
まず壁沿い移動の実装を考えてみたときに、大抵の方が
真っ先に思い浮かぶのが、
0.壁との内外判定で衝突判定テスト
1.衝突予定の壁と移動線分を順番に衝突判定
2.1で衝突した壁で壁沿い移動
3.壁の範囲を超えていたら補正
だと思うのですが。ここでこのまま思いついた通りにプログラムを組んで、
for(衝突予定リストを順番に) {
if(衝突している) {壁沿い移動;break;}
}
としてしまった場合、なんと。壁抜けが発生してしまうんですねえ;
ここで問題になるのが2の線分と線分の衝突判定での精度の
問題でして。この衝突判定、ちょうど線分の頂点で衝突していた
場合、衝突していないとして返される可能性が高いのです。
つまり、壁の辺の間でぐりぐりと移動していると衝突していると
判断されるべきが衝突してないよウフフ、として判定されるために
壁抜けしてしまいます。
じゃあどうすればいいかと色々と考えてみましたが。このままだと
どうしようも無いので第3者の情報を借りてきてそれと比較することで
解決することにしました。具体的には、現在壁の実装方法は
地面のポリゴンが存在していない部分については壁という風に
実装しているのですが。。この地面の情報を元に、自身の
真下の地面のポリゴンの3辺とまず一度内外判定を行い、
2辺以上外に判定された辺が存在する、且つ1辺が壁の場合は
強制的に2辺で共有する頂点位置に設定することで無事
解決できるようになりました。(他にも色々と条件分岐が複雑
なのですが、ここでは面倒臭いので抜きにします苦笑)
それにしても、これにたどり着くまでに大分試行錯誤してしまいました。
途中「floatからdoubleにすると精度上がって直るかな?」なんて
考えたりもしましたが、現在既にほとんどの関数でfloatによる実装を
してしまっていて変更がとんでもなく大変な上に根本的な解決に
ならないと思うので。とりあえずやる前に解決できてよかったのでした笑。