【发布时间】:2018-08-31 23:05:16
【问题描述】:
我正在创建一个基于 sprite-kit 的游戏,允许玩家建造建筑物。我想创建一个撤消按钮,如果玩家放置一个块并使整个建筑物分崩离析,它会后退一步。
我正在考虑一种方法,在他们放置某些东西之前保存 sprite-kit 场景,如果他们点击“撤消”,它将用之前保存的场景替换场景。
这是最好的使用方法,也是最小化内存使用的最佳方法吗?是否有可以使用的恶意套件预置的东西?
【问题讨论】:
标签: swift sprite-kit
我正在创建一个基于 sprite-kit 的游戏,允许玩家建造建筑物。我想创建一个撤消按钮,如果玩家放置一个块并使整个建筑物分崩离析,它会后退一步。
我正在考虑一种方法,在他们放置某些东西之前保存 sprite-kit 场景,如果他们点击“撤消”,它将用之前保存的场景替换场景。
这是最好的使用方法,也是最小化内存使用的最佳方法吗?是否有可以使用的恶意套件预置的东西?
【问题讨论】:
标签: swift sprite-kit
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(后进先出 顺序),其中您最后推送的元素是第一个在下一次弹出时出现的元素。然后,您可以创建在此示例中称为 UserAction 的自定义 LIFO 元素,您可以在其中保存操作类型(删除、添加、旋转..)和所涉及对象的 name 属性(例如例如,如果您有一个名为box1 的SKSpriteNode,您还应该实现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
}
}
【讨论】:
lastUserAction 之类的 lastObjectState 在用户开始新操作之前存储名称、位置和物理参数,我的意思是有关当前状态的更多信息。仅当有人希望避免像您正确显示的那样重复场景时,该解决方案才可以使用
我只会复制您的 GameScene,然后当您需要撤消时,只需重新加载副本即可。
let copy = scene.copy() as? GameScene
view.presentScene(copy)
除非您开始发现问题,否则我不会过于关注内存消耗。我们有时倾向于做的事情是过度优化到没有投资回报 (ROI) 的程度。只要您没有对保留或创建僵尸的对象进行管理不善,使用此方法就不会出现太多问题。
【讨论】: