【Godot】Geometryを使用した衝突判定

このページでは Geometry を使用した衝突判定について紹介します

Geometry を使う理由

Godot Engineで衝突判定を行う場合、基本的には CollisionShapeノードを使用します。

ただ衝突の形状を動的に生成したい場合、CollisionShape では不便なことがあります。そのため Godot には「Geometry」というヘルパーノードが用意されており、このノードの関数を使用して衝突判定をすることができます。

Geometryの使用例

is_point_in_polygon(): ポリゴンの内部に点があるかどうか

Polygon2Dノードを以下のように作成済みとすると、

Geometry.is_point_in_polygon() で衝突判定をすることができます。

extends Node2D

onready var polygon = $Polygon2D
onready var label = $Label

func _ready() -> void:
	pass # Replace with function body.

func _process(delta: float) -> void:
	var pos = get_viewport().get_mouse_position()
	if Geometry.is_point_in_polygon(pos, polygon.polygon):
		polygon.color = Color.red
		label.text = "ヒット"
	else:
		polygon.color = Color.white
		label.text = ""

こちらはマウスカーソルがポリゴン内部にあるかどうかを判定するサンプルとなります。

is_point_in_circle(): 円の内部に点があるかどうか

Geometry.is_point_in_circle() では、円の内部に点があるかどうかを判定できます。

extends Node2D


var circle_position = Vector2(520, 240) # 中心
var circle_radius = 80 # 半径

onready var label = $Label

func _process(delta: float) -> void:
	var pos = get_viewport().get_mouse_position()
	# マウスカーソルが円の中に存在するかどうか
	if Geometry.is_point_in_circle(pos, circle_position, circle_radius):
		label.text = "ヒット"
	else:
		label.text = ""

func _draw() -> void:
	# 円を描く
	draw_circle(circle_position, circle_radius, Color.white)

intersect_polyline_with_polygon_2d(): 線分と三角形の交差判定

正確にはポリラインとポリゴンの交差判定ですが、Geometry.intersect_polyline_with_polygon_2d() を使用することで判定できます。

extends Node2D

# 三角形
var triangle = [Vector2(120, 120), Vector2(180, 300), Vector2(520, 240)]
var trianble_color = Color.white
# 線分
var line_pos = Vector2()
var line_dir = Vector2(200, 100)

onready var label = $Label

func _process(delta: float) -> void:
	line_pos = get_viewport().get_mouse_position()
	# ポリラインを作る
	var line = [line_pos, line_pos + line_dir]

	if Geometry.intersect_polyline_with_polygon_2d(line, triangle):
		trianble_color = Color.red
		label.text = "ヒット"
	else:
		trianble_color = Color.white
		label.text = ""
	
	update()

func _draw() -> void:
	# 三角形を描く
	var colors = []
	for v in triangle:
		colors.append(trianble_color)
	draw_polygon(triangle, colors)
	
	# 線を描く
	draw_line(line_pos, line_pos+line_dir, Color.green)

その他2Dゲームでよく使いそうな関数

その他2Dゲームでよく使いそうな関数をまとめておきました

intersect_polygons_2d(PoolVector2Array polygon_a, PoolVector2Array polygon_b): 2Dポリゴンの重なりを返す

polygon_a と polygon_b との重なりを返す関数です。戻り値は重なりを表現するポリゴン(頂点配列)となります。

line_intersects_line_2d(Vector2 from_a, Vector2 dir_a, Vector2 from_b, Vector2 dir_b): 線分同士の交差判定

2つの線分 (from_a, dir_a) と (from_b, dir_b) が交差しているかどうかを判定する関数です。戻り値は交差した点を表す Vector2 です。

注意点として、始点と終点を指定するのではなく、始点と方向ベクトルを指定する関数となります。

point_is_inside_triangle(Vector2 point, Vector2 a, Vector2 b, Vector2 c): 三角形の内部に点があるかどうか

ポリゴンではなく三角形で判定して問題ない場合、is_point_in_polygon() の代わりに使うことができます。

segment_intersects_circle(Vector2 segment_from, Vector2 segment_to, Vector2 circle_position, float circle_radius): 線分が円と交差しているかどうか

交差している場合は「0〜1」の値を返します。交差しない場合は「-1」を返します。

公式ドキュメント

より詳しい情報を知りたい場合は、上記のドキュメントが参考になるかと思います。