Search code examples
swiftclasssprite-kitskspritenode

SpriteKit calling function from class


This is from a simple game in SpriteKit with a Ball() class that has a function shieldOn() which, for the moment, simply replaces the texture of a single ball to that of a ball surrounded by a shield.

The ball is created like this in GameScene:

func getBall() {
   let ball = Ball()
   ball.createBall(parentNode: self)
}

Here is the Ball class

class Ball: SKSpriteNode {

   func createBall(parentNode: SKNode) {
      let ball = SKSpriteNode(texture: SKTexture(imageNamed: "ball2"))
      ball.physicsBody = SKPhysicsBody(circleOfRadius: 25)
      ball.name = "ball"
      parentNode.addChild(ball)
      ball.size = CGSize(width: 50, height: 50)
      ball.position = CGPoint(x: 20, y: 200)

      launch(spriteNode: ball, parentNode: parentNode)
   }


   private func launch(spriteNode: SKSpriteNode, parentNode: SKNode) {
      spriteNode.physicsBody?.applyImpulse(CGVector(dx: 5, dy: 0))
   }

   func shieldOn() {
      self.texture = SKTexture(imageNamed: "ballShield")
   }

   func shieldOff() {
      self.texture = SKTexture(imageNamed: "ball2")
   }
}

In the main section of my code (GameScene.swift) I don't have a reference to the ball. So I cycle through all of the nodes on the screen and try to cast the matching one as shown below. I crash with an error saying that it could not cast value of type SKSpriteNode to Ball.

for node in self.children {
   if node.name == "ball" {
      let ball = node as! Ball
      ball.shieldOn()
   }
 }

I've tried a few variations with no luck. Am I at least working in the right direction? Thanks!


Solution

  • With the new information I think you want something like this:

    Ball Class:

    class Ball: SKSpriteNode{
    
    
    init() {
    
        let texture = SKTexture(imageNamed: "ball2")
        let size = CGSize(width: 50, height: 50)
    
        super.init(texture: texture, color: UIColor.clear, size: size)
    
        self.name = "ball"
        self.physicsBody = SKPhysicsBody(circleOfRadius: size.height/2)
    
        self.physicsBody?.applyImpulse(CGVector(dx: 5, dy: 0))
    
    }
    
    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
        func shieldOn() {
            self.texture = SKTexture(imageNamed: "ballShield")
        }
    
        func shieldOff() {
            self.texture = SKTexture(imageNamed: "ball2")
        }
    
    }
    

    Then use this to create the ball:

    func getBall() {
        let ball = Ball()
        ball.position = CGPoint(x: 20, y: 200)
        scene?.addChild(ball)
    }