Ios 如何获得两个SKSpriteNode对象之间的距离,以便在势场算法中使用?

Ios 如何获得两个SKSpriteNode对象之间的距离,以便在势场算法中使用?,ios,swift,artificial-intelligence,Ios,Swift,Artificial Intelligence,首先作为免责声明,我非常清楚SpriteKit物理体能够收集碰撞。这不是我想做的。我正试图建立一个势场AI,为了计算吸引向量和排斥向量,需要两个物体之间的距离 我认为计算距离只需使用距离公式,但由于某些原因,我得到的距离结果非常不可靠,因此我想咨询一下是否有人能发现我做错了什么 下面我使用一个简单的距离公式,点的位置与它们的中心对齐 func getDistanceBetweenTwoObjects(sourceNode:SKSpriteNode, destinationNode:SKSprit

首先作为免责声明,我非常清楚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 getAttractionVector(节点:SKSpriteNode,目的节点:SKSpriteNode,价差:CGFloat,强度:CGFloat)->(xSpeed:CGFloat,ySpeed:CGFloat){
var sourceNodeRadius=sqrt(功率(节点大小宽度/2,2))
var destNodeRadius=sqrt(功率(destinationNode.size.width/2,2))
变量半径=源节点半径+目标节点半径
var distance=GetDistanceBetween对象(节点,destinationNode:destinationNode)
如果距离<半径{
返回(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
如果半径(xSpeed:CGFloat,ySpeed:CGFloat){
var sourceNodeRadius=sqrt(功率(节点大小宽度/2,2))
var destNodeRadius=sqrt(功率(destinationNode.size.width/2,2))
变量半径=源节点半径+目标节点半径
var distance=GetDistanceBetween对象(节点,destinationNode:destinationNode)
如果距离>扩展+半径{
返回(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(“\(距离):\(半径)”)

如果半径在计算节点的垂直中心点时,您错误地使用了
size.width
。(即:
centerSourceNode.y+=sourceNode.size.width/2
应为
sourceNode.size.height/2
,与
centerDestNode
相同)


在更高的层次上,您是否查看了iOS 9中新的
UIFieldBehavior
类型,以及用于路径查找的游戏工具包?

在计算节点的垂直中心点时,您错误地使用了
size.width
。(即:
centerSourceNode.y+=sourceNode.size.width/2
应为
sourceNode.size.height/2
,与
centerDestNode
相同)


在更高的层次上,您是否查看了iOS 9中新的
UIFieldBehavior
类型,以及用于路径查找的Gameplay Kit?

Larry可能会有所了解,因为您使用
centerSourceNode.x+=sourceNode.size.width/2
表示节点的锚点为(0,0),而不是默认值(0.5,0.5)

使用默认值,精灵的位置是它的中心在父节点中的位置,这意味着除了两个节点的位置之外,你不需要考虑任何东西。 正如我在评论中提到的,这也让我们有了一个相当不错的可能性,即通过扩展CGPoint来解决这个问题:

extension CGPoint {
    func distanceFromCGPoint(point:CGPoint)->CGFloat{
        return sqrt(pow(self.x - point.x,2) + pow(self.y - point.y,2))
    }
}
然后,无论您在何处需要此功能,您都可以通过简单的呼叫获得距离:


让distance=spriteA.position.distanceFromCGPoint(spriteB.position)
拉里可能有点问题,因为您使用的
centerSourceNode.x+=sourceNode.size.width/2
表示节点的锚点为(0,0),而不是默认值(0.5,0.5)

使用默认值,精灵的位置是它的中心在父节点中的位置,这意味着除了两个节点的位置之外,你不需要考虑任何东西。 正如我在评论中提到的,这也让我们有了一个相当不错的可能性,即通过扩展CGPoint来解决这个问题:

extension CGPoint {
    func distanceFromCGPoint(point:CGPoint)->CGFloat{
        return sqrt(pow(self.x - point.x,2) + pow(self.y - point.y,2))
    }
}
然后,无论您在何处需要此功能,您都可以通过简单的呼叫获得距离:


let distance=spriteA.position.distanceFromCGPoint(spriteB.position)

+1我将查找UIFieldBehavior,这似乎很有趣。至于宽度,因为我使用的是正方形宽度=高度,那么为什么会产生影响?+1我将查找UIFieldBehavior,这似乎很有趣。至于宽度,因为我使用的是正方形宽度=高度,那么为什么会产生影响?您的距离函数指示t你的节点的锚点是(0,0)而不是默认的(0.5,0.5),这可能是你出现问题的原因吗?如果是,你可以将该函数减少为一个线性函数,或者更好地将其作为CGPoint的扩展…你的距离函数表明你的节点的锚点是(0,0),而不是默认的(0.5,0.5)这可能是你的问题的原因吗?如果是的话,你实际上可以把这个函数简化为一个线性函数,或者更好的是将它作为CGPoint的一个扩展…对象的锚定点在0.5,0.5,因此我不需要将位置偏移到中间。这是我关于spritekit的一个问题。如果我理解正确,这个位置如果更改锚点,对象的位置将发生变化?即:如果锚点为0.5,0.5,位置将是对象的中心,如果锚点为0,0,位置将位于左下角。这是对的吗?对象的锚点位于0.5,0.5,因此我不需要将位置偏移到中间。这是我的问题之一spritekit。如果我理解正确,对象的位置会随着锚点的改变而改变?即:如果锚点为0.5,0.5,位置将是对象的中心,如果锚点为0,0,位置将是左下角。这对吗?