Swift:在节点之间接触时执行命令



现在,我有一块砖从屏幕上掉了下来。当它击中我的广场时,什么也没发生。正如你在下面的图片中看到的,我有四个三角形,在同一个地方组成了一个正方形,但不透明度很低。这有助于区分接触的是正方形的哪一边。然而,当砖块击中三角形(组成正方形的三角形(时,没有重生者或亡命者获胜

游戏图片

func spawnBrick()  {
let randomFunc = [self.spawnbrickTop, self.spawnbrickBottom, self.spawnbrickLeft, self.spawnbrickRight]
let randomResult = Int(arc4random_uniform(UInt32(randomFunc.count)))
randomFunc[randomResult]()
}

func spawnbrickTop() {
brickTop.size = CGSize(width: 210, height: 105)
brickTop.name = "BrickTop"
brickTop.position = CGPoint(x: frame.midX, y: frame.maxY)
brickTop.zPosition = 1.5
//physics stuff begins here
brickTop.physicsBody = SKPhysicsBody(circleOfRadius: max(brickTop.size.width / 2,
brickTop.size.height / 2))
brickTop.physicsBody?.categoryBitMask = PhysicsCategories.brickTopCategory
brickTop.physicsBody?.contactTestBitMask = PhysicsCategories.basicTopCategory |
PhysicsCategories.basicBottomCategory |
PhysicsCategories.basicLeftCategory |
PhysicsCategories.basicRightCategory
brickTop.physicsBody?.collisionBitMask = PhysicsCategories.none
//bye bye physics
self.addChild(brickTop)
}
func spawnbrickBottom() {
brickBottom.size = CGSize(width: 230, height: 101)
brickBottom.name = "BrickBottom"
brickBottom.position = CGPoint(x: frame.midX, y: frame.maxY)
brickBottom.zPosition = 1.5
//physics stuff begins here
brickBottom.physicsBody = SKPhysicsBody(circleOfRadius: max(brickBottom.size.width / 2,
brickBottom.size.height / 2))
brickBottom.physicsBody?.categoryBitMask = PhysicsCategories.brickBottomCategory
brickBottom.physicsBody?.contactTestBitMask = PhysicsCategories.basicTopCategory |
PhysicsCategories.basicBottomCategory |
PhysicsCategories.basicLeftCategory |
PhysicsCategories.basicRightCategory
brickBottom.physicsBody?.collisionBitMask = PhysicsCategories.none
//bye bye physics
self.addChild(brickBottom)
}
func spawnbrickLeft() {

brickLeft.size = CGSize(width: 170, height: 80)
brickLeft.name = "BrickLeft"
brickLeft.position = CGPoint(x: frame.midX, y: frame.maxY)
brickLeft.zPosition = 1.5
//physics stuff begins here
brickLeft.physicsBody = SKPhysicsBody(circleOfRadius: max(brickLeft.size.width / 2,
brickLeft.size.height / 2))
brickLeft.physicsBody?.categoryBitMask = PhysicsCategories.brickLeftCategory
brickLeft.physicsBody?.contactTestBitMask = PhysicsCategories.basicTopCategory |
PhysicsCategories.basicBottomCategory |
PhysicsCategories.basicLeftCategory |
PhysicsCategories.basicRightCategory
brickLeft.physicsBody?.collisionBitMask = PhysicsCategories.none
//bye bye physics
self.addChild(brickLeft)
}

func spawnbrickRight() {
brickRight.size = CGSize(width: 140, height: 95)
brickRight.name = "BrickRight"
brickRight.position = CGPoint(x: frame.midX, y: frame.maxY)
brickRight.zPosition = 1.5
//physics stuff begins here
brickRight.physicsBody = SKPhysicsBody(circleOfRadius: max(brickRight.size.width / 2,
brickRight.size.height / 2))
brickRight.physicsBody?.categoryBitMask = PhysicsCategories.brickRightCategory
brickRight.physicsBody?.contactTestBitMask = PhysicsCategories.basicTopCategory |
PhysicsCategories.basicBottomCategory |
PhysicsCategories.basicLeftCategory |
PhysicsCategories.basicRightCategory
brickRight.physicsBody?.collisionBitMask = PhysicsCategories.none
//bye bye physics
self.addChild(brickRight)
}

func spawnBasicBrick() {
basicBrick.size = CGSize(width: 200, height: 177.6)
basicBrick.position = CGPoint(x: frame.midX, y: frame.minY + basicBrick.size.width)
basicBrick.zPosition = 1

basicBrick.physicsBody = SKPhysicsBody(rectangleOf: basicBrick.size)
basicBrick.physicsBody?.categoryBitMask = PhysicsCategories.basicBrickCategory
basicBrick.physicsBody?.isDynamic = false
basicBrick.physicsBody?.allowsRotation = true
addChild(basicBrick)
}
func spawnBasicTop() {
basicTop.size = CGSize(width: 400, height: 400)
basicTop.position = CGPoint(x: 230, y: 200)
basicTop.zPosition = 1.5
basicTop.alpha = 0.3
basicTop.name = "BasicTop"
//physics stuff begins here
basicTop.physicsBody = SKPhysicsBody(rectangleOf: basicTop.size)
basicTop.physicsBody?.categoryBitMask = PhysicsCategories.basicTopCategory
basicTop.physicsBody?.isDynamic = false
basicTop.physicsBody?.allowsRotation = true
//bye bye physics

addChild(basicTop)
}
func spawnBasicBottom() {
basicBottom.size = CGSize(width: 400, height: 400)
basicBottom.position = CGPoint(x: 230, y: 200)
basicBottom.zPosition = 1.5
basicBottom.alpha = 0.3
basicBottom.name = "BasicBottom"
//physics stuff begins here
basicBottom.physicsBody = SKPhysicsBody(rectangleOf: basicBottom.size)
basicBottom.physicsBody?.categoryBitMask = PhysicsCategories.basicBottomCategory
basicBottom.physicsBody?.isDynamic = false
//bye bye physics

addChild(basicBottom)
}
func spawnBasicLeft() {
basicLeft.size = CGSize(width: 400, height: 400)
basicLeft.position = CGPoint(x: 230, y: 200)
basicLeft.zPosition = 1.5
basicLeft.alpha = 0.3
basicLeft.name = "BasicLeft"
//physics stuff begins here
basicLeft.physicsBody = SKPhysicsBody(rectangleOf: basicLeft.size)
basicLeft.physicsBody?.categoryBitMask = PhysicsCategories.basicLeftCategory
basicLeft.physicsBody?.isDynamic = false
//bye bye physics

addChild(basicLeft)
}
func spawnBasicRight() {
basicRight.size = CGSize(width: 400, height: 400)
basicRight.position = CGPoint(x: 230, y: 200)
basicRight.zPosition = 1.5
basicRight.alpha = 0.3
basicRight.name = "BasicRight"
//physics stuff begins here
basicRight.physicsBody = SKPhysicsBody(rectangleOf: basicRight.size)
basicRight.physicsBody?.categoryBitMask = PhysicsCategories.basicRightCategory
basicRight.physicsBody?.isDynamic = false
//bye bye physics

addChild(basicRight)
}

extension GameScene: SKPhysicsContactDelegate {
func didBegin(_ contact: SKPhysicsContact) {
//01
//10
//11
let contactMask = contact.bodyA.categoryBitMask |
contact.bodyB.categoryBitMask
if contactMask == PhysicsCategories.brickTopCategory |
(PhysicsCategories.basicTopCategory) {
if let brickTop = contact.bodyA.node?.name == "BrickTop" ? contact.bodyA.node
as? SKSpriteNode : contact.bodyB.node as? SKSpriteNode {
if contact.bodyA.node?.name == "BrickTop" &&
contact.bodyB.node?.name == "BasicTop" {
print("Correct!")
brickTop.run(SKAction.fadeOut(withDuration: 0.05), completion: {
self.brickTop.removeFromParent()
self.spawnBrick()
})
}
}
else if contactMask == PhysicsCategories.brickBottomCategory |
(PhysicsCategories.basicBottomCategory) {
if let brickBottom = contact.bodyA.node?.name == "BrickBottom" ? contact.bodyA.node
as? SKSpriteNode : contact.bodyB.node as? SKSpriteNode {
if contact.bodyA.node?.name == "BrickBottom" &&
contact.bodyB.node?.name == "BasicBottom" {
print("Correct!")
brickBottom.run(SKAction.fadeOut(withDuration: 0.05), completion: {
self.brickBottom.removeFromParent()
self.spawnBrick()
})
}
}
else if contactMask == PhysicsCategories.brickLeftCategory |
(PhysicsCategories.basicLeftCategory) {
if let brickLeft = contact.bodyA.node?.name == "BrickLeft" ? contact.bodyA.node
as? SKSpriteNode : contact.bodyB.node as? SKSpriteNode {
if contact.bodyA.node?.name == "BrickLeft" &&
contact.bodyB.node?.name == "BasicLeft" {
print("Correct!")
brickLeft.run(SKAction.fadeOut(withDuration: 0.05), completion: {
self.brickLeft.removeFromParent()
self.spawnBrick()
})
}
}
else if contactMask == PhysicsCategories.brickRightCategory |
(PhysicsCategories.basicRightCategory) {
if let brickRight = contact.bodyA.node?.name == "BrickRight" ? contact.bodyA.node
as? SKSpriteNode : contact.bodyB.node as? SKSpriteNode {
if contact.bodyA.node?.name == "BrickRight" &&
contact.bodyB.node?.name == "BasicRight" {
print("Correct!")
brickRight.run(SKAction.fadeOut(withDuration: 0.05), completion: {
self.brickRight.removeFromParent()
self.spawnBrick()
})
}
}
else {
gameOver()
}
}
}
}
}
}
}

enum PhysicsCategories {
static let none: UInt32 = 0
static let brickCategory: UInt32 = 1//01
static let brickTopCategory: UInt32 = 1 //01
static let brickBottomCategory: UInt32 = 1//01
static let brickLeftCategory: UInt32 = 1//01
static let brickRightCategory: UInt32 = 1//01
static let basicTopCategory: UInt32 = 1 //10; shifts all bits to the left
static let basicBottomCategory: UInt32 = 1 //10; shifts all bits to the left
static let basicLeftCategory: UInt32 = 1 //10; shifts all bits to the left
static let basicRightCategory: UInt32 = 1 //10; shifts all bits to the left
static let basicBrickCategory: UInt32 = 1
}

问题可能出现在以下行中:

brickTop.physicsBody?.contactTestBitMask = PhysicsCategories.basicTopCategory
brickTop.physicsBody?.contactTestBitMask = PhysicsCategories.basicBottomCategory
brickTop.physicsBody?.contactTestBitMask = PhysicsCategories.basicLeftCategory
brickTop.physicsBody?.contactTestBitMask = PhysicsCategories.basicRightCategory

在这个代码中,接触位掩码最终只是basicRight。你想把它们结合起来。这是假设您正确设置了类别,以开头(如1、2、4、8等(

你希望它更像这样:


brickTop.physicsBody?.contactTestBitMask = PhysicsCategories.basicTopCategory |
PhysicsCategories.basicBottomCategory |
PhysicsCategories.basicLeftCategory |
PhysicsCategories.basicRightCategory

以下是的工作原理

  1. 场景中有一堆节点
  2. 您将它们分组为具有类似行为的类别
  3. 您为每个类别创建一个类别枚举/值,作为掩码(1、2、4等(中的一个位,即(0x1<<0、0x1<
  4. 将节点放入类别中(使用|组合类别值(
  5. 设置contactTest和collisionDetect位掩码(使用|组合类别值(

我不知道你的游戏应该如何工作,但你的代码有一些奇怪的地方。

  1. 不同类别使用相同的数字
  2. 你不能把它们组合成比特掩码

想象一下我有Pong游戏。我想检测球何时击中

  1. 反弹的侧壁
  2. 屏幕的顶部和底部记录输出
  3. 划桨使它弹跳

节点

  1. 左墙
  2. 右侧墙
  3. 底部
  4. 顶部
  5. 顶部桨叶
  6. 底部桨叶
  7. 玩家1分
  8. 玩家2得分

Categories(这只是一个例子,不是唯一的方法(

  1. 类别无:0
  2. 类别GamePiece:1
  3. 类别OutDetector:2
  4. 类别非交互式:4(用于分数节点(

球从球拍和侧壁上弹开。它还与顶部和底部的不可见外部探测器相互作用。它分为两类(使用|(

ball.categoryBitMask = CategoryGamePiece | CategoryOutDetector
ball.collisionBitMask = CategoryGamePiece
ball.contactTestBitMask = CategoryOutDetector

球拍和侧墙仅作为棋子(碰撞(与球相互作用

paddleTop.categoryBitMask = CategoryGamePiece
paddleTop.collisionBitMask = CategoryGamePiece
paddleTop.contactTestBitMask = CategoryNone
leftWall.categoryBitMask = CategoryGamePiece
leftWall.collisionBitMask = CategoryGamePiece
leftWall.contactTestBitMask = CategoryNone

底部只与球进行接触测试(不会改变其运动(

bottomOut.categoryBitMask = CategoryOutDetector
bottomOut.collisionBitMask = CategoryNone
bottomOut.contactTestBitMask = CategoryOutDetector

最新更新