简体   繁体   中英

How to do i set up proper collision detection in SpriteKit, Swift 3

I had just recently set up collision detection in my game it is doesn't seem to be working. I am very new to spritekit and i would like to know what is happening. Below i will provide you the gamscene class, didMoveToView, a function that is spawning the balls in the view, and my Did begin contact function. Please note that i am working with just the red Ball and the red block right now so they are the only two colliding. Please tell me if theres anything else in the project that you need to see and is not provided below.

import SpriteKit
import GameplayKit

class GameScene: SKScene, SKPhysicsContactDelegate {



var greenBlock = SKSpriteNode ()
var redBlock = SKSpriteNode()
var yellowBlock = SKSpriteNode()
var blueBlock = SKSpriteNode()

var greenBall = SKSpriteNode()
var redBall = SKSpriteNode()
var yellowBall = SKSpriteNode()
var blueBall = SKSpriteNode()
var ball = SKSpriteNode()

var ballSpeedTop = CGVector(dx: 0, dy: 5)
var ballSpeedBottom = CGVector(dx: 0, dy: -5)

This is where i define the numbers for the categoryBitMask

let redBallCategory: UInt32 = 0x1 << 0
let greenBallCategory: UInt32 = 0x1 << 1
let blueBallCategory: UInt32 = 0x1 << 2
let yellowBallCategory: UInt32 = 0x1 << 3

let redBlockCategory: UInt32 = 0x1 << 4
let yellowBlockCategory: UInt32 = 0x1 << 5
let greenBlockCategory: UInt32 = 0x1 << 6
let blueBlockCategory: UInt32 = 0x1 << 7


override func didMove(to view: SKView) {

    physicsWorld.contactDelegate = self

Where i am applying the physics bodies to the block.

    redBlock = self.childNode(withName: "redBlock") as! SKSpriteNode
    redBlock.physicsBody?.categoryBitMask = redBlockCategory
    redBlock.physicsBody?.collisionBitMask = redBallCategory
    redBlock.physicsBody?.contactTestBitMask = redBallCategory


    yellowBlock = self.childNode(withName: "yellowBlock") as! SKSpriteNode
    greenBlock = self.childNode(withName: "greenBlock") as! SKSpriteNode
    blueBlock = self.childNode(withName: "blueBlock") as! SKSpriteNode

    redBlock.physicsBody?.affectedByGravity = false
    redBlock.physicsBody?.isDynamic = true

    greenBlock.physicsBody?.affectedByGravity = false
    greenBlock.physicsBody?.isDynamic = true

    blueBlock.physicsBody?.affectedByGravity = false
    blueBlock.physicsBody?.isDynamic = false

    yellowBlock.physicsBody?.affectedByGravity = false
    yellowBlock.physicsBody?.isDynamic = false

    initializeGame()

    print("hello")





}


