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

时间:2016-01-03 22:42:38

标签: ios swift sprite-kit sprite

我制作了一个基础知识的游戏,如果一个精灵节点与一个墙壁发生碰撞我会失败,如果它与一个单独的节点(Ball2)相撞,你就会赢。我已经制定了如何检测碰撞,这会让你输掉比赛,但是当球与球2碰撞时却没有。所以我的问题是如何进行两种不同的碰撞,使不同的事情发生? 我真的很想得到一些帮助,谢谢

    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

    }
}

2 个答案:

答案 0 :(得分:3)

你的代码中有很多东西是错误的......首先,你必须从拼写错误和冗余代码中清理你的项目,例如这没有意义:

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):

//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),也可能发生联系,反之亦然。这取决于您如何设置接触/碰撞位掩码。你可以在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 = selfdidBeginContact的调用方式,请查看this。 对于我刚刚为您写的内容有点不同的实现,但是如何完成相同的事情的一个很好的例子,请看看this

但最后,官方docs总是一个好的开始,或者如果你不确定任何事情就回来。

答案 1 :(得分:1)

你需要有一些对于所有可以碰撞的对象都是通用的字段,在这种情况下,可以作为类型标识符的墙和球。然后,当您处理碰撞时,您需要检查该字段是否有条件说明&#34;如果它是墙,做丢失的东西,否则如果它是一个球,做获胜的东西&#34;