【问题标题】:Swift 3: class doesn't function correctlySwift 3:类无法正常运行
【发布时间】:2016-11-13 08:04:35
【问题描述】:

所以我有一个名为FlashyPaddleEffect 的类。我还在另一堂课GameScene 中提到过它,但它并没有应用任何应有的效果。桨应该闪烁蓝色和白色,但它只是保持白色。当它是蓝色时,桨也应该失去它的物理体。

如果您需要任何其他信息,请随时询问。

注意:我给出的代码可能有问题(由于缩进,每行缩进 4 个空格来编写代码非常棘手,抱歉)。

import SpriteKit
import GameplayKit

class FlashyPaddleEffect {

    var node = SKSpriteNode()
    var ballNode = SKSpriteNode()
    var updateTimer: Timer? = nil

    var timer: Timer? = nil

    @objc func changeNodeColor() {

        switch node.color {

        case SKColor.blue: node.color = SKColor.white
        case SKColor.white: node.color = SKColor.blue

        default: _ = 1 + 2

        }

    }

    @objc func update() //I used the objc prefix to silence the warning the selectors of the timers produced. {

        let previousPhysicsBody = node.physicsBody

        if node.color == SKColor.blue {

            node.physicsBody = nil

        }

        node.physicsBody = previousPhysicsBody

    }

    func make(applyEffectTo: SKSpriteNode, ball: SKSpriteNode) {

        node = applyEffectTo
        ballNode = ball

        timer = Timer.scheduledTimer(timeInterval: 0.6, target: self, selector: #selector(changeNodeColor), userInfo: nil, repeats: true)
        updateTimer = Timer.scheduledTimer(timeInterval: 0.3, target: self,      selector: #selector(update), userInfo: nil, repeats: true)

        _ = node
        _ = timer

    }

}

class GameScene: SKScene {

    var ball =  SKSpriteNode()
    var player = SKSpriteNode()
    var enemy = SKSpriteNode()

    var scores = [0, 0]
    var initScores = [0, 0]
    var  scoreLabels: [SKLabelNode]? = nil

    let playLabel = SKLabelNode()
    let timeLabel = SKLabelNode()
    let timeUpLabel = SKLabelNode()

    var secondsLeft: Int = 180
    var initialTime: Int? = nil

    var timer = Timer()

    var amountOfPauseMenuCloses = 0

    var resultsLabel = SKLabelNode()

    let flashEffect = FlashyPaddleEffect() //I define a variable to mention the class easier later on.

    override func didMove(to view: SKView) {

        //Initialize nodes of the scene editor.
        ball =  self.childNode(withName: "Ball") as! SKSpriteNode
        player = self.childNode(withName: "PPaddle") as! SKSpriteNode
        enemy = self.childNode(withName: "EPaddle") as! SKSpriteNode

        //Set styles for the Play Notification Label (referred to as PNL later)
        playLabel.position = CGPoint(x: 0, y: 0)
        playLabel.text = "Tap anywhere to play."
        playLabel.name = "playLabel"

        //Set styles for the Timer Label (referred to as Timer later)
        timeLabel.position = CGPoint(x: 90, y: 0)
        timeLabel.text = String(secondsLeft)

        //Doing manipulations connected with scores here.
        scores = [0, 0]
        initScores = scores
        scoreLabels = [self.childNode(withName: "PScoreLabel") as! SKLabelNode, self.childNode(withName: "EScoreLabel") as! SKLabelNode]

        //Create a border for our ball to bounce off.
        let border = SKPhysicsBody(edgeLoopFrom: self.frame)
        border.friction = 0
        border.restitution = 1
        border.linearDamping = 0
        border.angularDamping = 0
        self.physicsBody = border

       //To avoid the ball's damping.
       ball.physicsBody?.linearDamping = 0
       ball.physicsBody?.angularDamping = 0

       showPause() //Show the (pause) menu at the beginning

       //Set a variable to refer to as a time standard later.
       initialTime = secondsLeft

       //The game timer.
       timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(reduceSecondFromTimer), userInfo: nil, repeats: true)

        flashEffect.make(applyEffectTo: player, ball: ball) //This is where I reference the class in another class. 

    }

    //A function to show the (pause) menu.
    func showPause(hideNodes: Bool = true) {

        self.addChild(playLabel)

        if hideNodes == true {

            ball.removeFromParent()
            player.removeFromParent()
            enemy.removeFromParent()
            scoreLabels?[0].removeFromParent()
            scoreLabels?[1].removeFromParent()

        }

    }

    override func update(_ currentTime: TimeInterval) {

        var alreadyChangedTextLabel = false

        for i in scoreLabels! {

            if i.name == "PScoreLabel" {i.text = String(scores[0])}
            if i.name == "EScoreLabel" {i.text = String(scores[1])}


        }

        if ball.position.y <= player.position.y {scores[1] += 1}
        if ball.position.y >= enemy.position.y {scores[0] += 1}

        if secondsLeft == 0 {

            showPause(hideNodes: false)

            if alreadyChangedTextLabel == false {

                timeUpLabel.text = "TIME UP! \(whoIsWinning(scores: scores)) won!"
                alreadyChangedTextLabel = true

            }

            timeUpLabel.name = "timeUpLabel"
            timeUpLabel.position = CGPoint(x: 0, y: 180)

            if !(self.children.contains(timeUpLabel)) {

                self.addChild(timeUpLabel)

            }

            timeLabel.removeFromParent()

        }

        if self.children.contains(playLabel) {

            secondsLeft = initialTime!

        }

        timeLabel.text = String(secondsLeft)

        let alignWithBall = SKAction.move(to: CGPoint(x: ball.position.x, y: enemy.position.y), duration: 0.8)
    enemy.run(alignWithBall)

    }

    func initGame() {

        //Initializing process for every game.

        scores = initScores
        ball.position = CGPoint(x: 0, y: 0)

        if amountOfPauseMenuCloses == 1  {ball.physicsBody?.applyImpulse(CGVector(dx: 15, dy: 15))}

        secondsLeft = initialTime!
        timeLabel.text = String(secondsLeft)

    }



    override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {

        for childNode in self.children {

            if childNode.name == "playLabel" {

                if self.children.contains(playLabel) {

                    playLabel.removeFromParent()

                }


                if !(self.children.contains(player)) {

                    self.addChild(player)

                }

                if !(self.children.contains(enemy)) {

                    self.addChild(enemy)

                }

                if !(self.children.contains(ball)) {

                    self.addChild(ball)

                }

                if !(self.children.contains((scoreLabels?[0])!)) {

                    self.addChild((scoreLabels?[0])!)

                }

                if !(self.children.contains((scoreLabels?[1])!)) {

                    self.addChild((scoreLabels?[1])!)    
                }

                if !(self.children.contains(timeLabel)) {

                    self.addChild(timeLabel)

                }

                if self.children.contains(timeUpLabel) {

                    timeUpLabel.removeFromParent()

                }

                amountOfPauseMenuCloses += 1

                initGame()

            }

        }

    }




    override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {

    for t in touches {

            if self.nodes(at: t.location(in: self)).contains(player) {player.position.x = t.location(in: self).x}

        }

    }

    func reduceSecondFromTimer() {

        secondsLeft -= 1

    }

    func whoIsWinning(scores: Array<Int>) -> String {

        var r: String? = nil

        if scores[0] >= scores[1] {

            r = "You"

        }

        if scores[1] >= scores[0] {

            r = "Enemy"

        }

        return r!

    }

}

