SKTiled

SKTiled 是一个用于集成 Tiled 资源与 Apple 的 SpriteKit 的框架,从头开始使用 Swift 构建。这个项目最初是为了学习 Apple 新的编程语言而为游戏项目创建的,但我决定将其作为开源发布,希望其他人会觉得它有用。 SKTiled 是最新的,并支持 Tiled 的主要功能,包括所有地图和对象类型。

Demo Image

请查看 官方文档

功能特性

系统要求

安装

Carthage

对于 Carthage 安装,请在项目的根目录中创建一个 Cartfile 文件

github "mfessenden/SKTiled" ~> 1.2

要使用新的 二进制框架 格式,请将 --use-xcframeworks 参数传递给构建命令

carthage update --use-xcframeworks

有关更多信息,请参阅 Carthage 安装 文档。

CocoaPods

对于 CocoaPods,通过在您的 podfile 文件中引用进行安装

pod 'SKTiled', '~> 1.2'

用法

加载图块地图非常简单

if let tilemap = SKTilemap.load(tmxFile: "sample-map") {
    scene.addChild(tilemap)
}

加载后,渲染的 SKTilemap 节点会反映原始场景中定义的各种属性

SKTilemap 节点还允许用户访问子图层、图块集、对象或单个图块。

使用图层

图层表示包含各种类型数据的容器

所有 SKTiled 图层类型都是基类 SKTiledLayerObject 对象的子类,并提供对坐标变换和定位信息的访问。此外,每种图层类型都可以具有单独的偏移变换和渲染标志。

可以通过类型、名称或索引访问图层

// query layers by type
let tileLayers = tilemap.tileLayers
let objectGroups = tilemap.objectGroups
let imageLayers = tilemap.imageLayers
let groupLayers = tilemap.groupLayers

// query named layers
let groundLayers = tilemap.getLayers(named: "Ground") as! [SKTileLayer]
let objectGroups = tilemap.getLayers(named: "Objects") as! [SKObjectGroup]
let hudLayers = tilemap.getLayers(named: "HUD") as! [SKImageLayer]

// query layer at a specific index
if let firstLayer = tilemap.getLayer(atIndex: 1) as! SKTileLayer {
    firstLayer.visible = true
}

使用图块

有多种方法可以访问和操作图块对象。可以从 SKTilemap 节点或父 SKTileLayer 图层查询图块

// access a tile via CGPoint
let tileCoord = CGPoint(x: 7, y: 12)
if let tile = groundLayer.tileAt(coord: tileCoord) {
    tile.tileData.tileOffset.x += 8
}

// access a tile with integer coordinates
if let tile = groundLayer.tileAt(7, 12) {
    tile.tileData.tileOffset.x += 8
}

// query tiles at a specific coordinate (all layers)
let tiles = tilemap.tilesAt(2, 4)

Tiled 中分配了自定义属性的图块可以在 SKTiled 中访问

// query tiles of a certain type
if let fireTiles = tilemap.getTiles(ofType: "fire") {
    // do something fiery here...
}

您还可以返回具有特定 ID 值的图块

if let waterTiles = waterLayer.getTiles(globalID: 17) {
    // do something watery here...
}

使用对象

可以从 SKTilemapSKObjectGroup 节点查询 SKTileObject 对象

let allObjects = tilemap.getObjects()
let allTreeObjects = tilemap.getObjects(named: "Tree")
let allCollisionObjects = tilemap.getObjects(ofType: "Collision")

// get objects from the objects group layer
let entrances = objectsLayer.getObjects(ofType: "Entrance")

访问图块数据

SKTilemap 节点存储从原始 Tiled 文档解析的各个图块集数组。可以从 SKTileset 对象访问各个图块数据

let tileSet = tilemap.getTileset("spritesheet-16x16")
// get data for a specific id
let tileData = tileSet.getTileData(globalID: 177)

以及父 SKTilemap

let tileData = tilemap.getTileData(globalID: 177)

添加节点

图块数据包括纹理数据,SKTile 对象是可以使用图块集数据初始化的 SKSpriteNode 子类

let newTile = SKTile(data: tileData)
scene.addChild(newTile)

坐标信息可通过 SKTiledLayerObject.pointForCoordinate 方法从每个图层获得

let tilePoint = groundLayer.pointForCoordinate(4, 5)
tile.position = tilePoint

可以将新节点(任何 SKNode 类型)直接添加到任何图层。所有 SKTiledLayerObject 图层类型都扩展了便捷方法,用于添加带有坐标和 z 轴位置的子节点。

let roadRoot = SKNode()
groundLayer.addChild(roadRoot, 4, 5, zpos: 100.0)

SKTiled 还提供了从 UITouchNSEvent 鼠标事件获取坐标数据的方法

// get the coordinate at the location of a touch event
let touchLocation: CGPoint = objectsLayer.coordinateAtTouchLocation(touch)

动画图块

当图块地图节点添加到 SKScene.update 方法时,带有动画的图块将自动动画。可以从 SKTilemap 节点或父图层访问动画图块。

// get all animated tiles, including nested layers
let allAnimated = tilemap.animatedTiles(recursive: true)

// pause/unpause tile animation
for tile in allAnimated {
    tile.isPaused = true
}

// run animation backwards
for tile in allAnimated {
    tile.speed = -1.0
}

// get animated tiles from individual layers
let layerAnimated = groundLayer.animatedTiles()

自定义属性

所有对象类型都支持自定义属性。所有 SKTiled 对象都符合 SKTiledObject 协议,并允许访问和解析自定义属性。

Tiled 中添加到对象的任何属性都将被转换并存储在 SKTiledObject.properties 字典中。

let layerDepth = groundLayer.getValue(forProperty: "depth")
groundLayer.setValue(12.5, forProperty: "depth")

要查询给定类型的图块

let waterTiles = groundLayer.getTiles(ofType: "water")
let allWaterTiles = tilemap.getTiles(ofType: "water")

对于特定的属性/值类型

let groundWalkable = groundLayer.getTilesWithProperty("walkable", true)
let allWalkable = tilemap.getTilesWithProperty("walkable", true")

致谢