在iOS上的SpriteKit的坐标,框架和子节点的混淆?

我还在iOS上学习SpriteKit,并一直在做大量的阅读和大量的实验。 我很困惑的东西我已经find*关于坐标,框架和子节点。

考虑这段代码,其中我正在试图围绕我的飞船精灵绘制一个绿色的框来进行debugging:

func addSpaceship() { let spaceship = SKSpriteNode.init(imageNamed: "rocketship.png") spaceship.name = "spaceship" // VERSION 1 spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) let debugFrame = SKShapeNode(rect: spaceship.frame) debugFrame.strokeColor = SKColor.greenColor() spaceship.addChild(debugFrame) // VERSION 2 // spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) spaceship.setScale(0.50) self.addChild(spaceship) } 

如果我把上面标有“VERSION 1”的行添加到飞船精灵上,我会得到:

版本1

这显然是错误的。 但是,如果我注释掉上面标记为“版本1”的行,而是使用标记为“版本2”的行,就可以得到我想要的:

版本2

请注意,标记为版本1和版本2的行的实际代码是相同的:spaceship.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame))

那么为什么当我设定太空船精灵的位置时呢?

按照我的思路,宇宙飞船精灵的位置与debugging帧的位置无关,因为debugging帧是宇宙飞船精灵的一个子,所以它的坐标应该是相对于宇宙飞船精灵的相对位置的。

感谢WM

*这与我昨天所问的一个问题有些相关:

在iOS上的SpriteKit中,缩放纹理的sprite会产生不正确的帧?

但是a)我现在明白了一个,b)这是不同的,它应该有自己的问题。

更新:

嗯 – 谢谢,下面的想法的家伙,但我还是不明白,也许这将有助于。

我修改了我的代码来打印出相关位置和框架:

 func addSpaceship() { let spaceship = SKSpriteNode.init(imageNamed: "rocketship.png") spaceship.name = "spaceship" println("Spaceship0 Pos \(spaceship.position) Frame = \(spaceship.frame)") // VERSION 1 (WRONG) spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) println("Spaceship1 Pos \(spaceship.position) Frame = \(spaceship.frame)") let debugFrame = SKShapeNode(rect: spaceship.frame) println("DEBUG Pos \(debugFrame.position) Frame = \(debugFrame.frame)") debugFrame.strokeColor = SKColor.greenColor() spaceship.addChild(debugFrame) // VERSION 2 (RIGHT) // spaceship.position = CGPointMake(CGRectGetMidX(self.frame), CGRectGetMidY(self.frame)) // println("Spaceship2 Pos \(spaceship.position) Frame = \(spaceship.frame)") spaceship.setScale(0.50) self.addChild(spaceship) } 

然后,我跑了两边,得到了这些结果。 由于我了解第2版,所以我们从这里开始。

运行“VERSION 2(RIGHT)”代码,我得到:

 Spaceship0 Pos (0.0,0.0) Frame = (-159.0,-300.0,318.0,600.0) DEBUG Pos (0.0,0.0) Frame = (-159.5,-300.5,319.0,601.0) Spaceship2 Pos (384.0,512.0) Frame = (225.0,212.0,318.0,600.0) 

默认情况下,飞船节点的位置在屏幕的左下angular(Spaceship0)。 它的框架也是以它的锚点(中心)被设置在屏幕的左下方,因此它的框架原点的负数表示。

debugging框架然后被创build,其位置被设置为0,0默认情况下,其框架被设置为与飞船相同。

然后,代码(Spaceship2)将飞船节点移动到视图坐标(384.0,512.0)中的一个位置,并通过将新位置添加到旧原点(即384 + -159 = 225)来移动它的原点。

一切都很好。

不幸的是,我还没有得到版本1。

当我运行“VERSION 1(错误)”代码时,我得到了

 Spaceship0 Pos (0.0,0.0) Frame = (-159.0,-300.0,318.0,600.0) Spaceship1 Pos (384.0,512.0) Frame = (225.0,212.0,318.0,600.0) DEBUG Pos (0.0,0.0) Frame = (0.0,0.0,543.5,812.5) 

如上所述,默认情况下,飞船节点的位置在屏幕的左下angular(Spaceship0)。 它的框架也是以它的锚点(中心)被设置在屏幕的左下方,因此它的框架原点的负数表示。

然后代码(Spaceship1)将飞船节点移动到视图坐标(384.0,512.0)中的一个位置,并通过将新位置添加到旧原点(即384 + -159 = 225)来移动其帧的原点。

debugging框架然后创build与它的位置设置为0,默认情况下,其框架设置为一个奇怪的宽度(543.5)和一个奇怪的高度(812.5)。 因为我正在用spaceship.frame初始化debugFrame.frame(我认为这就是默认的初始化工具),所以我期望新的debugFrame.frame与飞船的框架相同 – 但事实并非如此! debugging帧的宽度和高度值显然来自将实际宽度和高度添加到飞船节点帧的原点(543.5 = 225 + 318.5)。 但是,如果是这样的话,为什么t的帧矩形原点仍然是0,0和不相同的加法(225.0 + 0 = 225.0)?

我不明白。

您正在使用精灵框架(在场景坐标中)创build形状节点。 由于该形状将是精灵的子节点,因此应该在精灵的坐标中创build该节点。 例如,如果使用太空船的尺寸创buildSKShapeNode

 let debugFrame = SKShapeNode(rectOfSize: spaceship.size) 

无论何时设置船的位置, debugFrame都将以飞船为中心,而不是使用飞船的框架。 而且, debugFrame将会随船只适当地缩放/移动。

回应你的'我不明白'。 你的代码是好的,但有一个合乎逻辑的问题。 “框架”相对于父坐标进行计数。 请认识到飞船的父母和debugging窗口的父母在你的代码中是不同的。

两种方法来解决你的问题:

  1. 为debugging窗口添加一个零偏移量,并使用飞船作为父级。 这样做的好处是,debugging窗口将移动,与宇宙飞船的比例: let rectDebug = CGRectMake( 0, 0, spaceship.frame.size.width, spaceship.frame.size.height) let debugFrame = SKShapeNode(rect:rectDebug) spaceship.addChild(debugFrame)
  2. 将带有飞船“框架”坐标的debugging窗口添加到飞船的父母(这是“自我”)。 这样做的缺点是你必须移动,调整窗口自己的代码,因为它不会被附加到飞船上: let debugFrame = SKShapeNode(rect:spaceship.frame) self.addChild(debugFrame)

两种解决scheme都被广泛使用 你应该select哪个更适合你的情况。 另外三个问题可能会出现:

1.我的代码中可能存在代码错误,我只是直接在Web窗口中input这些代码,而没有进行xcode语法检查。

2.两个物体的锚点可能不同。 所以你可能需要在你的代码中alignment。

3.也要考虑物体的位置,这些物体不会隐藏在其他物体的下面。

为了回应你正在努力解决的问题,也许showPhysics会有所帮助:

  skView.showsFPS = YES; skView.showsNodeCount = YES; skView.showsPhysics = YES; 

这与您提到的其他问题几乎是一样的问题。 frame是包含positionsize的属性。 他们两个都受到其祖先节点的缩放。 请参阅https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Nodes/Nodes.html#//apple_ref/doc/uid中的 “节点将其许多属性应用于其后代”一节/ TP40013043-CH3-SW13

同样:永远不要对节点应用缩放,在完全构build其层次结构之前,不要移动节点,除非需要一些特殊或奇怪的效果。