【问题标题】:Different sprite position with the same code相同代码的不同精灵位置
【发布时间】:2015-04-06 03:17:00
【问题描述】:

我的精灵位置有一个奇怪的问题,我尝试干净构建,重新启动 xcode,并在不同的方案(iPhone5s,iPhone6)中运行,它们都返回相同的奇怪问题。 我尝试通过以下方式设置精灵的位置:

balls.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame) + self.frame.size.width)

所以当我 println(balls.position) 到控制台时,它返回 (0.0, 0.0)

但是当我尝试时

println(CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame) + self.frame.size.width)

它返回 (512.0,1408.0),这是球应该在的正确位置。

我遇到了最后一个函数 func ballPosition 的问题,它用于确定精灵“球”的位置。出于某种原因,它总是 (0, 0)。

以下是我的测试项目的完整代码:

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {

    var circle = SKShapeNode()
    var balls = SKShapeNode()
    var ballColor = ["red", "blue", "green", "yellow"]
    var points = ["up", "down", "left", "right"]

    override func didMoveToView(view: SKView) {

        backgroundColor = SKColor.whiteColor()

        // set circle position and size

        circle = SKShapeNode(circleOfRadius: 100 ) // Size of Circle
        circle.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))  //Middle of Screen
        circle.strokeColor = SKColor.whiteColor()
        circle.fillColor = SKColor.orangeColor()
        self.addChild(circle)

    }

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        /* Called when a touch begins */

        circleRotate()

        ballPosition()
        // test ball position, this is the part with the issue I mentioned above.
        println(balls.position) // (0, 0)
        println(CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame) + self.frame.size.width)) // (512.0,1408.0)

    }

    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */

    }

    func circleRotate() {

        let circleAction = SKAction.rotateByAngle(CGFloat(-M_PI * 2 / 3), duration: 0.1)

        circle.runAction(SKAction.repeatAction(circleAction, count: 1))

    }

    func ballMove() {

        let ballMovement = SKAction.moveTo(CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)), duration: 5)
        balls.runAction(ballMovement)

    }

    func randomColor() {

        let ballColorIndex = Int(arc4random_uniform(UInt32(ballColor.count)))

        balls = SKShapeNode(circleOfRadius: 10 )

        if ballColorIndex == 0 {

            balls.strokeColor = SKColor.whiteColor()
            balls.fillColor = SKColor.redColor()
            // balls.zPosition = 10
            ballMove()

        } else if ballColorIndex == 1 {

            balls.strokeColor = SKColor.whiteColor()
            balls.fillColor = SKColor.blueColor()
            // balls.zPosition = 10
            ballMove()

        } else if ballColorIndex == 2 {

            balls.strokeColor = SKColor.whiteColor()
            balls.fillColor = SKColor.greenColor()
            // balls.zPosition = 10
            ballMove()

        } else if ballColorIndex == 3 {

            balls.strokeColor = SKColor.whiteColor()
            balls.fillColor = SKColor.yellowColor()
            // balls.zPosition = 10
            ballMove()

        }

    }

    func ballPosition() {

        let ballPointIndex = Int(arc4random_uniform(UInt32(points.count)))

        if ballPointIndex == 0 {

            balls.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame) + self.frame.size.width)
            randomColor()
            self.addChild(balls)

        } else if ballPointIndex == 1 {

            balls.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame) - self.frame.size.height)
            randomColor()
            self.addChild(balls)

        } else if ballPointIndex == 2 {

            balls.position = CGPoint(x:CGRectGetMidX(self.frame) - self.frame.size.width, y:CGRectGetMidY(self.frame))
            randomColor()
            self.addChild(balls)


        } else if ballPointIndex == 3 {

            balls.position = CGPoint(x:CGRectGetMidX(self.frame) + self.frame.size.width, y:CGRectGetMidY(self.frame))
            randomColor()
            self.addChild(balls)

        }

    }

}

【问题讨论】:

  • 屏幕中间是(512.0, 384.0),精灵应该从屏幕顶部移动到屏幕中。但相反,精灵总是来自屏幕左下方的外部。控制台中的位置总是打印 (0, 0)
  • 谢谢,我也会修改代码,方便大家阅读。
  • 我发现了问题并包含了您的代码工作版本的示例。您可能会发现要替换节点或添加多个节点,但这只是一个小调整。

标签: ios swift sprite-kit


【解决方案1】:

问题是您正在覆盖 randomColor() 中的 ball - 您正在创建一个尚未添加到父视图的新节点。

根本问题是您的代码结构导致混乱和错误。您应该保持功能单一。他们应该按照他们所说的去做。名为 randomColor() 的函数不应移动球或设置球的大小。位置函数不应该设置颜色。

