【Godot】Polygon2Dを分割するサンプル

Polygon2Dを分割するサンプルを作りました

Polygon2Dを分割するサンプル

今回はソースコードとサンプルプロジェクトのみです。まだ不十分なところも多いので、今後修正される可能性があります

  • 分割する対象を最初に存在するオブジェクト($obj)のみとしています(切れなかったときの判定が未実装)
  • 分割後にオブジェクトの Rigidbody2D の移動値が初期化されています

サンプルコード

extends Node2D

# マウス開始座標
var start_pos = Vector2()
# カットするオブジェクト(Rigit2D)
onready var obj = $obj

func _process(delta: float) -> void:
	if Input.is_action_just_pressed("ui_click"):
		start_pos = get_global_mouse_position()
	if Input.is_action_just_released("ui_click"):
		var end_pos = get_global_mouse_position()
		var dir = end_pos - start_pos
		var distance = dir.length()
		dir = dir.normalized() # 方向はノーマライズ必須.
		var ofs = obj.position
		var pos = start_pos - ofs # オフセットを消しておく
		# カットするシェイプを作成
		var cut_shape = create_beam_polygon(dir, distance, 3, 3, pos)
		var cut_p = Polygon2D.new()
		# 表示用は位置が異なる
		var cut_shape2 = create_beam_polygon(dir, distance, 3, 3, start_pos)
		cut_p.set_polygon(cut_shape2)
		add_child(cut_p)
		
		# ポリゴン分割する
		var new_polygons:Array = Geometry.clip_polygons_2d($obj/Polygon2D.polygon, cut_shape)
		obj.queue_free()
		
		# 分割したポリゴンを生成
		for p in new_polygons:
			var rigid = RigidBody2D.new()
			var poly = Polygon2D.new()
			var col = CollisionPolygon2D.new()
			poly.set_polygon(p)
			poly.modulate = Color.red
			col.set_polygon(p)
			rigid.position = ofs # オフセットを足し込む
			rigid.add_child(poly)
			rigid.add_child(col)
			add_child(rigid)

#creates a beam with a seperate start and end width
# https://github.com/SoloByte/godot-polygon2d-fracture
# @param dir 方向
# @param distance 距離
# @param start_width 開始の幅
# @param end_width 終端の幅
# @param start_point_local
func create_beam_polygon(dir : Vector2, distance : float, start_width : float, end_width : float, start_point_local := Vector2.ZERO) -> PoolVector2Array:
	var beam : PoolVector2Array = []
	if distance == 0: 
		return beam
	
	if start_width <= 0.0 and end_width <= 0.0:
		return beam
	
	if distance < 0:
		dir = -dir
		distance *= -1.0
	
	var end_point : Vector2 = start_point_local + (dir * distance)
	var perpendicular : Vector2 = dir.rotated(PI * 0.5)
	
	if start_width <= 0.0:
		beam.append(start_point_local)
		beam.append(end_point + perpendicular * end_width * 0.5)
		beam.append(end_point - perpendicular * end_width * 0.5)
	elif end_width <= 0.0:
		beam.append(start_point_local + perpendicular * start_width * 0.5)
		beam.append(end_point)
		beam.append(start_point_local - perpendicular * start_width * 0.5)
	else:
		beam.append(start_point_local + perpendicular * start_width * 0.5)
		beam.append(end_point + perpendicular * end_width * 0.5)
		beam.append(end_point - perpendicular * end_width * 0.5)
		beam.append(start_point_local - perpendicular * start_width * 0.5)
	
	return beam

マウスの移動に対応する線分のポリゴンを作るために、create_beam_polygon() という関数を使っています。この関数は、参考にしたプロジェクトからお借りしたものとなります

プロジェクトファイル

参考