ども、皆様お久しぶりでございます!
ゲレゲレです!
違いますって!全然飽きたとかじゃないですって!
ただちょっと本業の方が忙しくなってしまったのでちょっとお休みしていただけですってば!
…いやーホントに忙しかった。
堕天使エルギオスを倒して世界を救ったり、秘宝を78個集めて世界を救ったりね!
まったく。オレがいないと世界はすぐピンチに陥るからさぁ。
さて、では行きますか。
吉里吉里でオンライン対戦マリオブラザーズを作ろう!
第9回です!
つーことで今回はコリジョン判定です。
コリジョン判定ってのはオブジェクト同士が接触したかどうかをチェックするってことです。
マリオが敵と接触すると一機死ぬ、とか
マリオがジャンプしてブロックを叩く、とか
叩かれたブロックの上にいた敵はひっくり返る、とか。
そもそもマリオが地面に立ってる、なんてのにも使います。
今までは毎フレームupdate関数が呼ばれ、その中でキー入力などに応じてキャラクター(と他のオブジェクト)の
位置、状態の更新をしていました。
今度はそこにオブジェクトと衝突(コリジョン)しているかチェックを行い、衝突していたら位置の修正、状態の変化
などを追加します。
大体こんな感じです。
方向キーが入力された
→キャラクター位置の更新
→移動先の位置で他のオブジェクトと衝突しているか?
→していたら衝突していない位置に戻す
→していなければそこに移動
あるいは、
方向キーが入力された
→キャラクター位置の更新
→移動先の位置で敵キャラと衝突しているか?
→していたら死にモーション再生
→していなければそこに移動
で、当たってるかどうかの判定は
いろいろあるんですが、とりあえず四角形同士が重なってるかの判定でいいでしょう。
右上から当たってるか、左上から当たってるか、右下からあたってるか、左下から当たってるか、
自分より相手が大きい場合、自分がすっぽり相手に囲まれてしまっているか、
逆に自分より相手が小さい場合、相手が自分の中にすっぽり入ってしまっているか、
といったあたりをチェックすればOKです。
が、これを全オブジェクト同士で総当たりチェックするととんでもない回数の計算を
一フレーム内で行わなければならなくなります。
上のチェックだと一対一のオブジェクトで6パターンのチェックを行うわけですが、
対象オブジェクトが自機、敵10体、弾20個、障害物20個なんてものを表示していたとすると
総当たりでは51の階乗(約1.55×10^66)回のチェックを行う必要が出てきます。
10の66乗って日本語でなんて言うのか知りませんが、ともかくあり得ないくらいデカい数字ってことです。
それに加えて同じフレーム内で画像の再表示やら、音の制御やら通信制御なんかもしなければならないわけで。
ともかく無駄な処理はできるだけ省きたいわけです。
ということで工夫が必要なんですが、要するに不要な判定はやりたくないということです。
で、どうするかというと。
まずは判定の必要なものをグループ分けする、とかですかね。
今は全オブジェクトを配列に突っ込んでおいて、ループでupdateをかけてるわけですが、
これをたとえば、プレイヤー配列、敵オブジェクト&弾配列、障害物配列、自弾配列とかに分類しておくわけです。
とすれば、プレイヤーと自弾はあたりをチェックする必要はないですし、敵同士、味方同士なんて
無駄なチェックする必要はなくなりますよね?
もちろん仕様次第では必要になる時もありますが、その場合はグループ分けを考え直しましょう。
さてさて、これで万事OK!とおもいきや。これでもまだ無駄が多いわけです。
たとえば自機が画面左上にいたとき、画面右側にある敵やら障害物なんてのはチェックするまでもないですよね?
なので、画面を分割して、各オブジェクトがどこのエリアにいるかを逐次登録して、各エリアごとにそのエリア内にいる者同士でのみ判定を行うとよりいい感じになるわけです。
詳しくは4分木空間分割(3Dは8分木)でググってくだせい。
ただ、これはこれでやりゃあいいってもんでもないわけで。
あんまり細かく分割してもかえって登録の手間が無駄になってしまうし、大きく分割しすぎてもあまり効果がないし。
ってなわけで実際は扱うオブジェクトの数だとか、大きさ、空間の広さによってどの程度に分割するのが
最適かという調整が必要になってくるわけですね。
で、ウチの場合なんですけど。
実はここまで言っといてなんですが、4分木は使ってません。
なぜかというと、オレが作りたいのは初代マリオブラザーズ。
2人対戦だし。敵は一度に2,3匹でいいし。障害物だってせいぜい20個くらい?
弾幕シューティングとかじゃないのでそんなにオブジェクト数がないので効果が薄い、
というか毎フレームごとに移動に伴うセルへの登録、削除のオーバヘッドの方が大きいから。
ま、20人対戦とかにする時には考え直す必要があるかもですが。
つーことで、今回はグルーピングだけにしておきましたよと。
ではでは、次回、第10回 敵キャラ(NPC)配置してみる!にてー。