JohnnieMac JohnnieMac - 2 months ago 12
Swift Question

SpriteKit - TileDefinition and userData being update for all tiles?

I thought I would create a tile map with the new Tile Map Nodes available in iOS 10.

I have a tile which if you stand on it, it will crumble. So I though I would place a userData field called timer in the tileGroup definition.

func crumbleTile(pos :CGPoint, dt : TimeInterval){
let column = roomMap.tileColumnIndex(fromPosition: pos)
let row = roomMap.tileRowIndex(fromPosition: pos)

let objectTile = roomMap.tileDefinition(atColumn: column , row: row)

if var timer = objectTile?.userData?.value(forKey: "timer") as? Double {
print("tile pos \(column),\(row)")
print("timer-from tile:\(timer)")
timer = timer - dt
objectTile?.userData?.setValue(timer, forKey: "timer")
print("timer-update tile:\(timer)")
if timer < 0.0 {
//move to next frame
if var crumbleFrame = objectTile?.userData?.value(forKey: "crumble") as? Int {

crumbleFrame = crumbleFrame - 1
print("crumble:\(crumbleFrame)")
objectTile?.userData?.setValue(crumbleFrame, forKey: "crumble")

if crumbleFrame < 1 {
//delete tile
print("delete tile")
removeTile(pos: pos)
} else {
//move to next frame
print("next frame")

if crumbleFrame == 2 {
print("change frame 2")


}
if crumbleFrame == 1 {
print("change frame 1")


}
if crumbleFrame == 0 {
print("change frame 0")


}
}


}

}


}

}
func removeTile(pos : CGPoint) {
let column = roomMap.tileColumnIndex(fromPosition: pos)
let row = roomMap.tileRowIndex(fromPosition: pos)
roomMap.setTileGroup(nil, forColumn: column, row: row)
}


Instead of each tile having it's own timer setting it appear that I am either adjusting a single timer or simultaneously adjust every timer for that tile.

It can be seen in the log file.

tile pos 51,11
timer-from tile:-0.104295339999993
timer-update tile:-0.125737270999991
crumble:-1
delete tile
2:crumble floor right
tile pos 52,11
timer-from tile:-0.125737270999991
timer-update tile:-0.164520885999991
crumble:-2
delete tile


tile at position 52,11 has the same timer value as 52,11 had ?

So the question is, is there a way to individually access each tiles userData ?

Thanks in Advance.

Answer

The userData that you add in the sks file is applied to every tile of that type used on the map, not per instance of the tile e.g. if you have a mountain tile with userData mountain:true then each mountain tile you place on the map will return true. If you update the userData to false, then all mountain tiles would be false.

Since each tile is uniquely identified by column and row index, you could create a data structure like an array of tuples to store timer info;

var timerInfo:[(column: Int, row: Int, timer: Double)] = []