为什么我总是必须将精灵的位置更改为其他位置才能获得所需的工作位置

Why do I always have to change the position of a sprite to something else before I can get the desired position to work

个人觉得这个

我刚刚使用 SpriteKit 开发了一款游戏。我创建了 SKSpriteNode 的子 class 以创建一个显示游戏剩余时间、分数等的精灵。我将其命名为 GameBanner.

我现在正尝试在横幅的左上角放置一个 SKLabelNode。我不知道它的确切位置所以我写了这个:

timerTitle.position = //CGPointMake(CGRectGetMinX(self.frame) + 
    timerTitle.frame.width / 2 + 20, CGRectGetMaxY(self.frame) - 
    self.frame.height / 2 - 20)
// timerTitle is the label node that shows "Time Left"

但是我只能在屏幕上看到横幅的背景图片,而没有 "Time Left"。我认为这是因为我以某种方式将 timerTitle 的位置设置在横幅之外。

然后我想,好吧,这对我来说太麻烦了,让我们"trial and error"这个!

我首先尝试使用 (0, 0)。它把标签放在中间。然后我尝试了这些:

  1. (-100, 0) - 标签不可见("Maybe it's too far left?" 我认为)
  2. (-40, 0) - 标签在中心附近,向左偏移一点("If -40 is this little left, then -100 would work!",我认为)
  3. (-100, 0) - 标签可见,位置正确。 ("Wait a minute! Why the first time it didn't work?",我以为)
  4. (当我尝试使用 (-160, 0) 和 (-160, 20) 时会发生同样的事情,即第一次它不可见时,将其更改为另一个值并 运行 它,将其改回 (-160, 0) 并且有效)

希望你能通过截图理解我的问题:

这是我第一次将位置设置为(-160, 20):

然后我把它改成(-160, 0),结果显示:

之后,我将其改回 (-160, 20),它神奇地起作用了!

这里是 GameBanner class:

class GameBanner: SKSpriteNode {
    let timerTitle = SKLabelNode(text: "Time Left:")
    let timerLabel = SKLabelNode(text: "60")
    let collectedBlocksLabel = SKLabelNode(text: "Collected Blocks")
    let scoreLabel = SKLabelNode(text: "Score:")

    override init(texture: SKTexture?, color: UIColor, size: CGSize) {
        super.init(texture: texture, color: color, size: size)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    //Call this initializer with Position: (302.08, 860.78), Size: (604.16, 100.0) to reproduce
    convenience init(position: CGPoint, size: CGSize) {
        self.init(texture: SKTexture(imageNamed: "banner"), color: UIColor.clearColor(), size: size)
        self.position = position
        configureLabels(timerTitle, timerLabel, collectedBlocksLabel, scoreLabel)
        // This is the part that doesn't work as I have said above
        timerTitle.position = CGPointMake(-160, 20)

        addChild(timerTitle)
        //addChild(timerLabel)
        //addChild(collectedBlocksLabel)
        //  addChild(scoreLabel)

        zPosition = 10000
    }

    private func configureLabels(labels: SKLabelNode...) {
        for label in labels {
            label.fontColor = UIColor.whiteColor()
            label.fontName = "Chalkduster"
            label.fontSize = 25
        }
    }
}

这是横幅的背景图片。也许这很重要:

我认为您的问题与 ignoresSiblingOrder 属性 有关。

目前,您有这样的东西:

父项(即 GameBanner)已 zPosition 设置为 10000。

label (timerTitle) 被添加到父级,并且默认 zPosition 设置为 0.0,这意味着渲染(全局)zPosition 将是 10000 + 0 = 10000。意味着,它有时会在(下面)之前渲染),有时在其父级之后(上方)。

尝试明确设置标签的 zPosition,将其置于其父级之上:

 convenience init(position: CGPoint, size: CGSize) {
        //...
        timerTitle.zPosition = 1
       //...
        zPosition = 10000
    }

现在,全局渲染 zPositiot 将为 10000+1 = 10001,这意味着该标签将始终位于横幅图像的顶部。

关于ignoresSiblingOrder属性:

The default value is NO, which means that when multiple nodes share the same z position, those nodes are sorted and rendered in a deterministic order. Parents are rendered before their children, and siblings are rendered in array order. When this property is set to YES, the position of the nodes in the tree is ignored when determining the rendering order. The rendering order of nodes at the same z position is arbitrary and may change every time a new frame is rendered. When sibling and parent order is ignored, SpriteKit applies additional optimizations to improve rendering performance. If you need nodes to be rendered in a specific and deterministic order, you must set the z position of those nodes.

更多关于如何渲染节点树的信息:

Creating The Node Tree