I want to create a scene where I have buttons to move a cursor from tile to tile inside a SKTileMapNode. I created a 10x8 SKTileMapNode in an extern .sks
file in the Spritekit Scene Editor. To set the cursors position exactly on the same as a tile, i wanted to register the specific column and row index of the tile and then find out his position. Using the functions numberOfColumns
and tileRowIndex
give me higher values than numberOfRows
and tileRowIndex
, which are 10 and 8. As a result of this Problem my cursor is being displayed on a wrong position. It isn't even even aligned on any tiles position.
class Spielfeld: SKScene {
var x: Int = 0 // Anzahl Felder in x-Richtung
var y: Int = 0 // Anzahl Felder in y-Richtung
var tilemap: SKTileMapNode = SKTileMapNode()
var up: SKSpriteNode = SKSpriteNode()
var down: SKSpriteNode = SKSpriteNode()
var left: SKSpriteNode = SKSpriteNode()
var right: SKSpriteNode = SKSpriteNode()
var cursor: SKSpriteNode = SKSpriteNode(imageNamed: "Cursor1Blue")
override func sceneDidLoad() {
up = self.childNode(withName: "Up") as! SKSpriteNode
down = self.childNode(withName: "Down") as! SKSpriteNode
left = self.childNode(withName: "Left") as! SKSpriteNode
right = self.childNode(withName: "Right") as! SKSpriteNode
tilemap = self.childNode(withName: "Tile Map Node") as! SKTileMapNode
cursor.position = tilemap.centerOfTile(atColumn: 5, row: 5)
cursor.zPosition = 0.1
self.addChild(cursor)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch:UITouch = touches.first! as UITouch
let positionInScene = touch.location(in: self)
let touchedNode = self.atPoint(positionInScene)
print(touchedNode.name!)
if(touchedNode.name == "Tile Map Node") {
let map = touchedNode as! (SKTileMapNode)
print(map.tileColumnIndex(fromPosition: positionInScene)) // higher than 10
print(map.tileRowIndex(fromPosition: positionInScene)) // higher than 8
print(map.numberOfColumns) // 10
print(map.numberOfRows) // 8
print(map)
}
}
}
When getting the index with tileColumnIndex
/tileRowIndex
you need to check against the position within the tile map. In your example you give the position for the scene, which might not be the same, depending on where the tile map is positioned.
If you use the touched location in the map, you should get the correct indexes returned.
let positionInMap = touch.location(in: map)
let column = map.tileColumnIndex(fromPosition: positionInMap)
let row = map.tileRowIndex(fromPosition: positionInMap)
An updated version of touchesBegan()
from your example
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch:UITouch = touches.first! as UITouch
let positionInScene = touch.location(in: self)
let touchedNode = self.atPoint(positionInScene)
if(touchedNode.name == "Tile Map Node") {
let map = touchedNode as! (SKTileMapNode)
let positionInMap = touch.location(in: map) // Get the touched position in map
print(map.tileColumnIndex(fromPosition: positionInMap))
print(map.tileRowIndex(fromPosition: positionInMap))
print(map.numberOfColumns)
print(map.numberOfRows)
print(map)
}
}
To ensure that your cursor gets aligned with the tiles when using centerOfTile
to position it, add it as a child to the tile map to ensure they are on the same coordinate system. Else you'll have to add the necessary offsets to the cursor position.
tilemap.addChild(cursor)