    func initializeGame (){


    Timer.scheduledTimer(timeInterval: TimeInterval(randomBetweenNumbers(firstNum: 2, secondNum: 4)), target: self, selector: #selector(topBall), userInfo: nil, repeats: true)

    Timer.scheduledTimer(timeInterval: TimeInterval(randomBetweenNumbers(firstNum: 2, secondNum: 4)), target: self, selector: #selector(bottomBall), userInfo: nil, repeats: true)



}

// top ball spawner

func topBall () -> SKSpriteNode {

    let ball: SKSpriteNode?;


    if Int(randomBetweenNumbers(firstNum: 0, secondNum: 2)) == 0 {


        ball = SKSpriteNode(imageNamed: "redBall")
        ball?.name = "redBall"
        ball!.physicsBody?.categoryBitMask = redBallCategory
        ball!.physicsBody?.collisionBitMask = redBlockCategory
        ball!.physicsBody?.contactTestBitMask = redBlockCategory


    } else {


        ball = SKSpriteNode(imageNamed: "greenBall")
        ball?.name = "greenBall"




    }




    ball!.size = CGSize(width: 30, height: 30)
    ball!.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    ball!.position = CGPoint(x: 0, y: 0)

    ball!.physicsBody = SKPhysicsBody(circleOfRadius: ball!.size.height / 2)
    ball!.physicsBody?.affectedByGravity = false
    ball!.physicsBody?.isDynamic = true

    ball!.zPosition = 2


    self.addChild(ball!)

    ball!.physicsBody?.applyImpulse(ballSpeedTop)

    return ball!


}

the contact function

    func didBegin(_ contact: SKPhysicsContact) {


    if (contact.bodyA.categoryBitMask == redBallCategory && contact.bodyB.categoryBitMask == redBlockCategory){

        print("touched red block")

    } else if (contact.bodyB.categoryBitMask == redBallCategory && contact.bodyA.categoryBitMask == redBlockCategory){

        print("touched a red block")
    }






}

UPDATE::: i found where i went wrong but my problem is not technically solved yet. i had applied the properties of the redBall outside the if statement which meant that the redballs category bit mask, etc. is applied to both balls, i need a way to apply the redBall category bit mask to the redBall when it spawns and a different categorybitmask to the green ball when it spawns.

    func topBall () -> SKSpriteNode {

    let ball: SKSpriteNode?;


    if Int(randomBetweenNumbers(firstNum: 0, secondNum: 2)) == 0 {


        ball = SKSpriteNode(imageNamed: "redBall")
        ball?.name = "redBall"


    } else {


        ball = SKSpriteNode(imageNamed: "greenBall")
        ball?.name = "greenBall"




    }




    ball!.size = CGSize(width: 30, height: 30)
    ball!.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    ball!.position = CGPoint(x: 0, y: 0)

    ball!.physicsBody = SKPhysicsBody(circleOfRadius: ball!.size.height / 2)
    ball!.physicsBody?.affectedByGravity = false
    ball!.physicsBody?.isDynamic = true
    ball!.physicsBody?.categoryBitMask = redBallCategory
    ball!.physicsBody?.collisionBitMask = redBlockCategory
    ball!.physicsBody?.contactTestBitMask = redBlockCategory


    ball!.zPosition = 2


    self.addChild(ball!)

    ball!.physicsBody?.applyImpulse(ballSpeedTop)

    return ball!


}

this is how i got it to work but the problem is that i want to apply individual categorybitmasks to the ball depending on wether it is green or red.

Use temporary variables to store the appropriate category , collision and contactTest bitmasks in the same block of code where you set the spawned ball's image and name, and then use these temporary variables to set the actual values in the physicsbody:

  var categoryBitMask: UInt32
  var collisonBitMask: UInt32
  var contactTestBitMask: Uint32

  if Int(randomBetweenNumbers(firstNum: 0, secondNum: 2)) == 0 {
        ball = SKSpriteNode(imageNamed: "redBall")
        ball?.name = "redBall"
        categoryBitMask = redBallCategory
        collisionBitMask = redBlockCategory
        contactTestBitMask = redBlockCategory

    } else {
        ball = SKSpriteNode(imageNamed: "greenBall")
        ball?.name = "greenBall"
        categoryBitMask = greenBallCategory
        collisionBitMask = greenBlockCategory
        contactTestBitMask = greenBlockCategory
    }

    ball!.size = CGSize(width: 30, height: 30)
    ball!.anchorPoint = CGPoint(x: 0.5, y: 0.5)
    ball!.position = CGPoint(x: 0, y: 0)

    ball!.physicsBody = SKPhysicsBody(circleOfRadius: ball!.size.height / 2)
    ball!.physicsBody?.affectedByGravity = false
    ball!.physicsBody?.isDynamic = true
    ball!.physicsBody?.categoryBitMask = categoryBitMask
    ball!.physicsBody?.collisionBitMask = collisionBitMask
    ball!.physicsBody?.contactTestBitMask = contactTestBitMask

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM