use two sprite objects at the same time with single touch? - ios

Currently, I can only use one at a time, and not make the two paddles (one on each side of the screen) act independently when different finger movements are used with each one. Here is the class. Any ideas?
let BallCategoryName = "ball"
let GameMessageName = "gameMessage"
let BallCategory : UInt32 = 0x1 << 0
let LeftCategory : UInt32 = 0x1 << 1
let BlockCategory : UInt32 = 0x1 << 2
let PaddleCategory : UInt32 = 0x1 << 3
let BorderCategory : UInt32 = 0x1 << 4
class GameScene: SKScene, SKPhysicsContactDelegate {
var isFingerOnPaddleL = false
var isFingerOnPaddleR = false
override func didMove(to view: SKView) {
super.didMove(to: view)
let borderBody = SKPhysicsBody(edgeLoopFrom: self.frame)
borderBody.friction = 0
self.physicsBody = borderBody
physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)
physicsWorld.contactDelegate = self
let ball = childNode(withName: BallCategoryName) as! SKSpriteNode
ball.physicsBody!.applyImpulse(CGVector(dx: 2.0, dy: -2.0))
let paddleL = childNode(withName: "paddleL") as! SKSpriteNode
//let paddleR = childNode(withName: "paddleR") as! SKSpriteNode
let leftRect = CGRect(x: frame.origin.x, y: frame.origin.y, width: 1, height: frame.size.height)
let left = SKNode()
left.physicsBody = SKPhysicsBody(edgeLoopFrom: leftRect)
addChild(left)
left.physicsBody!.categoryBitMask = LeftCategory
ball.physicsBody!.categoryBitMask = BallCategory
paddleL.physicsBody!.categoryBitMask = PaddleCategory
borderBody.categoryBitMask = BorderCategory
ball.physicsBody!.contactTestBitMask = LeftCategory
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let touchLocation = touch!.location(in: self)
if let body = physicsWorld.body(at: touchLocation) {
if body.node!.name == "paddleL" {
print("Began touch on paddleL")
isFingerOnPaddleL = true
}
else if body.node!.name == "paddleR" {
print("Began touch on paddleR")
isFingerOnPaddleR = true
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
// 1
if isFingerOnPaddleL {
// 2
let touch = touches.first
let touchLocation = touch!.location(in: self)
let previousLocation = touch!.previousLocation(in: self)
// 3
let paddle = childNode(withName: "paddleL") as! SKSpriteNode
// 4
var paddleY = paddle.position.y + (touchLocation.y - previousLocation.y)
// 5
paddleY = max(paddle.size.height/2, paddleY)
paddleY = min(size.height - paddle.size.height/2, paddleY)
// 6
paddle.position = CGPoint(x: paddle.position.x, y: paddleY)
}
else if isFingerOnPaddleR {
// 2
let touch = touches.first
let touchLocation = touch!.location(in: self)
let previousLocation = touch!.previousLocation(in: self)
// 3
let paddle = childNode(withName: "paddleR") as! SKSpriteNode
// 4
var paddleY = paddle.position.y + (touchLocation.y - previousLocation.y)
// 5
paddleY = max(paddle.size.height/2, paddleY)
paddleY = min(size.height - paddle.size.height/2, paddleY)
// 6
paddle.position = CGPoint(x: paddle.position.x, y: paddleY)
}
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
if (isFingerOnPaddleL == true) {
isFingerOnPaddleL = false
}
else if (isFingerOnPaddleR == true) {
isFingerOnPaddleR = false
}
}
func didBegin(_ contact: SKPhysicsContact) {
// 1
var firstBody: SKPhysicsBody
var secondBody: SKPhysicsBody
// 2
if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
firstBody = contact.bodyA
secondBody = contact.bodyB
} else {
firstBody = contact.bodyB
secondBody = contact.bodyA
}
// 3
if firstBody.categoryBitMask == BallCategory && secondBody.categoryBitMask == LeftCategory {
print("Hit left. First contact has been made.")
}
}
}

