游戏编程模式算是一本比较著名的书了,全书针对游戏编程中的问题介绍了多种设计模式。学习设计模式可以加强我们的程序架构能力,写出更加强大和优雅的程序。

在线C#

写在前面

其实针对设计模式,之前我就学习过《大话设计模式》自己也随书将二十多种设计模式实现了一遍;但我在学习游戏开发的过程中发现,标准的设计模式并非对游戏编程支持良好,故而有了专门看一看游戏设计模式的打算,加上寒假学习cpp,让我有了拿起这本书的想法。
此文仅为学习记录,欢迎指正。

设计模式并不是刻意为之的东西,是前辈经验的总结,也许你在不知不觉中就已经使用了某种设计模式。

命令模式

将一个请求封装成一个对象,从而允许你使用不同的请求、队列和日志将将客户端参数化,支持请求的撤销与恢复。

从上述的描述中我们可以找到几个关键点:请求队列日志撤销与恢复
如果你需要这些特性,此事不妨试试命令模式吧。

适用场景

  1. 试想一下,我们在游戏中需要监听用户的输入,以让我们控制的角色响应玩家发布的命令,这个命令可能是移动,攻击,也可能是打开菜单,退出游戏。在需要复杂的输入检测时,你可能需要将玩家输入进行组合,如在恰当的时机按下某几个键位就可以使用特殊技能。
  2. 在网络游戏中,我们操控我们的角色需要在所有连接的客户端中同步,其中有一种同步方式称为状态同步,及玩家操作角色时,客户端会向所有服务器执行相同的命令,以同步角色的状态信息。这样的情况,多少也使用了命令模式在里面。
  3. 如果你需要撤销和重做,如一款回合制策略游戏,你可能需要撤销之前的动作,让玩家更专注于策略本身。

代码

根据上述描述,我们可以建立一个最基础的命令模式模板。

using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
  public static void Main()
  {
    var pl=new Player(0,0);
    Console.WriteLine(pl);
    var moveC=new MoveCommand(1,0,pl);
    moveC.Excute();
    Console.WriteLine(pl);
    moveC.Undo();
    Console.WriteLine(pl);
  }
}

public class Player
{
  public int x,y;

  public Player(int x,int y)
  {
    this.x=x;
    this.y=y;
  }

  public override string ToString()
  {
    return $"玩家pos:[{x},{y}]";
  }
}

public abstract class Command
{
  public abstract void Excute();
  public abstract void Undo();
}

public class MoveCommand:Command
{
  private int x,y;
  private Player player;
  public MoveCommand(int x,int y,Player pl){this.x=x;this.y=y;this.player=pl;}
  public override void Excute()
  {
    Console.WriteLine("Move Excute!");
    Console.WriteLine("Move To {0},{1}",x,y);
    player.x+=x;
    player.y+=y;
  }
  public override void Undo()
  {
    Console.WriteLine("Move Undo!!");
    player.x-=x;
    player.y-=y;
  }
}

如上所示就是一个命令模式的基本使用,在某些情况下我们应该将所有操作用命令管理,尽管这样比较麻烦,但一旦建立起一个统一的管理模式后,你会发现一切都是值得的。

存在的问题

仔细观察你会发现,我们每次我们使用一个命令都会创建一个命令对象,如果我们频繁的使用命令我们就会不断的创建对象,而这些对象其实我们只使用了一次。怎么解决这个问题呢?下一章的享元模式让我们一起来解决吧。