Move enemy to player's new position

143 Views Asked by At

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
0

There are 0 best solutions below