关于坐标,框架和混乱的困惑iOS上的SpriteKit中的子节点?

时间:2014-12-31 08:19:24

标签: ios swift sprite-kit skspritenode skshapenode

我还在玩iOS中学习SpriteKit的工作。一直在做很多阅读和阅读大量的实验。我发现*关于坐标,框架和其他的东西我感到困惑。子节点。

考虑这段代码,我试图在我的宇宙飞船精灵周围画绿框以进行调试:

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"的行中。上面,我明白了:

Version 1

这显然是错误的。但是,如果我评论 out 标记为" VERSION 1"上面,而是使用标记为" VERSION 2"的行,我得到我想要的:

Version 2

请注意,标有版本1&的行的实际代码版本2完全相同: spaceship.position = CGPointMake(CGRectGetMidX(self.frame),CGRectGetMidY(self.frame))

那么为什么在我设置宇宙飞船精灵的位置时这很重要?

根据我的思维方式,宇宙飞船精灵的位置与debugFrame的位置无关,因为debugFrame是宇宙飞船精灵的一个孩子。因此,它的坐标应该相对于宇宙飞船的精灵框架 - 对吧?

由于 WM

*这与我昨天提出的问题有些相关:

In SpriteKit on iOS, scaling a textured sprite produces an incorrect frame?

但是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(右)"代码,我得到了:

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)

默认情况下,宇宙飞船节点的位置位于屏幕的左下角(Spaceship0)。它的框架也用它在屏幕左下角设置的锚点(中心)来表示,因此它的框架矩形的原点是负数。

然后创建调试帧,其位置设置为0,0默认情况下为&它的框架设置为与宇宙飞船相同。

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

一切都很好。

不幸的是,我仍然没有获得第1版。

当我使用" VERSION 1(错误),#34;代码,我得到

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)

如上所述,默认情况下,宇宙飞船节点的位置位于屏幕的左下角(Spaceship0)。它的框架也用它在屏幕左下角设置的锚点(中心)来表示,因此它的框架矩形的原点是负数。

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

然后创建调试帧,其位置设置为0,0默认情况下为&它的框架设置为具有奇怪的宽度(543.5)&一个奇怪的高度(812.5)。由于我使用spaceship.frame初始化debugFrame.frame(我认为是默认初始化程序所做的),我希望新的debugFrame.frame与宇宙飞船的框架 - 但它不是!调试帧宽度&高度值显然来自于添加实际宽度和宽度。太空船节点框架的原点高度(543.5 = 225 + 318.5)。但如果是这样的话,为什么T&0的帧矩形起源仍然是0,0和0。添加不一样(225.0 + 0 = 225.0)???

我不明白。

3 个答案:

答案 0 :(得分:7)

您正在使用精灵的框架创建形状节点,该框架位于场景坐标中。因为形状将是精灵的子元素,所以应该在精灵坐标中创建节点。例如,如果您使用太空船的大小创建SKShapeNode

let debugFrame = SKShapeNode(rectOfSize: spaceship.size)

而不是使用宇宙飞船的框架,debugFrame将以太空飞船为中心,无论您何时设置飞船的位置。此外,debugFrame将与船舶适当缩放/移动。

答案 1 :(得分:1)

回应你的'我不明白'。 您的代码没问题,但存在逻辑问题。 “框架”相对于父坐标计数。请注意,您的代码中太空船的父级和调试窗口的父级是不同的。

解决问题的两种方法:

  1. 为调试窗口添加零偏移量,并使用太空船作为父级。 这样做的好处是调试窗口将移动,与宇宙飞船一起扩展: let rectDebug = CGRectMake( 0, 0, spaceship.frame.size.width, spaceship.frame.size.height) let debugFrame = SKShapeNode(rect:rectDebug) spaceship.addChild(debugFrame)
  2. 将太空船“框架”坐标的调试窗口添加到太空船的父级(即“自我”)。这样做的缺点是你必须移动,在代码中自己调整调试窗口,因为它不会附加到太空船上: let debugFrame = SKShapeNode(rect:spaceship.frame) self.addChild(debugFrame)
  3. 两种解决方案都被广泛使用。在你的情况下,你应该选择哪个更适合你。 可能会出现其他三个问题:

    1.我的代码中可能存在代码错误,我只是在没有xcode语法检查的情况下直接将它们输入到Web窗口中。

    2.两个物体的锚点可能不同。因此,您可能需要在代码中进行对齐。

    3.还应考虑对象的zPosition,因此这些对象不会隐藏在某些其他对象下。

    为了回应你想要解决的问题,也许showPhysics会有所帮助:

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

答案 2 :(得分:0)

这与您提到的其他问题几乎相同。 frame是一个包含positionsize的媒体资源。它们都受到祖先节点缩放的影响。阅读部分"节点将许多属性应用于其后代"在https://developer.apple.com/library/ios/documentation/GraphicsAnimation/Conceptual/SpriteKit_PG/Nodes/Nodes.html#//apple_ref/doc/uid/TP40013043-CH3-SW13

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