我正在使用SpriteKit在Swift中制作一个平台游戏,其中涉及一个跳跃的主角。但是,一旦水平加载,玩家便会立即跌落地面。 You can see it in action here.

我正在使用SKTilemapNode创建地面,并在加载某个关卡时在图块上循环以在图块地图的子节点上创建SKPhysicsBody。这与WWDC 2016的“ SpriteKit的新增功能”视频中演示的内容非常相似:


  因此,这里有一个我构建的小平台。一个可以跑来跑去的小家伙。您会看到我在后台进行了视差滚动。您会注意到我正在与这里的瓷砖碰撞。而且我通过利用可放置在每个磁贴上的自定义用户数据来实现此目的。在这里,我将在我们的图块集中向您展示。在此处选择一种变体。
  您会看到我们这里有一些用户数据。我只有一个名为edgeTile的值,它是一个布尔值,我设置为1。
  因此,在代码中,我将在此处的平台演示中浏览切片地图,并且正在寻找所有这些边缘切片。
  每当我找到一个时,我都会创建一些物理数据以允许玩家与之碰撞。


我基于SKTilemapNode创建物理物体的功能如下:

extension SKTileMapNode {

//In order for this to work, edge tile definitions must have the "edge" property in user data
func createPhysicsBody() -> SKPhysicsBody {
    var physicsBodies = [SKPhysicsBody]()

    for row in 0 ..< self.numberOfRows {
        for column in 0 ..< self.numberOfColumns {
            if self.tileDefinition(atColumn: column, row: row)?.userData?["edge"] != nil {
                physicsBodies.append(SKPhysicsBody(rectangleOf: self.tileSize, center: self.centerOfTile(atColumn: column, row: row)))
            }

        }
    }

    let body = SKPhysicsBody(bodies: physicsBodies)
    body.affectedByGravity = false
    body.isDynamic = false
    body.allowsRotation = false
    body.pinned = true
    body.restitution = 0
    body.collisionBitMask = 0b1111
    body.categoryBitMask = 0b1111
    body.contactTestBitMask = 0b1000

    return body
}

func initializePhysicsBody() {
    let node = SKNode()
    node.name = "Tilemap"
    node.physicsBody = createPhysicsBody()

    addChild(node)
}

}


因此,在场景设置中,我要做的就是调用tileMap.initializePhysicsBody()来完成所需的一切。

我的玩家的SKPhysicsBody如下:

let rect = CGSize(width: 16 * xScale, height: 24 * yScale)
let physics = SKPhysicsBody(rectangleOf: rect)
physics.isDynamic = true
physics.allowsRotation = false
physics.pinned = false
physics.affectedByGravity = true
physics.friction = 0
physics.restitution = 0
physics.linearDamping = 0
physics.angularDamping = 0
physics.density = 100
physics.categoryBitMask = 0b0001
physics.collisionBitMask = 0b0001
physics.contactTestBitMask = 0b0011
physics.usesPreciseCollisionDetection = true

physicsBody = physics


我不确定问题出在哪里,但是如果我将SKTilemapNode的物理主体设置为动态主体,则可以正常工作。这就是直到现在为止我一直在进行游戏的方式,但是,这会在地面上产生很多抖动,因为它是由于玩家击打而移动的。因此,至少感谢您阅读本文,并且提出了任何建议。

最佳答案

编辑。
我认为错误这里没有使用UInt 32

body.categoryBitMask: UInt32 = 2
body.collisionBitMask: UInt32 = 1
body.contactTestBitMask: UInt32 = 1


和播放器

physics.categoryBitMask: UInt32 = 1
physics.collisionBitMask: UInt32 = 2
physics.contactTestBitMask: UInt32 = 2


这肯定应该工作

也可以对tileMapNode(如下所示)尝试这种方式,而不要创建扩展名。这是由dontangg在苹果开发人员论坛上给出的。

self.tileMap = self.childNode(withName: "Tile Map") as? SKTileMapNode
guard let tileMap = self.tileMap else { fatalError("Missing tile map for the level") }

let tileSize = tileMap.tileSize
let halfWidth = CGFloat(tileMap.numberOfColumns) / 2.0 * tileSize.width
let halfHeight = CGFloat(tileMap.numberOfRows) / 2.0 * tileSize.height

for col in 0..<tileMap.numberOfColumns {
    for row in 0..<tileMap.numberOfRows {
        let tileDefinition = tileMap.tileDefinition(atColumn: col, row: row)
        let isEdgeTile = tileDefinition?.userData?["edgeTile"] as? Bool
        if (isEdgeTile ?? false) {
            let x = CGFloat(col) * tileSize.width - halfWidth
            let y = CGFloat(row) * tileSize.height - halfHeight
            let rect = CGRect(x: 0, y: 0, width: tileSize.width, height: tileSize.height)
            let tileNode = SKShapeNode(rect: rect)
            tileNode.position = CGPoint(x: x, y: y)
            tileNode.physicsBody = SKPhysicsBody.init(rectangleOf: tileSize, center: CGPoint(x: tileSize.width / 2.0, y: tileSize.height / 2.0))
            tileNode.physicsBody?.isDynamic = false
            tileNode.physicsBody?.collisionBitMask = playerCollisionMask | wallCollisionMask
            tileNode.physicsBody?.categoryBitMask = wallCollisionMask
            tileMap.addChild(tileNode)
        }
    }
}

关于ios - Swift SKPhysicsBody陷入带有匹配位掩码的静态SKPhysicsBody中,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44208131/

10-10 20:39