0

I'm getting the error: Cannot convert value of type 'SKSpriteNode.Type' to expected argument type 'SKSpriteNode'

I've been having trouble just trying to get the collisionBullet() function to run when the sprite nodes enemy and smallball collide. I'm open to changing my setup however possible I just can't for the life of me seem to get the function to work.

import SpriteKit import GameplayKit

class GameScene: SKScene, SKPhysicsContactDelegate {

let mainballcategory:UInt32 = 0x1 << 0
let smallballcategory:UInt32 = 0x1 << 1
let enemycategory:UInt32 = 0x1 << 3
var Mainball = SKSpriteNode(imageNamed: "Ball")
var enemytimer = Timer()

override func didMove(to view: SKView) {
    self.physicsWorld.contactDelegate = self

    Mainball.size = CGSize(width: 100, height: 100)
    Mainball.position = CGPoint(x:frame.width / 80, y:frame.height / 80)
    Mainball.zPosition = 1.0
    Mainball.physicsBody = SKPhysicsBody(circleOfRadius: Mainball.size.width/2)
    Mainball.physicsBody?.categoryBitMask = mainballcategory
    Mainball.physicsBody?.collisionBitMask = enemycategory
    Mainball.physicsBody?.contactTestBitMask = enemycategory
    Mainball.name = "Mainball"
    Mainball.physicsBody?.affectedByGravity = false
    self.addChild(Mainball)
    Timer.scheduledTimer(withTimeInterval: 0.8, repeats: true) { timer in
        let randomNumber = Int.random(in: 1...20)
        print("Number: \(randomNumber)")
        if randomNumber > 10 {
            self.Enemies()
        }
    }
}
    
func didBegin(_ contact: SKPhysicsContact) {
    let collision:UInt32 = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
    if collision == smallballcategory | enemycategory {
       collisionBullet(enemy: SKSpriteNode, smallball: SKSpriteNode) 
    }  
}

func collisionBullet(enemy : SKSpriteNode, smallball : SKSpriteNode){
    enemy.physicsBody!.isDynamic = true
    enemy.physicsBody!.affectedByGravity = true
    enemy.physicsBody!.mass = 6.0
    smallball.physicsBody?.mass = 10.0
    enemy.removeAllActions()
    smallball.removeAllActions()
    enemy.removeFromParent()
}

func touchDown(atPoint pos : CGPoint) {
}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    for t in touches { self.touchDown(atPoint: t.location(in: self))
        for _ in (touches ){
            }
    }
    let smallball = SKSpriteNode(imageNamed: "Ball")
    
    smallball.position = Mainball.position
    smallball.size = CGSize(width: 30, height: 30)
    smallball.physicsBody = SKPhysicsBody(circleOfRadius: smallball.size.width / 2)
    
    smallball.physicsBody!.categoryBitMask = smallballcategory
    smallball.physicsBody!.collisionBitMask = enemycategory
    smallball.physicsBody!.contactTestBitMask = enemycategory
    smallball.name = "smallball"
    smallball.physicsBody!.isDynamic = true
    smallball.physicsBody!.affectedByGravity = true
    self.addChild(smallball)
    
    for t in touches { self.touchDown(atPoint: t.location(in: self))
        for touch in (touches ){
            let spot = touch.location(in: self)

            var dx = CGFloat(spot.x - Mainball.position.x)
            var dy = CGFloat(spot.y - Mainball.position.y)
            let magnitude = sqrt(dx * dx + dy * dy)
            dx /= magnitude
            dy /= magnitude
            let vector = CGVector(dx: 35.0 * dx, dy: 35.0 * dy)
            
            smallball.physicsBody!.applyImpulse(vector)
        }
    }
}

