在上一周的读书笔记中,我介绍了设计模式的概念、目的是什么,以及最后的最重要的面向对象的七大原则,在这篇读书笔记中,我要介绍其中的一种设计模式:状态模式。
PS:这本书主要是以一个小游戏《p阵地》作为一个实战例子进行强行拆分,把游戏开发的每一个小部分都套用了一种设计模式,我个人认为这种方式非常好,虽然看着可能很生硬,但是确实是有效果的,但鉴于游戏开发使用Unity引擎及其使用的部分API可能都被弃用,所以我不采用实战代码,而是自己贴上自己理解的模拟代码。
前言
既然设计模式要与游戏开发完美贴合,那么我就先来说说游戏。相信很多人都玩过游戏,就算再不喜欢玩游戏的人,你的手机里面可能都有一个天天消消乐(一款三消游戏),那么平常玩的时候你肯定是没有注意到游戏是怎么开始的。可能是由于手机网络、qq等的普及,你下意识的就是知道,我要玩游戏,首先要用手机绑定账号,然后还有进入选择角色界面,然后进入不同关卡进行游玩。而这些东西在玩家意识中就是一个流程而已,而在我们游戏程序员眼里,这种东西叫做游戏场景,比如登录场景,战斗场景,结算场景,退出游戏场景。一些更复杂的游戏,比如MMORPG(大型多人社交角色扮演在线网游),里面有不同的副本,就可能有多个战斗场景。这就是我们游戏上面所说的当一个游戏比较复杂的时候,我们通常会设计成多个场景,让玩家在几个场景之间转换,某一个场景可能是角色在一个大地图上行走,而另外一个场景则是在地下洞穴探险。本书中的形容非常恰当——“这样的设计方式其实很像是舞台剧的呈现方式,编剧们设计了一幕幕的场景让演员们在其间穿越演出,而每幕之间的差异,可能是在布景摆设或参与演出角色的不同,但对于观众来说,同时间只会看到演员们在某一个场景中的演出
**eg:拿最简单的“三场景的游戏来讲”,三场景就是:登陆场景、主画面场景、战斗场景。
登陆场景:负责游戏片头、加载游戏数据、出现游戏主画面、等待玩家登陆游戏。
主画面场景:负责进入游戏画面、玩家在主城/主画面中的操作、在地图上打怪掉宝…
战斗场景:负责与玩家组队之后进入副本关卡、挑战王怪…

在游戏场景规划完成后,就可以利用“状态图”将各个场景的关系连接起来,并且说明它们之间的转化条件以及状态转换的流程,如下图所示:

就算一个游戏类型发生改变,游戏的大致流程都不会发生改变。那么我们这样费尽心机的分割场景有啥好处呢?
切分场景的好处
将游戏中不同的功能分类在不同的场景中来执行,除了可以将游戏功能执行时所需要的环境明确进行分类以外,“重复使用”也是使用场景的好处之一。几乎每一款游戏都有登录场景。而在一般的登录场景之中,会实现游戏初始化的功能或者玩家登录游戏的功能。因为这个通用性能,所以大部分的游戏公司都希望这个东西都可以复用在多个项目之中,可以大大减少开发时间,以及降低代码的错误率。(一个已经被使用的功能,和一个正在开发却没有测试过的功能相比,错误率自然是大大降低了)
游戏场景可能的实现方式
我们先来讲一下一般的实现方法代码如下:

