ゲームでは正確性よりもスピードが求められる場面がある。
当たり判定もその一つで、キャラ同士がぶつかったかどうかの判定は矩形や正円などに単純化して表現される。
今回Twitterで羽毛田氏がたい焼きのキャラの当たり判定の方法を模索してるようなので以下の画像を提案してみた。
キャラを正円の組み合わせで表現できれば、3×3で9通りの正円の当たり判定を行えば良いことになる。
今回はキャラ同士ではなく、正円同士がぶつかっているかどうかの判定用にクラスを書いてみた。
クラス名はCollisionSenser。
コードはこちら。
PublicNameAsStringPublic X AsDoublePublic Y AsDoublePublic Radius AsDoubleFunction DoesHit(c As CollisionSenser) DoesHit = Radius + c.Radius > CalcDiagonalDistance(Abs(X - c.X),Abs(Y - c.Y))EndFunctionPrivateFunction CalcDiagonalDistance(a, b) CalcDiagonalDistance = VBA.Math.Sqr(a ^ 2+ b ^ 2)EndFunctionPublicPropertyGet Self()AsObjectSet Self =MeEndProperty
パブリックフィールドとして名前とX座標とY座標と半径を持たせており、当たり判定用のDoesHit関数はCollisionSenserオブジェクトを受け取って自分と当たっているかどうかを返す。
正円同士の当たりは、円の中心同士の距離が半径の合計を超えているかどうかで判定できる。
円の中心同士の距離は三平方の定理で求まる。
■三平方の定理
A^2 + B^2 = C^2
つまりC = sqr(A^2 + B^2)
以下のコードでテストしてみた。
Sub TestCollisionSenser()Dim CollisionSensers As Collection Set CollisionSensers =New Collection Dim sh As Shape ForEach sh In Selection.ShapeRange WithNew CollisionSenser .Name= sh.Name.Radius = sh.Width/2.X = sh.Left+.Radius .Y = sh.Top +.Radius CollisionSensers.Add.Self EndWithNextDim cs1 As CollisionSenser, cs2 As CollisionSenser ForEach cs1 In CollisionSensers ForEach cs2 In CollisionSensers IfNot cs1 Is cs2 ThenIf cs1.DoesHit(cs2)Then Debug.Print cs1.Name&" does hit to "& cs2.NameEndIfEndIfNextNextEndSub
複数の円を選択してコードを実行すると、
イミディエイトウィンドウに次のように表示される。
Oval 5 does hit to Oval 6 Oval 6 does hit to Oval 5 Oval 6 does hit to Oval 10 Oval 9 does hit to Oval 11 Oval 10 does hit to Oval 6 Oval 11 does hit to Oval 9
あとはキャラ用のクラスがこのCollisionSenserを必要数保持すれば複雑な形のキャラ同士でも簡易当たり判定できるかと思う。
以上
経緯
#VBAのクラスモジュールで、クラスらしいクラスを作れたためしがない😭
— チン☆テクラ (@akashi_keirin) 2018年9月7日
いつも静的クラスみたいなのばっかり。
大量の「たい焼き」を作製して、それぞれの「たい焼き」が思い思いに動く、みたいなことをしてみたい。
大量のたい焼きが動く動画。
— はけた@Excel最高の学び方発売中 (@excelspeedup) 2018年9月8日
当然、たい焼きクラスを作って、たい焼きクラスで移動を実装してます。
1匹1匹、色を変えられなかったのが残念。 pic.twitter.com/2McNfYyEIQ
あとは、イメージの重なり判定ができれば、VBAでゲーム作れそう。
— はけた@Excel最高の学び方発売中 (@excelspeedup) 2018年9月8日
ただ、全イメージが円とか、長方形なら比較的簡単だけれど、今回の「たい焼き」のような不定形のキャラクターの重なり判定をどうしたらいいかがわからない。
いっそのこと、セルでドット絵書く方式にすればいいのかな? https://t.co/Wkzn1Yu5M7