cocos2d-xでSTGを作るために(当たり判定編)

始めてブログというものを書いてみました。gear1554です。

このブログには複数人の中の人が居るのですが、とりあえず私が1番最初の更新かもしれません。

 

最近coccos2d-xが流行り始めてきたので、早速ゲームを作ってみようと実践している方は多いはず。

実装のセオリーがそこそこ確立しているゲームの定番?といえばシューティングゲーム(STG)かアドベンチャーゲーム(ADV)ですよね。

今回はcocos2d-xでSTGを作る場合の当たり判定について書きたいと思います。

 

シューティングゲームでここ数年(でもないかも)多いのは縦スクロールの弾幕STGでしょうか。

主に敵機の弾が大量に飛んできて、それを避けるアレです。

 

ゲーム画面内のオブジェクト(自機、敵機、弾)の数が多ければ多いほど、オブジェクト同士が当たっているかを判定する処理が行われる回数は増えていきます。

 

1番実装が簡単なのが、総当たりで当たっているかをチェックする方法ですが、処理のコストは1番大きいです。forループをぶん回すことになるわけですから・・・

 

下記のようにゲーム画面をグリッド状にグループ分けして、グループ内同士だけで判定する方法というのがあり、これをはじめて知った時は目から鱗でした。

シューティングゲームにおける弾の空間分割 - 当たり判定 - tomoemonの日記

その8 4分木空間分割を最適化する!

 

この空間グループ内同士で当たり判定を調べる手法を

cocos2d-xで利用可能なクラスとして作成してみました。

GitHubで公開しているCollisionDetectionクラスはCCNodeが入っているCCArrayを渡すと上記の空間分割の手法で当たり判定をやってくれます。

gear1554/CollisionDetectionTest · GitHub


CollisionDetectionTest - YouTube

 

動画では実際にどんな感じで空間の分割が行われ、判定回数がどうなっているかを視覚化

するためにグリッド状の格子と、空間内のオブジェクト数を表示しています。

左上の緑のデバッグ情報は下記の情報を表示しています。

  • SpaceLevel:空間の分割レベル
  • CheckHitCount:1フレームに当たり判定のチェックを行った回数
  • ScanSpaceCount:1フレームに空間の走査を行った回数(空間の分割レベルが上がるにつれ増大)
  • HitObjectPair:当たっているオブジェクトのペアの数
  • GameObjectCount:画面上に表示されているオブジェクトの数
  • DelayTime:1フレームあたりの処理にかかった所用時間(秒)

グリッド状の格子とラベルの描画のコストが思った以上に大きく、

FPSが30前後に見えますが、グリッドとラベルの表示を止めると60FPS出ていました。

グリッドはオフスクリーンのレンダリング、ラベルはビットマップフォントを使いましたが、描画に要する処理コストはやっぱり高い・・・

 

総当たりの判定の場合は、70個前後のオブジェクトの計算に1フレームあたり約2000回、

空間分割(84分割)による判定の場合は1フレームあたり約400~600回。

少なくとも総当たりの判定よりは判定回数を抑えられていました。

 

空間の分割数によってかなり計算回数が変わってきます。

 

空間分割レベル0(総当たり)

f:id:survive-engineer:20140111022219p:plain

 

空間分割レベル1

f:id:survive-engineer:20140111022348p:plain

 

空間分割レベル2

f:id:survive-engineer:20140111022412p:plain

 

空間分割レベル3

f:id:survive-engineer:20140111022434p:plain

 

空間分割レベル4

f:id:survive-engineer:20140111022447p:plain

空間分割レベル4にもなると、空間を走査するコストも増大するので、空間分割レベル2〜3辺りが最適な感じ

 

Box2Dを使って当たり判定を実装したこともありましたが、STGで貫通弾をやろうとした際にオブジェクト同士が必要以上に重なると極端に処理が重くなってしまい、断念しました。複雑な図形の判定が簡単に出来るのは非常に魅力的でしたが・・・

STGに限らず、アクションゲーム等の当たり判定を行うゲームにも流用してみようと思います。