godot - 我如何能够检测到碰撞形状多边形何时形成一个有碰撞的圆
问题描述
这是一个很难提出问题的想法,我已经制作了一个玩家在屏幕上绘制圆圈的系统,我希望玩家要么触摸了自己的另一条线,从那个位置开始一个新的圆圈,我遇到的问题是不知道如何让它发生碰撞,我有一个想法,但不确定它是否会起作用,我的想法太简单了,它使用不同的碰撞形状,在相互连接的点上以及当鼠标与之碰撞时创建自己特定的碰撞形状再次开始,这是我拥有的最佳选择还是有另一种方法可以检测何时形成圆圈。
这是我想要的视频: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]))
的,在添加点之前和之后应该是相同的。如果它改变,那么形状是凹的。
对于一个圆,所有点到中心的距离都差不多。因此,如果您检查到中心的最小和最大长度之间的比例,您就可以衡量循环的圆度。对于一个圆圈,该比例将等于 1。如何找到中心?您可以计算包含点的较小的轴对齐边界框(即计算点之间的最小和最大 x 和 y 坐标),并且框的中心将匹配循环的中心......假设它是对称的,如果它不是,你会发现它不是很圆,所以没关系。
推荐阅读
- c - 什么字符'!' C中数组赋值的平均值
- python - Python自动化
- python - 开始使用 Django 频道时遇到问题
- android - 当对上的媒体流不可用时,画布中的背景变得透明
- javascript - Appium - 滚动到一个不起作用的按钮
- php - 从外部 wordpress 的订单 ID 中获取产品 ID 和变体 ID
- php - 如何使用 init 文件和无密码连接到 redis 服务器
- php - 如何知道最后一次点击加载更多按钮php ajax
- reactjs - ReactJS:如何使用 `react-dates` 自定义样式
- java - 如何在其他类中实现接口和扩展