Dismissing GameScene in swift 3 - ios

I'm making a simple pong game with Swift in SpriteKit.
I'm new to SpriteKit so I can't yet solve my problem. I have menu UIViewController, GameViewController and a UINavigationController to switch between them:
Everything is OK but when one of the players gets 10 points I want to go back to the menu. I searched but nothing works for me.
GameScene code:
import SpriteKit
import GameplayKit
var currentgame = gameType.deafoult //game type enumeration
class GameScene: SKScene {
//If game start enumeration
enum gamestart {
case yes, no
}
//Variables
var start = gamestart.no
var ball = SKSpriteNode()
var enemy = SKSpriteNode()
var main = SKSpriteNode()
var tplab = SKLabelNode()
var btlab = SKLabelNode()
var startlab = SKLabelNode()
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let position = touch.location(in: self)
if position.y > 0 && currentgame == .player2 {
enemy.run(SKAction.moveTo(x: position.x, duration: 0.2))
}
if position.y < 0 {
main.run(SKAction.moveTo(x: position.x, duration: 0.2))
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let position = touch.location(in: self)
if position.y > 0 && currentgame == .player2 {
enemy.run(SKAction.moveTo(x: position.x, duration: 0.2))
}
if position.y < 0 {
main.run(SKAction.moveTo(x: position.x, duration: 0.2))
}
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if start == .no {
let touch = touches.first
let touchLocation = touch!.location(in: self)
var minusx = touchLocation.x - startlab.position.x
var minusy = touchLocation.y - startlab.position.y
if minusx < 0 {
minusx = -minusx
}
//checking if player click on label to start game
if minusy < 0 {
minusy = -minusy
}
if minusx > 0 && minusx < 16 && minusy > 0 && minusy < 16 {
start = .yes
startlab.alpha = 0
startgame()
}
print(touchLocation)
print(startlab.position)
}
}
var score = [0,0] //scores
//start game fun
func startgame() {
ball.position = CGPoint(x: 0, y: 0)
ball.physicsBody?.applyImpulse(CGVector(dx:10, dy: 10))
score = [0,0]
btlab.text = String(score[0])
tplab.text = String(score[1])
}
func addscore(WhoWin: SKNode) {
ball.position = CGPoint(x: 0, y: 0)
ball.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
if WhoWin == main {
score[0] += 1
ball.physicsBody?.applyImpulse(CGVector(dx: 10, dy: 10))
}else {
score[1] += 1
ball.physicsBody?.applyImpulse(CGVector(dx: -10, dy: -10))
}
btlab.text = String(score[0])
tplab.text = String(score[1])
if score[0] == 10 {
print("test 1")
//go to menu
}else if score[1] == 10 {
print("test 1")
//go to menu
}
}
override func didMove(to view: SKView) {
startlab = self.childNode(withName: "labstart") as! SKLabelNode
startlab.position.x = ((self.view?.frame.width)!/2) - 50
ball = self.childNode(withName: "ball") as! SKSpriteNode
enemy = self.childNode(withName: "enemy") as! SKSpriteNode
enemy.position.y = ((self.view?.frame.height)!/2) - 50
tplab = self.childNode(withName: "labeltop") as! SKLabelNode
btlab = self.childNode(withName: "labelbt") as! SKLabelNode
main = self.childNode(withName: "main") as! SKSpriteNode
main.position.y = -(((self.view?.frame.height)!/2) - 50)
let border = SKPhysicsBody(edgeLoopFrom: self.frame)
border.friction = 0
border.restitution = 1
self.physicsBody = border
start = .no
}
override func update(_ currentTime: TimeInterval) {
switch currentgame {
case .easy:
enemy.run(SKAction.moveTo(x: ball.position.x, duration: 0.8))
case .medium:
enemy.run(SKAction.moveTo(x: ball.position.x, duration: 0.5))
case .hard:
enemy.run(SKAction.moveTo(x: ball.position.x, duration: 0.3))
case .endless:
enemy.run(SKAction.moveTo(x: ball.position.x, duration: 0.1))
default: break
}
if ball.position.y <= main.position.y - 30 {
addscore(WhoWin: enemy)
}else if ball.position.y >= enemy.position.y + 30 {
addscore(WhoWin: main)
}
}
}
My ViewController with menu code:
import UIKit
enum gameType {
case player2, hard, easy, medium, endless, deafoult
}
class MyVCViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
#IBAction func Player2(_ sender: Any) {
gotogame(game: .player2)
}
#IBAction func EasyMode(_ sender: Any) {
gotogame(game: .easy)
}
#IBAction func Mediummode(_ sender: Any) {
gotogame(game: .medium)
}
#IBAction func hardmode(_ sender: Any) {
gotogame(game: .hard)
}
#IBAction func endlessmode(_ sender: Any) {
gotogame(game: .endless)
}
func gotogame(game: gameType) {
let gameVC = self.storyboard?.instantiateViewController(withIdentifier: "gameVC") as! GameViewController
currentgame = game
self.navigationController?.pushViewController(gameVC, animated: true)
}
}
And my GameViewController code:
import UIKit
import SpriteKit
import GameplayKit
class GameViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.sks'
if let scene = SKScene(fileNamed: "GameScene") {
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
scene.size = view.bounds.size
// Present the scene
view.presentScene(scene)
}
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
override var shouldAutorotate: Bool {
return true
}
override var supportedInterfaceOrientations: UIInterfaceOrientationMask {
if UIDevice.current.userInterfaceIdiom == .phone {
return .allButUpsideDown
} else {
return .all
}
}
override var prefersStatusBarHidden: Bool {
return true
}
}
How can I go back to the menu when one of the players get 10 points?

Related

How do I register a tap to the screen to restart the game

