【问题标题】:collision detection not working fully碰撞检测不能完全工作
【发布时间】:2017-09-06 15:43:49
【问题描述】:
import SpriteKit
import GameplayKit

class GameScene: SKScene, SKPhysicsContactDelegate {
    let balls = [
    SKSpriteNode(imageNamed: "blueball.png"),
    SKSpriteNode(imageNamed: "greenball.png"),
    SKSpriteNode(imageNamed: "realredball.png"),
    ]
let redRectangle = SKSpriteNode(imageNamed: "redrectangle.png")
let blueRectangle = SKSpriteNode(imageNamed: "bluerectangle.png")
let greenRectangle = SKSpriteNode(imageNamed: "greenrectangle.png")

let blueBallCategory :UInt32 = 0x1 << 0
let greenBallCategory :UInt32 = 0x1 << 1
let realRedBallCategory :UInt32 = 0x1 << 2
let redRectangleCategory : UInt32 = 0x1 << 3
let blueRectangleCategory : UInt32 = 0x1 << 4
let greenRectangleCategory : UInt32 = 0x1 << 5

override func didMove(to view: SKView) {
    spawnBallsandRectangles()
    physicsWorld.contactDelegate = self
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    physics()
}
func didBegin(_ 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
    }
    if firstBody.categoryBitMask == blueBallCategory && secondBody.categoryBitMask == blueRectangleCategory {
        print("alive")
        }
    else if firstBody.categoryBitMask == greenBallCategory && secondBody.categoryBitMask == greenRectangleCategory {
        print("alive")
    }
    else if firstBody.categoryBitMask == realRedBallCategory && secondBody.categoryBitMask == redRectangleCategory {
        print("alive")
    }
    else if firstBody.categoryBitMask == blueBallCategory || firstBody.categoryBitMask == greenBallCategory && secondBody.categoryBitMask == redRectangleCategory{
        print("dead")
    }
    else if firstBody.categoryBitMask == realRedBallCategory || firstBody.categoryBitMask == greenBallCategory && secondBody.categoryBitMask == blueRectangleCategory {
        print("dead")
    }
    else if firstBody.categoryBitMask == realRedBallCategory || firstBody.categoryBitMask == blueBallCategory && secondBody.categoryBitMask == greenBallCategory {
    print("dead")
        }
    }


func spawnBallsandRectangles() {
    let ball = balls[Int(arc4random_uniform(UInt32(balls.count)))]
    ball.position = CGPoint(x: -200, y: 250)
    ball.size = CGSize(width: 70, height: 70)
    redRectangle.position = CGPoint(x: 0, y: -600)
    redRectangle.size = CGSize(width: 200, height: 20)
    blueRectangle.position = CGPoint(x: -200, y: -600)
    blueRectangle.size = CGSize(width: 200, height: 20)
    greenRectangle.position = CGPoint(x: 200, y: -600)
    greenRectangle.size = CGSize(width: 200, height: 20)
    self.addChild(ball)
    self.addChild(redRectangle)
    self.addChild(blueRectangle)
    self.addChild(greenRectangle)

}
func physics(){
    for ball in balls{
        ball.physicsBody = SKPhysicsBody(circleOfRadius: ball.size.height/2)
               }
    redRectangle.physicsBody = SKPhysicsBody(rectangleOf: redRectangle.size)
    redRectangle.physicsBody?.affectedByGravity = false
    redRectangle.physicsBody?.isDynamic = false
    blueRectangle.physicsBody = SKPhysicsBody(rectangleOf: redRectangle.size)
    blueRectangle.physicsBody?.affectedByGravity = false
    blueRectangle.physicsBody?.isDynamic = false
    greenRectangle.physicsBody = SKPhysicsBody(rectangleOf: redRectangle.size)
    greenRectangle.physicsBody?.isDynamic = false
    greenRectangle.physicsBody?.affectedByGravity = false
    balls[0].physicsBody?.categoryBitMask = blueBallCategory
    balls[1].physicsBody?.categoryBitMask = greenBallCategory
    balls[2].physicsBody?.categoryBitMask = realRedBallCategory
    balls[0].physicsBody?.contactTestBitMask = redRectangleCategory
    balls[1].physicsBody?.contactTestBitMask = redRectangleCategory
    balls[1].physicsBody?.contactTestBitMask = blueRectangleCategory
    balls[2].physicsBody?.contactTestBitMask = blueRectangleCategory
    balls[0].physicsBody?.contactTestBitMask = greenRectangleCategory
    balls[2].physicsBody?.contactTestBitMask = greenRectangleCategory
    balls[0].physicsBody?.contactTestBitMask = blueRectangleCategory
    balls[1].physicsBody?.contactTestBitMask = greenRectangleCategory
    balls[2].physicsBody?.contactTestBitMask = redRectangleCategory
    redRectangle.physicsBody?.categoryBitMask = redRectangleCategory
    blueRectangle.physicsBody?.categoryBitMask = blueRectangleCategory
    greenRectangle.physicsBody?.categoryBitMask = greenRectangleCategory


}
}

