我在一个侧面游戏中工作,我需要知道某个区域中有哪些节点可以实现类似"视线"。现在我尝试使用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或更远时它变成红色的情况,如果绘图稍微偏离,或者小于被评估的实际区域。您可以将其粘贴到项目中以复制问题。
这可能是因为这只是测试版,还是我做错了什么?
答案 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
希望这有帮助。