2016-12-27 63 views
3

我正在爲我正在開發的iOS遊戲創建瓷磚地圖。地圖是一個島嶼的俯視圖。大部分瓷磚都是水,但有些是土地。水磚被重新用於創建水,但沒有一個地磚被多次使用,因爲所有的地磚都是獨一無二的。我已經通過文檔的SKTileDefinition,SKTileGroup,SKTileGroupRule,SKTileSet和SKTileMap看,這就是我想出了:以編程方式創建SpriteKit SKTileMap的正確方法是什麼?

func createTileMap() { 
    let waterTile = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-1")) 
    let waterTileGroup = SKTileGroup(tileDefinition: waterTile) 

    let landTile64 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-64")) 
    let landTile63 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-63")) 
    let landTile56 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-56")) 
    let landTile55 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-55")) 
    let landTile54 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-54")) 
    let landTile53 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-53")) 
    let landTile48 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-48")) 
    let landTile47 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-47")) 
    let landTile46 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-46")) 
    let landTile45 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-45")) 
    let landTile44 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-44")) 
    let landTile43 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-43")) 
    let landTile40 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-40")) 
    let landTile39 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-39")) 
    let landTile37 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-37")) 
    let landTile36 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-36")) 
    let landTile35 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-35")) 
    let landTile34 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-34")) 
    let landTile31 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-31")) 
    let landTile30 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-30")) 
    let landTile27 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-27")) 
    let landTile26 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-26")) 
    let landTile25 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-25")) 
    let landTile23 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-23")) 
    let landTile22 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-22")) 
    let landTile21 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-21")) 
    let landTile20 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-20")) 
    let landTile18 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-18")) 
    let landTile17 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-17")) 
    let landTile13 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-13")) 
    let landTile12 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-12")) 
    let landTile11 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-11")) 
    let landTile3 = SKTileDefinition(texture: SKTexture(imageNamed: "map-tile-3")) 

    let landTileGroupRule = SKTileGroupRule(adjacency: .adjacencyAll, tileDefinitions: [landTile64, landTile63, landTile56, landTile55, landTile54, landTile53, landTile48, landTile47, landTile46, landTile45, landTile44, landTile43, landTile40, landTile39, landTile37, landTile36, landTile35, landTile34, landTile31, landTile30, landTile27, landTile26, landTile25, landTile23, landTile22, landTile21, landTile20, landTile18, landTile17, landTile13, landTile12, landTile11, landTile3]) 

    let landTileGroup = SKTileGroup(rules: [landTileGroupRule]) 

    let tileSet = SKTileSet(tileGroups: [waterTileGroup, landTileGroup], tileSetType: .grid) 

    tileMap = SKTileMapNode(tileSet: tileSet, columns: 8, rows: 8, tileSize: waterTile.size) 
    tileMap.fill(with: waterTileGroup) 

    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile64, forColumn: 7, row: 0) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile63, forColumn: 6, row: 0) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile56, forColumn: 7, row: 1) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile55, forColumn: 6, row: 1) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile54, forColumn: 5, row: 1) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile53, forColumn: 4, row: 1) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile48, forColumn: 7, row: 2) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile47, forColumn: 6, row: 2) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile46, forColumn: 5, row: 2) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile45, forColumn: 4, row: 2) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile44, forColumn: 3, row: 2) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile43, forColumn: 2, row: 2) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile40, forColumn: 7, row: 3) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile39, forColumn: 6, row: 3) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile37, forColumn: 4, row: 3) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile36, forColumn: 3, row: 3) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile35, forColumn: 2, row: 3) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile34, forColumn: 1, row: 3) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile31, forColumn: 6, row: 4) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile30, forColumn: 5, row: 4) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile27, forColumn: 2, row: 4) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile26, forColumn: 1, row: 4) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile25, forColumn: 0, row: 4) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile23, forColumn: 6, row: 5) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile22, forColumn: 5, row: 5) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile21, forColumn: 4, row: 5) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile20, forColumn: 3, row: 5) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile18, forColumn: 1, row: 5) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile17, forColumn: 0, row: 5) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile13, forColumn: 4, row: 6) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile12, forColumn: 3, row: 6) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile11, forColumn: 2, row: 6) 
    tileMap.setTileGroup(landTileGroup, andTileDefinition: landTile3, forColumn: 2, row: 7) 

    self.addChild(tileMap) 
} 

現在,這是相當總值的代碼,但我不知道在那裏我可以從這裏出發。我正在加載每個地塊,然後明確告訴它它應該進入哪一列和哪一行。沒有明確佈置的任何圖塊都是水圖塊。我想避免使用任何Xcode的GUI工具,並完全以編程方式創建地圖。這段代碼很有用,它提高了性能(我最初只是滾動整個地圖圖片,而不是使用圖塊),它非常難看,尖叫着「這樣做一定要有一個更簡潔的方法!」。我在這裏錯過了什麼?

+1

一些'for'循環怎麼樣? :) – jtbandes

+0

@jtbandes,這是首先想到的解決方案,但是因爲我需要爲每個圖塊以及每個圖塊的特定行和列創建一個變量,所以我不知道如何創建循環。 – SpacemanDeMars

+1

爲什麼你需要每個瓷磚的變量?你不能將它們存儲在數組或字典中嗎? – jtbandes

回答

5

一種方法是在文本文件中定義地圖佈局,其中的列和行指定要在特定位置放置哪個圖塊。然後可以爲每個遊戲級別指定不同的地圖,同時仍然使用相同的場景。這個例子假設只有一個SKTileSet並且不需要填充背景。

// Level1.txt 
01 01 01 01 01 01 63 64 
01 01 01 01 53 54 55 56 
01 01 43 44 45 46 47 48 
01 34 35 36 37 01 39 40 
25 26 27 01 01 30 31 01 
17 18 01 20 21 22 23 01 
01 01 11 12 13 01 01 01 
01 01 03 01 01 01 01 01 

遍歷每個列和行,檢索指定的瓷磚和調用setTileGroup

let path = Bundle.main.path(forResource: "Level1.txt", ofType: nil) 
do { 
    let fileContents = try String(contentsOfFile:path!, encoding: String.Encoding.utf8) 
    let lines = fileContents.components(separatedBy: "\n") 

    for row in 0..<lines.count { 
     let items = lines[row].components(separatedBy: " ") 

     for column in 0..<items.count { 
      let tile = tileMap.tileSet.tileGroups.first(where: {$0.name == "map-tile-" + items[column]}) 
      tileMap.setTileGroup(tile, forColumn: column, row: row) 
     } 
    } 
} catch { 
    print("Error loading map") 
} 

這消除了示例中的第二個代碼塊。如果您想在使用Xcode GUI Tools時稍微妥協一點,那麼可以通過將SKTileGroup創建爲sks文件來消除第一個代碼塊。

雖然使用SKTileMapNode時我會推薦使用GUI工具,因爲它們提供了很多功能。

+2

這似乎是一個很好的解決方法。我試圖儘可能避免使用所有Xcode GUI工具。 – SpacemanDeMars

相關問題