Как лучше всего закодировать функцию отмены в SpriteKit? - PullRequest
0 голосов
/ 29 августа 2018

Я создаю игру на основе спрайт-кита, которая позволяет игрокам строить здания. Я хотел бы создать кнопку отмены, которая возвращает шаг назад, если игрок помещает блок и разрушает целое здание.

Я рассматривал способ, при котором непосредственно перед тем, как они помещают что-либо, сцена спрайт-набора сохраняется, и если они нажимают «Отменить», она заменит сцену ранее сохраненной сценой.

Это лучший метод для использования и лучший способ минимизации использования памяти? Есть ли что-то заранее встроенное в набор для спайтов, который можно использовать?

Ответы [ 2 ]

0 голосов
/ 29 августа 2018

Я бы просто сделал копию вашей GameScene, а затем, когда вам нужно отменить, просто перезагрузите копию.

let copy = scene.copy() as? GameScene


view.presentScene(copy)

Я бы не стал слишком сильно фокусироваться на потреблении памяти, если только вы не начнете видеть проблему. То, что мы иногда склонны делать, это чрезмерная оптимизация до такой степени, что нет возврата инвестиций (ROI). Пока вы не управляете объектами, которые вы сохраняете или создаете зомби, вы не должны видеть слишком много проблем с использованием этого метода.

0 голосов
/ 29 августа 2018

Нет определенной UNDO техники, предварительно встроенной в sprite-kit. Мой совет по экономии памяти и производительности - создать стек пользовательских действий. Вы можете сделать что-то вроде:

public struct Stack<T> {
    fileprivate var array = [T]()

    public var count: Int {
        return array.count
    }

    public var isEmpty: Bool {
        return array.isEmpty
    }

    public mutating func push(_ element: T) {
        array.append(element)
    }

    public mutating func pop() -> T? {
        return array.popLast()
    }

    public var top: T? {
        return array.last
    }
}
enum ActionType:String {
    case remove, add, moveTo, scale, rotate // add all the available user actions
}
struct UserAction {
    var type: ActionType
    var objectName: String
}

Итак, во-первых, вы можете создать LIFO ( последний пришел-первый-вышел порядок), в котором элемент, который вы нажали последним, является первым, который сработает со следующей поп-музыкой. Затем вы можете создать свой пользовательский элемент LIFO, называемый в этом примере UserAction, где вы сохраняете тип действия ( remove, add, rotate .. ) и свойство name соответствующего объекта (например, если у вас есть SKSpriteNode с именем box1, вы должны также реализовать box1.name = "box1" просто для идентификации вашего вовлеченного узла.

Использование:

var undoArray = Stack(array:[])
let currentAction = UserAction.init(type: .remove, objectName: "box1")
print(" - User has \(currentAction.type.rawValue) the \(currentAction.objectName)")
undoArray.push(currentAction)

Очевидно, это только реализация массива UNDO. Следующим шагом должно быть создание каждого отдельного действия, такого как удаление, добавление, вращение, для репликации действия пользователя.

Другими словами, чтобы сделать другой пример, когда пользователь нажимает кнопку ОТМЕНА, вы должны «вытолкнуть» элемент из вашего стека:

// ...

if let lastEl = undoArray.pop() {
    let lastUserAction = lastEl as! UserAction
    switch lastUserAction.type {
    case .remove: print("replicate remove action")
    case .add: print("replicate add action")
    case .moveTo : print("replicate moveTo action")
    // ... add the other user actions
    default:break
    }
}
...