func Enemies(){
    let enemy = SKSpriteNode(imageNamed: "Ball")
    enemy.size = CGSize(width: 25, height: 25)
    enemy.color = UIColor(red: 0.9, green: 0.1, blue: 0.1, alpha: 1.0)
    enemy.colorBlendFactor = 1.0

   //Physics
    enemy.physicsBody = SKPhysicsBody(circleOfRadius: enemy.size.width / 2)
    enemy.physicsBody!.categoryBitMask = enemycategory
    enemy.physicsBody!.contactTestBitMask = smallballcategory | mainballcategory
    
    enemy.physicsBody!.collisionBitMask = smallballcategory | mainballcategory
    enemy.physicsBody!.isDynamic = false
    enemy.name = "enemy"
    
    let RandomPosNmbr = arc4random() % 6
    
    switch RandomPosNmbr{
    case 0:
        enemy.position = CGPoint(x:self.view!.bounds.width, y:self.view!.bounds.height)
        self.addChild(enemy)
        break
    case 1:
        enemy.position = CGPoint(x:self.view!.bounds.width * -1, y:self.view!.bounds.height)
        self.addChild(enemy)
        break
    case 2:
        enemy.position = CGPoint(x:self.view!.bounds.width, y:self.view!.bounds.height * -1)
        self.addChild(enemy)
        break
    case 3:
        enemy.position = CGPoint(x:self.view!.bounds.width * -1, y:self.view!.bounds.height * -1)
        self.addChild(enemy)
        break
    case 4:
        enemy.position = CGPoint(x:self.view!.bounds.width / 10, y:self.view!.bounds.height * -1)
        self.addChild(enemy)
        break
    case 5:
        enemy.position = CGPoint(x:self.view!.bounds.width / 10, y:self.view!.bounds.height)
        self.addChild(enemy)
        break
    default:
        break
    }

    enemy.run(SKAction.move(to: Mainball.position, duration: 5))
}

override func update(_ currentTime: TimeInterval) { 
}

}

Steve Ives
  • 7,894
  • 3
  • 24
  • 55
  • 1
    The message is saying that you're trying to pass `SKSpriteNode` (a type) to `collisionBullet`. You want to be passing the nodes themselves. Get them from `contact.bodyA.node` and `contact.bodyB.node`. – bg2b Sep 28 '22 at 11:42

1 Answers1

1

Are you sure didBegin() is begin called? Try coding didBegin like this:

      func didBegin(_ contact: SKPhysicsContact) {
         print("didBeginContact entered for \(String(describing: contact.bodyA.node!.name)) and \(String(describing: contact.bodyB.node!.name))")
    
         let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask
    
         switch contactMask {
         case smallBallCategory | enemyCategory:
            print("smallBall and enemy have contacted.")
            let smallBallNode = contact.bodyA.categoryBitMask == smallBallCategory ? contact.bodyA.node : contact.bodyB.node
            let enemyNode = contact.bodyA.categoryBitMask == enemyCategory ? contact.bodyA.node : contact.bodyB.node
            collisionBullet(enemy: enemyNode, smallball: smallBallNode)
         default:
            print("Some other contact occurred")
         }

You'll see a message if didBegin() is called - no message then your contact testing is configured incorrectly.

As the earlier comment said, you are passing a type to collisionBullet when you should be passing 2 actual nodes.

Also, do you need to have all that code in collisionBullet() to the enemy node when you are just going to remove it anyway? could you not have that code in didBegin() like this:

         case smallBallCategory | enemyCategory:
            print("smallBall and enemy have contacted.")
            let smallBallNode = contact.bodyA.categoryBitMask == smallBallCategory ? contact.bodyA.node : contact.bodyB.node
            let enemyNode = contact.bodyA.categoryBitMask == enemyCategory ? contact.bodyA.node : contact.bodyB.node
            smallBallNode.physicsBody?.mass = 10.0
            smallBallNode.removeAllActions()
            enemyNode.removeFromParent()

You may find these helpful (quite old, but hopefully still relevant) :

My step-by-step guide for collisions and contacts: https://stackoverflow.com/a/51041474/1430420

And a guide to collision and contactTest bit masks: https://stackoverflow.com/a/40596890/1430420

Manipulating bit masks to turn individual collision and contacts off and on. https://stackoverflow.com/a/46495864/1430420

Small sample project with contacts, collision and touches https://stackoverflow.com/a/43605825/1430420

Edit:

I'm not saying that my way is the best way to code didBegin(), but I find doing it this way is, for me, quite clear with the different case statements highlighting the different collisions quite clearly.

Steve Ives
  • 7,894
  • 3
  • 24
  • 55