如何在潜在场算法中计算两个SKSpriteNode对象之间的距离?

首先声明一下,我完全了解SpriteKit的物理体可以检测碰撞,但这并不是我想要做的。我正在尝试构建一个潜在场AI系统,而计算吸引和排斥向量的一部分需要知道两个对象之间的距离。

我以为计算距离只需使用距离公式就行了,但不知为何我的距离计算结果非常不准确,所以我想咨询一下是否有人能发现我做错了什么。

下面我使用了一个简单的距离公式,点的位置对齐到它们的中心。

func getDistanceBetweenTwoObjects(sourceNode:SKSpriteNode, destinationNode:SKSpriteNode) -> CGFloat{    var centerSourceNode = CGPoint(x: sourceNode.position.x, y: sourceNode.position.y)    centerSourceNode.x += sourceNode.size.width/2    centerSourceNode.y += sourceNode.size.width/2    var centerDestNode = CGPoint(x: destinationNode.position.x, y: destinationNode.position.y)    centerDestNode.x += destinationNode.size.width/2    centerDestNode.y += destinationNode.size.width/2    var distance = sqrt(pow((centerSourceNode.x - centerDestNode.x), 2) + pow((centerSourceNode.y - centerDestNode.y), 2))    return distance}

这是我用来创建吸引向量的函数。

func getAttractionVector(node:SKSpriteNode, destinationNode:SKSpriteNode, spread:CGFloat, strength:CGFloat) -> (xSpeed: CGFloat, ySpeed: CGFloat){    var sourceNodeRadius = sqrt(pow(node.size.width/2,2))    var destNodeRadius = sqrt(pow(destinationNode.size.width/2,2))    var radius = sourceNodeRadius + destNodeRadius    var distance = getDistanceBetweenTwoObjects(node, destinationNode: destinationNode)    if distance < radius{        return (0,0)    }    var angle = atan((destinationNode.position.y - node.position.y)/(destinationNode.position.x - node.position.x))    var xSpeed:CGFloat = 0    var ySpeed:CGFloat = 0    if radius <= distance && distance <= spread + radius{        xSpeed = strength * (distance - radius) * cos(angle)        ySpeed = strength * (distance - radius) * sin(angle)    }else if distance > spread + radius{        xSpeed = strength * spread * cos(angle)        ySpeed = strength * spread * sin(angle)    }    return (xSpeed, ySpeed)}

我使用类似的数学方法来计算排斥向量:

    func getRepelVector(node:SKSpriteNode, destinationNode:SKSpriteNode, spread:CGFloat, strength:CGFloat) -> (xSpeed: CGFloat, ySpeed: CGFloat){    var sourceNodeRadius = sqrt(pow(node.size.width/2,2))    var destNodeRadius = sqrt(pow(destinationNode.size.width/2,2))    var radius = sourceNodeRadius + destNodeRadius    var distance = getDistanceBetweenTwoObjects(node, destinationNode: destinationNode)    if distance > spread + radius{        return (0,0)    }    var angle = atan((destinationNode.position.y - node.position.y)/(destinationNode.position.x - node.position.x))    var xSpeed:CGFloat = 0    var ySpeed:CGFloat = 0    println("\(distance) : \(radius)")    if radius <= distance && distance <= spread + radius{        xSpeed = strength * (spread + radius - distance) * cos(angle)        ySpeed = strength * (spread + radius - distance) * sin(angle)    }else if distance < radius{        xSpeed = getSign(cos(angle)) * CGFloat.max        ySpeed = getSign(sin(angle)) * CGFloat.max        println("HERE")    }    return (xSpeed, ySpeed)}

不幸的是,距离公式显然对我不起作用,我多次发现节点在接触时没有被检测到,或者在未接触时被误认为是接触的。是否有人能看出我哪里做错了,或者建议一个更简单的方法来准确计算两个SpriteNodes之间的距离?希望问题很简单。谢谢。

下图显示了我的AINode解决迷宫(橙色),一个需要避开的障碍物(蓝色)和我的目标(绿色)。

在这个例子中,AINode的宽度为20。障碍物的宽度为50。

在调试器暂停在AINode非法穿越障碍物的无效状态下,使用上述公式计算中心点之间的距离读数为“28.28”。实际距离是7。 enter image description here

更新

我发现我的吸引和排斥向量存在一个重大错误,这加剧了问题。我的距离公式有点偏差,但由于我计算角度的方式错误而被放大了。角度需要使用atan2而不是atan来计算。原因是如果不使用atan2,返回的角度将位于错误的象限,这扭曲了排斥向量的方向并导致了重大错误。


回答:

Related Posts

L1-L2正则化的不同系数

我想对网络的权重同时应用L1和L2正则化。然而,我找不…

使用scikit-learn的无监督方法将列表分类成不同组别,有没有办法?

我有一系列实例,每个实例都有一份列表,代表它所遵循的不…

f1_score metric in lightgbm

我想使用自定义指标f1_score来训练一个lgb模型…

通过相关系数矩阵进行特征选择

我在测试不同的算法时,如逻辑回归、高斯朴素贝叶斯、随机…

可以将机器学习库用于流式输入和输出吗?

已关闭。此问题需要更加聚焦。目前不接受回答。 想要改进…

在TensorFlow中,queue.dequeue_up_to()方法的用途是什么?

我对这个方法感到非常困惑,特别是当我发现这个令人费解的…

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注