Spritekit检测Sprite重叠与冲突关闭

时间:2018-04-19 16:51:50

标签: ios swift sprite-kit

目前我有一个Swift / Spritekit应用程序可以从天空中删除一个精灵,它们会发生冲突,因此它们会掉到地板上,但是我试图发出一个声明来检测玩家精灵何时接触精灵掉落然后从天空中删除该孩子,并在分数变量上添加一个点。

更新:04/29/18 2:10 CST 截至目前,这就是我所拥有的

import SpriteKit
import GameplayKit

class GameScene: SKScene, SKPhysicsContactDelegate {
    var activePlayer:SKSpriteNode! = SKSpriteNode() //Sets active character
    var bg:SKSpriteNode! = SKSpriteNode()
    var bananaCollected = 0 //Defines banana var
    var timer: Timer?
    let bananaCat : UInt32 = 0x1 << 1
    let playerCat : UInt32 = 0x1 << 2

    func bananaDrop() { //Defines bananaDrop
        let banana = SKSpriteNode(imageNamed:"banana")
        //print("- Debug: [bananaDrop] successfully initiated -")
        banana.name = "banana"

        //Size of banana
        banana.xScale = 0.25
        banana.yScale = 0.25

        //Defines physics properties
        let physicsBody = SKPhysicsBody(circleOfRadius: 15)
        //let physicsBody = SKPhysicsBody()
        //physicsBody.pinned = true //Suspend in air
        physicsBody.allowsRotation = false
        physicsBody.affectedByGravity = true
        //physicsBody.collisionBitMask = 0
        banana.physicsBody?.categoryBitMask = bananaCat
        banana.physicsBody?.collisionBitMask = 0
        banana.physicsBody?.contactTestBitMask = playerCat

        //categoryBitMask is what the physics category of the object is
        //banana.physicsBody!.categoryBitMask = playerCategory
        //collisionBitMask is what the physics category of objects that this cannot pass through are...multiple categories would be typed like... `cat1 | cat2`
        //banana.physicsBody!.collisionBitMask = 0
        //contactTestBitMask is what the physics category of the objects that we get alerted to upon contact
        //activePlayer.physicsBody!.contactTestBitMask = obstacleCategory

        banana.physicsBody = physicsBody

        //Starting Location Defined
        var x: CGFloat = 0 //Defines X
        let y: CGFloat = 400 //Defines how high up banana drops

        let bananaDrop = GKShuffledDistribution(lowestValue: 1, highestValue: 11)

        //Drop locations defined (relation to X)
        switch bananaDrop.nextInt() {
        case 1:
            x = -170
        case 2:
            x = -160
        case 3:
            x = -120
        case 4:
            x = -80
        case 5:
            x = -40
        case 6:
            x = 0
        case 7:
            x = 40
        case 8:
            x = 80
        case 9:
            x = 120
        case 10:
            x = 160
        case 11:
            x = 170
        default:
            fatalError("Case num outside range")
        }
        banana.position = CGPoint(x: x, y: y)

        //Adds banana
        self.addChild(banana)
    }
    func bDropF() { //Defintes Banana Drop Final
        Timer.scheduledTimer(withTimeInterval: 1, repeats: true, block: { [weak self] timer in
            self?.timer = timer
            self?.timerTime()
        })
    }
    //Stop droping bananas
    deinit {
        self.timer?.invalidate()
    }
    func timerTime() {
        bananaDrop()
    }
    override func didMove(to view: SKView) {
        print("- Debug: Game Scene Loaded -")
        bDropF() //Calls banana drop
        if let setupBG:SKSpriteNode = self.childNode(withName: "bg") as? SKSpriteNode {
            bg = setupBG
            bg.name = "bg"
            bg.physicsBody?.affectedByGravity = false
            bg.zPosition = -1
        }
        func didBeginContact(_ contact: SKPhysicsContact){ //Banana Collect
            if let firstNode = contact.bodyA.node as? SKSpriteNode, let secondNode = contact.bodyB.node as? SKSpriteNode {

                let object1: String = firstNode.name!
                let object2: String = secondNode.name!

                if (object1 == "player") || (object2 == "banana") {
                    print("colliding!")
                }
            }
        }
        //Player Definitions
        if let randoPlayer:SKSpriteNode = self.childNode(withName: "player") as? SKSpriteNode { //Test for Char type
            activePlayer = randoPlayer      //Char Set
            activePlayer.physicsBody?.isDynamic = true     //Set dynamic
            activePlayer.physicsBody?.affectedByGravity = true     //Set dynamic gravity
            activePlayer.name = "player"
            print("Player Initiated")
            print("Physics set :: Dynamic(true):AffectedByGravity(true)")
        } else {
            print("Failed to initiate player")
        }
    }
    func moveActivePlayerR() {//Right Touch Player Movements Defined
        let walkAnimation:SKAction = SKAction(named: "WalkRight")!
        let moveAction:SKAction = SKAction.moveBy(x: 100, y: 0, duration: 0.5) //Move Right Side
        //let moveRight:SKAction = SKAction.group([walkAnimation, moveAction]) //Depricated
        let sound = SKAction.playSoundFileNamed("walk.wav", waitForCompletion: false)

        let finalWalkR:SKAction = SKAction.group([walkAnimation, moveAction, sound])

        activePlayer.run(finalWalkR)
    }
    func moveActivePlayerL() { //Left Touch Player Movements Defined
        let walkAnimation:SKAction = SKAction(named: "WalkLeft")!
        let moveAction:SKAction = SKAction.moveBy(x: -100, y: 0, duration: 0.5) //Move Left Side
        //let moveRight:SKAction = SKAction.group([walkAnimation, moveAction]) //Depricated
        let sound = SKAction.playSoundFileNamed("walk.wav", waitForCompletion: false)

        let finalWalkL:SKAction = SKAction.group([moveAction, sound, walkAnimation])

        activePlayer.run(finalWalkL)
    }
    func touchDown(atPoint pos : CGPoint) {
        print("touch \( pos.x),\(pos.y)") //Debug print
        if(pos.x > 0) { //if touched right side of screen
            print("Right touch")
            moveActivePlayerR()
        } else if (pos.x < 0) { //if touched left side of screen
            print("Left touch")
            moveActivePlayerL()
        }
    }
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

