Search code examples
iosswiftskspritenodesknode

Swift: Run function after collecting item


I have a class that creates collectable items:

class CollectableCreate {

    var collectable = SKSpriteNode()
    var type = String()

    var onCollect : () -> Void = {}

    init(type: String, position: CGPoint, text: String = "This collectable uses no text!", onCollect : () -> Void) {

        self.type = type.lowercaseString

        switch self.type {

            default:
                collectable.size = CGSize(width: 1, height: 200)
                collectable.color = SKColor.blueColor()
                collectable.physicsBody = SKPhysicsBody(rectangleOfSize: collectable.size)
                break
        }

        collectable.position = position

        collectable.name = self.type
        collectable.physicsBody?.categoryBitMask = PhysicsCategory.Collectable
        collectable.physicsBody?.collisionBitMask = PhysicsCategory.Player
        collectable.physicsBody?.contactTestBitMask = PhysicsCategory.Player


        self.onCollect = onCollect
    }


    func chatBoxActivate() -> SKSpriteNode {
        collectable.physicsBody?.dynamic = false
        collectable.physicsBody?.affectedByGravity = false
        return collectable
    }

    func collect() {
        self.onCollect()
    }

}

I create the collectable item like this:

let d = CollectableCreate(type: "chatbox", position: CGPoint(x: 500, y: 100), onCollect: {
        self.createChatBox("test blalb|blablalba")
    })

self.addChild(d.chatBoxActivate())

And on didBeginContact I have this:

if (firstBody.categoryBitMask == PhysicsCategory.Collectable || secondBody.categoryBitMask == PhysicsCategory.Collectable) {

    let collectableBody = (firstBody.categoryBitMask == PhysicsCategory.Collectable ? firstBody.node : secondBody.node)
    //collectableBody.collect() <---                
    collectableBody?.removeFromParent()

}

I want to run the CollectableCreate().collect() function when I run into a collectable. How to I make this happen?


Solution

  • I'm afraid i'm shooting in the dark here since i've never worked with SpriteKit, so please feel free to add to/or edit my answer.

    You should subclass SKSpriteNode:

    class Collectable : SKSpriteNode {
    
        var type: String?
        var onCollect: (() -> ())?
    
        convenience init(type: String, position: CGPoint, text: String = "This collectable uses no text!", onCollect : () -> Void) {
            self.init()
    
            self.type = type.lowercaseString
    
            switch self.type {
    
            default:
                self.size = CGSize(width: 1, height: 200)
                self.color = SKColor.blueColor()
                self.physicsBody = SKPhysicsBody(rectangleOfSize: self.size)
                break
            }
    
            self.position = position
    
            self.name = self.type
            self.physicsBody?.categoryBitMask = PhysicsCategory.Collectable
            self.physicsBody?.collisionBitMask = PhysicsCategory.Player
            self.physicsBody?.contactTestBitMask = PhysicsCategory.Player
    
    
            self.onCollect = onCollect
        }
    
        func chatBoxActivate() -> SKSpriteNode {
            self.physicsBody?.dynamic = false
            self.physicsBody?.affectedByGravity = false
    
            return self
        }
    
        func collect(){
            self.onCollect?()
        }
    }
    

    And use it in the following matter, and add whatever class you are subclassing in your controller, and add the correct delegates:

    class SomeClass {
    
        func someFunc(){
    
            let collectable = Collectable(type: "chatbox", position: CGPoint(x: 500, y: 100), onCollect: {
                self.createChatBox("FooBar")
            })
    
            self.addChild(collectable.chatBoxActivate())
        }
    
        func didBeginContact(contact: SKPhysicsContact){
    
            let firstBody = contact.bodyA
            let secondBody = contact.bodyB
    
            if (firstBody.categoryBitMask == PhysicsCategory.Collectable || secondBody.categoryBitMask == PhysicsCategory.Collectable) {
    
                let collectableBody = firstBody.categoryBitMask == PhysicsCategory.Collectable ? firstBody.node : secondBody.node
    
                if let collectable = collectableBody as? Collectable {
                    collectable.collect()
                }
    
                collectableBody?.removeFromParent()
    
            }
    
        }
    
        func addChild(collectable: SKSpriteNode){
            // Some logic
        }
    
        func createChatBox(text: String) {
            // Some logic
        }
    
    }
    

    Hope this can point you in the right direction!

    SpriteKit Docs