在Spritenode范围内检测其他Spritenode?

时间:2016-03-15 17:32:54

标签: swift sprite-kit

我有一个(移动)精灵节点。

我想检测此节点特定范围内的其他(移动)精灵节点。一旦检测到一个,它应该执行一个动作。

演奏动作部分对我来说没有问题,但我似乎无法弄清楚范围内的检测。有任何想法如何去做?

2 个答案:

答案 0 :(得分:1)

一种简单但有效的方法是比较场景didEvaluateActions方法中的位置。 didEvaluateActions一次调用一次(在评估动作之后但在运行物理模拟计算之前)。您触发的任何新操作都将开始在下一帧进行评估。

由于计算真实距离需要平方根操作(这可能很昂贵),我们可以编写自己的squaredDistance并跳过该步骤。只要我们的检测范围/半径也是平方的,我们的比较将按预期进行。此示例显示了具有"真实范围的检测" 25岁。

// calculated the squared distance to avoid costly sqrt operation
func squaredDistance(p1: CGPoint, p2: CGPoint) -> CGFloat {
    return pow(p2.x - p1.x, 2) + pow(p2.x - p1.x, 2)
}

// override the didEvaluateActions function of your scene
public override func didEvaluateActions() {
    // assumes main node is called nodeToTest and
    // all the nodes to check are in the array nodesToDetect
    let squaredRadius: CGFloat = 25 * 25
    for node in nodesToDetect {
        if squareDistance(nodeToTest.position, p2: node.position) < squaredRadius {
            // trigger action
        }
    }
}

如果操作只应触发一次,您需要在第一次检测后退出循环并添加某种检查,以便在没有适当的冷却期的情况下在下次更新时不会再次触发。您可能还需要将位置转换为正确的坐标系。

另外,请查看documentation for SKScene。根据您的设置,didEvaluateActions可能不是您的最佳选择。例如,如果你的游戏还依赖于物理来移动你的节点,那么最好将这个逻辑移动到didFinishUpdate(渲染场景之前的最终回调,在所有动作,物理模拟和约束应用于帧)。

答案 1 :(得分:0)

我能想到的最简单的方法就是为您要点击的范围添加一个SKNodeSKPhysicsBody,并使用这个新节点contactBitMask确定是否他们在这个范围内。

像这样(伪代码):

//Somewhere inside of setup of node
let node = SKNode()
node.physicsBody = SKPhysicsBody(circleOfRadius: 100)
node.categoryBitMask = DistanceCategory
node.contactBitMask = EnemyCategory
sprite.addNode(node)



//GameScene
func didBeginContact(...)
{
  if body1 contactacted body2
  {
     do something with body1.node.parent
     //we want parent because the contact is going to test the bigger node
  }
}