        for t in touches {
            self.touchDown(atPoint: t.location(in: self))
        }
    }
}

然而,即使设置了这些类别,我仍然无法让它们正常碰撞。当他们互相接触时,我的控制台中没有任何东西表明他们已经相撞。请帮忙!

1 个答案:

答案 0 :(得分:1)

您无需设置collisionBitMask即可检测联系,您只需将contactTestBitMask设置为要检测碰撞的障碍物的类别即可。然后,在didBegin函数中检查冲突。确保您在场景中设置了SKPhysicsContactDelegate

class GameScene: SKScene, SKPhysicsContactDelegate

self.physicsWorld.contactDelegate = self
设置对象时

//categoryBitMask is what the physics category of the object is    
object.physicsBody!.categoryBitMask = playerCategory
//collisionBitMask is what the physics category of objects that this cannot pass through are...multiple categories would be typed like... `cat1 | cat2`    
object.physicsBody!.collisionBitMask = 0
//contactTestBitMask is what the physics category of the objects that we get alerted to upon contact
object.physicsBody!.contactTestBitMask = obstacleCategory

你场景中的didBegin func

func didBeginContact(_ contact: SKPhysicsContact) {

    if let firstNode = contact.bodyA.node as? SKSpriteNode, let secondNode = contact.bodyB.node as? SKSpriteNode {

        let object1: String = firstNode.name!
        let object2: String = secondNode.name!

        if (object1 == "obstacle") || (object2 == "obstacle") {
            //run some code because these 2 have collided
        }
    }
}

...或...

func didBeginContact(_ contact: SKPhysicsContact) {

    if contact.bodyA.categoryBitMask == PhysicsCategory.obstacleCategory || contact.bodyB.categoryBitMask == PhysicsCategory.obstacleCategory {
        //obstacle has hit player do something
    }
}