You can process the paddles independently by tracking each touch throughout its lifecycle (began/moved/ended). First, define a dictionary with the touch object as the key and the node's name as the value
var touchTracker:[UITouch:String] = [:]
then in touchesBegan, store the name of paddle(s) touched by the user
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let touchLocation = touch.location(in: self)
let node = atPoint(touchLocation)
if let name = node.name {
if name == "paddleL" {
print("Began touch on paddleL")
touchTracker[touch] = name
}
else if name == "paddleR" {
print("Began touch on paddleR")
touchTracker[touch] = name
}
}
}
}
In touchesMoved, use the touch object to retrieve the node's name from the dictionary, and use the name to access the appropriate paddle.
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let touchLocation = touch.location(in: self)
if let name = touchTracker[touch] {
if let paddle = childNode(withName: name) as? SKSpriteNode {
// Move a paddle
paddle.position = CGPoint(x:paddle.position.x, y:touchLocation.y)
}
}
}
}
Lastly, remove the touch/name from the dictionary when a touch ends.
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
if touchTracker[touch] != nil {
touchTracker.removeValue(forKey: touch)
}
}
}

Related

How to drag and flick a node in SpriteKit while gravity is present?

With my current code, the node is extremely laggy, and moves or teleports in random directions for some reason when its flicked. How can i fix this, and also can someone explain why it is teleporting and moving to random places in the scene.
Also, is there anyway to allow the node to be moved only when it is dragged from its position, rather than being at the gesturerecognizer's coordinates at all times?
override func didMove(to view: SKView) {
let gestureRecognizer = UIPanGestureRecognizer(target: self, action: #selector(self.pan(_:)))
view.addGestureRecognizer(gestureRecognizer)
circleNode.physicsBody = SKPhysicsBody(circleOfRadius: 20)
self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
self.addChild(circleNode)
}
#objc func pan(_ recognizer: UIPanGestureRecognizer) {
if recognizer.state == .changed {
self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
var location = recognizer.location(in: self.view!)
location = self.convertPoint(fromView: location)
circleNode.position = location
}
if recognizer.state == .ended {
self.physicsWorld.gravity = CGVector(dx: 0, dy: -9.8)
let transformerX = 1024/self.view!.frame.size.width
let transformerY = 768/self.view!.frame.size.height
let velocity = recognizer.velocity(in: self.view)
circleNode.physicsBody?.applyForce(CGVector(dx: velocity.x * transformerX, dy: velocity.y * transformerY))
}
}
Here is some code I was playing around with. I'm able to drag and flick a spear (spear Image) and also "pop" a pig head. This is the whole GameScene.Remove the code you don't need. :)
import SpriteKit
import CoreMotion
class GameScene: SKScene, SKPhysicsContactDelegate {
enum CollisionTypes: UInt32{
case spear = 1
case wall = 2
case head = 4
}
var touchPoint: CGPoint = CGPoint()
var touching: Bool = false
override func didMove(to view: SKView) {
self.physicsBody = SKPhysicsBody(edgeLoopFrom: self.frame)
//Add contact delegate
physicsWorld.contactDelegate = self
self.backgroundColor = .white
self.addChild(spearNode)
self.addChild(headNode)
}
lazy var spearNode: SKSpriteNode = {
let node = SKSpriteNode(imageNamed: "spear2")
node.name = "Spear"
node.physicsBody = SKPhysicsBody(texture: node.texture!,
size: CGSize(width: node.frame.width , height: node.frame.height))
node.position = CGPoint(x:self.frame.midX , y:self.frame.midY)
node.physicsBody?.affectedByGravity = true
node.physicsBody?.allowsRotation = false
node.size = CGSize(width: node.frame.width , height: node.frame.height )
node.physicsBody?.categoryBitMask = CollisionTypes.spear.rawValue
node.physicsBody?.contactTestBitMask = CollisionTypes.head.rawValue
node.physicsBody?.collisionBitMask = CollisionTypes.head.rawValue
return node
}()
lazy var headNode: SKSpriteNode = {
let node = SKSpriteNode(imageNamed: "Pig")
node.name = "Pig"
node.physicsBody = SKPhysicsBody(texture: node.texture!,
size: CGSize(width: node.frame.width , height: node.frame.height))
node.position = CGPoint(x:self.frame.midX , y:self.frame.maxY - 100)
node.physicsBody?.affectedByGravity = true
node.physicsBody?.allowsRotation = false
node.size = CGSize(width: node.frame.width / 2 , height: node.frame.height / 2 )
node.physicsBody?.categoryBitMask = CollisionTypes.head.rawValue
return node
}()
func didBegin(_ contact: SKPhysicsContact){
guard let nodeA = contact.bodyA.node else {return}
guard let nodeB = contact.bodyB.node else {return}
print("Contacted")
if nodeA.name == "Pig" && nodeB.name == "Spear"{
nodeA.removeFromParent()
}
if nodeA.name == "Spear" && nodeB.name == "Pig"{
nodeB.removeFromParent()
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first!
let location = touch.location(in:self)
if spearNode.frame.contains(location) {
touchPoint = location
touching = true
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first!
let location = touch.location(in: self)
touchPoint = location
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
touching = false
}
override func update(_ currentTime: TimeInterval) {
physicsWorld.gravity = CGVector(dx:0, dy: -9.8)
if touching {
let dt:CGFloat = 1.0/60.0
let distance = CGVector(dx: touchPoint.x-spearNode.position.x, dy: touchPoint.y-spearNode.position.y)
let velocity = CGVector(dx: distance.dx/dt, dy: distance.dy/dt)
spearNode.physicsBody!.velocity=velocity
}
}
}
Why not simply impart a force to the object based upon the swipe gesture rather than turning off gravity, manually moving the object, and then turning on gravity again when the swipe is over?

How to move single SKspritenode from array

I have an array of sprites and I move it when click on it, the problem is that it is moving all the sprites and I want it to move a single element, how can I do this? thank you in advance
This is my code:
var containerPieces: [ContainerPieces] = []
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for touch in touches {
let location = touch.location(in: self)
let rsCurrent = self.atPoint(location)
for nodo in containerPieces {
let rsBody = nodo.block.physicsBody
if rsBody == rsCurrent.physicsBody {
if nodo.block.frame.contains(location) {
nodo.block.position = location
nodo.block.run(blinkAnimation(), withKey:"wiggle")
isFingerOnPaddle = true
}
}
}
}
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
if isFingerOnPaddle {
let touch = touches.first
let touchLocation = touch!.location(in: self)
let previousLocation = touch!.previousLocation(in: self)
for nodo in containerPieces{
var paddleX = nodo.block.position.x + (touchLocation.x - previousLocation.x)
var paddleY = nodo.block.position.y + (touchLocation.y - previousLocation.y)
paddleX = max(paddleX, nodo.block.size.width/2)
paddleX = min(paddleX, size.width - nodo.block.size.width/2)
paddleY = max(paddleY, nodo.block.size.width/2)
paddleY = min(paddleY, size.width - nodo.block.size.width/2)
nodo.block.position = CGPoint(x: paddleX, y: paddleY)
}
}
}

Trying to move / drag SKSpriteNode in y axis

I'm trying to create a small game ,and in there there is a pipe , and i want to move that pipe along with the y axis , i want to do thins for finger swipe , i tried to do this with touches began but its doesn't looks smooth , so i tried to use uipangesture , but in not familiar with the sprite integration ,
can someone help me to achive this
class GameScene: SKScene,SKPhysicsContactDelegate {
var pipeTextureUp:SKTexture!
var pipeTextureDown:SKTexture!
var pipeUp:SKSpriteNode!
var pipeDown:SKSpriteNode!
var circleTouch: UITouch?
var verticalPipeGap:Double = 60.0
var moveStatus: Bool!
override func didMoveToView(view: SKView) {
/* Setup your scene here */
backgroundColor = SKColor.whiteColor()
//set the gravity
self.physicsWorld.gravity = CGVector(dx: 0.0, dy: 0.0)
self.physicsWorld.contactDelegate = self
//first create the pipe in a random location
pipeTextureUp = SKTexture(imageNamed: "PipeUp")
pipeTextureUp.filteringMode = .Nearest
pipeTextureDown = SKTexture(imageNamed: "PipeDown")
pipeTextureDown.filteringMode = .Nearest
pipeUp = SKSpriteNode(texture: pipeTextureUp)
pipeUp.setScale(2.0)
pipeUp.name = "pipeUp"
pipeUp.position = CGPoint(x: size.width * 0.9, y: 0.0)
pipeDown = SKSpriteNode(texture: pipeTextureDown)
pipeDown.setScale(2.0)
pipeDown.name = "pipeDown"
pipeDown.position = CGPoint(x: Double(size.width) * 0.9 , y: Double(pipeDown.size.height) + verticalPipeGap)
//addChild(pipeDown)
addChild(pipeUp)
}
func didBeginContact(contact: SKPhysicsContact) {
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch:UITouch = touches.first!
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
if let name = touchedNode.name
{
if (name == "pipeUp" || name == "pipeDown" )
{
print("touches started")
moveStatus = true
circleTouch = touch
}
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch:UITouch = touches.first!
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
print(positionInScene)
if let name = touchedNode.name
{
if (name == "pipeUp" || name == "pipeDown" )
{
//let fingerPoint = CGPoint(x: size.width * 0.9, y: 0.3)
let actionUpMove:SKAction = SKAction.moveToY(positionInScene.y, duration: 1.0)
pipeUp.runAction(actionUpMove)
pipeUp.position.y = positionInScene.y
}
}
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch:UITouch = touches.first!
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
if let name = touchedNode.name
{
if (name == "pipeUp" || name == "pipeDown" )
{
//let fingerPoint = CGPoint(x: size.width * 0.9, y: 0.3)
circleTouch = nil
}
}
}
}
If you want to intercept your swiping along Y coordinate you could put this code in didMoveToView:
let swipeUp:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(GameScene.swipedUp(_:)))
swipeUp.direction = .Up
swipeUp.cancelsTouchesInView = true
swipeUp.delaysTouchesBegan = true
view.addGestureRecognizer(swipeUp)
let swipeDown:UISwipeGestureRecognizer = UISwipeGestureRecognizer(target: self, action: #selector(GameScene.swipedDown(_:)))
swipeDown.direction = .Down
swipeDown.cancelsTouchesInView = true
swipeDown.delaysTouchesBegan = true
view.addGestureRecognizer(swipeDown)
Then your methods are:
func swipedUp(sender:UISwipeGestureRecognizer){
print("swiped up")
}
func swipedDown(sender:UISwipeGestureRecognizer){
print("swiped down")
}
UPDATE : apparently this is what i had to do ,
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch:UITouch = touches.first!
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
if let name = touchedNode.name
{
if (name == "pipeUp" || name == "pipeDown" )
{
handleTouch(touches.first!, name: name)
}
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch:UITouch = touches.first!
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
if let name = touchedNode.name
{
if (name == "pipeUp" || name == "pipeDown" )
{
handleTouch(touches.first!, name: name)
}
}
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
let touch:UITouch = touches.first!
let positionInScene = touch.locationInNode(self)
let touchedNode = self.nodeAtPoint(positionInScene)
if let name = touchedNode.name
{
if (name == "pipeUp" || name == "pipeDown" )
{
handleTouch(touches.first!, name: name)
}
}
}
func handleTouch(touch: UITouch , name : String) {
let location = touch.locationInNode(self) // get the current point
let node = self.nodeAtPoint(location) //get the current node based on the touched location
let previousLocation = touch.previousLocationInNode(self) //get the previous location in node
let diff = location.y - previousLocation.y; //get the different of location
let newPosition = CGPointMake(node.position.x, node.position.y + diff);
var newPipeDownPosition :CGPoint;
if (name == "pipeDown" )
{
newPipeDownPosition = CGPointMake(self.pipeUp.position.x, self.pipeUp.position.y + diff);
pipeDown.position.y = newPosition.y
pipeUp.position.y = newPipeDownPosition.y
}else{
newPipeDownPosition = CGPointMake(self.pipeDown.position.x, self.pipeDown.position.y + diff);
pipeUp.position.y = newPosition.y
pipeDown.position.y = newPipeDownPosition.y
}
}
now the pipe moves according to top and down direction

How to make an object (SKSprite node) disappear on click

I want the node to disappear when I click on the object. The object is moving around the screen and currently is removed when you click anywhere on the screen. However, I want it to be removed only when the object has been clicked on.
The code is as follows:
import SpriteKit
import GameplayKit
struct Physics {
static let Enemy: UInt32 = 0x1 << 1
let BorderCategory : UInt32 = 0x1 << 2
let BottomCategory : UInt32 = 0x1 << 3
let BallCategory : UInt32 = 0x1 << 4
}
class GameScene: SKScene {
var Enemy = SKSpriteNode()
var gameStarted = Bool()
var gameState = "running"
var destX : CGFloat = 0.0
var destY : CGFloat = 0.0
var score = 0
override func didMove(to view: SKView) {
let borderBody = SKPhysicsBody(edgeLoopFrom: self.frame)
borderBody.friction = 0
self.physicsBody = borderBody
Enemy.name = "Enemys"
Enemy = SKSpriteNode(imageNamed: "red2")
Enemy.size = CGSize(width: 60, height: 70)
Enemy.position = (CGPoint(x: self.frame.width / 6 - Enemy.frame.width, y: self.frame.height / 10))
Enemy.physicsBody = SKPhysicsBody(circleOfRadius: Enemy.frame.height / 2)
Enemy.physicsBody?.categoryBitMask = Physics.Enemy
//Enemy.physicsBody?.categoryBitMask = Physics.Ground | Physics.wall
//Enemy.physicsBody?.contactTestBitMask = Physics.Ground | Physics.wall
Enemy.physicsBody?.affectedByGravity = false
Enemy.physicsBody?.isDynamic = true
Enemy.physicsBody?.restitution = 1
Enemy.physicsBody?.friction = 0
Enemy.physicsBody?.angularDamping = 0
Enemy.physicsBody?.linearDamping = 0
self.addChild(Enemy)
let force = SKAction.applyForce(CGVector(dx: 300, dy: 300) , duration: 0.1)
Enemy.run(force)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first as UITouch!
let touchLocation = touch?.location(in: self)
let targetNode = atPoint(touchLocation!) as! SKSpriteNode
if(targetNode.name == "Enemys"){
Enemy.removeFromParent()
}
}
I personally find that the easiest way to handle this is to subclass SKSpriteNode and dig into the fact that it is descendant of UIResponder.
class AlienSprite: SKSpriteNode {
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.removeFromParent()
}
}
You also need to set the isUserInteractionEnabled = true on the instance somewhere.
You have to determine which node is under the touch, SKNode has methods about this: nodeAtPoint and nodesAtPoint:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first as UITouch!
let touchLocation = touch?.location(in: self)
if let hit = yourRootNode.nodeAtPoint(touchLocation) {
if hit.name=="Enemy" {
hit.removeFromParent();
}
}
}

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