Search code examples
swiftcollision-detectionphysicscollisioncontacts

Cannot assign a value of type "Game Scene" to a value of type "SKPhysicsContactDelegate"


I am trying to build flappy bird on my own. Everything works fine but now I have added the CategoryBitMasks and all that stuff and every time I try adding this piece of code:

self.physicsworld.contactDelegate = self

I get the error message :

Cannot assign a value of type 'GameScene' to a value of type 'SKPhysicsContactDelegate'.

Here is the code that I have written so far:

import SpriteKit

class GameScene: SKScene {

    //---------------
    //Bird
    //---------------
    var bird = SKSpriteNode()

    //---------------
    //Pipe's
    //---------------
    var pipeUp:SKSpriteNode = SKSpriteNode()
    var pipeDown:SKSpriteNode = SKSpriteNode()
    var pipeDownAnimation:NSMutableArray = NSMutableArray()
    var pipeUpAnimation:NSMutableArray = NSMutableArray()

    //---------------
    //Pipe spawningtimes
    //---------------
    var lastYieldTimeInterval:NSTimeInterval = NSTimeInterval()
    var lastUpdateTimeInterval:NSTimeInterval = NSTimeInterval()

    //---------------
    //Category bitmasks
    //---------------
    let birdCategory:UInt32 = 0x1 << 2
    let pipeUpCategory:UInt32 = 0x1 << 1
    let pipeDownCategory:UInt32 = 0x1 << 0

    //didMoveToView Funtion
    override func didMoveToView(view: SKView) {

        setUpWorld()

    }

    override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {

        if bird.position.y > frame.size.height - bird.size.height/2 {

        }
        else {
            bird.physicsBody!.velocity = CGVectorMake(0, 0.0)
            bird.physicsBody!.applyImpulse(CGVectorMake(0, 17))
        }
    }

    func setUpWorld () {

        //---------------
        //Physics World
        //---------------
        physicsWorld.gravity = CGVectorMake(0, -5.0)

        //---------------
        //setting up the background
        //---------------
        var background = SKSpriteNode(imageNamed: "background")
        background.position = CGPointMake(frame.size.width/2, frame.size.height/2)
        background.size = CGSizeMake(frame.size.width, frame.size.height)
        background.zPosition = -1.0

        addChild(background)

        //---------------
        //setting up the hills
        //---------------
        var hills = SKSpriteNode(imageNamed: "hills")
        hills.position = CGPointMake(frame.size.width/2, 300)
        hills.size = CGSizeMake(frame.size.width, 300)
        hills.zPosition = 0

        addChild(hills)

        //---------------
        //setting up the ground
        //---------------
        var ground = SKSpriteNode(imageNamed: "ground")
        ground.size = CGSizeMake(frame.size.width, 150)
        ground.position = CGPointMake(frame.size.width/2, 75)
        ground.zPosition = 2.0

        ground.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(ground.size.width, ground.size.height))
        ground.physicsBody!.dynamic = false
        ground.physicsBody!.affectedByGravity = false;

        addChild(ground)
        //---------------
        //setting up the bird
        //---------------
        bird = SKSpriteNode(imageNamed: "bird")
        bird.position = CGPointMake(100, frame.size.height/2)
        bird.setScale(0.7)
        bird.zPosition = 1.0

        bird.physicsBody = SKPhysicsBody(rectangleOfSize: bird.size)
        bird.physicsBody!.dynamic = true
        bird.physicsBody!.categoryBitMask = birdCategory
        bird.physicsBody!.contactTestBitMask = pipeUpCategory
        bird.physicsBody!.contactTestBitMask = pipeDownCategory
        bird.physicsBody!.collisionBitMask = pipeUpCategory & pipeDownCategory
        bird.physicsBody!.usesPreciseCollisionDetection = true