我已经设置了碰撞检测,这样如果一个球碰撞到一个匹配颜色的矩形,程序就会打印(“alive”)。如果颜色不匹配,程序应该打印(“死”)。如果颜色匹配并打印(“alive”)但不打印(“dead”),它会检测到碰撞。有人可以帮忙吗,谢谢。

【问题讨论】:

  • 球和矩形的颜色是否相同,即您能否比较它们的 .color 属性以进行匹配?如果没有,你能把它们做成同样的颜色吗?
  • 它们是图像(png),所以我不知道该怎么做

标签: ios swift sprite-kit


【解决方案1】:

您可能会发现像这样构建您的 didBegin() 可能有助于摆脱所有这些 else ifs:

func didBegin(_ contact: SKPhysicsContact) {

    let contactMask = contact.bodyA.categoryBitMask | contact.bodyB.categoryBitMask

    switch contactMask {

    case blueBallCategory | blueRectangleCategory:
       print("Alive! Blue ball has hit blue rectangle.")

    case greenBallCategory | greenRectangleCategory:
       print("Alive! Green ball has hit green rectangle.")

    case redBallCategory | redRectangleCategory:
       print("Alive! Red ball has hit red rectangle.")

    default :
        print("Dead! Some other contact has occurred")
    }
}

如果一个球碰到一个不同颜色的矩形,你想发生什么?

编辑:

来自physics() 函数中的这段代码:

balls[0].physicsBody?.contactTestBitMask = redRectangleCategory
balls[1].physicsBody?.contactTestBitMask = redRectangleCategory
balls[1].physicsBody?.contactTestBitMask = blueRectangleCategory
balls[2].physicsBody?.contactTestBitMask = blueRectangleCategory
balls[0].physicsBody?.contactTestBitMask = greenRectangleCategory
balls[2].physicsBody?.contactTestBitMask = greenRectangleCategory
balls[0].physicsBody?.contactTestBitMask = blueRectangleCategory
balls[1].physicsBody?.contactTestBitMask = greenRectangleCategory
balls[2].physicsBody?.contactTestBitMask = redRectangleCategory

每次您为特定物理体的 contactTestbitMask 分配一个新值时,您是在覆盖之前的值,而不是添加到它。因此,唯一重要的行是:

balls[0].physicsBody?.contactTestBitMask = blueRectangleCategory
balls[1].physicsBody?.contactTestBitMask = greenRectangleCategory
balls[2].physicsBody?.contactTestBitMask = redRectangleCategory

所以balls[0](蓝色球)只接触蓝色矩形,balls[1](绿色球)只接触绿色矩形,balls[2](真正的红色球)只接触红色矩形。所以didBegin() 不会被调用,如果一个球接触到一个不同颜色的矩形,这就是为什么你永远看不到你的“死”消息。

另一个编辑:

如果您希望所有球在接触任何矩形时触发 didBegin(),那么您的球的 contactTestBitMasks 应包括所有矩形:

for ball in balls {
    balls.physicsBody?.contactTestBitMask = blueRectangleCategory | greenRectangleCategory | redRectangleCategory
}

或者如果球已经定义了一些接触并且您只想将矩形添加到它们的碰撞位掩码中:

for ball in balls {
    balls.physicsBody?.contactTestBitMask |= (blueRectangleCategory | greenRectangleCategory | redRectangleCategory)
}

【讨论】:

  • 谢谢,我尝试运行它并没有打印任何内容,但这种方式似乎比 if/else 方式更容易。有没有另一种方法可以写这个,所以它会起作用。
  • 实际上它适用于相同颜色的节点,但它不适用于默认情况(““死了!发生了其他联系”),抱歉我的控制台很慢。
  • 尝试将print("Contact detected") 添加为didBegin() 的第一行,看看会发生什么。
  • 查看我的编辑 - 如果球击中不同颜色的矩形,didBegin() 不会被调用。
  • 谢谢,这是有道理的,看起来应该可以工作,但默认仍然不打印。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-25
相关资源
最近更新 更多