I am developing a game where the boat and stone collide. The game is over When the boat collides the stone. I implemented intersects() method for the intersection of boat and stone. For each coin I collect, I increment the score by +1. I am performing a segue when both boat and stone collide. The segue is performed and the game score is displayed with the restart option. Everything is smooth until I restart the game and when the game restarted there are some problems. The following are the problems :
At first the game is smooth, the GameOver controller is shown when the collision happens but when I choose to restart.
Problem #1 When the boat collides the stone, the segue is shown twice and after restarting again
Problem #2 When I am playing for the 3rd time it does not detect an intersection and it is throwing an error
Here is the screen shot of the error.
I can play the game for the first time, but I cannot play the game when I restart. The game is not working correctly when restarted.
This is happening when segues are used, when I use UIAlertView the game is working smoothly. I want to implement segues.
here is the 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)
}
Here is the GameOver.swift which has the restart button, implementing segue to previous controller.
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.
}
*/
}
I think the problem is when I use touchesBegan and touchesMoved.
Any advice will be valuable.
Thank You.
From your code What I can see that you trigger a segue from ViewController.swift to GameOver.swift which is ok and it means you're presenting the GameOverViewController. The problem is you should not segue from GameOverViewController back to your ViewController.swift you have to dismiss your gameOverViewController
inside your restart function
@IBAction func restartGame(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
The second problem I can see is you're trying to call a function from your prepare for segue
You shouldn't use this segue back to your 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()
}
}
}
You can use unwindSegue, delegate, notification... to trigger your startGame() function