游戏设计模式-重访设计模式

游戏设计模式-重访设计模式

读《游戏设计模式》第一部分的总结-代码没运行只是提示模式的构建方法

命令模式

特点:Character根据情况获取相应Command,Command命令Character执行方法。
场景:Character的方法情况判断需要解耦。多种情况会在多种Character的方法中进行判断
注意:真正的运行方法都是在Character下的,Command可以简化为委托

public interface Command{
    public void execute(Character go);//这里使用游戏对象基类(能检测输入的基类)更好
}
public class JumpCommand implements Command{
    public void execute(Character go){
        go.jump();
    }
}
public class RunCommand implements Command{
    public void execute(Character go){
        go.run();
    }
}
public class InputCommands{
    RunCommand run=new RunCommand();
    JumpCommand jump=new JumpCommand();
    public Command getInput(){
        if(Input.GetKeyDown("W"))return run;
        else if(Input.GetKeyDown("Space") return jump;
        else return null;
    }
}
public class Character{
    void Update(){
        Command command=InputCommands.getInput();
        if(command!=null)command.excute(this);
    }
    void run(){}
    void jump(){}
}

观察者模式

特点:被观察者注册观察者,需要通知时向所有观察者通知信息
场景:两种不同功能的模块(之间只有事件通知关系)需要也应该解耦成观察者和被观察者,不混杂在一起
注意:

  • 两个模块都有各自的作用,和命令模式相比,命令可以简化成委托,为Character服务;但观察者只是和被观察者有事件上的耦合
  • 如果被观察者不销毁而观察者已经不再使用,需要手动去销毁观察者(因为被观察者始终持有引用)
public class Observer{
     private beNotified(){
     }
}
public class BeObserved{
    private ArrayList<Observer> obs=new ArrayList<Observer>();
    private notify(){
        for(int i=0;i<obs.length;i++){
            obs.get(i).beNotified();
        }
    }
}

原型模式

特点:通过现有的对象克隆出相同的对象,克隆结束后两者之间是相互独立的
场景:当类的实例化比较复杂且比较相似时使用
注意:和享元模式相比,各个个体之间是没有联系的,数据也是相互独立的

public abstract class Shape implements Cloneable{
    @Override
    public Object clone() {
      Object clone = null;
      try {
         clone = super.clone();
      } catch (CloneNotSupportedException e) {
         e.printStackTrace();
      }
      return clone;
   }
}
public class Circle extends Shape{}
public class Rectangle extends Shape{}

享元模式

特点:大量对象持有一个共同的引用,所以这个引用只被实例化一次
场景:需要创建大量重复的对象,同时这些对象的部分数据是不变的或是分成几类的
注意:共同的引用其状态不应该经常被改变

//字段不变
public class TreeModel{//每个树的材质、纹理、叶子等都相同
    Mesh mesh;
    Texture bark;
    Texture leaves;
}
public class Tree
{
  TreeModel model_;
  //以下的字段每个对象都不同
  Vector position_;
  double height_;
  double thickness_;
  Color barkTint_;
  Color leafTint_;
};

//字段枚举
public class Terrain{
  int getMovementCost() const { return movementCost_; }
  bool isWater() const { return isWater_; }
  const Texture getTexture() const { return texture_; }
  
  int movementCost_;
  bool isWater_;
  Texture texture_;
}
public class World{
    Terrain grassTerrain=new Terrain(XXXXX);
    Terrain blockTerrain=new Terrain(XXXXX);
    ....
    Terrain[] terrains=new Terrain[10[10];//之后让terrains指向不同的XXXTerrain
    
}

状态模式

特点:通过管理对象的状态来定义对象的行为,通常需要画状态机
场景:对象的行为基于一些内在状态,状态可以被严格地分割为相对较少的不相干项目。而对象需要响应各种输入(或其他条件判断)
注意:当状态管理过于复杂(制作更强大的AI时)使用行为树和规划系统

//简单的情况下可以使用枚举来管理对象的状态
enum State
{
  STATE_STANDING,
  STATE_JUMPING,
  STATE_DUCKING,
  STATE_DIVING
}
//复杂的情况使用状态机
interface BasicState{
    public BasicState handleInput(Heroine heroine, Input input);
    public void update(Heroine heroine);
    //入口方法,当进入该状态时需要调用,相对的也可以定义出口方法。
    public void enter(Heroine heroine);
}
//如果你的State都不需要有其他的变量(比如用来计时等)则简化为委托(但一般都有其他变量)
class StandState implements BasicState{
    public BasicState handleInput(Heroine heroine, Input input) {
        if (input == PRESS_A){
            return new JumpState();
        }
    }
    public void update(Heroine heroine){
    //dosomething
    }
    public void enter(Heroine heroine){
        heroine.setGraphics(IMAGE_STAND);
    }
}
class JumpState implements BasicState{
    public BasicState handleInput(Heroine heroine, Input input) {
        if (input == PRESS_DOWN){
            return new OtherState();
        }
    }
    public void update(Heroine heroine){
    //dosomething
    }
    public void enter(Heroine heroine){
        heroine.setGraphics(IMAGE_JUMP);
    }
}
class OtherState implements BasicState{//...}
class Heroine{
//如果状态使用者是一个单例(不是单例模式)可以使用静态参数来使用状态
    BasicState state=new StandState();
    void handleInput(Input input){
        BasicState newState = state.handleInput(this, input);
        if (newState != NULL){
            Destroy(state);//清理工作
            state = newState;
            state.enter(this)
        }
    }
    void update(){
        state.update(this);
    }
}

并发状态

当状态之间具有叠加关系时,可以在Heroine再定义一个state来指向叠加状态。但要注意叠加的越多,状态之间if判断越复杂。比如持枪状态和未持枪状态下的各种跳跃、行走

分层状态

当状态之间具有相似关系时,可以在使用继承来模拟状态的分层。子状态可以调用父状态的handleInput和update,不同子状态又有各自的处理,减少代码

下推自动机

当Heroine需要记住上一状态等操作时,可以维护一个容器(比如栈)来存储状态

单例模式

特点:类有且只有一个实例化对象,是可以被全局访问的,通常是惰性初始化
场景:创建多个对象会出错的类、文件读写类、需要全局访问的类
注意:尽可能的少使用单例模式
缺点:

  • 全局变量将会使代码变得不可维护
  • 过渡滥用单例模式,单例模式解决两个问题(单例和全局),但实际上只需要解决一个问题
  • 对并行不友好
  • 惰性初始化在游戏开发中是不可控的因素
    解决:
  • 可以使用静态类解决惰性初始化
  • 观察是否真的需要单例模式,XXXManager往往可以在XXX类执行,而不需要通过一个特定、单独的管理器管理
  • 如果是为了实现单例,可以在多次创建时抛出异常等方法控制。让该类只有一个非全局的示例。被正确销毁后允许创建下一个实例
  • 如果是为了获取访问,可以考虑在方法里传参、在基类里定义保护对象、加入到已有的全局变量里、从服务器定位中获得
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值