In the code below I move the player to a tile that the player touches, and then what I expect to happen is also move the enemy to the player's new position. What actually happens is the enemy moves to the tile that the player was on before moving. Can someone explain why this is happening and how to get my desired result??
import SpriteKit
import GameplayKit
class GameScene: SKScene {
var player: SKSpriteNode!
var enemy: SKSpriteNode!
var grid: SKTileMapNode!
var turnState: String = "pause"
var touchLocation: CGPoint = .zero
override func didMove(to view: SKView) {
self.backgroundColor = .white
loadSceneNodes()
}
func loadSceneNodes() {
setupGrid()
setupCharacter()
setupEnemy()
}
func setupGrid() {
let columns = 10
let rows = 10
let size = CGSize(width: 64, height: 64)
guard let tileSet = SKTileSet(named: "Ground Tiles") else {
fatalError("Tile set not found")
}
grid = SKTileMapNode(tileSet: tileSet, columns: columns, rows: rows, tileSize: size)
addChild(grid)
grid.name = "grid"
let tileGroups = tileSet.tileGroups
guard let dirtLightTile = tileGroups.first(where: {$0.name == "DirtLight Tile"}) else {
fatalError("No DirtLight tile definition found")
}
guard let dirtDarkTile = tileGroups.first(where: {$0.name == "DirtDark Tile"}) else {
fatalError("No DirtDark tile definition found")
}
for column in 0...columns {
for row in 0...rows {
if (row % 2 == 0) && (column % 2 == 0) {
grid.setTileGroup(dirtLightTile, forColumn: column, row: row)
} else if (row % 2 != 0) && (column % 2 != 0) {
grid.setTileGroup(dirtLightTile, forColumn: column, row: row)
} else {
grid.setTileGroup(dirtDarkTile, forColumn: column, row: row)
}
}
}
}
func setupCharacter() {
player = SKSpriteNode(imageNamed: "knight")
let height = player.size.height
let scaleFactor = grid.tileSize.height / height
player.setScale(scaleFactor)
player.position = grid.centerOfTile(atColumn: 0, row: 0)
addChild(player)
}
func setupEnemy() {
enemy = SKSpriteNode(imageNamed: "knight")
let height = enemy.size.height
let scaleFactor = grid.tileSize.height / height
enemy.setScale(scaleFactor)
enemy.position = grid.centerOfTile(atColumn: 9, row: 9)
addChild(enemy)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let touchedNodes = self.nodes(at: touchLocation)
for node in touchedNodes {
if node.name == "grid" {
touchLocation = touch.location(in: self)
turnState = "player"
}
}
print("touch location: (row: \(grid.tileRowIndex(fromPosition: touchLocation)), column: \(grid.tileColumnIndex(fromPosition: touchLocation)))")
print("player current position: \(getRowCol(character: player))")
}
override func update(_ currentTime: TimeInterval) {
switch turnState {
case "player":
print("moving player")
movePlayer()
turnState = "enemy"
print("finished moving player")
case "enemy":
print("moving enemy")
moveEnemy()
turnState = "pause"
print("finished moving enemy")
default:
return
}
print("frame finished")
}
func movePlayer() {
let touchRow = grid.tileRowIndex(fromPosition: touchLocation)
let touchCol = grid.tileColumnIndex(fromPosition: touchLocation)
print("moving player to: (row: \(touchRow), column: \(touchCol))")
let newTile = grid.centerOfTile(atColumn: touchCol, row: touchRow)
let move = SKAction.move(to: newTile, duration: 0.5)
player.run(move)
}
func moveEnemy() {
let playerRow = getRowCol(character: player).row
let playerCol = getRowCol(character: player).column
print("moving enemy to: (row: \(playerRow), column: \(playerCol))")
let newTile = grid.centerOfTile(atColumn: playerCol, row: playerRow)
let move = SKAction.move(to: newTile, duration: 0.5)
enemy.run(move)
}
func getRowCol(character: SKSpriteNode) -> (row: Int, column: Int) {
let row = grid.tileRowIndex(fromPosition: character.position)
let col = grid.tileColumnIndex(fromPosition: character.position)
return (row, col)
}
}
output below when clicking on tile (row: 0, column: 1):
touch location: (row: 0, column: 1)
player current position: (row: 0, column: 0)
moving player
moving player to: (row: 0, column: 1)
finished moving player
frame finished
moving enemy
moving enemy to: (row: 0, column: 0)
finished moving enemy
frame finished