通常、Sprite同士の当たり判定を行う場合、Collision ノードを使用します。これは異なる形状のオブジェクトや細かい調整が効きやすい反面、ノードを毎回組み合わせる必要があるので、ちょっとした当たり判定を行いたい場合にやや回りくどいです。(ただ通常は Collision を使ったほうが良いケースが多いので、この記事はややマニアックな方法となります)
ということで、この記事では Collision ノードを使用せずに Sprite同士の当たり判定を行う方法を紹介します。
Sprite同士の当たり判定
Geometry.intersect_polygons_2d() を使用するとポリゴンの頂点リストを PoolVector2Array として渡すことで衝突判定が行えるのでこれを利用します。
実装サンプルコード
以下、実装してみたサンプルコードとなります。
# スプライト同士が衝突しているかどうか
func _is_hit(spr1:Sprite, spr2:Sprite) -> bool:
# Spriteの画像データを頂点として取得する
var v1 = _spr_to_vec2array(spr1)
var v2 = _spr_to_vec2array(spr2)
if Geometry.intersect_polygons_2d(v1, v2):
# 衝突している
return true
return false;
# スプライトから頂点リストを作る
func _spr_to_vec2array(spr:Sprite) -> PoolVector2Array:
var ret = PoolVector2Array()
var pos:Vector2 = spr.position
var rect:Rect2 = spr.get_rect()
# スケールを反映
var w = rect.size.x * spr.scale.x
var h = rect.size.y * spr.scale.y
var w2 = w / 2
var h2 = h / 2
var v1 = Vector2(0, 0) # 左上
var v2 = Vector2(w, 0) # 右上
var v3 = Vector2(w, h) # 右下
var v4 = Vector2(0, h) # 左下
if spr.centered:
# 中央揃え
v1 = Vector2(-w2, -h2) # 左上
v2 = Vector2( w2, -h2) # 右上
v3 = Vector2( w2, h2) # 右下
v4 = Vector2(-w2, h2) # 左下
# 回転(ラジアン)を求める
var rad = spr.rotation
ret.push_back(pos + v1.rotated(rad))
ret.push_back(pos + v2.rotated(rad))
ret.push_back(pos + v3.rotated(rad))
ret.push_back(pos + v4.rotated(rad))
return ret
ただ、Spriteの変形は様々な方法があるので、ここでひとまず、「中央揃えかどうか」「スケール値」「回転値」のみの対応としています。
完成プロジェクト
今回作成したプロジェクトを添付しておきます。