2017-05-26 26 views
0

我正在Swift中製作一個平臺遊戲,SpriteKit涉及跳轉的主角。然而,等級加載後,玩家立即落地。 You can see it in action here.Swift SKPhysicsBody通過匹配位掩碼的靜態SKPhysicsBody墜落

我正在使用SKTilemapNode創建地面,並在水平加載時通過瓦片循環以在瓦片地圖的子節點上創建SKPhysicsBody。這與2016年WWDC的「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的物理身體是動態的,它的工作原理。這就是我在這之前讓遊戲工作的原因,但是,這會造成很多地面上的抖動,因爲玩家正在移動它。所以,感謝您閱讀這個至少,並且任何建議將不勝感激。

+0

您是否嘗試將body.isDynamic切換爲true? – sicvayne

+0

正如我所看到的,玩家與第一幀上的瓦片相交,在這種情況下,沒有任何碰撞。你能否試着將玩家移動到瓦片之上?也許它會工作。 –

+0

@PéterKovács感謝您的回答,但不幸的是,我的角色仍然通過@sicvayne來了,是的,這對我來說是過去的工作,我只是覺得它沒有任何意義,因爲它停止工作'body.isDynamic = false '。我最終設置了'body.isDynamic = false; body.mass = CGFloat(Int.max)'來解決這個問題。 – TempixTL

回答

0

編輯。 我認爲錯誤在這裏沒有使用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) 
     } 
    } 
} 
+0

感謝您的回答,我試過這個,但它不工作不幸。我嘗試使用枚舉,而沒有任何運氣。由於我找不到任何邏輯原因,我決定只是將瓷磚貼圖的物理體設置爲動態,並將其設置爲「CGFloat(Int.max)」,這對我來說已經足夠了。 – TempixTL

+0

我有一個可用的物理接觸系統。使用枚舉與:UInt32。讓我編輯我的答案 –

+0

請看看我的編輯。請記住使用UInt32。這一點很重要。再加上我的動態,但它的工作。這應該肯定有效。如果你想要更多的位掩碼,它會去4 8 16 32等 –