SKTiled Framework
repository·master·Indexed 42 days ago
https://github.com/mfessenden/sktiledA Swift framework for integrating Tiled assets with Apple's SpriteKit. It supports TMX file loading via SKTilemap.load, various map projections, all layer types (tile, object, image, and group), custom properties, and animated tiles. The framework provides utilities for coordinate conversion between SpriteKit and Tiled, debug drawing options, and the ability to map Tiled custom types to specific Swift classes via the SKTilemapDelegate protocol.
What's inside SKTiled
- SKTiled is a Swift framework designed to enable the use of Tiled assets within Apple's SpriteKit engine. It provides specialized frameworks for macOS, iOS, and tvOS, allowing developers to bridge tile-based map data from the Tiled editor into SpriteKit scenes.
How the 'type' property works in SKTiled
masterThe
SKTiledObjectprotocol includes atypeproperty. This allows you to assign a type to any object in your scene, including tilesets, all layer types, and the map itself.If an object in Tiled has a built-in
typeproperty, that value is assigned. If the object does not have a built-in type but has a custom string property namedtype, that custom value will be used instead.Understand the SKTiled class hierarchy
masterSKTiled is built on top of Apple's SpriteKit framework. Most SKTiled components inherit from standard SpriteKit nodes like
SKNode,SKEffectNode, orSKSpriteNode. Understanding this hierarchy helps you determine how to add SKTiled objects to your scene and how they interact with the SpriteKit rendering tree.Core Hierarchy Overview
- Scenes:
SKTiledSceneinherits fromSKScene(which is anSKEffectNode). - Tilemaps:
SKTilemapinherits fromSKEffectNode. - Layers:
SKTiledLayerObjectinherits fromSKEffectNode. Specific layer types include:SKTileLayerSKObjectGroupSKImageLayerSKGroupLayer
- Tiles:
SKTileinherits fromSKSpriteNode. - Objects:
SKTileObjectinherits fromSKShapeNode. - Cameras:
SKTiledSceneCamerainherits fromSKCameraNode.
- Scenes:
Use Tile and Text objects from Tiled
masterSKTiled supports specialized object types from Tiled:
- Tile Objects: Objects assigned a tile ID. They render the associated tile within the object's bounds, including support for animated textures.
- Text Objects: Objects assigned text properties. They automatically render text within the shape's bounds. You can create dynamic labels by updating the
SKTileObject.textattribute or any font attributes, which triggers an automatic redraw.
How layers work in SKTiled
masterLayers in SKTiled are containers for different data types and are all subclasses of
SKTiledLayerObject. This base class provides coordinate transformation and positioning information.Supported layer types include:
- Tile layers: Hold an array of tile sprites and tileset data.
- Object groups: Contain vector shape objects.
- Image layers: Display a single image.
- Group layers: Encapsulate other layers.
You can query layers by their specific type, by their name, or by their index.
// 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 }Avoid protocol implementation issues when subclassing SKTilemapDelegate
masterIn Swift, if a base class conforms to a protocol with default implementations (like
SKTilemapDelegate), subclassing that base class to override protocol methods may fail because Swift may favor the default protocol implementation over your subclass's override.To ensure your custom logic is called, you have two options:
- Implement the protocol on the base class: Ensure the base class provides the necessary implementation so that overrides in the subclass are recognized.
- Use a secondary method pattern: Implement the protocol method in the base class, which then calls a separate, non-protocol method. You can then override that secondary method in your subclass.
It is generally recommended to implement protocols directly on your objects rather than relying on subclassing classes that already conform to them.
// Recommended pattern: Use a secondary method to bypass protocol implementation issues class BaseScene: SKScene, SKTilemapDelegate { func didRenderMap(_ tilemap: SKTilemap) { // call a secondary method that can be overridden setupTilemap(tilemap) } func setupTilemap(_ tilemap: SKTilemap) { print("BaseScene: setting up tilemap: \"\(tilemap.name!)\"") } } class LevelScene: BaseScene { override func setupTilemap(_ tilemap: SKTilemap) { print("LevelScene: setting up tilemap: \"\(tilemap.name!)\"") } }Enable physics for objects (Dynamics)
masterYou can enable physics for objects to allow them to act as dynamic bodies in your scene. This is typically achieved by passing properties from Tiled to the objects. For example, assigning a property likeisDynamic = trueto a shape object orisCollider = trueto a floor object allows them to interact with physics engines in your scene.Identify SKTiled protocols and delegates
masterSKTiled uses several protocols to define object capabilities and delegate patterns for scene and tilemap management.
SKTiledObject Protocol
Objects conforming to
SKTiledObjectinclude:SKTilesetSKTilesetDataSKTiledLayerObjectSKTilemap
Delegate Protocols
SKTiledSceneDelegate: Used bySKTiledSceneto handle scene-specific events.SKTilemapDelegate: Used bySKTiledSceneto handle tilemap-specific events.SKTiledSceneCameraDelegate: Used by bothSKTiledSceneandSKTilemapto handle camera-related events.XMLParserDelegate: Used bySKTilemapParserfor parsing tilemap data.
How the Tiled Scene architecture works
masterA standard Tiled scene setup typically involves an
SKTiledSceneDelegatewhich manages the relationship between a camera, a world container, and the tilemap.In this model:
- World Node: A container node (usually at 0,0) that parents all Tiled assets.
- Tilemap: The loaded
SKTilemapis parented to the world node. - Camera: An
SKTiledSceneCamerainteracts with the world node to allow navigation via mouse or touch events.
By conforming to
SKTiledSceneDelegate, you can implement a template for how maps are loaded and how the camera behaves.public protocol SKTiledSceneDelegate: class { var worldNode: SKNode! { get set } var cameraNode: SKTiledSceneCamera? { get set } var tilemap: SKTilemap? { get set } func load(tmxFile: String) -> SKTilemap? }Test custom resources in the Demo project
masterTo test your own resources using the provided demo targets, add your custom resource files to theDemo/Assets/User/directory and then compile one of the demo targets in Xcode.Enable Effects and Shaders on Tilemaps
masterSince
SKTilemapandSKTiledLayerObjectare subclasses ofSKEffectNode, you can apply Core Image effects, shaders, and distortions.To use shaders, you must set
shouldEnableEffects = true.Warning: Enabling effects consumes more CPU/GPU. Additionally,
SKEffectNodeuses a buffer with a maximum texture size of 2048x2048. If your map exceeds these dimensions, it will appear cropped. Enabling effects also softens the edges of nearest-neighbor textures, which may affect the look of retro-style games.// 1. Enable effects tilemap.shouldEnableEffects = true // 2. Load and configure shader let shader = SKShader(fileNamed: "waves") shader.attributes = [SKAttribute(name: "a_map_size", type: .vectorFloat2)] tilemap.shader = shader // 3. Pass data to shader tilemap.setValue(SKAttributeValue(vectorFloat2: tilemap.sizeInPoints.toVec2), forAttribute: "a_map_size")Debug the navigation graph visually
masterTo visually inspect the navigation graph of an
SKTileLayer, set itsdebugDrawOptionsproperty to.drawGraph.graphLayer.debugDrawOptions = .drawGraph