获取特定区域中的节点列表?

时间:2014-07-20 14:11:15

标签: swift sprite-kit

我在一个侧面游戏中工作,我需要知道某个区域中有哪些节点可以实现类似"视线"。现在我尝试使用enumerateBodyiesInRect(),但它从被评估的矩形中检测到20px或更多的物体,我无法弄清楚它为何如此不精确。

这就是我现在正在尝试的:

import SpriteKit
import CoreMotion

class GameScene: SKScene, SKPhysicsContactDelegate
{
var player = SKShapeNode()
var world = SKShapeNode()
var rShape = SKShapeNode()

override func didMoveToView(view: SKView) {
    self.physicsWorld.contactDelegate = self
    self.scaleMode = SKSceneScaleMode.AspectFit
    self.size = view.bounds.size

    // Add world
    world = SKShapeNode(rectOfSize: view.bounds.size)
    world.physicsBody = SKPhysicsBody(edgeLoopFromPath: world.path)
    world.position = CGPointMake(self.frame.size.width/2, self.frame.size.height/2) // Move camera
    self.addChild(world)

    // Add player
    player = SKShapeNode(rectOfSize: CGSize(width: 25, height: 25))
    player.physicsBody = SKPhysicsBody(rectangleOfSize: player.frame.size)
    player.physicsBody.dynamic = false
    player.strokeColor = SKColor.blueColor()
    player.fillColor = SKColor.blueColor()
    player.position = CGPointMake(90, -50)
    world.addChild(player)
    }


override func update(currentTime: CFTimeInterval) {
    // Define rect position and size (area that will be evaluated for bodies)
    var r : CGRect = CGRect(x: 200, y: 200, width: 25, height: 25)

    // Show rect for debug
    rShape.removeFromParent()
    rShape = SKShapeNode(rect: r)
    rShape.strokeColor = SKColor.redColor()
    self.addChild(rShape)

    // Evaluate rect
    rShape.fillColor = SKColor.clearColor()
    self.physicsWorld.enumerateBodiesInRect(r) {
        (body: SKPhysicsBody!, stop: UnsafePointer<ObjCBool>) in
         self.rShape.fillColor = SKColor.redColor() // Paint the area blue if it detects a node
         }
    }
}

此代码应在屏幕上显示已评估的rect和ray(用于调试目的),如果它们与播放器节点联系,则将其绘制为红色。但是你可以在截图中看到当玩家离它25px或更远时它变成红色的情况,如果绘图稍微偏离,或者小于被评估的实际区域。您可以将其粘贴到项目中以复制问题。

这可能是因为这只是测试版,还是我做错了什么?

The rect should only be red only if the player is inside it (blue square), however it's red when the player is near

6 个答案:

答案 0 :(得分:1)

我相信你想要SKPhysicsWorld的enumerateBodyiesInRect()实例方法,它将迭代给定矩形中的所有节点。如果您希望通过场景进入物理世界,那么使用情况可能如下所示:

self.physicsWorld.enumerateBodiesInRect(CGRect(x: 0, y: 0, width: 50, height: 50)) {(body: SKPhysicsBody!, stop: UnsafePointer<ObjCBool>) in
    // enumerates all nodes in given frame
}

答案 1 :(得分:1)

您正在创建一个物理世界,其中有一个具有特殊属性的特定矩形&#39; - 这是您在enumerateBodiesInRect()中使用的矩形。为什么不创建一个具有所需矩形尺寸的隐形惰性物理体,然后使用SKPhysicsBody检查碰撞和/或接触?然后,您可以使用allContactedBodies()或一些委托回调来了解特殊矩形内的其他实体。

把它想象成一个拖拉机梁#39;或者是一个扭曲的矩形&#39;。

答案 2 :(得分:1)

我现在用enumerateBodiesInRect进行了相当多的实验,我发现它非常不准确。它似乎没有任何声明的功能,而是产生随机结果。老实说,我甚至无法确定其产品的任何模式。

enumerateBodiesAlongRay似乎更好,但仍然非常错误。该函数的问题似乎是Screen和PhysicsWorld坐标之间的转换。我也会避免那个。

我认为您的解决方案应该只是使用现有的接触检测系统。您可以使用didBeginContact()didEndContact()函数编写所有所需的功能。这样做的另一个好处是允许您为进入和离开区域指定不同的功能。您还可以添加粒子效果,动画等,以及故意忽略特定类型的节点。

确保此方法成功的唯一方法是澄清联系区域具有唯一类别,contactTestBitMask包含所有所需节点,collisionBitMask设置为0。

答案 3 :(得分:0)

只有nodesAtPoint:方法。

要达到你想要的效果,你最好将所有敌人存储在一个数组中并拥有一个int变量,例如nextEnemyIndex。这种方法可以让你轻松返回下一个敌人节点,它比尝试在场景中找到一个节点更有效率。

答案 4 :(得分:0)

是因为您的播放器图像可能会出现问题,例如尝试使用10px较小的机身尺寸:

player.physicsBody = SKPhysicsBody(rectangleOfSize: CGRectMake(self.frame.origin.x, self.frame.origin.y, self.size.width-10, self.size.height-10)));

答案 5 :(得分:0)

enumerateBodiesInRect的{​​{1}}方法需要rect参数位于场景坐标中。这个很重要。如果您有节点的场景层次结构,则需要将计算的矩形从参考节点转换为场景坐标。

我遇到了很多问题,这个方法返回了左侧等30px等值的物体,最后意识到问题是由于在场景坐标空间中没有定义的矩形参数。

就我而言,我的场景中有SKPhysicsWorld,所有对象都是在worldNode中创建的。我的相机正在移动worldNode,并对其进行缩放以缩小和缩小。

为了正确使用worldNode,我必须采取以下措施:

enumerateBodiesInRect

希望这有帮助。