我如何能够检测到碰撞形状多边形何时已形成碰撞圆

How would I be able to detect when a collision shape polygon has made a circle with collision

这是一个很难提出问题的想法,我制作了一个玩家在屏幕上画圆圈的系统,我希望玩家可以触摸到它自己的另一条线,从那个位置开始一个新的圆圈,我遇到的问题是不知道如何让它发生碰撞,我有一个想法但不确定它是否会起作用,我的想法太简单了使用不同的碰撞形状来在相互连接的点上创建自己以及何时鼠标与那个特定的碰撞形状碰撞再次开始,这是我拥有的最佳选择还是有另一种检测圆圈何时形成的方法。

这是我想要的视频:https://youtu.be/wSolVcaIszE?t=998

这是我的视频:https://www.youtube.com/watch?v=BDnd-n3PEdQ

代码:

extends Node2D

var points_array = PoolVector2Array()
var index : int = 0
onready var collision = $Area2D/CollisionPolygon2D

func _physics_process(delta):
    collision.polygon = points_array
    
    if Input.is_action_just_pressed("Left_click"): #This sets a position so that the next line can work together
        points_array.append(get_global_mouse_position()) # This makes a empty vector and the mouse cords is assigned too it
        points_array.append(Vector2())
    if Input.is_action_pressed("Left_click"): #This checks the distance between last vector and the mouse vector
        points_array[-1] = get_global_mouse_position() # Gets the last position of the array and sets the mouse cords
        if points_array[index].distance_to(get_global_mouse_position()) > 20:
            points_array.append(get_global_mouse_position())
            index += 1
    if points_array.size() > 25: # This adds a length to the circle/line so it wont pass 18 mini lines
        index -= 1
        points_array.remove(0) #Removes the first array to make it look like it has a length
    if Input.is_action_just_released("Left_click"): # This just clears the screen when the player releases the button
        points_array = PoolVector2Array()
        index = 0

假设你保持点数较短。一个简单的段-段冲突检查就足以检测环路。

像这样:

func _segment_collision(a1:Vector2, a2:Vector2, b1:Vector2, b2:Vector2) -> bool:
    # if both ends of segment b are to the same side of segment a, they do not intersect
    if sign(_wedge_product(a2 - a1, b1 - a1)) == sign(_wedge_product(a2 - a1, b2 - a1)):
        return false

    # if both ends of segment a are to the same side of segment b, they do not intersect     
    if sign(_wedge_product(b2 - b1, a1 - b1)) == sign(_wedge_product(b2 - b1, a2 - b1)):
        return false

    # the segments must intersect
    return true

func _wedge_product(a:Vector2, b:Vector2) -> float:
    # this is the length of the cross product
    # it has the same sign as the sin of the angle between the vectors
    return a.x * b.y - a.y * b.x

并像这样使用:

    if points_array.size() > 3:
        for index in range(0, points_array.size() - 3):
            if _segment_collision(
                    points_array[-1],
                    points_array[-2],
                    points_array[index],
                    points_array[index + 1]
                ):
                    loop(index)
                    break

其中 loop(index) 表示在有循环时执行任何操作。


这并不是真正检测到一个圆。只是一个循环。 顺便说一句,参考视频也没有检测到圆圈。只是循环。

您可以使用楔积检查环路是否为凸环。如果形状是凸的sign(_wedge_product(points_array[-1] - points_array[-2], points_array[-2] - points_array[-3]))加点前后应该是一样的。如果改变了,那么形状就是凹的。

对于一个圆,所有点到圆心的距离大致相同。因此,如果您检查到中心的最小和最大长度之间的比例,您就可以衡量环路的圆度。该比例将等于一个圆圈。如何找到中心?您可以计算包含点的较小的轴对齐边界框(即计算点之间的最小和最大 x 和 y 坐标),并且框的中心将与循环的中心匹配......假设它是对称的,如果它不是,你会发现它不是很圆,所以没关系。