Sprite 套件中的 SKShapeNode 碰撞检测未检测到碰撞

Posted

技术标签:

【中文标题】Sprite 套件中的 SKShapeNode 碰撞检测未检测到碰撞【英文标题】:SKShapeNode collision detection in Sprite kit not detecting collision 【发布时间】:2019-01-28 20:09:13 【问题描述】:

我正在尝试实现SKShapeNode(圆形节点)和SKShapeNode(方形节点)之间的碰撞检测,就像应用程序“Snake VS Blocks”一样。

以下是我的节点创建的代码 sn-p

蛇创造

 private func addSnake() 
        snake = SKShapeNode(circleOfRadius: Constants.snakeRadius)
        snake.fillColor = Constants.snakeColor
        let snakeXPosition = (Helper.getScreenWidth() / 2.0) - Constants.snakeRadius
        snake.position = CGPoint(x: snakeXPosition, y: size.height * 0.3)
        snake.physicsBody = SKPhysicsBody(rectangleOf: snake.frame.size)
        snake.physicsBody?.isDynamic = false
        snake.physicsBody?.categoryBitMask = PhysicsCategory.snake
        snake.physicsBody?.contactTestBitMask = PhysicsCategory.block
        snake.physicsBody?.collisionBitMask = PhysicsCategory.none
        snake.name = "Snake"
        addChild(snake)
    

块创建

func addBlocks() 
    for index in 0...(blockCount-1) 
       let hasBlock = getRandomBool()
        if hasBlock 
            let block = getBlock(for: index)
            block.fillColor = .red
            addChild(block)
            let actionMove = getBlockMoveAction(for: block, atIndex: index)
            let actionMoveDone = SKAction.removeFromParent()
            block.run(SKAction.sequence([actionMove, actionMoveDone]))
        
    


func getBlockMoveAction(for block: SKShapeNode, atIndex: Int) -> SKAction 
    return SKAction.move(to: CGPoint(x:  CGFloat(atIndex) * width, y: -block.frame.size.height),
                  duration: TimeInterval(blockMovementDuration))


func getBlock(for index: Int) -> SKShapeNode 
    let rect = CGRect(x: 0, y: 0, width: width, height: width)
    let block = SKShapeNode(rect: rect, cornerRadius: Constants.blockCornerRadius)
    block.name = "Block"
    block.position = CGPoint(x: CGFloat(index) * width, y: (Helper.getScreenHeight() + width))
    block.physicsBody = SKPhysicsBody(rectangleOf: block.frame.size)
    block.physicsBody?.isDynamic = false
    block.physicsBody?.categoryBitMask = PhysicsCategory.block
    block.physicsBody?.contactTestBitMask = PhysicsCategory.snake
    block.physicsBody?.collisionBitMask = PhysicsCategory.none
    return block


func getRandomBool() -> Bool 
    return arc4random_uniform(2) == 0

下面是上述代码的结果图片:

我的第一个问题是,我不知道为什么,但是当我启用时,skview 显示物理, view.showsPhysics = true

我发现我的视图不在正确的框架中

其次,我已经确认联系代表了

physicsWorld.contactDelegate = self

但是我的

didBegin(_ contact: SKPhysicsContact)

没有被触发

碰撞检测代码:

extension GameScene: SKPhysicsContactDelegate 

func didBegin(_ contact: SKPhysicsContact) 
    
    var firstBody: SKPhysicsBody
    var secondBody: SKPhysicsBody
    if contact.bodyA.categoryBitMask < contact.bodyB.categoryBitMask 
        firstBody = contact.bodyA //snake
        secondBody = contact.bodyB //block
     else 
        firstBody = contact.bodyB //block
        secondBody = contact.bodyA //snake
    
    
    if ((firstBody.categoryBitMask & PhysicsCategory.snake != 0) &&
        (secondBody.categoryBitMask & PhysicsCategory.block != 0)) 
        if let snake = firstBody.node as? SKShapeNode,
            let block = secondBody.node as? SKShapeNode 
            snakeDidCollideWithBlock(snake: snake, block: block)
        
    


func snakeDidCollideWithBlock(snake: SKShapeNode, block: SKShapeNode) 
    print("Hit")
    block.removeFromParent()
    



我在***中搜索了类似问题的其他问题,但没有找到任何解决方案。

【问题讨论】:

【参考方案1】:

“isDynamic”中的一个或两个都应该为真。否则,它们将表现得像一堵墙,从不参与物理模拟。

【讨论】:

这很快..我忘了我把两个身体都设置为动态假。你能告诉我为什么我的块的框架有一些偏移,而不是你在上图中看到的应该是什么。 静止物理体的框架和节点的框架有不同的锚点。一个在节点的中心(0.5,0.5),另一个在一个顶点(0,0)。如果物理体在模拟中,物理世界引擎会修正它的位置以匹配节点,你不会注意到差异。

以上是关于Sprite 套件中的 SKShapeNode 碰撞检测未检测到碰撞的主要内容,如果未能解决你的问题,请参考以下文章

是否可以在 Sprite Kit 中使用圆形(SKShapeNode)作为蒙版?

绕过子类中的Initialization:Swift和SpriteKit

Sprite Kit SKShapeNode 创建两个节点而不是一个

更换 Sprite 套件中的场景时崩溃

如何在 Sprite 套件中的返回键上隐藏键盘?

如何在Sprite-kit中画一条线