        addChild(bird)
    }

    func addPipes () {

        //---------------
        //Random Pipe Positions
        //---------------
        var randomPositionUp = CGPoint()
        var randomPositionDown = CGPoint()

        var random = arc4random() % 10

        if random == 0 {
            randomPositionUp = CGPointMake(frame.size.width + pipeUp.size.width * 2, frame.size.height/2 - 170)
            randomPositionDown = CGPointMake(randomPositionUp.x, frame.size.height - 40)
        }
        else if random == 1 {
            randomPositionUp = CGPointMake(frame.size.width + pipeUp.size.width * 2, frame.size.height/2 - 160)
            randomPositionDown = CGPointMake(randomPositionUp.x, frame.size.height - 30)
        }
        else if random == 2 {
            randomPositionUp = CGPointMake(frame.size.width + pipeUp.size.width * 2, frame.size.height/2 - 150)
            randomPositionDown = CGPointMake(randomPositionUp.x, frame.size.height - 20)
        }
        else if random == 3 {
            randomPositionUp = CGPointMake(frame.size.width + pipeUp.size.width * 2, frame.size.height/2 - 140)
            randomPositionDown = CGPointMake(randomPositionUp.x, frame.size.height - 10)
        }
        else if random == 4 {
            randomPositionUp = CGPointMake(frame.size.width + pipeUp.size.width * 2, frame.size.height/2 - 130)
            randomPositionDown = CGPointMake(randomPositionUp.x, frame.size.height)
        }
        else if random == 5 {
            randomPositionUp = CGPointMake(frame.size.width + pipeUp.size.width * 2, frame.size.height/2 - 120)
            randomPositionDown = CGPointMake(randomPositionUp.x, frame.size.height + 10)
        }
        else if random == 6 {
            randomPositionUp = CGPointMake(frame.size.width + pipeUp.size.width * 2, frame.size.height/2 - 110)
            randomPositionDown = CGPointMake(randomPositionUp.x, frame.size.height + 20)
        }
        else if random == 7 {
            randomPositionUp = CGPointMake(frame.size.width + pipeUp.size.width * 2, frame.size.height/2 - 100)
            randomPositionDown = CGPointMake(randomPositionUp.x, frame.size.height + 30)
        }
        else if random == 8 {
            randomPositionUp = CGPointMake(frame.size.width + pipeUp.size.width * 2, frame.size.height/2 - 90)
            randomPositionDown = CGPointMake(randomPositionUp.x, frame.size.height + 40)
        }
        else if random == 9 {
            randomPositionUp = CGPointMake(frame.size.width + pipeUp.size.width * 2, frame.size.height/2 - 80)
            randomPositionDown = CGPointMake(randomPositionUp.x, frame.size.height + 50)
        }

        //---------------
        //Pipe UP
        //---------------
        pipeUp = SKSpriteNode(imageNamed: "PipeUp")
        pipeUp.position = randomPositionUp
        pipeUp.setScale(0.5)
        pipeUp.zPosition = 1.0

        pipeUp.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(pipeUp.size.width, pipeUp.size.height))
        pipeUp.physicsBody!.dynamic = false
        pipeUp.physicsBody!.affectedByGravity = false
        pipeUp.physicsBody!.categoryBitMask = pipeUpCategory
        pipeUp.physicsBody!.contactTestBitMask = birdCategory
        pipeUp.physicsBody!.collisionBitMask = birdCategory
        pipeUp.physicsBody!.usesPreciseCollisionDetection = true

        addChild(pipeUp)

        pipeUpAnimation.addObject(SKAction.moveToX(-pipeUp.size.width * 2, duration: 7))
        pipeUpAnimation.addObject(SKAction.removeFromParent())
        pipeUp.runAction(SKAction.sequence(pipeUpAnimation as [AnyObject]))

        //---------------
        //Pipe Down
        //---------------
        pipeDown = SKSpriteNode(imageNamed: "PipeDown")
        pipeDown.position = randomPositionDown
        pipeDown.setScale(0.5)
        pipeDown.zPosition = 1.0

        pipeDown.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(pipeDown.size.width, pipeDown.size.height))
        pipeDown.physicsBody!.dynamic = false
        pipeDown.physicsBody!.affectedByGravity = false
        pipeDown.physicsBody!.categoryBitMask = pipeDownCategory
        pipeDown.physicsBody!.contactTestBitMask = birdCategory
        pipeDown.physicsBody!.collisionBitMask = birdCategory
        pipeDown.physicsBody!.usesPreciseCollisionDetection = true

        addChild(pipeDown)

        pipeDownAnimation.addObject(SKAction.moveToX(-pipeUp.size.width * 2, duration: 7))
        pipeDownAnimation.addObject(SKAction.removeFromParent())
        pipeDown.runAction(SKAction.sequence(pipeDownAnimation as [AnyObject]))
    }

    func updateWithTimeSinceLastUpdate (timeSinceLastUpdate: CFTimeInterval) {

        lastYieldTimeInterval += timeSinceLastUpdate

        if lastYieldTimeInterval > 2 {
            lastYieldTimeInterval = 0
            addPipes()
        }

    }

    override func update(currentTime: CFTimeInterval) {

        var timeSinceLastUpdate = currentTime - lastUpdateTimeInterval
        lastUpdateTimeInterval = currentTime

        if timeSinceLastUpdate > 1 {

            timeSinceLastUpdate = 1/60
            lastUpdateTimeInterval = currentTime

        }
        updateWithTimeSinceLastUpdate(timeSinceLastUpdate)
    }

    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 & birdCategory != 0 && secondBody.categoryBitMask & pipeDownCategory != 0 {
            birdDidCollidWithPipeDown(firstBody.node as! SKSpriteNode, pipeDown: secondBody.node as! SKSpriteNode)
        }
    }

    func birdDidCollidWithPipeDown(bird: SKSpriteNode, pipeDown: SKSpriteNode) {

        bird.removeFromParent()

    }
}

Solution

  • You need to make GameScene conform to SKPhysicsContactDelegate, like so:

    class GameScene: SKScene, SKPhysicsContactDelegate {
        // ...
    }
    

    Now you can implement the delegate methods you want, all the methods in SKPhysicsContactDelegate are optional, and they'll get called at the appropriate time.

    For more information on Protocols, I would recommend looking at The Swift Programming Language: Protocols