如何检测Sprite Kit中的碰撞?

时间:2016-01-25 22:21:43

标签: ios swift sprite-kit

我正在尝试在角色接触时删除一个对象(一个orb节点),但它只是像一个圆圈一样,当它到达顶部时角色会掉落。我删除了碰撞检测的代码,因为我不知道它是否正确。

这是我的GameScene.swift代码:

import SpriteKit

class GameScene: SKScene, SKPhysicsContactDelegate {
override init(size:CGSize){
    super.init(size:size)

    let CollisionCategoryPlayer
    : UInt32 = 0x1 << 1

    let CollisionCategoryPowerUpOrbs
    : UInt32 = 0x1 << 2

    character.physicsBody?.categoryBitMask = CollisionCategoryPlayer
    character.physicsBody?.contactTestBitMask = CollisionCategoryPowerUpOrbs
    character.physicsBody?.collisionBitMask = 0

    orbNode.physicsBody?.categoryBitMask = CollisionCategoryPowerUpOrbs
    orbNode.physicsBody?.collisionBitMask = 0
}

required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
}

//variables
let character = SKSpriteNode(imageNamed:"square_red.png")
let floor = SKSpriteNode(imageNamed: "platform.jpg")
let platform1 = SKSpriteNode(imageNamed: "platform2.png")
let platform2 = SKSpriteNode(imageNamed: "platform2.png")
let orbNode = SKSpriteNode(imageNamed: "PowerUp.png")
var characterSize:CGFloat = 0.2
var foodCount = 0

override func didMoveToView(view: SKView) {
    //World Physics
    self.physicsWorld.gravity = CGVectorMake(0.0, -5.0)
    self.physicsWorld.contactDelegate = self
    self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)
    //Character
    character.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
    character.setScale(characterSize)
    character.physicsBody = SKPhysicsBody(rectangleOfSize: character.size)
    character.physicsBody?.allowsRotation = false
    self.addChild(character)
    //floor
    floor.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)*0.2)
    floor.setScale(2.0)
    floor.physicsBody = SKPhysicsBody(rectangleOfSize: floor.size)
    floor.physicsBody?.dynamic = false
    self.addChild(floor)

    //platform one
    platform1.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)*0.7)
    platform1.setScale(0.4)
    platform1.physicsBody = SKPhysicsBody(rectangleOfSize: platform1.size)
    platform1.physicsBody?.dynamic = false
    self.addChild(platform1)

    //platform two
    platform2.position = CGPoint(x: CGRectGetMidX(self.frame)*1.4, y: CGRectGetMidY(self.frame)*1)
    platform2.setScale(0.4)
    platform2.physicsBody = SKPhysicsBody(rectangleOfSize: platform2.size)
    platform2.physicsBody?.dynamic = false
    self.addChild(platform2)

    //orbNode
    orbNode.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
    orbNode.setScale(0.2)
    self.addChild(orbNode)
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    character.removeActionForKey("moveAction")
    character.removeActionForKey("shrink")
    character.removeActionForKey("rotate")
}

    override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    for touch:AnyObject in touches {
        let location = touch.locationInNode(self)

        if location.x < CGRectGetMidX(self.frame) && location.y < CGRectGetMidY(self.frame)*0.7{
            //shrinks with each movement
            characterSize-=0.005
           let moveAction = SKAction.repeatActionForever(SKAction.moveByX(-30, y: 0, duration: 0.1))
            let shrink = SKAction.repeatActionForever(SKAction.scaleTo(characterSize, duration: 0.1))
             character.runAction(moveAction, withKey: "moveAction")
            character.runAction(shrink, withKey: "shrink")
        } else if location.x > CGRectGetMidX(self.frame) && location.y < CGRectGetMidY(self.frame)*0.7{
            //shrinks with each movement
            characterSize-=0.005
            let moveAction = SKAction.repeatActionForever(SKAction.moveByX(30, y: 0, duration: 0.1))
            let shrink = SKAction.repeatActionForever(SKAction.scaleTo(characterSize, duration: 0.1))
            character.runAction(moveAction, withKey: "moveAction")
            character.runAction(shrink, withKey: "shrink")
        } else if location.y > character.position.y + 15  {
            //shrinks with each movement
            characterSize-=0.005
            character.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 50))
            let shrink = SKAction.repeatActionForever(SKAction.scaleTo(characterSize, duration: 0.1))
            character.runAction(shrink, withKey: "shrink")
                        }
    }

    func didBeginContact(contact: SKPhysicsContact){

    }
func update(currentTime: CFTimeInterval) {
/* Called before each frame is rendered */

        }

}
}

1 个答案:

答案 0 :(得分:0)

你应该对你的物理团体进行分组,你的代码似乎到处都是。你得到错误的原因也是因为你在设置玩家之前设置了物理体,并且错过了一些Orbs。

这是相同的代码重写,我认为更具可读性和可理解性。

import SpriteKit

/// Physics category
struct PhysicsCategory {
    static let player: UInt32 = 0x1 << 0
    static let orb: UInt32 = 0x1 << 1
    static let floor: UInt32 = 0x1 << 2
    static let platform: UInt32 = 0x1 << 3
 }

/// Image names
struct ImageName {
     static let platform1 = "platform2.png"
     static let platform2 = "platform2.png"