Everything I need are commented down below, I have a function that when I tap it, the game should restart. The restart function works by its self, but I only want it to restart after the user taps the screen. If you need some clearing up on what certain parts of the code do, just comment down below please Could you please let me know what I've done wrong, thanks!
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var ball = SKSpriteNode()
var enemy = SKSpriteNode()
var main = SKSpriteNode()
var topLbl = SKLabelNode()
var btmLbl = SKLabelNode()
var score = [Int]()
func pauseGame() { // PAUSE GAME FUCTION
self.isPaused = true
self.physicsWorld.speed = 0
self.speed = 0.0
self.scene?.view?.isPaused = true
}
func test(gestureRecognizer: UITapGestureRecognizer) { // MY FUNC TO RESTART THE GAME
let skView = self.view!
skView.presentScene(scene)
}
override func didMove(to view: SKView) {
topLbl = self.childNode(withName: "topLabel") as! SKLabelNode
btmLbl = self.childNode(withName: "btmLabel") as! SKLabelNode
ball = self.childNode(withName: "ball") as! SKSpriteNode
print(self.view?.bounds.height)
enemy = self.childNode(withName: "enemy") as! SKSpriteNode
enemy.position.y = (self.frame.height / 2) - 50
main = self.childNode(withName: "main") as! SKSpriteNode
main.position.y = (-self.frame.height / 2) + 50
let border = SKPhysicsBody(edgeLoopFrom: self.frame)
border.friction = 0
border.restitution = 1
self.physicsBody = border
startGame()
}
func startGame() {
score = [0,0]
topLbl.text = "\(score[1])"
btmLbl.text = "\(score[0])"
ball.physicsBody?.applyImpulse(CGVector(dx: 10 , dy: 10))
}
func addScore(playerWhoWon : SKSpriteNode){
ball.position = CGPoint(x: 0, y: 0)
ball.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
if playerWhoWon == main {
score[0] += 1
ball.physicsBody?.applyImpulse(CGVector(dx: 10, dy: 10))
}
else if playerWhoWon == enemy {
score[1] += 1
ball.physicsBody?.applyImpulse(CGVector(dx: -10, dy: -10))
}
if score[0] >= 10 {
pauseGame()
test() // HERE'S WHERE I TRY AND CALL THE FUNCTION, BUT IT's NOT WORKING
}
else if
score [1] >= 10 {
pauseGame()
test() // HERE'S WHERE I TRY AND CALL THE FUNCTION, BUT IT's NOT WORKING AGAIN
}
topLbl.text = "\(score[1])"
btmLbl.text = "\(score[0])"
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
if currentGameType == .player2 {
if location.y > 0 {
enemy.run(SKAction.moveTo(x: location.x, duration: 0.2))
}
if location.y < 0 {
main.run(SKAction.moveTo(x: location.x, duration: 0.2))
}
}
else {
main.run(SKAction.moveTo(x: location.x, duration: 0.2))
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
if currentGameType == .player2 {
if location.y > 0 {
enemy.run(SKAction.moveTo(x: location.x, duration: 0.2))
}
if location.y < 0 {
main.run(SKAction.moveTo(x: location.x, duration: 0.2))
}
}
else{
main.run(SKAction.moveTo(x: location.x, duration: 0.2))
}
}
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
switch currentGameType {
case .easy:
enemy.run(SKAction.moveTo(x: ball.position.x, duration: 1.3))
break
case .medium:
enemy.run(SKAction.moveTo(x: ball.position.x, duration: 1.0))
break
case .hard:
enemy.run(SKAction.moveTo(x: ball.position.x, duration: 0.7))
break
case .player2:
break
}
if ball.position.y <= main.position.y - 30 {
addScore(playerWhoWon: enemy)
}
else if ball.position.y >= enemy.position.y + 30 {
addScore(playerWhoWon: main)
}
}
}
As far as I understand, SKScene conforms to UIResponder protocol since you're using touchesBegan and touchesMoved methods. The protocol also has touchesEnded(Set<UITouch>, with: UIEvent?) method.
Basucally you need to add something like:
override func touchesEnded(Set<UITouch>, with: UIEvent?)
{
let skView = self.view!
skView.presentScene(scene)
}
This method is invoked when user removes his finger from the screen after tapping the GameScene object.
You can use UITapGestureRecognizer as well. To do so however, you need to create an instance of it, declare your class as its delegate, add the view you want to tap into its collection and attach a method to it. I've never done this programmatically, only in the IB. The setup looks like so:
To add a tap gesture via code:
In your GameScene class:
weak var tapGesture : UITapGestureRecognizer!
override func didMoveToView(view: SKView) {
tapGesture = UITapGestureRecognizer(target:self,action:#selector(self.handleTap:)
view.addGestureRecognizer(tapGesture )
}
func handleTap(sender:UITapGestureRecognizer){
//restartLogic here
}
deinit{
view.removeGestureRecognizer(tapGesture)
}
Skip the gesture recognizer.
Simply call the restart code from touchesEnded if the game is not in progress.

Moving the player freely all over the screen

I'm making a game where the ball(the player) is suppose to avoid other balls passing by the screen. Basically I want the ball always to follow the location of the touch. So wherever I'm moving my finger on the screen, the ball follows.
This is the player Class:
import SpriteKit
struct ColliderType {
static let Player: UInt32 = 1
static let Blue: UInt32 = 2
static let Green: UInt32 = 3
static let Yellow: UInt32 = 4
static let Red: UInt32 = 5
}
class Player: SKSpriteNode {
func initialize() {
self.name = "Player"
self.zPosition = 1
self.anchorPoint = CGPoint(x: 0.5, y: 0.5)
self.physicsBody = SKPhysicsBody(circleOfRadius: self.size.height /
2)
self.physicsBody?.affectedByGravity = false
self.physicsBody?.categoryBitMask = ColliderType.Player
self.physicsBody?.collisionBitMask = ColliderType.Blue |
ColliderType.Green | ColliderType.Red | ColliderType.Yellow
self.physicsBody?.contactTestBitMask = ColliderType.Blue |
ColliderType.Green | ColliderType.Red | ColliderType.Yellow
}
}
This is the GameplayScene:
import SpriteKit
class GameplayScene: SKScene, SKPhysicsContactDelegate {
var player = Player()
var ball = SKSpriteNode()
var scoreLabel = SKLabelNode()
var score = 0
var counter = Timer()
override func didMove(to view: SKView) {
initialize()
}
override func update(_ currentTime: TimeInterval) {
}
override func touchesBegan(_ touches: Set<UITouch>, with event:
UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
if atPoint(location).name == "Retry" {
self.removeAllActions()
self.removeAllChildren()
initialize()
}
if atPoint(location).name == "Quit" {
let mainmenu = MainMenuScene(fileNamed: "MainMenuScene")
mainmenu!.scaleMode = .aspectFill
self.view?.presentScene(mainmenu!, transition:
SKTransition.fade(withDuration: TimeInterval(1)))
}
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event:
UIEvent?) {
}
override func touchesMoved(_ touches: Set<UITouch>, with event:
UIEvent?) {
}
func didBegin(_ contact: SKPhysicsContact) {
var firstBody = SKPhysicsBody()
var secondBody = SKPhysicsBody()
if contact.bodyA.node?.name == "Player" {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
if firstBody.node?.name == "Player" && secondBody.node?.name ==
"Red" {
playerDied()
firstBody.node?.removeFromParent()
}
if firstBody.node?.name == "Player" && secondBody.node?.name ==
"Blue" {
playerDied()
firstBody.node?.removeFromParent()
}
if firstBody.node?.name == "Player" && secondBody.node?.name ==
"Green" {
playerDied()
firstBody.node?.removeFromParent()
}
if firstBody.node?.name == "Player" && secondBody.node?.name ==
"Yellow" {
playerDied()
firstBody.node?.removeFromParent()
}
}
func initialize() {
score = 0
physicsWorld.contactDelegate = self
createPlayer()
createBackground()
spawnRedBall()
spawnBlueBall()
spawnGreenBall()
spawnYellowBall()
createLabel()
counter = Timer.scheduledTimer(timeInterval: TimeInterval(0.7),
target: self, selector: "incrementScore", userInfo: nil, repeats: true)
}
func createPlayer() {
player = Player(imageNamed: "Player")
player.initialize()
player.position = CGPoint(x: 0, y: 0)
self.addChild(player)
}
func createBackground() {
let bg = SKSpriteNode(imageNamed: "BG")
bg.name = "BG"
bg.anchorPoint = CGPoint(x: 0.5, y: 0.5)
bg.position = CGPoint(x: 0, y: 0)
self.addChild(bg)
}
func createRedBall() {
let ball = SKSpriteNode(imageNamed: "Red")
ball.name = "Red"
ball.anchorPoint = CGPoint(x: 0.5, y: 0.5)
ball.zPosition = 1
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height /
2)
ball.physicsBody?.categoryBitMask = ColliderType.Red
ball.physicsBody?.affectedByGravity = false
ball.physicsBody?.isDynamic = false
ball.position.y = self.size.height + 100
ball.position.x = CGFloat.randomBetweenNumbers(firstNum: -345,
secondNum: 345)
self.addChild(ball)
let destination = self.frame.height * 2
let move = SKAction.moveTo(y: -destination, duration:
TimeInterval(10))
let remove = SKAction.removeFromParent()
ball.run(SKAction.sequence([move, remove]), withKey: "MoveRed")
}
func spawnRedBall() {
let spawn = SKAction.run({ () -> Void in
self.createRedBall()
})
let delay = SKAction.wait(forDuration: TimeInterval(0.5))
let sequence = SKAction.sequence([spawn, delay])
self.run(SKAction.repeatForever(sequence), withKey: "SpawnRed")
}
func createBlueBall() {
let ball = SKSpriteNode(imageNamed: "Blue")
ball.name = "Blue"
ball.anchorPoint = CGPoint(x: 0.5, y: 0.5)
ball.zPosition = 1
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height /
2)
ball.physicsBody?.categoryBitMask = ColliderType.Blue
ball.physicsBody?.affectedByGravity = false
ball.physicsBody?.isDynamic = false
ball.position.y = -self.size.height + 100
ball.position.x = CGFloat.randomBetweenNumbers(firstNum: -345,
secondNum: 345)
self.addChild(ball)
let destination = self.frame.height * 2
let move = SKAction.moveTo(y: destination, duration:
TimeInterval(10))
let remove = SKAction.removeFromParent()
ball.run(SKAction.sequence([move, remove]), withKey: "MoveBlue")
}
func spawnBlueBall() {
let spawn = SKAction.run({ () -> Void in
self.createBlueBall()
})
let delay = SKAction.wait(forDuration: TimeInterval(0.5))
let sequence = SKAction.sequence([spawn, delay])
self.run(SKAction.repeatForever(sequence), withKey: "SpawnBlue")
}
func createGreenBall() {
let ball = SKSpriteNode(imageNamed: "Green")
ball.name = "Green"
ball.anchorPoint = CGPoint(x: 0.5, y: 0.5)
ball.zPosition = 1
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height /
2)
ball.physicsBody?.categoryBitMask = ColliderType.Green
ball.physicsBody?.affectedByGravity = false
ball.physicsBody?.isDynamic = false
ball.position.x = -self.size.width + 200
ball.position.y = CGFloat.randomBetweenNumbers(firstNum: -637,
secondNum: 637)
self.addChild(ball)
let destination = self.frame.height * 2
let move = SKAction.moveTo(x: destination, duration:
TimeInterval(10))
let remove = SKAction.removeFromParent()
ball.run(SKAction.sequence([move, remove]), withKey: "MoveGreen")
}
func spawnGreenBall() {
let spawn = SKAction.run({ () -> Void in
self.createGreenBall()
})
let delay = SKAction.wait(forDuration: TimeInterval(0.5))
let sequence = SKAction.sequence([spawn, delay])
self.run(SKAction.repeatForever(sequence), withKey: "SpawnGreen")
}
func createYellowBall() {
let ball = SKSpriteNode(imageNamed: "Yellow")
ball.name = "Yellow"
ball.anchorPoint = CGPoint(x: 0.5, y: 0.5)
ball.zPosition = 1
ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height /
2)
ball.physicsBody?.categoryBitMask = ColliderType.Green
ball.physicsBody?.affectedByGravity = false
ball.physicsBody?.isDynamic = false
ball.position.x = self.size.width + 200
ball.position.y = CGFloat.randomBetweenNumbers(firstNum: -637,
secondNum: 637)
self.addChild(ball)
let destination = self.frame.height * 2
let move = SKAction.moveTo(x: -destination, duration:
TimeInterval(10))
let remove = SKAction.removeFromParent()
ball.run(SKAction.sequence([move, remove]), withKey: "MoveYellow")
}
func spawnYellowBall() {
let spawn = SKAction.run({ () -> Void in
self.createYellowBall()
})
let delay = SKAction.wait(forDuration: TimeInterval(0.5))
let sequence = SKAction.sequence([spawn, delay])
self.run(SKAction.repeatForever(sequence), withKey: "SpawnYellow")
}
func createLabel() {
scoreLabel.zPosition = 3
scoreLabel.position = CGPoint(x: -320, y: 600)
scoreLabel.fontName = "Verdana"
scoreLabel.fontSize = 70
scoreLabel.text = "0"
self.addChild(scoreLabel)
}
func incrementScore() {
score += 1
scoreLabel.text = String(score)
}
func playerDied() {
counter.invalidate()
let highscore = GameManager.instance.getHighscore()
if highscore < score {
GameManager.instance.setHighscore(highscore: score)
}
let retry = SKSpriteNode(imageNamed: "Retry")
let quit = SKSpriteNode(imageNamed: "Quit")
retry.name = "Retry"
retry.anchorPoint = CGPoint(x: 0.5, y: 0.5)
retry.position = CGPoint(x: -150, y: -50)
retry.zPosition = 2
retry.setScale(0)
quit.name = "Quit"
quit.anchorPoint = CGPoint(x: 0.5, y: 0.5)
quit.position = CGPoint(x: 150, y: -50)
quit.zPosition = 2
quit.setScale(0)
let scaleUp = SKAction.scale(to: 1, duration: TimeInterval(0.5))
retry.run(scaleUp)
quit.run(scaleUp)
self.addChild(retry)
self.addChild(quit)
}
}
Add the following property:
var ballIsTouched = false
and then implement the touch methods:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let location = touches.first.location(in: self) {
if ball.containsPoint(location) {
ballIsTouched = true
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if (ballIsTouched == true) {
ball.position = (touches.first?.location(in: self))!
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
ballIsTouched = false
}
I think it is more natural when implementing a dragging, to drag a sprite from the touch location rather than from the center of the sprite. To do this, you should calculate the offset and add it the new sprite's position, like this:
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let current = touch.location(in: self)
let previous = touch.previousLocation(in: self)
if ball.contains(current) {
let offset = CGPoint(x: current.x - previous.x , y: current.y - previous.y)
ball.position = CGPoint(x: ball.position.x + offset.x , y: ball.position.y + offset.y)
}
}
}
Here is a sample project to show how to implement a draggable sprite.:
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var ballIsTouched = false
var ball = SKSpriteNode()
override func didMove(to view: SKView) {
ball = SKSpriteNode(color: .blue, size: CGSize(width:100, height:100))
ball.position = CGPoint(x: 0, y: 0)
addChild(ball)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
if ball.contains(touch.location(in: self)) {
ballIsTouched = true
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if (ballIsTouched == true) {
ball.position = (touches.first?.location(in: self))!
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
ballIsTouched = false
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}
This only allows for the single specified sprite to be dragged. Here is an example with multiple sprites that can be dragged:
import SpriteKit
import GameplayKit
extension SKColor {
static func random() -> SKColor {
let colours = [SKColor.lightGray, SKColor.white, SKColor.gray, SKColor.red, SKColor.green, SKColor.blue, SKColor.cyan, SKColor.yellow, SKColor.magenta, SKColor.orange, SKColor.purple, SKColor.brown]
return colours[Int(arc4random_uniform(UInt32(colours.count)))]
}
}
class GameScene: SKScene {
var touchedSprite : SKSpriteNode?
override func didMove(to view: SKView) {
for i in -1...1 {
let ball = SKSpriteNode(color: SKColor.random(), size: CGSize(width:100, height:100))
ball.position = CGPoint(x: 0, y: i * 200)
addChild(ball)
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
touchedSprite = self.atPoint(touch.location(in: self)) as? SKSpriteNode
touchedSprite?.setScale(1.25)
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if (touchedSprite != nil) {
touchedSprite?.position = (touches.first?.location(in: self))!
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
touchedSprite?.setScale(1)
touchedSprite = nil
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}
You could also implement a draggable protocol or something to limit which sprites can be dragged.

spritekit: unable to detect collision

so i tried to use skphysicscontact but when the "cat" and "spinnynode" collides there is no output from them, even when there is physical interaction
on another note, why can't the timer function work? it doesn't seem to call out the function at all.
please help, I'm a newbie. Thanks
import SpriteKit
import GameplayKit
import UIKit
import Foundation
struct physicsCollision {
static let cat: UInt32 = 1
static let spinnyNode: UInt32 = 2
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var entities = [GKEntity]()
var graphs = [String : GKGraph]()
var catTimer = Timer()
var score = 0
private var lastUpdateTime : TimeInterval = 0
private var label : SKLabelNode?
private var spinnyNode : SKShapeNode?
let meow = SKAction.playSoundFileNamed("cat meow", waitForCompletion: false)
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
//random range
func randomInRange(lo: Float, hi : Float) -> Float{
return lo + Float(arc4random_uniform(UInt32(hi - lo + 1)))
}
//spawn cat
func spawnCat(){
// x coordinate between MinX (left) and MaxX (right):
let randomX = randomInRange(lo: Float(self.frame.minX + 5), hi: Float(self.frame.maxX + 5))
let startPoint = CGPoint(x: CGFloat(randomX), y: self.frame.height * 1.2)
let endPoint = CGPoint(x: CGFloat(randomX), y:self.frame.height * -0.5)
let cat = SKSpriteNode(imageNamed: "before right")
cat.name = "cat"
cat.setScale(0.3)
cat.position = startPoint
cat.zPosition = 1
cat.physicsBody = SKPhysicsBody(rectangleOf: CGSize(width: cat.size.width, height: cat.size.height))
cat.physicsBody?.affectedByGravity = false
cat.physicsBody?.categoryBitMask = physicsCollision.cat
cat.physicsBody?.contactTestBitMask = physicsCollision.spinnyNode
cat.physicsBody?.collisionBitMask = physicsCollision.spinnyNode
cat.physicsBody?.isDynamic = false
self.addChild(cat)
let moveCat = SKAction.move(to: endPoint, duration: 5)
let deleteCat = SKAction.removeFromParent()
let catSequence = SKAction.sequence([moveCat, meow, deleteCat])
cat.run(catSequence)
}
//contact func
func didBeginContact(contact:SKPhysicsContact){
var firstBody = SKPhysicsBody()
var secondBody = SKPhysicsBody()
if contact.bodyA.node?.name == "cat"
{
firstBody = contact.bodyA
secondBody = contact.bodyB
}
else{
firstBody = contact.bodyB
secondBody = contact.bodyA
}
if firstBody.node?.name == "cat" && (secondBody.node?.name)! == "skinnynode"{
print("contacted")
}
}
override func sceneDidLoad() {
self.physicsWorld.contactDelegate = self
self.lastUpdateTime = 0
//spawn cat at intervals,, time interval to decrease when points increase, use if loop
catTimer = Timer.init(timeInterval: 1 , target: self, selector: Selector(("cat")), userInfo: nil, repeats: true)
// Create shape node to use during mouse interaction
let w = (self.size.width + self.size.height) * 0.05
self.spinnyNode = SKShapeNode.init(rectOf: CGSize.init(width: w, height: w), cornerRadius: w * 0.5)
spinnyNode?.name = "spinnynode"
spinnyNode?.physicsBody = SKPhysicsBody(circleOfRadius: 0.5)
spinnyNode?.physicsBody?.affectedByGravity = false
spinnyNode?.zPosition = 1
spinnyNode?.physicsBody?.categoryBitMask = physicsCollision.spinnyNode
if let spinnyNode = self.spinnyNode{
spinnyNode.lineWidth = 1.5
spinnyNode.run(SKAction.repeatForever(SKAction.rotate(byAngle: CGFloat(Double.pi), duration: 1)))
spinnyNode.run(SKAction.sequence([SKAction.wait(forDuration: 0.5),
SKAction.fadeOut(withDuration: 0.3),
SKAction.removeFromParent()]))
}
//create score label
let scoreLabel = UILabel(frame: CGRect(x:((self.frame.height) * 0.5) , y:((self.frame.width) * 0.3), width: (self.frame.size.width)/3, height: 30))
scoreLabel.center = CGPoint(x: (self.frame.size.width)/1.6 , y: (self.frame.size.height)/2)
scoreLabel.textColor = UIColor.white
scoreLabel.text = "\(score)"
self.view?.addSubview(scoreLabel)
}
func touchDown(atPoint pos : CGPoint) {
if let n = self.spinnyNode?.copy() as! SKShapeNode? {
n.position = pos
n.strokeColor = SKColor.green
self.addChild(n)
}
}
func touchMoved(toPoint pos : CGPoint) {
if let n = self.spinnyNode?.copy() as! SKShapeNode? {
n.position = pos
n.strokeColor = SKColor.purple
self.addChild(n)
}
}
func touchUp(atPoint pos : CGPoint) {
if let n = self.spinnyNode?.copy() as! SKShapeNode? {
n.position = pos
n.strokeColor = SKColor.red
self.addChild(n)
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
spawnCat()
if let label = self.label {
label.run(SKAction.init(named: "Pulse")!, withKey: "fadeInOut")
}
for t in touches { self.touchDown(atPoint: t.location(in: self)) }
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
// Initialize _lastUpdateTime if it has not already been
if (self.lastUpdateTime == 0) {
self.lastUpdateTime = currentTime
}
// Calculate time since last update
let dt = currentTime - self.lastUpdateTime
// Update entities
for entity in self.entities {
entity.update(deltaTime: dt)
}
self.lastUpdateTime = currentTime
}
}
You spelled the function wrong. It is never getting called. This is the correct protocol function name:
func didBegin(_ contact: SKPhysicsContact) {
// Your stuff here..
}
You can use autocomplete to avoid this problem. Start typing "didbegin" and you will have Xcode fill out the correct function:
As an aside:
Also, you are using hardcoded strings which can cause problems later on. Perhaps you could try using a constant value or a struct to avoid potential future spelling mistakes in strings:
let names = (cat: "cat", spinnynode: "spinnynode")
// cat.name = names.cat, etc...
func didBeginContact(contact:SKPhysicsContact){
// ...
if contact.bodyA.node?.name == names.cat
{
firstBody = contact.bodyA
secondBody = contact.bodyB
}
else{
firstBody = contact.bodyB
secondBody = contact.bodyA
}
if firstBody.node?.name == names.cat && secondBody.node!.name == names.spinnynode {
print("contacted")
}
}
Have you tried using the categoryBitMask method of the SKPhysicsContactDelegate? You may be able to fix your issue by going into the GameScene.sks file and assigning the Category Mask to a number other than the default. Do this for both of your bodies, but assign different values for each of the bodies.
Then, inside your GameScene.swift, your didBegin contact function might look something like this:
class GameScene: SKScene, SKPhysicsContactDelegate {
//set these values to the same number in your GameScene.sks file
let catCategory = 2
let skinnyNodeCategory = 3
func didBegin(_ contact: SKPhysicsContact) {
let bodyA = contact.bodyA
let bodyB = contact.bodyB
//check to see if the bodies in contact match
//the category mask numbers you defined
//here the conditional is set to say that either of the bodies
//in contact match the categoryBitMask number set in the GameScene.sks file
//using && may not work depending on how the categoryBitMask identifiers
//are assigned by the physicsContactDelegate
if bodyA.categoryBitMask == catCategory || bodyB.categoryBitMask == catCategory {
print("contacted")
}
}
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
}

having a node follow at a constant speed

I'm trying to make a small mini game where you drag a ball around the screen and every 10 seconds a ball gets added in that follows you. so far the you can drag a ball around the screen and a ball follows you, but when another ball gets added in the balls group together. I think this is because the ball is following me depending on how fast I'm going. so is there a certain way in which I can have the balls follow me at a certain speed constantly, like 10 pixels a second or something, and that should prevent the balls from grouping together.
I am currently working on the score so it should soon go up every second you survive. and you die if you touch one of the balls.
below is the code and a short gif of my current code
!(https://gyazo.com/1d6a56527bfd0884e8a26cff730f4e03)
import SpriteKit
import GameplayKit
struct physicsCatagory{
static let me : UInt32 = 0x1 << 1
static let enemy : UInt32 = 0x1 << 2
}
class GameScene: SKScene, SKPhysicsContactDelegate {
private func makeEnemyName() -> String {
enemyCounter += 1
return "enemy\(enemyCounter)"
}
private func addEnemyToDict(enemy: SKSpriteNode, target: SKSpriteNode) {
if let name = enemy.name { spriteDictionary[name] = (enemy, target) }
else { print("enemy not found") }
}
private func removeEnemyFromDict(enemy: SKSpriteNode) {
if let name = enemy.name { spriteDictionary[name] = nil }
else { print("enemy not removed from dictionary!") }
}
private func moveFollowerToTarget(_ sprites: FollowerAndTarget) {
let action = SKAction.move(to: sprites.target.position, duration: 1)
sprites.follower.run(action)
}
private func allEnemiesMoveToTarget() {
for sprites in spriteDictionary.values {
moveFollowerToTarget(sprites)
}
}
let enemySpeed: CGFloat = 300
var me = SKSpriteNode()
// Tuple to keep track of enemy objects:
typealias FollowerAndTarget = (follower: SKSpriteNode, target: SKSpriteNode)
// [followerName: (followerSprite, targetSprite):
var spriteDictionary: [String: FollowerAndTarget] = [:]
// Give each enemy a unique name for the dictionary:
var enemyCounter = 0
var died = Bool()
override func didMove(to view: SKView) {
createScene()
}
func createEnemy () {
if died == true{
}
else {
let enemy = SKSpriteNode(imageNamed: "enemy1")
enemy.name = makeEnemyName()
addEnemyToDict(enemy: enemy, target: me)
moveFollowerToTarget((follower: enemy, target: me))
enemy.size = CGSize(width: 60, height: 60)
enemy.position = CGPoint(x:667, y: 200)
enemy.physicsBody?.restitution = 0.5
enemy.physicsBody = SKPhysicsBody(circleOfRadius: 60)
enemy.physicsBody?.affectedByGravity = false
enemy.zPosition = 2
enemy.physicsBody?.linearDamping = 0
enemy.physicsBody?.isDynamic = true
enemy.physicsBody?.categoryBitMask = physicsCatagory.enemy
enemy.physicsBody?.collisionBitMask = physicsCatagory.me
enemy.physicsBody?.contactTestBitMask = physicsCatagory.me
addChild(enemy)
}
}
func didBegin(_ contact: SKPhysicsContact) {
let firstBody = contact.bodyA
let secondBody = contact.bodyB
if firstBody.categoryBitMask == physicsCatagory.me && secondBody.categoryBitMask == physicsCatagory.enemy || firstBody.categoryBitMask == physicsCatagory.enemy && secondBody.categoryBitMask == physicsCatagory.me {
died = true
restartScene()
}
}
var lose: SKLabelNode!
func restartScene(){
self.removeAllChildren()
self.removeAllActions()
died = false
if let nextScene = GameScene(fileNamed: "menuScene"){
nextScene.scaleMode = self.scaleMode
let transition = SKTransition.fade(withDuration: 1)
view?.presentScene(nextScene, transition: transition)
}
}
func createScene(){
me = self.childNode(withName: "me") as! SKSpriteNode
me.physicsBody = SKPhysicsBody(circleOfRadius: 20)
me.physicsBody?.affectedByGravity = false
me.physicsBody?.categoryBitMask = physicsCatagory.me
me.physicsBody?.collisionBitMask = physicsCatagory.enemy
me.zPosition = 2
self.physicsWorld.contactDelegate = self
let border = SKPhysicsBody (edgeLoopFrom: self.frame)
border.friction = 0
self.physicsBody = border
run(SKAction.repeatForever(SKAction.sequence([SKAction.run(createEnemy), SKAction.wait(forDuration: 4.0)])))
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
me.run(SKAction.moveTo(x: location.x, duration: 0))
me.run(SKAction.moveTo(y: location.y, duration: 0))
allEnemiesMoveToTarget()
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
me.run(SKAction.moveTo(x: location.x, duration: 0))
me.run(SKAction.moveTo(y: location.y, duration: 0))
allEnemiesMoveToTarget()
}
}
override func update(_ currentTime: TimeInterval) {
// Will iterate through dictonary and then call moveFollowerToTarget()
// thus giving each enemy a new movement action to follow.
allEnemiesMoveToTarget()
}
}
Here you go:
import SpriteKit
import GameplayKit
struct physicsCatagory{
static let me : UInt32 = 0x1 << 1
static let enemy : UInt32 = 0x1 << 2
static let coin : UInt32 = 0x1 << 3
}
class GameScene: SKScene, SKPhysicsContactDelegate {
var lose: SKLabelNode!
var me = SKSpriteNode()
// Tuple to keep track of enemy objects:
typealias FollowerAndTarget = (follower: SKSpriteNode, target: SKSpriteNode)
// [followerName: (followerSprite, targetSprite):
var spriteDictionary: [String: FollowerAndTarget] = [:]
// Give each enemy a unique name for the dictionary:
var enemyCounter = 0
let enemySpeed: CGFloat = 3
var died = Bool()
var timer = SKLabelNode()
var timerValue: Int = 0 {
didSet {
timer.text = "\(timerValue)"
}
}
private func makeEnemyName() -> String {
enemyCounter += 1
return "enemy\(enemyCounter)"
}
private func addEnemyToDict(enemy: SKSpriteNode, target: SKSpriteNode) {
if let name = enemy.name { spriteDictionary[name] = (enemy, target) }
else { print("enemy not found") }
}
private func removeEnemyFromDict(enemy: SKSpriteNode) {
if let name = enemy.name { spriteDictionary[name] = nil }
else { print("enemy not removed from dictionary!") }
}
// dont change anything outside of this, this is what makes the enemy follow you, so i have to have the enemy follow me at a constant speed
private func moveFollowerToTarget(_ sprites: FollowerAndTarget) {
let location = me.position
// Aim
let dx = location.x - sprites.follower.position.x
let dy = location.y - sprites.follower.position.y
let angle = atan2(dy, dx)
sprites.follower.zRotation = angle
// Seek
let vx = cos(angle) * enemySpeed
let vy = sin(angle) * enemySpeed
sprites.follower.position.x += vx
sprites.follower.position.y += vy
}
private func allEnemiesMoveToTarget() {
for sprites in spriteDictionary.values {
moveFollowerToTarget(sprites)
}
}
private func keepEnemiesSeparated() {
for sprites in spriteDictionary.values {
let iterator = sprites.follower
iterator.constraints = []
// get every other follower:
var otherFollowers: [SKSpriteNode] = []
for sprites in spriteDictionary.values {
if sprites.follower == iterator { continue }
else { otherFollowers.append(sprites.follower) }
}
// Assign constrain
for follower in otherFollowers {
let distanceBetween = CGFloat(60)
let constraint = SKConstraint.distance(SKRange(lowerLimit: distanceBetween), to: follower)
iterator.constraints!.append(constraint)
}
}
}
func createEnemy () {
if died { return }
let enemy = SKSpriteNode(color: .green, size: CGSize(width: 60, height: 60))
enemy.size = CGSize(width: 60, height: 60)
enemy.zPosition = 2
enemy.position.y -= size.height / 2
enemy.physicsBody = {
let pb = SKPhysicsBody(circleOfRadius: 30)
pb.restitution = 0.5
pb.affectedByGravity = false
pb.linearDamping = 0
pb.isDynamic = true
pb.categoryBitMask = physicsCatagory.enemy
pb.collisionBitMask = physicsCatagory.me
pb.contactTestBitMask = physicsCatagory.me
return pb
}()
enemy.name = makeEnemyName()
addEnemyToDict(enemy: enemy, target: me)
moveFollowerToTarget((follower: enemy, target: me))
keepEnemiesSeparated()
addChild(enemy)
}
func createCoin () {
let coin = SKSpriteNode(color: .yellow, size: CGSize(width: 20, height: 20))
let height = self.view!.frame.height
let width = self.view!.frame.width
let randomPosition = CGPoint( x:CGFloat( arc4random_uniform( UInt32( floor( width ) ) ) ),
y:CGFloat( arc4random_uniform( UInt32( floor( height ) ) ) )
)
coin.position = randomPosition
addChild(coin)
}
func restartScene(){
self.removeAllChildren()
self.removeAllActions()
died = false
let nextScene = GameScene(size: self.size)
nextScene.scaleMode = self.scaleMode
let transition = SKTransition.fade(withDuration: 1)
view?.presentScene(nextScene, transition: transition)
}
func createScene(){
me = SKSpriteNode(color: .blue, size: CGSize(width: 60, height: 60))
me.physicsBody = SKPhysicsBody(circleOfRadius: 30)
me.physicsBody?.affectedByGravity = false
me.physicsBody?.categoryBitMask = physicsCatagory.me
me.physicsBody?.collisionBitMask = physicsCatagory.enemy
me.zPosition = 2
timer = SKLabelNode(fontNamed: "Chalkduster")
timer.text = "\(timerValue)"
addChild(me)
addChild(timer)
let wait = SKAction.wait(forDuration: 1)
let block = SKAction.run({
[unowned self] in
if self.timerValue >= 0{
self.timerValue += 1
}else{
self.removeAction(forKey: "countdown")
}
})
let sequence = SKAction.sequence([wait,block])
run(SKAction.repeatForever(sequence), withKey: "countdown")
self.physicsWorld.contactDelegate = self
let border = SKPhysicsBody (edgeLoopFrom: self.frame)
border.friction = 0
self.physicsBody = border
run(SKAction.repeatForever(SKAction.sequence([SKAction.run(createEnemy), SKAction.wait(forDuration: 2.0)])))
run(SKAction.repeatForever(SKAction.sequence([SKAction.run(createCoin), SKAction.wait(forDuration: TimeInterval(arc4random_uniform(11) + 5))])))
}
override func didMove(to view: SKView) {
scene?.anchorPoint = CGPoint(x: 0.5, y: 0.5)
createScene()
}
func didBegin(_ contact: SKPhysicsContact) {
let firstBody = contact.bodyA
let secondBody = contact.bodyB
if firstBody.categoryBitMask == physicsCatagory.me && secondBody.categoryBitMask == physicsCatagory.enemy
|| firstBody.categoryBitMask == physicsCatagory.enemy && secondBody.categoryBitMask == physicsCatagory.me {
died = true
restartScene()
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
me.run(SKAction.moveTo(x: location.x, duration: 0))
me.run(SKAction.moveTo(y: location.y, duration: 0))
allEnemiesMoveToTarget()
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches{
let location = touch.location(in: self)
me.run(SKAction.moveTo(x: location.x, duration: 0))
me.run(SKAction.moveTo(y: location.y, duration: 0))
allEnemiesMoveToTarget()
}
}
override func update(_ currentTime: TimeInterval) {
// Will iterate through dictonary and then call moveFollowerToTarget()
// thus giving each enemy a new movement action to follow.
allEnemiesMoveToTarget()
}
}

When I press run program my game loads but it won't start

I'm working with this tutorial: https://www.raywenderlich.com/118225/introduction-sprite-kit-scene-editor
When I press run program in Xcode, the simulator loads the game and pops up showing the first frame of the game but it is frozen. When I click, the player sprite is supposed to move to where I clicked and the AI sprites are supposed to try and catch the player, but nothing happens. Clicks don't work and I've tried just letting it sit for a while to see if it just hadn't finished loading or something but that hasn't worked either.
All the code for the program so far is here:
import SpriteKit
class GameScene: SKScene, SKPhysicsContactDelegate {
let playerSpeed: CGFloat = 150.0
let zombieSpeed: CGFloat = 75.0
var goal: SKSpriteNode?
var player: SKSpriteNode?
var zombies: [SKSpriteNode] = []
var lastTouch: CGPoint? = nil
override func didMoveToView(view: SKView) {
physicsWorld.contactDelegate = self
updateCamera()
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
handleTouches(touches)
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
handleTouches(touches)
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
handleTouches(touches)
}
private func handleTouches(touches: Set<UITouch>) {
for touch in touches {
let touchLocation = touch.locationInNode(self)
lastTouch = touchLocation
}
}
override func didSimulatePhysics() {
if let _ = player {
updatePlayer()
updateZombies()
}
}
private func shouldMove(currentPosition currentPosition: CGPoint, touchPosition: CGPoint) -> Bool {
return abs(currentPosition.x - touchPosition.x) > player!.frame.width / 2 ||
abs(currentPosition.y - touchPosition.y) > player!.frame.height/2
}
func updatePlayer() {
if let touch = lastTouch {
let currentPosition = player!.position
if shouldMove(currentPosition: currentPosition, touchPosition: touch) {
let angle = atan2(currentPosition.y - touch.y, currentPosition.x - touch.x) + CGFloat(M_PI)
let rotateAction = SKAction.rotateToAngle(angle + CGFloat(M_PI*0.5), duration: 0)
player!.runAction(rotateAction)
let velocotyX = playerSpeed * cos(angle)
let velocityY = playerSpeed * sin(angle)
let newVelocity = CGVector(dx: velocotyX, dy: velocityY)
player!.physicsBody!.velocity = newVelocity;
updateCamera()
} else {
player!.physicsBody!.resting = true
}
}
}
func updateCamera() {
if let camera = camera {
camera.position = CGPoint(x: player!.position.x, y: player!.position.y)
}
}
func updateZombies() {
let targetPosition = player!.position
for zombie in zombies {
let currentPosition = zombie.position
let angle = atan2(currentPosition.y - targetPosition.y, currentPosition.x - targetPosition.x) + CGFloat(M_PI)
let rotateAction = SKAction.rotateToAngle(angle + CGFloat(M_PI*0.5), duration: 0.0)
zombie.runAction(rotateAction)
let velocotyX = zombieSpeed * cos(angle)
let velocityY = zombieSpeed * sin(angle)
let newVelocity = CGVector(dx: velocotyX, dy: velocityY)
zombie.physicsBody!.velocity = newVelocity;
}
}
func didBeginContact(contact: SKPhysicsContact) {
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
if firstBody.categoryBitMask == player?.physicsBody?.categoryBitMask && secondBody.categoryBitMask == zombies[0].physicsBody?.categoryBitMask {
gameOver(false)
} else if firstBody.categoryBitMask == player?.physicsBody?.categoryBitMask && secondBody.categoryBitMask == goal?.physicsBody?.categoryBitMask {
gameOver(true)
}
player = self.childNodeWithName("player") as? SKSpriteNode
for child in self.children {
if child.name == "zombie" {
if let child = child as? SKSpriteNode {
zombies.append(child)
}
}
}
goal = self.childNodeWithName("goal") as? SKSpriteNode
}
private func gameOver(didWin: Bool) {
print("- - - Game Ended - - -")
let menuScene = MenuScene(size: self.size)
menuScene.soundToPlay = didWin ? "fear_win.mp3" : "fear_lose.mp3"
let transition = SKTransition.flipVerticalWithDuration(1.0)
menuScene.scaleMode = SKSceneScaleMode.AspectFill
self.scene!.view?.presentScene(menuScene, transition: transition)
}
}
The rest of the things completed in the program such as adding sprites and such was done in GameScene.sks so there is no code for it.
Your setup code is in the wrong place. Move this from didBeginContact to didMoveToView:
player = self.childNodeWithName("player") as? SKSpriteNode
for child in self.children {
if child.name == "zombie" {
if let child = child as? SKSpriteNode {
zombies.append(child)
}
}
}
goal = self.childNodeWithName("goal") as? SKSpriteNode
At least that's the difference I see when comparing your code to the sample project in the tutorial.

Resources