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

Posted

技术标签:

【中文标题】为啥我总是必须将精灵的位置更改为其他位置才能获得所需的位置【英文标题】:Why do I always have to change the position of a sprite to something else before I can get the desired position to work为什么我总是必须将精灵的位置更改为其他位置才能获得所需的位置 【发布时间】:2016-02-28 09:38:16 【问题描述】:

我个人认为这真的 真的很奇怪。

我只是在使用 SpriteKit 开发游戏。我创建了SKSpriteNode 的子类,以创建一个显示游戏剩余时间、分数等的精灵。我将其命名为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"

但我只能在屏幕上看到横幅的背景图片,而不是“剩余时间”。我认为这是因为我以某种方式将timerTitle 的位置设置在横幅之外。

然后我想,好吧,这对我来说很难确定它应该在哪里,让我们“试错”吧!

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

    (-100, 0) - 标签不可见(“也许它离左边太远了?”我想) (-40, 0) - 标签在中心附近,向左偏移一点(“如果 -40 是 this 向左一点,那么 -100 就可以了!”,我想) (-100, 0) - 标签可见,似乎在正确的位置。 (“等一下!为什么第一次没有用?”,我想) (当我尝试使用 (-160, 0) 和 (-160, 20) 时发生同样的事情,即第一次不可见时,将其更改为另一个值并运行它,将其更改回 (- 160, 0) 并且有效)

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

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

然后我把它改成(-160, 0),就出现了:

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

这是GameBanner 类:

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
        
    

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

【问题讨论】:

【参考方案1】:

我相信您的问题与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属性:

默认值为NO,表示当多个节点共享时 相同的 z 位置,这些节点被排序并呈现在一个 确定性顺序。父母被呈现在他们的孩子之前,并且 兄弟姐妹按数组顺序呈现。当此属性设置为 YES,确定时忽略树中节点的位置 渲染顺序。同一z节点的渲染顺序 位置是任意的,每次新帧出现时都可能改变 呈现。当兄弟和父顺序被忽略时,SpriteKit 应用 其他优化以提高渲染性能。如果你需要 节点以特定和确定的顺序呈现,您必须 设置这些节点的 z 位置。

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

Creating The Node Tree

【讨论】:

以上是关于为啥我总是必须将精灵的位置更改为其他位置才能获得所需的位置的主要内容,如果未能解决你的问题,请参考以下文章

如何将按钮的位置更改为窗口内所需的位置?

如何?编码 Android 应用程序以将用户的位置设置更改为关闭?

如何获得具有动作CCRotate的精灵的位置?

我怎样才能做到这一点?将复选框从只读更改为可用于检查

IOS:如何将UITabbar的位置更改为视图顶部

CodeDom 将生成的 .cs 文件保存在哪里?我们可以将此位置更改为其他文件夹吗