非常感谢您的回答。 P.S 这是我的第一个问题,所以不要严格评判我。

【问题讨论】:

  • 请将您的代码缩减到最简单的部分以重现您的问题。目前,有很多代码需要解析,从而掩盖了导致问题的原因。
  • “每行缩进 4 个空格来编写代码非常棘手。”?您可以配置 XCode 以正确执行此操作。如果你的意思是在 StackOverflow 上缩进 4 个空格:复制粘贴你的代码,然后选择问题框中的所有代码,然后单击“代码”格式图标 {},所有内容都会缩进 4 个额外的空格并变成一个代码块。
  • 正如 Evert 所说,想要帮助的人很难找到真正的问题所在。尝试用最少的必要代码重现问题,并以此为例(大部分时间到那时您将能够自己修复它)。

标签: swift sprite-kit skspritenode gameplay-kit


【解决方案1】:

1) 不要使用NSTimer 使用SKAction。我可以看到你这样做的方式,你一个接一个地堆叠计时器,这很糟糕。

2) 没有全局临时变量(本例中为节点),这会使代码难以阅读

3) 不要删除你的物理实体,只需删除类别即可。

func make(applyEffectTo: SKSpriteNode, ball: SKSpriteNode) {

    ballNode = ball
    let blue = SKAction.colorize(with SKColor.blue, colorBlendFactor: 1.0, duration sec: 0)
    let white = SKAction.colorize(with SKColor.white, colorBlendFactor: 1.0, duration sec: 0)
    let wait = SKAction.wait(for:0.6)
    let turnOnPhysics = SKAction.run({applyEffectTo.physicsBody?.categoryBitmask = #######})
    let turnOffPhysics = SKAction.run({applyEffectTo.physicsBody?.categoryBitmask = 0})
    let seq = [blue, turnOffPhysics,wait,white,turnOnPhysics,wait]
    let repeat = SKAction.repeatForever(seq)
    applyEffectTo.run(repeat, withKey:"flashing")

}

注意:我不知道你的categoryBitmask是什么,你需要填写

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-04-04
    • 1970-01-01
    • 2016-11-14
    • 2017-04-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多