【Godot】Collisionノードを使用せずにSprite同士の当たり判定を行う方法

通常、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の変形は様々な方法があるので、ここでひとまず、「中央揃えかどうか」「スケール値」「回転値」のみの対応としています。

完成プロジェクト

今回作成したプロジェクトを添付しておきます。