Как я могу определить, когда многоугольник формы столкновения образовал круг со столкновением?

Это сложная идея, чтобы задать вопрос, я создал систему, в которой игрок рисует круги на экране, я хочу, чтобы игрок либо коснулся другой своей линии, начал новый круг из этой позиции, проблема, с которой я столкнулся, заключается в не имея представления о том, как я могу заставить его столкнуться, у меня есть идея, но я не уверен, сработает ли она, моя идея слишком просто использовать другую форму столкновения, которая создает себя в точках, которые соединяются друг с другом, и когда мышь сталкивается с этим Определенная форма столкновения начинается снова, это лучший вариант, который у меня есть, или есть другой способ определить, когда создается круг.

Вот видео о том, что я хочу: 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

person Dragon20C    schedule 18.04.2021    source источник


Ответы (1)


При том, что вы стараетесь не набирать очки. Для обнаружения петли достаточно простой проверки на столкновение сегмент-сегмент.

Что-то вроде этого:

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 по точкам), и центр прямоугольника будет соответствовать центру цикла… Предполагая, что он симметричен, если он нет, вы в любом случае поймете, что он не очень круглый, так что это нормально.

person Theraot    schedule 19.04.2021
comment
Честно говоря, это потрясающе, потому что это работает, и я знаю, что вы даже добавили комментарии для меня, чтобы я понял, и я действительно не понимаю этого, но я ценю, что это работает, и я также более удивлен, что вы поняли, чего я хочу, я ужасен в объяснении того, что я хочу, и вы правы, я должен был использовать этот цикл вместо кружков, часть цикла (индекса), я полагаю, я могу разместить здесь свою собственную функцию, спасибо за вашу тяжелую работу! - person Dragon20C; 19.04.2021
comment
Хорошо, я действительно обнаружил проблему, которая, похоже, работает только тогда, когда мышь действительно сталкивается с линией, а не линия, сталкивающаяся с линией, может быть плохой код на моей стороне - person Dragon20C; 19.04.2021
comment
@ Dragon20C Не знаю, я переборщил с этим. Мой код избыточен, но вот он: mouse_lasso.gd. Я бы обычно помещал этот дополнительный класс в другой скрипт, но он находится в том же скрипте для удобства понимания сути. Таким образом, я бы не советовал использовать его дословно, но, возможно, он вам поможет. - person Theraot; 19.04.2021
comment
Честно говоря, перебор - это нормально, хотя код simpiler иногда лучше, когда кто-то не знает, что он делает, я взгляну на этот скрипт лассо - person Dragon20C; 19.04.2021