定义
将各种命令操作设计成类进行保存,使用时调用类的对象来实现操作。
优点:
- 操作设计成类后,相比于将操作封装成函数,在引起执行操作的条件不变时想要改变操作内容就不需要更改函数源代码,只需要获取新操作的对象。(例如游戏中K键代表攻击,当人物武器不同时,执行攻击时的动作不同。当需要获得新武器时,不需要更改函数代码去改变攻击动作,只需要设计新的攻击动作类,返回给人物调用即可)
- 容易实现撤销(UNDO)和重做(REDO)操作
- 实现了游戏物体与操作之间的解耦,增强了灵活性(游戏AI可以通过加入一系列操作或者删除一系列操作来控制游戏难度)
例子(基于U3D实现)
WSAD控制游戏物体前后左右行动
Z键撤销操作 R键重做操作
- Commands类(抽象命令类)
public abstract class Commands {
/// <summary>
/// 执行命令函数
/// </summary>
/// <param name="actor">执行命令的游戏对象</param>
public virtual void Execute(GameObject actor) { }
/// <summary>
/// 撤销命令函数
/// </summary>
/// <param name="actor"></param>
public virtual void UnDo(GameObject actor) { }
}
- WalkForward&&WalkBack(具体命令类)
public class WalkForward : Commands {
private Vector3 before;
public override void Execute(GameObject actor)
{
//记录当前位置用于实现撤销操作
before = actor.transform.localPosition;
//将操作的游戏物体向前移动一个单位
actor.transform.SetPositionAndRotation(Vector3.forward + before,Quaternion.identity);
}
public override void UnDo(GameObject actor)
{
//将操作的游戏物体恢复为原位置
actor.transform.SetPositionAndRotation(before, Quaternion.identity);
}
}
public class WalkBack : Commands {
private Vector3 before;
public override void Execute(GameObject actor)
{
//记录当前位置用于实现撤销操作
before = actor.transform.localPosition;
//将操作的游戏物体向后移动一个单位
actor.transform.SetPositionAndRotation(Vector3.back + before,Quaternion.identity);
}
public override void UnDo(GameObject actor)
{
//将操作的游戏物体恢复为原位置
actor.transform.SetPositionAndRotation(before, Quaternion.identity);
}
}
- InputHandler(响应键盘事件返回相应的命令对象)
public class InputHandler : MonoBehaviour {
//前进命令对象
public Commands command_F;
//后退命令对象
public Commands command_B ;
//根据相应事件返回相应的命令对象
public Commands Handler()
{
if (Input.GetKeyDown(KeyCode.W))
return command_F = new WalkForward();
if (Input.GetKeyDown(KeyCode.S))
return command_B = new WalkBack();
return null;
}
}
- Control(控制类)
public class Control : MonoBehaviour {
public GameObject player; //执行命令的游戏物体
private InputHandler input;
private Commands command; //当前执行的命令
private Commands PreCommand; //撤销操作命令
//命令队列保存已执行的命令 实现撤销多步操作
private LinkedList<Commands> list;
// Use this for initialization
void Start () {
list = new LinkedList<Commands>();
input = gameObject.GetComponent<InputHandler>();
}
// Update is called once per frame
void Update () {
ControlPlayer();
}
public void ControlPlayer()
{
command = input.Handler();
if(command!=null)
{
command.Execute(player);
//命令队列大小为4
//未满时加入队尾 已满时移除队首加入队尾
if(list.Count==4)
{
list.RemoveFirst();
list.AddLast(command);
}
else
{
list.AddLast(command);
}
}
//按键Z实现撤销操作
if (Input.GetKeyDown(KeyCode.Z))
{
if (list.Count!=0)
{
PreCommand = list.Last.Value;
list.RemoveLast();
PreCommand.UnDo(player);
}
}
}
}