如何使两种不同的碰撞发生不同的事情?

How to make two different collisions which makes different things happen?

我制作了一个游戏,其中的基础知识是,如果一个精灵节点与我松开的墙碰撞,如果它与一个单独的节点(Ball2)碰撞,你就会赢。我已经做了如何检测让你输掉比赛的碰撞,但不是当 Ball 与 ball2 碰撞时。所以我的问题是如何进行两种不同的碰撞,从而使不同的事情发生? 我真的很想得到一些帮助,谢谢

    struct PhysicsCategogy {
static let Ball : UInt32 = 0x1 << 1
static let Ball2 : UInt32 = 0x1 << 1
static let WallH : UInt32 = 0x1 << 2
static let WallH2 : UInt32 = 0x1 << 3
}

class GameScene: SKScene, SKPhysicsContactDelegate {

var Ball = SKSpriteNode(imageNamed: "Ball")
var Ball2 = SKSpriteNode(imageNamed: "Ball")
var WallH = SKSpriteNode(imageNamed: "WallH")


override func didMoveToView(view: SKView) {

    self.view?.paused = false

    self.physicsWorld.gravity = CGVector(dx: 0, dy: 0)
    self.physicsWorld.contactDelegate = self

    Ball.position = CGPointMake(self.frame.width / 2 - 450, self.frame.height / 2)
    Ball.setScale(0.5)
    Ball.physicsBody = SKPhysicsBody(rectangleOfSize: Ball.size)
    Ball.physicsBody?.affectedByGravity = false
    Ball.physicsBody?.dynamic = true
    Ball.physicsBody?.contactTestBitMask = PhysicsCategogy.Ball
    Ball.physicsBody?.collisionBitMask = 0
    Ball.physicsBody?.collisionBitMask = 2
    addChild(Ball)

    Ball2.position = CGPointMake(self.frame.width / 2 + 450, self.frame.height / 2)
    Ball2.setScale(0.5)
    Ball2.physicsBody = SKPhysicsBody(rectangleOfSize: Ball.size)
    Ball2.physicsBody?.affectedByGravity = false
    Ball2.physicsBody?.dynamic = true
    Ball2.physicsBody?.contactTestBitMask = PhysicsCategogy.Ball2
    Ball2.physicsBody?.collisionBitMask = 1

    addChild(Ball2)


    WallH.position = CGPointMake(self.frame.width / 2,   self.frame.height / 2 + 190)
    WallH.setScale(7.5)
    WallH.physicsBody = SKPhysicsBody(rectangleOfSize: WallH.size)
    WallH.physicsBody?.affectedByGravity = false
    WallH.physicsBody?.contactTestBitMask = PhysicsCategogy.WallH
    WallH.physicsBody?.collisionBitMask = 0

    self.addChild(WallH)

}

func didBeginContact(contact: SKPhysicsContact) {
    self.backgroundColor = SKColor.whiteColor()
    self.view?.paused = true

    }
}

您需要有一些对所有 "collidable" 对象通用的字段,在这种情况下,包括墙和球,可以充当类型标识符。然后,当您处理碰撞时,您需要使用 "if it's a wall, do stuff for losing, else if it's a ball, do stuff for winning"

条件检查该字段

您的代码中有很多地方是错误的...首先,您必须清除您的项目中的拼写错误和冗余代码,例如,这是没有意义的:

Ball.physicsBody?.collisionBitMask = 0  //Remove it
Ball.physicsBody?.collisionBitMask = 2

现在让我们从头开始。您错误地设置了物理类别。你想要这样的东西:

struct PhysicsCategory {
        static let Ball     : UInt32 = 1 << 0         //1
        static let Ball2    : UInt32 = 1 << 1         //2
        static let WallH    : UInt32 = 1 << 2         //4
        static let WallH2   : UInt32 = 1 << 3         //8
    }

接下来是如何正确设置类别、碰撞和接触位掩码。你不想要这个:

Ball.physicsBody?.contactTestBitMask = PhysicsCategory.Ball

这没有意义,因为屏幕上只有一个 Ball 实例。您想要检测 BallBall2 之间的联系人,如下所示:

Ball.physicsBody?.contactTestBitMask = PhysicsCategory.Ball2

所以让我们正确设置所有内容(请注意,您根本没有设置 Ball 的 categoryBitMask):

Ball.physicsBody?.categoryBitMask = PhysicsCategory.Ball
Ball.physicsBody?.contactTestBitMask = PhysicsCategory.Ball2
Ball.physicsBody?.collisionBitMask = PhysicsCategory.Ball2

这里您将 Ball 的类别设置为 PhysicsCategory.Ball,并将其接触和碰撞位掩码设置为 PhysicsCategory.Ball2。您这样做是因为您想要检测接触并使这两个物体之间发生碰撞。同样适用于 Ball2:

Ball2.physicsBody?.categoryBitMask = PhysicsCategogy.Ball2
Ball2.physicsBody?.contactTestBitMask = PhysicsCategogy.Ball
Ball2.physicsBody?.collisionBitMask = PhysicsCategogy.Ball

您也可以将相同的逻辑应用于墙壁。例如,如果你想让球和墙发生碰撞,但你不想在碰撞发生时注册接触(意思是,你不想 didBeginContact 被调用),你会做这样的事情(假设 categoryBitMask 为每个 body 设置正确):

//You don't want to register contacts between Ball and a WallH
Ball.physicsBody?.contactTestBitMask = PhysicsCategory.Ball2

//But still, you want collisions with Ball2 and a WallH
Ball.physicsBody?.collisionBitMask = PhysicsCategory.Ball2 | PhysicsCategory.WallH

//You don't want to register contacts between Ball2 and a WallH
Ball2.physicsBody?.contactTestBitMask = PhysicsCategory.Ball

//But still, you want collisions with Ball and a WallH
Ball2.physicsBody?.collisionBitMask = PhysicsCategory.Ball | PhysicsCategory.WallH

WallH.physicsBody?.collisionBitMask = PhysicsCategory.Ball | PhysicsCategory.Ball2

请确保您理解术语 接触碰撞 之间的区别。即使禁用碰撞 (collisionBitMask = 0) 也可能发生接触,反之亦然。这取决于您如何设置 contact/collision 位掩码。你可以在 SpriteKit 中选择你想要使用的物理引擎部分。接触检测、物理模拟或两者兼而有之。如果您对接触检测不感兴趣,由于性能原因,您不应该设置接触掩码。

最后,要处理联系人,你可以使用这样的东西:

func didBeginContact(contact: SKPhysicsContact) {

var firstBody, secondBody: SKPhysicsBody

if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask {

   firstBody = contact.bodyA
   secondBody = contact.bodyB
} else {

    firstBody = contact.bodyB
    secondBody = contact.bodyA
}


if ((firstBody.categoryBitMask & PhysicsCategory.Ball) != 0 &&
   (secondBody.categoryBitMask & PhysicsCategory.Ball2 != 0)) {

    //firstBody is a Ball
    //secondBody is a Ball2

    print ("Detected contact between Ball and a Ball2")

   }

}

如果您想更多地了解代码的某些部分,例如 self.physicsWorld.contactDelegate = self 的作用或 didBeginContact 的调用方式,请查看 。 对于我刚刚为您所写内容的稍微不同的实现,但这是如何完成同一件事的一个很好的例子,请查看 this.

但最后,官方 docs 始终是一个很好的起点,或者如果您不确定任何事情可以回来。