public class SceneManager{private  string m_state = "开始";public void ChangeScene(string StateName){m_state = StateName;switch(m_state){//根据m_state更换功能//如果要更新新的模块就要在这里面添加更多的内容}}}

的确这种常规的写法非常容易让人理解,实现也是非常容易,但是他的缺点也是不容小觑的:
只要增加一个状态,则所有switch(m_stated)的程序代码都需要增加对应的程序代码。
与每一个状态有关的对象,都必须要在SceneManager类中被保留,当这些对象被多个状态共享时候,可能造成混淆,不容易区分是由哪个状态进行设置的(这句话这样来理解,比如在我战斗场景中我可能要和别人聊天,也可能要打开商城场景,这样在这一个主状态——战斗场景中我就引用了多个状态对象,如果一旦场景发生混乱,我们是很不容易找到具体到底是哪个状态设置产生的),造成了程序调试上的困难。
每一个状态,比如战斗状态要调用数值类,动画类,也就是要使用不同的类对象,容易造成SceneManger类过度依赖其他类,让SceneManger类不容易移植到其他项目中。(我曾经练习写斗地主时候,使用了strangloc框架已经是解耦合很强了,都让我头绕晕了,不敢想象,如果这样写会怎样,哈哈)

状态模式
接下来就轮到“主角”——状态模式登场了,在此我引用本书中的话(个人觉得非常好)。
状态模式(state),在GOF(最最最原始的“四人帮”的设计模式)中解释是:
“让一个对象的行为随着内部状态的改变而变化,而该对象也像是换了类一样”。
可能这样理解的不太方便,再一次用到本书中的举例了、
““德鲁伊”是游戏中经常出现的一个角色,他的能力就是变化外形,当德鲁伊(对象)由人形变化为兽形状态(内部状态改变时候),他所施展的技能(对象的行为)也会有所变化,玩家此时就像是在操作另外一个完全不同的角色一样(像是换了类 )”

当某个对象状态改变时,虽然它“表现的行为”会有所变化,但是对于客户端来说,并不会因为这样的变化,而改变对它的“操作方法”或者“信息沟通”的方式。也就是说,这个对象与外界的对应方式不会有任何改变。但是,对象的内部确实会通过“更好状态类对象”的方式进行状态的转换。当状态对象更换到另外一个类时候,对象就会通过新的状态类,表现出它在这个状态下该有的行为。但是这一切只会发生对象内部,对于客户端来说,完全不需要了解这些状态转换的过程及对应的方式。
也就是说,只需要一个类,对外表现方法都不会发生改变,但是他内部就会使用不同的状态类的对象,模拟代码如下:

using System;
/// <summary>
/// 状态模式 把一个对象的多种状态分割开来 与传统的switch相比 各个状态类的属性和行为都是相对独立的代码的独立性很好
/// switch就纯粹把其他状态的类对象放在自己的管理类里面最后会造成混乱 每次增加也不是特别方便
/// 而状态模式就是真正的实现了同一个对象 的多种状态的切换
/// </summary>
namespace 状态模式
{class Program{/// <summary>/// 对象类/// </summary>class Context{State m_state = null;//表示当前对象的状态/// <summary>/// 使得外部能够访问该对象目前的状态 并且根据当前状态做出操作/// </summary>/// <param name="a">状态参数</param>public void Request(string a){m_state.Handle(a);}/// <summary>/// 使得外部能够设置该对象目前的状态/// </summary>/// <param name="state">状态参数</param>public void setState(State state){Console.WriteLine("当前状态:{0}",state);m_state = state;}}/// <summary>/// 状态基类/// </summary>abstract  class State{//状态要对应一个对象 此对象的状态随时在变化protected Context m_context = null;//给此对象进行初始化public State(Context context){m_context = context;}//在此状态下的行为public abstract void Handle(string a);}class StateA : State{public StateA(Context context) : base(context) { }/// <summary>/// A状态的行为/// </summary>public override void Handle(string a){Console.WriteLine("boss执行a状态的技能");if (a == "b"){m_context.setState(new StateB(m_context));//生成新的状态 就是把当前对象状态给覆盖了 同一个对象放入不同的状态}}}class StateB : State{public StateB(Context context) : base(context) { }/// <summary>/// A状态的行为/// </summary>public override void Handle(string a){Console.WriteLine("boss执行b状态的技能");if (a == "c"){m_context.setState(new StateC(m_context));}}}class StateC : State{public StateC(Context context) : base(context) { }/// <summary>/// A状态的行为/// </summary>public override void Handle(string a){Console.WriteLine("boss执行c状态的技能");if (a == "a"){m_context.setState(new StateA(m_context));}}}static void Main(string[] args){Context context = new Context();//生成一个具有多状态的对象context.setState(new StateA(context));//给这个对象一个初始状态A 不然state对象是空context.Request("b");context.Request("c");context.Request("a");Console.ReadKey();}}
}

那么以上就是本次的读书笔记

《设计模式与游戏完美开发》——第二周读书笔记相关推荐

  1. [读书笔记] 设计模式与游戏完美开发

    最近在看<设计模式与游戏完美开发>,文章将记录一些要点和一些设计模式实现 GoF定义的23种设计模式及应用场景 系统设计可以采用的设计模式:单例.状态(场景切换).外观(保证高内聚).中介 ...

  2. 《设计模式与游戏完美开发》——第六周读书笔记

