GameplayKit › График навигации редактора сцен › Как использовать его для поиска пути?

Не так давно Apple представила элементы GameplayKit в редакторе сцен Xcode, и это здорово. Однако у меня возникли проблемы с элементом Navigation Graph: График навигации редактора сцен

Чего я пытаюсь добиться, так это нарисовать GKGraph из редактора сцен, получить его в коде и использовать в качестве основы для поиска пути.

Итак, сначала я рисую GKGraph:

Редактор сцен нарисован GKGraph

Затем я получаю его в GameScene.swift следующим образом:

graph = self.graphs.values.first

где graphs — это предопределенный Apple массив для хранения GKGraphs из редактора сцен. Все идет нормально.

Затем я хочу, чтобы игрок нашел путь к месту касания на экране. Для этого я использую UITapGestureRecognizer со следующим методом обратного вызова:

var moving = false
func moveToLocation(recognizer: UITapGestureRecognizer) {
    var tapLocation = recognizer.location(in: recognizer.view!)
    tapLocation = self.convertPoint(fromView: tapLocation)

    guard (!moving) else { return }
    moving = true

    let startNode = GKGraphNode2D(point: vector_float2(Float(player.visualComponent.node.position.x), Float(player.visualComponent.node.position.y)))
    let endNode = GKGraphNode2D(point: vector_float2(Float(tapLocation.x), Float(tapLocation.y)))

    NSLog(graph.nodes.debugDescription)

    graph.connectToLowestCostNode(node: startNode, bidirectional: true)
    graph.connectToLowestCostNode(node: endNode, bidirectional: true)

    NSLog(graph.nodes.debugDescription)

    let path: [GKGraphNode] = graph.findPath(from: startNode, to: endNode)
    guard path.count > 0 else { moving = false; return }

    var actions = [SKAction]()

    for node: GKGraphNode in path {
        if let point2d = node as? GKGraphNode2D {
            let point = CGPoint(x: CGFloat(point2d.position.x), y: CGFloat(point2d.position.y))
            let action = SKAction.move(to: point, duration: 1.0)
            actions.append(action)
        }
    }

    graph.remove([startNode, endNode])

    // Convert those actions into a sequence action, then run it on the player node.
    let sequence = SKAction.sequence(actions)
    player.visualComponent.node.run(sequence, completion: { () -> Void in
        // When the action completes, allow the player to move again.
        self.moving = false
    })
}

Используя этот метод, я заставляю игрока перейти к месту касания. Проблема в том, что путь, возвращаемый GameplayKit, включает только startNode и endNode, а это означает, что игрок вообще не идет по предварительно нарисованному GKGraph, а идет прямо. в endNode.

Примечание. При первом запуске NSLog(graph.nodes.debugDescription) отображаются все 10 предварительно нарисованных узлов. Когда я снова запускаю его после graph.connectToLowestCostNode, я получаю все 12 узлов. Так что мой график, кажется, содержит все необходимое для поиска пути.

Как вы думаете, в чем проблема? Почему graph.findPath не использует предварительно нарисованные 10 узлов для определения пути? Ваши ответы будут высоко оценены.


person Filip Juncu    schedule 18.12.2016    source источник
comment
как получить этот объект графа в моем быстром коде?   -  person Araf    schedule 01.07.2017


Ответы (1)


Похоже, что метод GameplayKit .findPath не работает должным образом при вызове GKGraph, созданного из редактора сцен. Что я сделал, так это клонировал узлы из предварительно нарисованного GKGraph в программно созданный GKGraph:

let newGraph = GKGraph()
for drawnNode in graph.nodes! {
    newGraph.add([drawnNode])
}

Затем .findPath работает нормально:

newGraph.connectToLowestCostNode(node: startNode, bidirectional: true)
newGraph.connectToLowestCostNode(node: endNode, bidirectional: true)
let path: [GKGraphNode] = newGraph.findPath(from: startNode, to: endNode)

Переменная path теперь содержит путь, сгенерированный с учетом всех 10 + 2 узлов.

Подведение итогов: вы не можете напрямую использовать навигационную диаграмму, созданную в редакторе сцен, для поиска пути. Мое решение состояло в том, чтобы сначала клонировать его узлы в программно созданный GKGraph, а затем использовать последнюю версию, чтобы сделать все остальное.

person Filip Juncu    schedule 18.12.2016