【问题标题】:Swift SKSpriteNode Position Issues - logging correct, placement wrongSwift SKSpriteNode 位置问题 - 记录正确,位置错误
【发布时间】:2014-06-13 06:15:52
【问题描述】:

情况

我正在使用 Lynda.com video series (iOS Game Dev. With Sprite Kit),该教程是 Objective-C 的最后一代,作为培训练习,我将其转换为 Swift 并使用新功能。目标是一个老式的破砖游戏。

我有一个更新的full project repository on GitHub here

问题

在GameScene.swift文件中,我写了一个方法addBricks(size: CGSize)

func addBricks (size: CGSize){

    println(" the input parameter size: \(size)")

    var maxRows = 1
    var maxCols = 1
    var xPos : CGFloat
    var yPos : CGFloat

    for (var rows = 0; rows < maxRows; rows++){
        for (var i = 0; i < maxCols ; i++){

            var brick: SKSpriteNode = SKSpriteNode(imageNamed: "brick")
            brick.physicsBody = SKPhysicsBody(rectangleOfSize: brick.frame.size)

            xPos = CGFloat(size.width) / CGFloat(maxCols+1) * CGFloat(i + 1)
            yPos = CGFloat(size.height) - CGFloat(80 * rows) - 100.0

            brick.physicsBody.dynamic = false
            brick.physicsBody.categoryBitMask = brickCategory

            brick.shadowCastBitMask = 1
            brick.lightingBitMask = 1

            //brick.position = CGPointMake(CGFloat(xPos), CGFloat(yPos))
            brick.position = CGPointMake(320.0, 1036.0)

            println("Brick position - xpos: \(xPos), ypos: \(yPos) || overall:\(brick.position)")

            self.addChild(brick)

        }
    }

}

我首先在didMoveToView() 的场景中调用它,一切都很好,我的砖节点放置在适当的位置。在我的游戏逻辑中,我稍后从didBeginContact() 调用此方法,当球在逻辑检查后看到没有剩余的砖块后撞击桨时。在“当你用完砖时,添加更多”的感觉......

func didBeginContact(contact: SKPhysicsContact!){

    var notTheBall : SKPhysicsBody

    // check the contacts and find the one thats not the ball
    if ( contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask ){
        notTheBall = contact.bodyB
    } else {
        notTheBall = contact.bodyA
    }

    /* more logic here for other contacts */

    if ( notTheBall.categoryBitMask == paddleCategory ){

        self.runAction(playSFXBlip)

        //println("\(self.children.count) and \(staticSize)")

        if ( self.children.count <= 5 ){
            addBricks(self.frame.size)
        }

    }

}

在对addBricks() 的任何后续方法调用中,所有砖块都放置在视图左下角的点 0,0 处,即使在控制台显示它们被放置在不同位置时也是如此:

self 对象是SKScene println(self) 的当前实例 -> &lt;SKScene&gt; name:'(null)' frame:{{0, 0}, {640, 1136}}

我试过了:

  • 将我的位置计算的所有元素转换为Floats 和CGFloats
  • 通过设置静态浮点值来调试 addBricks 方法
  • 在联系方法之外为框架大小创建一个属性,并将该大小传递给 addBricks。
  • google 和咨询 the Swift Programming Language Guide 以及任何相关的文档

是什么导致了不适当的定位?提前感谢TL;DR

【问题讨论】:

  • 以防万一,我正在为 iPhone5s iOS8 构建。但为 iPhone5 构建时,其他所有功能在功能上都相似
  • 您的联络代表是谁? SKScene 还是其他类?
  • @Grimxn,如果我正确理解这一点,我应该使用 SKScene 类class GameScene: SKScene, SKPhysicsContactDelegate
  • 好吧,SKScene 类是显而易见的代表,但并非必须如此。我问是因为在您的“addBricks(self.frame.size)”行中,“self”是最重要的。 addBricks 的代码是什么?
  • 再次感谢您的回复,添加砖块功能的代码已在上面发布,并且有一个指向github上完整公共存储库的链接

标签: ios iphone objective-c swift


【解决方案1】:

问题是,您试图在 didBeginContact 方法中设置节点的位置。您不能在 didBeginContact 中定位已经有物理体的节点。

理想的解决方案是添加没有物理体的砖块,然后将其位置设置为您喜欢的任何位置,最后添加物理体。

另一个解决方案是创建一些在您运行 didBeginContact 后调用的代码。例如

func didBeginContact(contact: SKPhysicsContact!){

    var notTheBall : SKPhysicsBody

    if ( contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask ){
        notTheBall = contact.bodyB
    } else {
        notTheBall = contact.bodyA
    }

    if ( notTheBall.categoryBitMask == paddleCategory ){
        addBricksInUpdate = true
    }
}

func update:(currentTime: CFTimeInterval) {
    if (addBricksInUpdate) {
        if ( self.children.count <= 5 ){
            addBricks(self.frame.size)
        }
    }
}

【讨论】:

  • 这是一个很好的答案,可能也解决了我们的位置问题。但是你能解释一下为什么带有physicsBody 的节点不能定位在didBeginContact 中吗?
【解决方案2】:

我对你调用时的“self”是什么,或者self的属性和值是什么了解不够,但是当子节点出现在左下角时,通常是由于以下两个原因之一:

1- 对象被放置在 (0,0) - 或者因为这是它们的位置,或者因为其他一些约束,如大小或矩形,返回零值。所以你有一个大小为 (0,0) 或转换坐标等的父级。

[或]

2- 对象的父节点从“屏幕”矩形偏移/缩放/定位,这样您为孩子输入的位置值使孩子最终看起来像在左下角,即使它们实际上是相对于父级或父级坐标空间放置的。这很容易通过查看不同的坐标是否仍将对象放在同一个位置来检查。

因此,请检查您的父节点的锚点,无论是场景还是节点。并检查父级的大小和位置。我听说 swift 中的 sks 文件在 sprite kit 和场景大小方面有奇怪的默认大小设置,但还没有打开 swift 项目。

【讨论】:

  • 首先感谢您的回复 - self 对象是 SKScene println(self) -> &lt;SKScene&gt; name:'(null)' frame:{{0, 0}, {640, 1136}} 的当前实例 - 对此进行调查,因为我觉得这些整数应该是 CGfloats
  • 那么,显而易见的后续是,无论您输入的位置如何,对象都会出现在左下角吗?你有没有仔细检查过,在每个实例中它们实际上都被添加到同一个父级中?
  • 感谢您的回复 - 是的,输入的任何位置都会将它们放在左下角,同时仍会记录位置输入。正在研究如何检查他们被添加到的父母
  • 砖块被添加到同一个自身,但是在println(self) 上,砖块的位置似乎没有在随后的调用&lt;SKSpriteNode&gt; name:'(null)' texture:[&lt;SKTexture&gt; 'brick' (120 x 60)] position:{0, 0} size:{60, 30} rotation:0.00] 上设置...所以问题是为什么@987654326 @在第一次调用时设置位置
  • 找到了!您必须在分配物理体之前定义一个位置,否则您无法重新定位 SKNode stackoverflow.com/a/20359622/2397883
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-06-18
相关资源
最近更新 更多