Undo and redo

Another major benefit of having the call details packaged together in a class is the ability to undo an operation. Every modern desktop application, as well as the best web applications being made these days, features the ability to undo the last action or actions. This should be a standard that you strive to follow when implementing a level editor for your game.

Implementing a single level of undo in an application can seem like a large task. The naive approach might be to save the entire state of the application, possibly to a file, and reload that state when we need to undo. Depending on the application, there might be a lot of data to save. This method doesn't scale well in applications that can have dozens or hundreds of levels of undo. As the user does more actions, you would need to make sure to delete the oldest state before saving the current one.

This simple approach is even more difficult when you also need to implement redo. Obviously, the text editors and tools that we use every day don't store hundreds of undo and redo files on the hard drive. There must be a better way.

Instead of saving the entire state of the program, you only need to save information about the action that happened, and what data was changed. Saving a function and the parameters to the function sounds a lot like the Command pattern. Let's look at a simple example of moving a game object from one place to another in a level editor. We could create a command like this:

class MoveCommand: public Command 
{
public:
MoveCommand (Object* pObj, const Vec2D& moveTo) :
m_pObj(pObj), m_method(method), m_oldPos(pObj->pos)
{
}
virtual void Execute(void)
{
m_pObj->pos = m_moveTo;
}

//Add this method to the Command Interface
virtual void Undo(void)
{
m_pObj->pos = m_oldPos;
}
private:
Object* m_pObj;
Vec2D m_moveTo;
Vec2D m_oldPos;//Save the old position so we can redo
};

By adding the Undo method to the command interface and making sure to save the old data that will be modified in the Execute method, performing undo and redo becomes incredibly simple. First, we need to implement a command for every action that can be performed in our editor. Then, when the user interacts with the editor, instead of directly calling a function, they always call a command and add it to the end of our array of commands. Undoing and redoing is just a matter of calling the Execute or Undo method of the current array index.

It might seem like a lot of work to create all those commands, and it is. However, that work is replacing the work of hardcoding function calls when a user presses keys or clicks the mouse. In the end, you will build a better system that people will want to use.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.15.29.119