社区微信群开通啦,扫一扫抢先加入社区官方微信群
社区微信群
在游戏编程里面,有一个经常会被用到的设计模式-命令模式。
我对设计模式的理解是
1、为解决问题而生。
2、有大致流程,但是没有固定格式
3、为了沟通方便。
在游戏编程里面,或者软件开发里面,最能体现命令模式的应用场景是
"撤销"与"再做"
在策略游戏里面,有时候我们会提供给玩家去模拟下一步的功能,在他还没确定之前都是能够撤销我们的行为的。比如象棋,比如五子棋,或者在商店系统的时候,玩家购买完东西后悔了,我们可以让玩家去撤销操作。
在编写游戏工具给策划同事使用的时候,没有撤销功能的话会被亲爱的策划骂成狗的。
。。。
等等上面的需求出现之后,我们就可以考虑运用我们的命令模式来解决这个问题。
命令模式的宗旨是让命令类化,为了解耦,命令类将利用ConreteCommand类脱离宿主(接受命令的人,Reciver)的束缚,仅提供的是能够传入宿主的方法,自成一体。而命令与宿主之间的联系是靠一个Invoker来进行命令分发到宿主的。,Invoker里面包涵类的实例化,实例化的时候才挂钩命令与宿主。实例化命令之后就能够进行命令的调用了。
而作为最上层的调用客户,我们就是利用Invoker来进行操作的。
在我的这个例子里面,要演示的是如何利用命令模式去实现回退与重复。
小方块能够在移动之后利用UNDO返回之前的地点,也能利用REDO继续最后一步的时候的方向。
ClickTest.cs 按钮操作的类,Client
Command.cs 命令的抽象
ConcreteCommands.cs 具体的命令。
Cube.cs 方块的类,类里有各个方向移动的方法而已。
CubeController.cs 这家伙就是Invoker了,里面有一个命令的数组,保存命令只用,还有因为要去关联我们宿主,必须要有属性指向我们的Cube.Invoker的调用分三块,Undo,Redo,Go.分别对应三大类型的移动。
CubeEvent.cs 只是一个Enum而已,定义我们的方向。
链接:http://pan.baidu.com/s/1mg3Qgvm
附录代码:
using UnityEngine;
using System.Collections;
public class ClickTest : MonoBehaviour {
public GameObject user;
// Use this for initialization
void Start () {
}
public void LeftClick()
{
user.GetComponent<CubeController>().LetCubeMove((int)MoveEvent.left);
}
public void RightClick()
{
user.GetComponent<CubeController>().LetCubeMove((int)MoveEvent.right);
}
public void UpClick()
{
user.GetComponent<CubeController>().LetCubeMove((int)MoveEvent.up);
}
public void DownClick()
{
user.GetComponent<CubeController>().LetCubeMove((int)MoveEvent.down);
}
public void UndoClick()
{
user.GetComponent<CubeController>().Undo();
}
public void RedoClick()
{
user.GetComponent<CubeController>().Redo();
}
}
using UnityEngine;
using System.Collections;
//Invoker
public class CubeController : MonoBehaviour {
public GameObject _cube;
private ArrayList commands = new ArrayList();
private int current = 0;
public void Redo()
{
if (current>0)
{
Debug.Log("I can Redo now");
((MoveCommand)commands[commands.Count-1]).execute();
commands.Add(commands[commands.Count - 1]);
current++;
}
else
{
Debug.Log("当前没有前置行为");
}
}
public void Undo()
{
//Debug.Log("Undo " + levels + "levels");
if (current > 0)
{
Debug.Log("Current comm" + current);
int bakindex = current;
((MoveCommand)commands[--current]).unexecute();
Debug.Log("往前一步的下标:"+bakindex+",当前下标:"+current);
commands.RemoveAt(bakindex-1);
}
}
public void LetCubeMove(int move)
{
ICommand comm = new MoveCommand(move, _cube);
comm.execute();
commands.Add(comm);
Debug.Log("总命令数为:"+commands.Count);
current++;
}
}
using UnityEngine;
using System.Collections;
//Reciver Cube
public class Cube : MonoBehaviour {
public void OnMove(int move)
{
switch (move)
{
case 0 :
MoveForward();
break;
case 1:
MoveBack();
break;
case 2:
MoveLeft();
break;
case 3:
MoveRight();
break;
}
}
public void MoveForward()
{
gameObject.transform.localPosition += new Vector3(0, 0, 1);
}
public void MoveBack()
{
gameObject.transform.localPosition += new Vector3(0, 0, -1);
}
public void MoveLeft()
{
gameObject.transform.localPosition += new Vector3(-1, 0, 0);
}
public void MoveRight()
{
gameObject.transform.localPosition += new Vector3(1, 0, 0);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UnityEngine;
//ConcreteCommand 定义一个接受者和行为之间的弱耦合
class MoveCommand :ICommand
{
//Cube is a Reciver
private GameObject Cube;
public int _move;
public MoveCommand(int move,GameObject cube)
{
this.Cube = cube;
_move = move;
}
public void execute()
{
Cube.GetComponent<Cube>().OnMove(_move);
}
public void unexecute()
{
Cube.GetComponent<Cube>().OnMove(Undo(_move));
}
public int Undo(int move)
{
int UnMove = -1;
switch (move)
{
case (int)MoveEvent.up:
UnMove=(int)MoveEvent.down;
break;
case (int)MoveEvent.down:
UnMove=(int)MoveEvent.up;
break;
case (int)MoveEvent.left:
UnMove=(int)MoveEvent.right;
break;
case (int)MoveEvent.right:
UnMove=(int)MoveEvent.left;
break;
}
return UnMove;
}
}
using UnityEngine;
using System.Collections;
//创建了一个具体命令(ConcreteCommand)对象并确定其接收者
interface ICommand {
void execute();
void unexecute();
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
public enum MoveEvent
{
up,
down,
left,
right
}
如果觉得我的文章对您有用,请随意打赏。你的支持将鼓励我继续创作!