     // can do this for other images as well, but because you create loads of platforms its nice to have a refernce like this
}

  /// Always put your keys for removing actions etc into structs to avoid typos
 struct Key {
    static let moveAction = "moveAction"
    static let shrink = "shrink"
    static let rotate = "rotate"
  }

 /// GameScene
 class GameScene: SKScene, SKPhysicsContactDelegate {

//variables
let character = SKSpriteNode(imageNamed:"square_red.png")
let floor = SKSpriteNode(imageNamed: "platform.jpg")
var platform1 = SKSpriteNode()
var platform2 = SKSpriteNode()
let orbNode = SKSpriteNode(imageNamed: "PowerUp.png")
var characterSize:CGFloat = 0.2
var foodCount = 0

//didMoveToView
override func didMoveToView(view: SKView) {

    //World Physics
    self.physicsWorld.gravity = CGVectorMake(0.0, -5.0)
    self.physicsWorld.contactDelegate = self
    self.physicsBody = SKPhysicsBody(edgeLoopFromRect: self.frame)

    //Character
    character.position = CGPoint(x:CGRectGetMidX(self.frame), y:CGRectGetMidY(self.frame))
    character.setScale(characterSize)
    character.physicsBody = SKPhysicsBody(rectangleOfSize: character.size)
    character.physicsBody?.allowsRotation = false
    character.physicsBody?.dynamic = true // must be true for collision to fire
    character.physicsBody?.affectedByGravity = false
    character.physicsBody?.categoryBitMask = PhysicsCategory.player
    character.physicsBody?.contactTestBitMask = PhysicsCategory.orb
    character.physicsBody?.collisionBitMask = PhysicsCategory.floor | PhysicsCategory.platform
    self.addChild(character)

    //floor
    floor.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)*0.2)
    floor.setScale(2.0)
    floor.physicsBody = SKPhysicsBody(rectangleOfSize: floor.size)
    floor.physicsBody?.dynamic = false
    floor.physicsBody?.affectedByGravity = false
    floor.physicsBody?.categoryBitMask = PhysicsCategory.floor
    ///floor.physicsBody?.contactTestBitMask = not needed for now as character is set
    ///floor.physicsBody?.collisionBitMask =  not needed for now as character is set

    self.addChild(floor)

    //platform one
    platform1 = createPlatform(ImageName.platform1)
    platform1.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame)*0.7)
    platform1.setScale(0.4)
    self.addChild(platform1)

    //platform two
    platform2 = createPlatform(ImageName.platform2)
    platform2.position = CGPoint(x: CGRectGetMidX(self.frame)*1.4, y: CGRectGetMidY(self.frame)*1)
    platform2.setScale(0.4)
    self.addChild(platform2)

    //orbNode
    orbNode.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
    orbNode.setScale(0.2)
    orbNode.physicsBody = SKPhysicsBody(rectangleOfSize: character.size)
    orbNode.physicsBody?.allowsRotation = false
    orbNode.physicsBody?.dynamic = false
    orbNode.physicsBody?.affectedByGravity = false
    orbNode.physicsBody?.categoryBitMask = PhysicsCategory.orb
    //orbNode.physicsBody?.contactTestBitMask = // not needed for now because pla
    orbNode.physicsBody?.collisionBitMask = PhysicsCategory.platform //
    self.addChild(orbNode)
}

/// Create platform (this way you can crate multiple platforms and save yourself tones of code)
func createPlatform(imageNamed: String) -> SKSpriteNode {
    let platform = SKSpriteNode(imageNamed: imageNamed)
    platform.physicsBody = SKPhysicsBody(rectangleOfSize: platform.size)
    platform.physicsBody?.dynamic = false
    platform.physicsBody?.affectedByGravity = false
    platform.physicsBody?.categoryBitMask = PhysicsCategory.platform
    //platform.physicsBody?.contactTestBitMask =  /// not needed unless you want didBeginContact
    platform.physicsBody?.collisionBitMask = 0 /// Not needed if you tell character to collide with it
    return platform
}

override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    character.removeActionForKey(Key.moveAction)
    character.removeActionForKey(Key.shrink)
    character.removeActionForKey(Key.rotate)
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    for touch in touches {
        let location = touch.locationInNode(self)

        if location.x < CGRectGetMidX(self.frame) && location.y < CGRectGetMidY(self.frame)*0.7{
            //shrinks with each movement
            characterSize-=0.005
            let moveAction = SKAction.repeatActionForever(SKAction.moveByX(-30, y: 0, duration: 0.1))
            let shrink = SKAction.repeatActionForever(SKAction.scaleTo(characterSize, duration: 0.1))
            character.runAction(moveAction, withKey: Key.moveAction)
            character.runAction(shrink, withKey: Key.shrink)
        } else if location.x > CGRectGetMidX(self.frame) && location.y < CGRectGetMidY(self.frame)*0.7{
            //shrinks with each movement
            characterSize-=0.005
            let moveAction = SKAction.repeatActionForever(SKAction.moveByX(30, y: 0, duration: 0.1))
            let shrink = SKAction.repeatActionForever(SKAction.scaleTo(characterSize, duration: 0.1))
            character.runAction(moveAction, withKey: Key.moveAction)
            character.runAction(shrink, withKey: Key.shrink)
        } else if location.y > character.position.y + 15  {
            //shrinks with each movement
            characterSize-=0.005
            character.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 50))
            let shrink = SKAction.repeatActionForever(SKAction.scaleTo(characterSize, duration: 0.1))
            character.runAction(shrink, withKey: Key.shrink)
        }
    }
 }

 func didBeginContact(contact: SKPhysicsContact){

      var firstBody: SKPhysicsBody
      var secondBody: SKPhysicsBody

     if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {
           firstBody = contact.bodyA
           secondBody = contact.bodyB
        } else {
            firstBody = contact.bodyB
            secondBody = contact.bodyA
        }

       /// Player with Orb
       if (firstBody.categoryBitMask == PhysicsCategory.player) && (secondBody.categoryBitMask == PhysicsCategory.orb) {

            ///Player hit orb, remove Orb 
            secondBody.node?.removeFromParent()
       }
    }

    override func update(currentTime: CFTimeInterval) {
        /* Called before each frame is rendered */

     }

 }