Programmatically create SKTileMapNode in Swift
Asked Answered
P

2

8

does anyone know how to create an SKTileMapNode programmatically using Swift please? (NOTE: I do not want to do this using the editor, I want to achieve this programmatically only)

I have tried the following but does not render my tile map

let bgTexture = SKTexture(imageNamed: "background")
let bgDefinition = SKTileDefinition(texture: bgTexture, size: bgTexture.size())
let bgGroup = SKTileGroup(tileDefinition: bgDefinition)
let tileSet = SKTileSet(tileGroups: [bgGroup])
let bgNode = SKTileMapNode(tileSet: tileSet, columns: 5, rows: 5, tileSize: bgTexture.size())
bgNode.position = CGPoint(x: self.frame.size.width / 2, y: self.frame.size.height / 2)
bgNode.setScale(1)
self.addChild(bgNode)

Any help greatly appreciated

Predestine answered 16/9, 2016 at 14:14 Comment(6)
you never actually make your map, how does it know what tiles you are using, The node knows the tiles, and you create the space for the map, you need to actually make the map now, I do not know too much about this so I can't provide an answer for you.Cyanic
@Cyanic do you happen to know if a SKTileMapNode can be scaled?Trichocyst
@Confused, I wouldn't see why not, scale is a member of SKNode (well xScale yScale is)Cyanic
Yeah... I'm just not convinced anything or SceneKit or SpriteKit ever works as advertised... colour me skeptical, and confused ;)Trichocyst
More gotchas than a Palin interview.Trichocyst
@Trichocyst You can apply scaling to the SKCameraNode to e.g. adjust size for different devices and orientations.Redmund
R
7

To layout the entire map with the single background tile you would iterate through each column and each row. You'll need to retrieve the background tile first.

let tile = bgNode.tileSet.tileGroups.first(
    where: {$0.name == "background"})

for column in 0..4 {
    for row in 0..4 {
        bgNode.setTileGroup(tile, forColumn: column, row: row)
    }
}

There is also a convenience function to achieve a flood fill;

bgNode.fill(with: tile)

There is also an initialiser for SKTilemapNode that accepts SKTileGroup

let bgNode = SKTileMapNode(tileSet: tileSet, columns: 5, rows: 5, tileSize: bgTexture.size(), fillWithTileGroup: tile)

I strongly recommend to leverage the functionality built into Xcode for creating TileSets and TileMaps. You can still programatically fill the map.

Redmund answered 17/9, 2016 at 7:29 Comment(0)
H
6

In case it's helpful to anyone, here's the whole thing put together:

class MyGameScene: SKScene {
    override func didMove(to view: SKView) {
        guard let tileSet = SKTileSet(named: "testset") else {
            // hint: don't use the filename for named, use the tileset inside
            fatalError()
        }

        let tileSize = tileSet.defaultTileSize // from image size
        let tileMap = SKTileMapNode(tileSet: tileSet, columns: 5, rows: 5, tileSize: tileSize)
        let tileGroup = tileSet.tileGroups.first
        tileMap.fill(with: tileGroup) // fill or set by column/row
        //tileMap.setTileGroup(tileGroup, forColumn: 5, row: 5)
        self.addChild(tileMap)
    }
}
Hoop answered 21/3, 2018 at 4:34 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.