我重新排列了代码并运行了它。该错误已修复。您可以看到我所做的更改,并且现在应该能够更进一步。祝你好运。

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {

    var circle = SKShapeNode()
    var ball = SKShapeNode(circleOfRadius: 10)
    var ballColor = ["red", "blue", "green", "yellow"]
    var points = ["up", "dowm", "left", "right"]

    override func didMoveToView(view: SKView) {
        backgroundColor = SKColor.whiteColor()
        circle = SKShapeNode(circleOfRadius: 100 ) // Size of Circle
        circle.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))  //Middle of Screen
        circle.strokeColor = SKColor.whiteColor()
        circle.fillColor = SKColor.orangeColor()
        self.addChild(circle)
        self.addChild(ball)
        ball.position = CGPointMake(150, 0)
        println("Initial Ball Pos:   \(ball.position)")
    }

    override func touchesBegan(touches: NSSet, withEvent event: UIEvent) {
        circleRotate()
        setRandomBallPosition()
        setRandomColor()
        ballMove()
        // test ball position
        println("--------------")
        println("Ball Pos:   \(ball.position)")
        println("Circle pos: \(circle.position)")
        println("Midpoint:   \(CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame) + self.frame.size.width))")
        println("--------------")
    }

    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */
    }

    func circleRotate() {
        let circleAction = SKAction.rotateByAngle(CGFloat(-M_PI * 2 / 3), duration: 0.1)
        circle.runAction(SKAction.repeatAction(circleAction, count: 1))
    }

    func ballMove() {
        let ballMovement = SKAction.moveTo(CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)), duration: 5)
        ball.runAction(ballMovement)
    }

    func setRandomColor() {
        ball.strokeColor = SKColor.whiteColor()
        let ballColorIndex = Int(arc4random_uniform(UInt32(ballColor.count)))
        switch(ballColorIndex) {
        case 0:
            ball.fillColor = SKColor.redColor()
        case 1:
            ball.fillColor = SKColor.blueColor()
        case 2:
            ball.fillColor = SKColor.greenColor()
        case 3:
            ball.fillColor = SKColor.yellowColor()
        default:
            println("Unexpected random index value ", ballColorIndex)
        }
    }

    func setRandomBallPosition() {
        let ballPointIndex = Int(arc4random_uniform(UInt32(points.count)))
        println("ballPointIndex = \(ballPointIndex)")
        switch(ballPointIndex) {
        case 0:
            ball.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame) + (self.frame.size.width / 2))
        case 1:
            ball.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame) - (self.frame.size.height / 2))
        case 2:
            ball.position = CGPoint(x:CGRectGetMidX(self.frame) - (self.frame.size.width / 2), y:CGRectGetMidY(self.frame))
        case 3:
            ball.position = CGPoint(x:CGRectGetMidX(self.frame) + (self.frame.size.width / 2), y:CGRectGetMidY(self.frame))
        default:
            println("Unexpected random index value: ", ballPointIndex)
        }
        println("ball position = \(ball.position)")
    }
}

【讨论】:

  • 非常感谢。这真的对我有很大帮助,因为我是编程新手。我非常感谢您付出的努力并帮助我!我相信通过查看您提供的示例,我会学到很多东西。再次,非常感谢!
  • 它基本上是非常好的代码并且智能地完成了。对于一个新程序员来说,这是一项值得尊敬的努力。我已经编程了 35 年,其中大部分是为硅谷公司和许多重大项目工作的。如果你能理解我所做的更改以及我为什么做这些更改,并了解它如何帮助我找到你的错误并帮助你编写更易于解决的可维护代码,那么你将成为一个非常可靠和称职的程序员.感谢您的复选标记并让我知道!祝你好运!
  • @f_qi BTW:如果我必须做进一步的改进,我会尝试(通常)避免在函数中设置全局变量,而是将参数传递给函数并通过返回值返回结果.当不同的功能开始从难以查看和跟踪的位置和情况修改共享数据时,您可能会遇到问题。当您开始处理多线程代码时,它真的 变得一团糟。所以要研究函数参数和返回值。
  • 在 Swift/iOS 中使用的全局变量很方便,但在语言中是一个有争议的部分。您可以更轻松地做很多事情,但如果您至少不了解安全编程实践并尽量减少全局使用,您也可以编写蹩脚的代码。当你做这样的事情时,试着以尽可能自我记录的方式编写你的代码,这样如果你几个月或几年后回来看它,你可能会很快理解你在做什么。如果您还没有发现这一点,很快您就会发现最“简单”的代码在以后是如何难以弄清楚的。
  • 有意识地和描述性地命名你的函数和变量very,这样你的代码读起来更像一本书,你真的会省去很多麻烦。它实际上告诉你它在做什么。如果您以后必须努力破译所有内容,那就太麻烦了,而且浪费时间。而且你会比你想象的更快地忘记你在想什么:-) 纪律、良好的习惯和干净的代码可以帮助你避免一些真正的调试噩梦
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多