以编程方式创建SpriteKit SKTileMap的正确方法是什么?

时间:2016-12-27 21:08:12

标签: ios sprite-kit sktilemapnode

我正在为我正在制作的iOS游戏创建一个平铺地图。该地图是岛屿的俯视图。大多数瓷砖都是水,但有些是土地。水瓦被重新用于创造水,但是没有一块地砖被使用不止一次,因为所有的地砖都是独一无二的。我查看了SKTileDefinition,SKTileGroup,SKTileGroupRule,SKTileSet和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工具,并完全以编程方式创建地图。这段代码有效,并且它提高了性能(我最初只是在整个地图图像上滚动,而不是使用瓷砖),它只是非常丑陋和尖叫"必须有一个更简洁的方法来做到这一点! &#34 ;.我在这里缺少什么?

1 个答案:

答案 0 :(得分:6)

一种方法是在文本文件中定义地图布局,其中列和行指定要放置在特定位置的图块。然后,可以为每个游戏关卡指定不同的地图,同时仍然使用相同的场景。此示例假设只有一个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工具,因为它们提供了很多功能。