【问题标题】:Implementing a game with segues, crashing when restarted. Swift使用 segues 实现游戏,重新启动时崩溃。迅速
【发布时间】:2017-04-21 19:52:23
【问题描述】:

我正在开发一个船和石头碰撞的游戏。当船撞上石头时,游戏就结束了。我为船和石头的交集实现了 intersects() 方法。对于我收集的每枚硬币,我将分数增加 +1。当船和石头碰撞时,我正在执行一个segue。执行 segue 并显示带有重新启动选项的游戏分数。一切都很顺利,直到我重新启动游戏,当游戏重新启动时出现了一些问题。以下是问题:

一开始游戏很流畅,发生碰撞时会显示GameOver控制器,但当我选择重新启动时。

问题#1 当船撞到石头时,segue 显示两次,然后重新启动

问题 #2 当我第 3 次玩游戏时,它没有检测到交叉路口并抛出错误

这是错误的屏幕截图。

第一次可以玩,重启后就不能玩了。重启后游戏无法正常运行。

使用 segues 时会发生这种情况,当我使用 UIAlertView 时,游戏运行顺畅。我想实现segues。

这里是 ViewController.swift

   func movingStone() {


    stone = UIImageView(image: UIImage(named: "stones.png"))
    stone.frame = CGRect(x: 0, y: 0, width: 5.0, height: 5.0)



    stone.bounds = CGRect(x:0, y:0, width: 5.0, height:5.0)
    stone.contentMode = .center;



    stone.layer.position = CGPoint(x: boat.center.x - 5, y: 0.0)
    stone.transform = CGAffineTransform(rotationAngle: 3.142)


    self.view.insertSubview(stone, aboveSubview: myView)



    UIView.animate(withDuration: 5, delay: 0, options: UIViewAnimationOptions.curveLinear, animations: { () -> Void in
        self.stone.frame.origin.y = self.view.bounds.height + self.stone.frame.height + 10
    }) { (success:Bool) -> Void in

        self.stone.removeFromSuperview()
        self.movingStone()

    }



}

    func movingFood() {

    food = UIImageView(image: UIImage(named: "fishcoin2.png"))
    food.frame = CGRect(x: 0, y: 0, width: 5.0, height: 5.0)
    var stone3 = leftS + arc4random() % rightS


    food.bounds = CGRect(x:0, y:0, width: 5.0, height: 5.0)
    food.contentMode = .center;
    food.layer.position = CGPoint(x: boat.center.x + 20, y: 0.0)
    food.transform = CGAffineTransform(rotationAngle: 3.142)


    self.view.insertSubview(food, aboveSubview: myView)


    UIView.animate(withDuration: 5, delay: 0, options: UIViewAnimationOptions.curveLinear, animations: { () -> Void in
        self.food.frame.origin.y = self.view.bounds.height + self.food.frame.height - 50
    }) { (success:Bool) -> Void in


        self.food.removeFromSuperview()
        self.movingFood()

    }



}

   func intersectsAt(tap2 : Timer) {
  if(boat.layer.presentation()?.frame.intersects((food.layer.presentation()?.frame)!))!{
        food.layer.isHidden = true

        coins = +1
        collectedCoin.text = "\(coins)"
        if coins > 100 {
            super.performSegue(withIdentifier: "GameOverIdentifier", sender: self)

        }
  }

    if(boat.layer.presentation()?.frame.intersects((stone.layer.presentation()?.frame)!))! {
        stopGame()


    }

}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "GameOverIdentifier" {
        let gameOver = segue.destination as? GameOver
        gameOver?.coin = coins


    }
}

func stopGame() {

    tapTimer2.invalidate()

    boat.image = UIImage(named: "wreckboat.png")

    super.performSegue(withIdentifier: "GameOverIdentifier", sender: self)

}

这是带有重启按钮的 GameOver.swift,实现对前一个控制器的 segue。

import UIKit

class GameOver: UIViewController {

var coin = Int()


var restart : ViewController!

@IBOutlet weak var go: UILabel!
override func viewDidLoad() {
    super.viewDidLoad()

    go.text =  "\(self.coin)"
    // Do any additional setup after loading the view.
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


@IBAction func restartGame(_ sender: Any) {
    performSegue(withIdentifier: "goBack", sender: self)
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "goBack" {
        if let back = segue.destination as? ViewController {

            back.startGame()
    }

    }
}



/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // Get the new view controller using segue.destinationViewController.
    // Pass the selected object to the new view controller.
}
*/

}

我认为问题出在我使用 touchesBegan 和 touchesMoved 时。

任何建议都会很有价值。

谢谢。

【问题讨论】:

    标签: ios iphone swift touchesbegan


    【解决方案1】:

    从您的代码中,我可以看到您触发了从 ViewController.swift 到 GameOver.swift 的转场,这没问题,这意味着您正在呈现 GameOverViewController。问题是你不应该从 GameOverViewController 回到你的 ViewController.swift 你必须关闭你的 gameOverViewController

    在你的重启函数中

    @IBAction func restartGame(_ sender: Any) {
       self.dismiss(animated: true, completion: nil)
    }
    

    我可以看到的第二个问题是你试图从你的准备中调用一个函数

    你不应该使用这个 segue 回到你的 ViewController

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "goBack" {
        if let back = segue.destination as? ViewController {
            // this is wrong
            back.startGame()
         }
    
      }
    }
    

    您可以使用 unwindSegue、delegate、notification... 来触发您的 startGame() 函数

    【讨论】:

    • 我会解决这个问题,但是为什么当我按下重新启动时,segue 会执行两次,即对 GameOverVC 的 segue?下次它会抛出图像中的错误。是因为GameOver中的segue吗?
    • 所以你的意思是 startGame() 方法被错误地调用了,在 segue 的主体中?所以,这会让代码崩溃?
    • 我要放松一下,但是怎么调用startGame()我做了performSegue(withIdentifier: "unwindto", sender: self)
    • 当你从 prepareForSegue 调用 startGame() 时,它认为它永远没有机会执行你的 startGame() 函数,因为 prepareForSegue 发生在你的视图控制器有机会加载之前
    • 我正在使用重启按钮返回,所以当我按下重启它应该开始游戏。如何解决这个问题!?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多