실행 취소와 재실행
앞서 명령 패턴 (1) 에서는 기본적인 명령 패턴의 구조와 동작에 대해 정리했다.
명령 패턴 사용 예 중에서도 잘 알려져 있는 실행 취소와 재실행은 전략 게임, 게임 개발 툴 등에서 필수로 구현되어야 하는 부분이다.
Command 클래스를 상속받는 MoveUnitCommand 클래스를 하나 만들어주었다.
이전에는 execute 함수를 pure virtual 함수로 구현했었지만, MoveUnitCommand 클래스에서 execute 함수를 오버로딩하여 구현해야 했기에 변경하게 되었다.
MoveUnitCommand 함수에서는 매개변수를 전달하지 않는 execute 함수를 구현해주었는데, 이 클래스의 생성자에서 Actor와 이동하고자 하는 좌표 값을 받아 해당 좌표로 이동할 수 있는 동작을 구현해주었다.

Controller의 handleInput() 함수는 다음과 같이 수정해주었다.
이전과 다른 부분이 있다면 IsInputKeyDown을 쓰는 대신 WasInputKeyJustPressed 함수를 사용하였는데, 단순히 KeyDown만 체크할 시에는 우리가 원하는 턴제의 이동을 구현하기에 어려움이 있었기 때문이었다.
(WasInputKeyJustPressed: 전 프레임에는 해당 키가 Press 상태가 아니었지만, 현재 프레임에는 Press 상태인 경우 true 반환)
예제에서는 1만큼 움직이는 코드를 짰지만, 실제 구현되어 보이는 부분에서 1만큼의 이동은 너무 작아 100으로 수정해주었다.

입력에 따라 해당 액터가 이동하는 명령을 구현하였고, 아래 영상은 실행 화면이다.
화면에서 보는 것 처럼 앞키를 누르면 앞으로, 뒷키를 누르면 뒤로 갈 수 있도록 구현하였다.

이제 이 명령들을 실행취소할 수 있도록 undo() 함수를 정의한다.
undo 함수에서는 execute 에서 변경하는 게임 상태를 다시 반대로 바꿔주면 된다.
그렇기 때문에 execute 에서 어떤 변경을 했는지, 원래 유닛의 위치를 저장하는 코드 또한 추가해 주어야 한다.
원래 유닛의 위치를 저장하기 위해 xBefore_, yBefore_ 변수를 추가해주었다.


BackSpace 에 대한 입력 처리도 수정해주었는데, 이 때 명령을 저장해서 해당 명령에서 undo를 실행시킬 수 있게끔 구현해야 했다. 클래스의 멤버변수로 MoveUnitCommand* LatestMoveUnitCommand 를 선언해주었고, 각 명령이 실행될 때마다 해당 명령을 바인딩해주었다.
위 구현에 따른 실행화면이다.
왼쪽 상단에 나타나는 글씨에 따라 Up, Down 명령과 Back 명령을 볼 수 있다.

실행취소를 여러 단계 구성하고 싶을 때에는 스택을 활용하면 된다.
명령을 실행할 때 새로운 명령을 스택 위에 쌓고, 가장 위에 쌓인 명령을 "현재" 명령으로 기억하여 해당 객체에서 undo()를 호출해주면 된다.
스택을 활용한 다중 취소 및 재실행

위 그림처럼 스택에 명령들을 쌓고 가장 최근에 들어온 명령을 현재 명령으로 저장해둔다.
실행 취소를 할 때는 현재 명령 포인터를 이전 명령을 가리키도록 수정하고, 재실행 시에는 현재 명령 포인터를 다음 명령을 가리키도록 수정한다.
또한 실행 취소 후에 새로운 명령을 실행할 때에는 현재 명령 뒤 모든 명령들을 버리고 실행할 새로운 명령을 넣는다.
게임에서 "재실행"이 사용되는 경우
게임에서 흔히 볼 수 있는 리플레이 기능은 재실행을 이용하여 구현할 수 있다.
매 프레임마다 전체 게임의 상태를 저장하게 되면 메모리를 너무 많이 사용하게 된다.
따라서 많은 게임에서는 전체 게임의 상태를 저장하는 것이 아닌 전체 객체가 실행하는 명령들을 매 프레임마다 저장하여 리플레이 시 이전에 저장했던 명령들을 실행하는 방식으로 리플레이를 구현하고 있다.
C++ 에서는 일급함수를 제대로 지원하지 않아 명령 패턴을 클래스로 구현하였지만, 다른 언어에서는 명령 패턴을 구현할 때 함수를 통해 구현하기도 한다.
※ 전체 프로젝트 https://github.com/haram1117/GameDesignPatterns_Study
GitHub - haram1117/GameDesignPatterns_Study: GameDesignPatterns_Study
GameDesignPatterns_Study. Contribute to haram1117/GameDesignPatterns_Study development by creating an account on GitHub.
github.com
※ 명령 패턴 2 커밋 https://github.com/haram1117/GameDesignPatterns_Study/commit/ec8c13c5801b1269d0a715495b0b57139b0e4513
Command Pattern2 · haram1117/GameDesignPatterns_Study@ec8c13c
Show file tree Hide file tree Showing 10 changed files with 73 additions and 6 deletions.
github.com
'게임 개발 > 디자인 패턴' 카테고리의 다른 글
| Game Programming Design Patterns - 프로토타입 패턴 (1) (1) | 2022.08.09 |
|---|---|
| Game Programming Design Patterns - 관찰자 패턴 (2) (0) | 2022.08.05 |
| Game Programming Design Patterns - 관찰자 패턴 (1) (0) | 2022.08.04 |
| Game Programming Design Patterns - 경량 패턴 (0) | 2022.08.02 |
| Game Programming Design Patterns - 명령 패턴 (1) (0) | 2022.07.30 |