SKTiled 是一个用于将 Tiled 资产集成到 Apple 的 SpriteKit 的框架,完全使用 Swift 构建。该项目最初是为了学习 Apple 的新编程语言(用于游戏项目)而开始的练习,但我决定将其作为开源项目发布,希望其他人也会发现它有用。 SKTiled 保持最新并且支持 Tiled 的 主要功能,包括所有地图和对象类型。
查看 官方文档。
特性
- iOS & macOS 版本
- tvOS 版本
- 解析内联和外部瓦片集
- 将自定义属性转换为地图、图层、对象和瓦片
- 显示所有投影类型:(正交、等距、六边形和交错等距)
- 显示所有图层类型:(瓦片、对象、图像、组)
- 支持所有压缩类型:(base64、zlib、gzip)
- 显示动画和翻转瓦片
- 预加瓦片集
- 组节点
- 瓦片对象
- 文本对象
- 模板对象
- 自定义瓦片和对象类
- 从自定义属性生成 GKGridGraph 图
- 为
GKGridGraph
节点定义用户可定义的成本属性 - 无限地图
- 瓦片碰撞对象
- 支持 Zstandard 压缩
要求
- iOS 12
- tvOS 12
- macOS 10.12
- Xcode 11/Swift 5
安装
Carthage及CocoaPods支持
对于Carthage安装,请在您的项目根目录创建一个Cartfile
github "mfessenden/SKTiled" ~> 1.22
对于CocoaPods,通过在podfile中引用进行安装
pod 'SKTiled', '~> 1.22'
使用方法
加载瓦片地图很简单
if let tilemap = SKTilemap.load(tmxFile: "sample-map") {
scene.addChild(tilemap)
}
一旦加载,渲染的SKTilemap
节点反映了初始场景中定义的各种属性
SKTilemap.size
:地图的瓦片大小。SKTilemap.tileSize
:单个瓦片的大小。SKTilemap.orientation
:地图方向(例如正交、等角等)。
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...
}
与对象一起工作
SKTileObject
对象可以从SKTilemap
和SKObjectGroup
节点中查询。
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
对象或父级SKTilemap
let tileSet = tilemap.getTileset("spritesheet-16x16")
// get data for a specific id
let tileData = tileSet.getTileData(globalID: 177)
节点访问。
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还提供了从UITouch
和NSEvent
鼠标事件中获取坐标数据的方法。
// get the coordinate at the location of a touch event
let touchLocation: CGPoint = objectsLayer.coordinateAtTouchLocation(touch)
动画瓦片
动画瓷砖会在将瓷砖图节点添加到 SKScene.update
方法时自动播放动画。可以从前层的 SKTilemap
节点或父层中访问Animated瓷砖。
// 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")
致谢
- Thorbjørn Lindeijer:《Tiled》的创建者
- GZipSwift:zlib 解压缩扩展
- Steffen Itterheim:TilemapKit 的作者,是该项目的灵感来源
- Kenney Vleugels:sample spritesheet 资源
- Amit Patel:基于瓷砖的游戏逻辑
- Clint Bellanger:等距瓷砖数学