如何最好地在SpriteKit中编写撤消功能?



我正在创建一个基于精灵套件的游戏,允许玩家建造建筑物。我想创建一个撤消按钮,如果玩家放置一个方块并使整个建筑物分崩离析,该按钮会后退一步。

我正在考虑一种方法,在他们放置东西之前保存精灵套件场景,如果他们点击"撤消",它将用之前保存的场景替换场景。

这是最好的使用方法,也是最小化内存使用的最佳方法吗?是否有可以使用的预内置恶意工具包?

sprite-kit中没有预先构建的特定UNDO技术。为了节省内存和性能,我的建议是构建一个用户操作堆栈。你可以做一些东西,比如:

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在其中保存操作类型(删除、添加、旋转..(和所涉及的对象的name属性(例如,如果您有一个名为box1SKSpriteNode,则还应实现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 数组实现。下一步应该是构建每个操作,例如删除、添加、旋转,以复制用户操作。

换句话说,当用户按下 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
}
}

我只会制作您的 GameScene 的副本,然后当您需要撤消时,只需重新加载副本即可。

let copy = scene.copy() as? GameScene

view.presentScene(copy)

我不会太关注内存消耗,除非你开始看到问题。 我们有时倾向于做的事情是过度优化,以至于没有投资回报率(ROI(。只要您没有错误地管理要保留的对象或创建僵尸,使用此方法就不会有太大问题。

最新更新