SpriteKit中的碰撞

时间:2016-03-31 05:12:34

标签: ios swift sprite-kit

我有一个对象保持在两个栏之间。我设置了碰撞,但是当我与顶部或底部杆接触时我没有得到打印消息“我们有联系”,我不知道为什么?我认为这可能与边界物理学有关。下图是给出条形图的示例,其中对象保留在它们之间。enter image description here

     var gameOver = false



override func didMoveToView(view: SKView) {
    scene?.scaleMode = SKSceneScaleMode.AspectFill


    self.physicsWorld.gravity = CGVectorMake(0.0, 2.0)
    physicsWorld.contactDelegate = self

    object = SKSpriteNode( imageNamed: "object")
    object.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
    object.physicsBody = SKPhysicsBody(circleOfRadius: object.size.width / 0.32)

    object.physicsBody?.dynamic = true
    object.physicsBody?.allowsRotation = true
    self.addChild(object)
    object.zPosition = 2


    struct ColliderType {

        static let object: UInt32 = 0x1 << 0
        static let boundary: UInt32 = 0x1 << 1


    }
   let boundary = SKPhysicsBody(edgeLoopFromRect: CGRect(x: 253, y: 138, width:515, height:354))
   self.physicsBody = boundary
    self.physicsBody?.friction = 0
    let push = CGVectorMake(10, 10)
   object.physicsBody?.applyImpulse(push)


   object.physicsBody?.categoryBitMask = ColliderType.object
   object.physicsBody?.contactTestBitMask = ColliderType.boundary
   object.physicsBody?.collisionBitMask = ColliderType.boundary


    boundary.contactTestBitMask = ColliderType.object
    boundary.categoryBitMask = ColliderType.boundary
    boundary.collisionBitMask = ColliderType.object


    func didBeginContact(contact:SKPhysicsContact) {
        print("We have Contact")

        gameOver = true
        self.speed = 0

    }

2 个答案:

答案 0 :(得分:2)

在提出问题之前尝试浏览网页和stackoverflow,因为网上有很多教程甚至堆栈溢出。这个问题甚至可能会被关闭,因为碰撞检测是SpriteKit的基础知识之一,并且在SO上已被问到很多。

无论如何,您的代码中存在一些错误/遗漏,所以我们来看看。

1)您需要在场景“didMoveToView”方法中设置物理世界联系委托,以便它实际上正在侦听联系人。这是人们,包括我在内的第一件事,忘记并且不知道为什么没有什么工作。

 physicsWorld.contactDelegate = self

2)你也没有给你的精灵一个物理实体

 object.physicsBody = SKPhysicsBody(...)

你必须先给它们一个物理体,然后设置一些属性,比如contactTestBitMasks等。

3)尝试使用?代替 !在处理选项时避免零崩溃。尽管你知道它不是零,但要尽量做到这一点。所以说

...physicsBody?.contactTestBitMask...

而不是

...physicsBody!.contactTestBitMask...

你有时会这样做,有时候不这样做。

在你当前的代码中,你可能会崩溃,因为对象没有物理实体,但你强行解开它,基本上告诉它它确实有一个物理主体,这很危险。

例如,代码中的那行不应该起作用

 object.physicsBody?.applyImpulse(push)

因为物体上没有物理体,但因为它不是力展开(?)没有任何反应。尝试使用!更改该行!而你应该崩溃。 所以总是使用?处理选项时以及编译器允许的时候。

该行也应该在你之前没有设置对象精灵之后。

4)尝试以不同的方式编写您的物理类别,添加更多类别时,您的方式会很快变得混乱,因为您不能只增加最后一个数字。所以在你的例子中,下一个对撞机类型必须是4,8,16等。

请尝试此操作,只需将最后一个数字递增1。

 struct ColliderType {
    static let object: UInt32 = 0x1 << 0
    static let boundary: UInt32 = 0x1 << 1
    ....
 }

比这样使用

...contactTestBitMask = ColliderType.object
...

您的整个代码应该如下所示

  struct ColliderType {

static let object: UInt32 = 0x1 << 0
static let boundary: UInt32 = 0x1 << 1


 }

  class GameScene: SKScene, SKPhysicsContactDelegate {

var gameOver = false

var object: SKSpriteNode!


override func didMoveToView(view: SKView) {
    scene?.scaleMode = SKSceneScaleMode.AspectFill


    self.physicsWorld.gravity = CGVectorMake(0.0, 2.0)
    physicsWorld.contactDelegate = self

    object = SKSpriteNode( imageNamed: "Spaceship")
    object.zPosition = 2
    object.position = CGPoint(x: CGRectGetMidX(self.frame), y: CGRectGetMidY(self.frame))
    object.physicsBody = SKPhysicsBody(circleOfRadius: object.size.width / 0.32)

    object.physicsBody?.dynamic = true
    object.physicsBody?.allowsRotation = true
    object.physicsBody?.categoryBitMask = ColliderType.object
    object.physicsBody?.contactTestBitMask = ColliderType.boundary
    object.physicsBody?.collisionBitMask = ColliderType.boundary
    self.addChild(object)


    let boundary = SKPhysicsBody(edgeLoopFromRect: CGRect(x: 253, y: 138, width:515, height:354))
    self.physicsBody = boundary
    self.physicsBody?.friction = 0 
    boundary.contactTestBitMask = ColliderType.object
    boundary.categoryBitMask = ColliderType.boundary
    boundary.collisionBitMask = ColliderType.object

    let push = CGVectorMake(10, 10)
    object.physicsBody?.applyImpulse(push)
}


func didBeginContact(contact:SKPhysicsContact) {
    print("We have Contact")

    gameOver = true
    self.speed = 0
    }
 }

希望这有帮助

答案 1 :(得分:0)

您必须确保两个碰撞形状位于同一碰撞空间中,如果它们不在同一空间中,则永远不会调用碰撞检测算法。关于Seed12的注释,这两个对象不需要是一个刚体(physicsBody)来检查它们之间是否存在碰撞。