    在上一周的读书笔记中我介绍了中介者模式,本周的读书笔记来介绍一下桥接模式. 前言 现在流行的游戏都是有武器的.一个游戏不可能让玩家从头打到尾都是一把''小手枪''.例如,现在特别火的<贪婪洞窟2 ...

  3. 组队开发第二周第一次会议

    会议时间:组队开发第二周  星期一    开始时间晚上9:30-10:20 会议地点:学一食堂 二楼 到会人员:李志岩 孙存良 王亚蕊 安帅 薛禄坤 张新宇 会议内容概要: 会议主要完成了两项工作: ...

  4. 《Linux内核设计与实现》 第八周读书笔记 第四章 进程调度

    20135307 张嘉琪 第八周读书笔记 第四章 进程调度 调度程序负责决定将哪个进程投入运行,何时运行以及运行多长时间,进程调度程序可看做在可运行态进程之间分配有限的处理器时间资源的内核子系统.只有 ...

  5. 第六周读书笔记《浪潮之巅》

    第六周读书笔记<浪潮之巅> 沈三景 PB15061249 软件工程 读书笔记 前言 <浪潮之巅>是一本值得反复阅读的书籍,讲述了硅谷IT行业近百年来的风风雨雨,重点分析了AT& ...

  6. JAVA 第二周学习笔记

    JAVA第二周学习笔记 一.变量 1.变量的本质 2.变量的三大要素 a.变量名: b.变量值: c.变量类型: 3.变量的定义和使用 4.课后小练习: 5.变量的定义和使用 二.运算符 1.赋值运算 ...

  7. 《平衡掌握者—游戏数值战斗设计》读书笔记

    <平衡掌握者-游戏数值战斗设计>读书笔记 书名:平衡掌握者-游戏数值战斗设计 作者:似水无痕 出版社:电子工业出版社 简评: 本书对数值策划的定位.职责进行了简要的介绍.以RPG游戏的战斗 ...

  8. 第一行代码Android第二章读书笔记

    第一行代码Android第二章读书笔记 Activity 1.1 手动创建活动 1.2 Toast和Menu/销毁活动 Intent 2.1 显示/隐式 2.2 传递/返回数据 活动的生命周期 3.1 ...

  9. Linux第二周学习笔记(7)

    Linux第二周学习笔记(7) 2.13 文档查看cat_more_less_head_tail (1). cat命令 cat命令:用于查看一个文件的内容并将其显示在屏幕上 cat-A命令:显示所有的 ...

最新文章

  1. OpenCV入门要掌握的基本函数
  2. 树莓派10年销量4600万台!儿童玩具到工业设备它都可,创始人:最初只想造廉价电脑,不料第一天就卖出10万台...
  3. MySQL 打开federated存储引擎
  4. 广播,多播(二)(Broadcasting, Multicasting)
  5. 华为交换机s2700怎么重置_华为交换机忘记console的密码,怎么恢复出厂设置
  6. 洛希极限 (10 分)
  7. C++算法学习(力扣:402. 移掉K位数字)
  8. 凸优化中:单纯形是一种多面体的证明
  9. 使用Python在指定文件夹新建一个文本文档(其他类型文件也可)
  10. 太阳天顶角和方位角计算
  11. tftp 速度_PXE网络启动实战(第三篇 使用iPXE来提高PE启动速度)
  12. opencv库函数学习:Rect函数
  13. JavaWeb-16 (E家园项目案例1)
  14. 欢迎使用CS方分分分n编辑器
  15. 微信群发软件哪个好?好用的群发软件选择
  16. MySQL8高级优化,持续更新......
  17. micro:bit 了解
  18. 负反馈放大电路的电压放大倍数计算
  19. 操作系统(COPY自wk)
  20. skeleton 与 proxy 关系

热门文章

  1. go 协程(Goroutine)详解
  2. 苹果手机App Store正在载入或无法连接App Store的3种解决办法?
  3. Python编程-- BS4解析
  4. 零基础学习PHP编程——基本概念详解之域名解析与DNS缓存
  5. 人工智能换脸pythonapp_Python实现AI换脸功能
  6. python爬虫——Pyquery库
  7. rtklib 后处理_RTKLIB RTKLIB是一个开放源码的程序包 联合开发网 - pudn.com
  8. 谷歌开源同步定位与制图库Cartographer UBUNTU14.04安装方法
  9. 渲染管线_高清晰度渲染管线:艺术家入门指南
  10. 行为识别之C3D-network