代码之家  ›  专栏  ›  技术社区  ›  Ashwin Shrestha

Sprite工具包中的SKShapeNode碰撞检测未检测到碰撞

  •  0
  • Ashwin Shrestha  · 技术社区  · 5 年前

    我正在尝试实现 SKShapeNode (环状节点)和 斯科沙普诺德 (一个正方形的节点),就像应用程序“蛇与块”一样。

    下面是我创建节点的代码片段

    蛇的创造

     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
    }
    

    以下是上述代码的结果图像:

    Screenshot of the app

    我的第一个问题是,我不知道为什么,但是当我启用时,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()
    
    }
    
    }
    

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

    1 回复  |  直到 5 年前
        1
  •  2
  •   E.Coms    5 年前

    一个或两个“isDynamic”都应该是真的。否则,它们的行为就像一面墙,永远不会参与物理模拟。