使用 segues 实现游戏,重新启动时崩溃。 Swift
Implementing a game with segues, crashing when restarted. Swift
我正在开发一款舟石相撞的游戏。当船撞到石头时,游戏就结束了。我为船和石头的交集实现了 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,它有重启按钮,实现了与之前控制器的连接。
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 时。
任何建议都很有价值。
谢谢。
根据您的代码,我可以看到您触发了从 ViewController.swift 到 GameOver.swift 的转场,这没问题,这意味着您正在呈现 GameOverViewController。问题是你不应该从 GameOverViewController 回到你的 ViewController.swift 你必须关闭你的 gameOverViewController
在你的重启函数中
@IBAction func restartGame(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
我看到的第二个问题是您正试图从您的 prepare for segue 中调用一个函数
你不应该使用这个 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() 函数
我正在开发一款舟石相撞的游戏。当船撞到石头时,游戏就结束了。我为船和石头的交集实现了 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,它有重启按钮,实现了与之前控制器的连接。
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 时。
任何建议都很有价值。
谢谢。
根据您的代码,我可以看到您触发了从 ViewController.swift 到 GameOver.swift 的转场,这没问题,这意味着您正在呈现 GameOverViewController。问题是你不应该从 GameOverViewController 回到你的 ViewController.swift 你必须关闭你的 gameOverViewController
在你的重启函数中
@IBAction func restartGame(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
我看到的第二个问题是您正试图从您的 prepare for segue 中调用一个函数
你不应该使用这个 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() 函数