游戏设计入门——游戏程序框架设计
游戏开发这个世界太广阔了,这篇文章中,我只在程序实现的抽象逻辑上,开一个口子进行一些肤浅的阐述。
当我去设计一个游戏,一个玩法,包含规则,游戏对象等等一系列的游戏系统,用纸可以写下来,用嘴可以说出来,但是当我想要用程序去实现这一堆东西的时候,就有些无从下手。
比如我们大家都会下五子棋,它有一个明确的规则“一人一字交替放置棋子,率先5颗连成一线获胜”,在现实世界中,我们不用考虑五子棋的硬件配置,拿一张白纸,画上横纵格子,两人分别执笔就可以完成一场五子棋的游戏,或者是使用正规的五子棋盘和棋子。无论用什么玩,要实现“玩”是很简单的。
但是在做一个五子棋视频游戏的时候,那就需要把“棋子”“棋盘”这些东西用软件去实现,
进一步,作为抽象概念的“游戏规则”“胜负判断”也需要软件去实现,这就需要更多的“用计算机思维去思考”。
于是我花了一些时间,凭借有限的本科计算机基础以及一些自我东拼西凑的自学,总结了一下游戏框架的一个通用设计方案。
一.随便开个头
首先阐述一下大的抽象概念,这里也不用被“抽象”二字吓到了,什么是抽象,就是归纳总结出来的结论之类的东西,就像把自行车,飞机,汽车都抽象为“交通工具”一样,这里归纳总结一下这些玩意的共性,于是“交通工具”这一个抽象概念就诞生了。
视频游戏程序框架,我认为她(she)就是一个循环(Loop)过程性,“开始游戏——杀敌/解密/闯关/…——游戏胜利/游戏失败——开始游戏”,对吧,关键字,循环(Loop)的,过程的。
进一步对此概念进行细化,衍生出GameState(游戏状态)和GameController(游戏/规则控制器),至于为什么会有这两个概念?我是参考了UE4提供的GameState类和GameMode类,同时也参考了前辈们用Flash写的游戏逻辑,至此我总结为GS和GC两大块,至于更高级的学术阐述,受限于我学识水平目前还做不到。
二.GameState
GameState就是对游戏状态的描述,最基本的两个,GamePlay(开始游戏)GameOver(游戏结束),这里GameOver不能理解成玩家平时看见的GameOver,玩家平时看见的GameOver大多表示游戏失败,而在这里,这个概念只是表示游戏结束,因为无论你游戏胜利还是游戏失败,游戏都结束了(GameOver)。
在此之上,可以进行扩展,例如现在游戏都会有主菜单,也有暂停,或者有多人模式,游戏设置等等,于是我们可以在GameState中添加MainMenu,GamePause,MultiPlay,GameOption等等。
使用GameState进行游戏状态的管理有什么用?最重要的就是给你一个清晰的编程实现游戏的思路,或者说给你一个入手点,至于方便管理游戏进程,方便后续游戏程序功能性扩展,降低游戏程序各系统耦合性等等,实在太多了。
至于GameState如何使用?这东西就是用来切换的,作为标识游戏目前状态的一个Flag。
之前在阅读《游戏人工智能编程案例精粹》这本书中,其中详解了FSM(有限状态机)在游戏AI的应用和扩展,以此联想,对于GameState的处理使用FSM岂不是再合适不过了。《lua游戏开发实践指南》中提到“对于Singleton,无论什么情况下,只要它们提供方便就使用它们”,虽然这句话说的太满,不太符合中国人的思维,也不符合辩证法(笑),但也某种程度上表明Singleton的实用性和广泛性。所以更进一步,使用Singleton(单例模式)的FSM处理GameState,以我来看是极好的。
当然,以上是抽象概念的阐述,最终用到游戏程序设计上,还得按照一些编程语言的语法和特性来实现,这里,我也给出了一份Unity的C#的原型代码,可以当作伪代码吧。
Unity的C#的原型代码:
publicclassS_GameState : MonoBehaviour {
publicenumGameState
{
GamePlay,
GamePause,
GameOver,
GameReady,
GameInit
}
publicstaticS_GameState Instance;
privateGameState m_GameState;
void Awake()
{
Instance = this;
}
publicGameState GetGameState()
{
returnm_GameState;
}
publicvoid ToGamePlay()
{
m_GameState = GameState.GamePlay;
}
publicvoid ToGamePause()
{
m_GameState = GameState.GamePause;
}
publicvoid ToGameOver()
{
m_GameState = GameState.GameOver;
}
publicvoid ToGameInit()
{
m_GameState = GameState.GameInit;
}
}
补记:
至于FSM和Singleton,请教谷歌老师是一个很好方法,不过,这里我稍微阐述一些FSM的应用,FSM早些年用于游戏AI的构建,毕竟游戏AI不同于科研领域的AI,游戏AI不是为了让玩家无法战胜而设立的,基本上游戏AI就是一套规律的集合,比如《黑暗之魂3》的第一个BOSS——古达,其中一个规律就是半血之后会变身,变身时候有动画,不会攻击,玩家可以很安逸的砍空一条体力,然后全身而退,这个规律,打几百遍古达都不会变。
回到原来话题,FSM广泛应用于游戏AI的地位现在基本被行为树取代了,然后FSM现在就专职做起了角色动画的管理,比如第三人称玩家角色的各种动画切换,UE4和Unity都使用FSM进行动画状态切换的管理。
三.GameController
说完了GameState,就该说一下GameController了
GameController就是用来管理游戏规则的了,比如开始游戏了,要生成玩家角色,生成敌人,生成地图等等;玩家按了ESC,要暂停游戏了;玩家通关了,妙极,GameOver;
所以GameController比起GameState要更加具体,基本上GameController就是要处理GameState切换之后一系列工作,依旧是五子棋,比如GameState从MainMenu切换到了GamePlay,那么GameController就要加载一个载入画面,载入结束后,消掉载入画面,同时显示一个棋盘等待。当然,OnLoading也可以作为一个GameState,至于要不要这个OnLoading的GameState,就归到弹性选项里面好了(笑)。
这里就需要一个游戏状态的检测,如果游戏某一时刻切换了状态,那么作为GameController就得做点事情了,所以要快!准!狠!
于是在一个独立线程里面整个一while(true)来不断循环判断是否游戏状态进行了切换
当然GameController也可以使用一个Singleton来实现,我认为是不错的,不仅可以异步执行,而且很快,充分满足快准狠的需要,而且分离了游戏的渲染线程和逻辑线程,并行优化/劣化好像很不错(笑)——对于一般的小型游戏,多线程可能会杀鸡用牛刀,反而劣化的游戏性能。
不过现在游戏引擎都体统了一个每帧调用的函数,所以将游戏状态检测放在里面也是很好的,以下,提供一个Unity的C#代码,以供参考。
Unity的C#的原型代码:
void Awake()
{
Instance = this;
}
void Start()
{
m_StartWait = newWaitForSeconds(m_StartDelay);
m_EndWait = newWaitForSeconds(m_EndDelay);
StartCoroutine(GameStateOperator());
}
IEnumeratorGameStateOperator()
{
while(true)
{
switch(S_GameState.Instance.GetGameState())
{
caseS_GameState.GameState.GameInit:
GameInit();
break;
caseS_GameState.GameState.GameReady:
GameReady();
break;
caseS_GameState.GameState.GamePlay:
GamePlay();
break;
caseS_GameState.GameState.GamePause:
GamePause();
break;
caseS_GameState.GameState.GameOver:
GameOver();
break;
}
yieldreturnnull;
}
}
补记:
这里使用了Unity的伪线程——协程,方便使用多线程进行参考,同时也为了让代码结构清晰一些。
四.状态切换
GameState提供了游戏状态来切换,GameController提供了状态切换后的工作处理,那么问题来了,什么玩意儿来切换GameState呢?
自然是游戏对象了,GameObejct,玩家角色,Npc,某个子弹,某些触发器,键盘操作等等。回到上面看看GameState的切换函数使用了public,也是这个原因,反正都是static了,稍微裸一点,我觉得颇为不错(笑)。
回到原来话题,比如玩家角色也许有一个HP的属性,当HP==0时,GameOver,调用一下GameState的状态切换函数,将状态切换称GameOver,这时,GameController检测到了GameState切换了,开始做出响应,很完美。
当然GameController也可以用一用状态切换,比如一些类似关卡倒计时计算需要写在GameController里面,当倒计时为0是,游戏结束,这时候就需要GameController调用切换函数了。同样的,对于玩家角色的HP检测放到GameController里面也未尝不可,不过这显然不符合OOP的设计原则,这么明显的增加耦合性,软件工程老师要气死。但是我就是要气死他(笑)。
补记:
对于游戏对象的分析和设计,我觉得需要综合OOP思想和设计原则,虽然设计主流游戏类型,大多有原型了,比如UE4就很人性化,提供了各种类型游戏原型,这里UML之类工具使用起来也是极好的。当然不能忘了UI的设计,UI是要契合游戏程序的,有效利用GameState是很好的入口点。下一篇我应该会说说UI设计的东西。
游戏设计入门——游戏程序框架设计相关推荐
- 百问网七天物联网课程学习笔记——程序框架设计
以前我一直觉得只有做纯软件的程序员才需要注意程序框架的设计,上了韦东山老师的课之后才觉得做单片机的程序开发注意框架设计也是很必要的事情.要在单片机开发的过程中引入面向对象的思想,这样的代码更容易扩展, ...
- 视频教程-【平面设计】设计入门必看-海报设计视频教程-UI
[平面设计]设计入门必看-海报设计视频教程 教学产品线与企业合作项目负责人,移动互联学院教学总监,从事培训与UI/UED课程研发工作多年,拥有数万学员且平均薪资位居行业前列.曾就职于世界500强互联网 ...
- 【平面设计】设计入门必看-海报设计视频教程-孙伟-专题视频课程
[平面设计]设计入门必看-海报设计视频教程-273人已学习 课程介绍 本课程主要为初级学员录制,掌握纸媒印刷相关内容,是设计入门的基础:课程内容包含从平面的入门开始,从认识平面设计-- ...
- 美国款游戏计算机,美国一程序员设计计算机游戏 悼念早逝爱子(图)
据美国<今日>网站4月25日报道,美国科罗拉多州的程序员赖安•格林(Ryan Green)设计了一款叫做"癌症:那条猛龙"的游戏,以此纪念爱子约耳(Joel)短暂的一生 ...
- 游戏SDK(二)框架设计
前言 根据上一篇游戏SDK(一) 客户端整体架构,介绍了游戏SDK 及 游戏SDK的需求分析.根据需求分析,对游戏SDK的设计分为3大块: 客户端:接口统一,做好逻辑转发和处理.具体渠道具体实现,互不 ...
- Android 程序框架设计
http://blog.csdn.net/leehong2005/article/details/8535306 这篇文章主要内容来自于之前我讲的一个PPT文档,现在将其整理如下.欢迎指正.以下的内容 ...
- Android程序框架设计
1.一些概念 模式的定义: 每个模式都描述了一个在我们的环境中不断出现的问题,然后描述了该问题的解决方案的核心.通过这种方式,你可以无数次地使用那些已有的解决方案,无需在重复相同的工作. 什么是设计模 ...
- 基于单片机的嵌入式系统的典型的应用程序框架设计
在单片机应用程序中,最常用.也是最简单的一种典型框架就是前后台系统,这种框架通常是由主函数里的大循环和一个或几个中断服务程序组成,本文主要讲这种典型框架设计问题. 前后台系统适用于一些程序流程简单.实 ...
- Windows MFC编程入门——应用程序框架
一.SDK应用程序与MFC应用程序运行过程对比 程序运行都要有入口函数,在C/C++程序中都是main函数,而windows应用程序的入口函数是WinMain或wWinMain.MFC程序也是从这个入 ...
- Wordpress 网站设计入门5 级联菜单设计
有了网页和博客网页,我们还需把他们组织起来,形成一个网站,这就是菜单的设计. Wordpress 的菜单设计非常简单.在操作面板上 Apperarance->Menus 这样就进入了菜单的设计面 ...
最新文章
- c语言单链表数据显示,C++_C语言单链表常见操作汇总,C语言的单链表是常用的数据结 - phpStudy...
- 四中方式实现单例模式
- java之跳转_java学习之五种跳转关于jsp的
- html 文章阅读次数,关于浏览次数和浏览次数缓存的问题
- Netty in action—Bootstraping
- 数据挖掘、机器学习、深度学习、推荐系统、自然语言处理的区别与联系
- android真机模拟gps,使用命令模拟更改gps位置
- 怎样在word表格中快速输入序号?
- matlab最简矩阵,Matlab中,将矩阵A化为行最简阶梯型矩阵,需借助指令:
- layui 汉字乱码_layui table中文乱码
- 不要用战术上的勤奋掩盖战略上的懒惰
- portal使用常见错误
- 位图(bitset)的使用【STL】
- 上海亚商投顾:两市震荡引分化 汽车产业链获青睐
- python --安装pylab
- 正则表达式生成器,测试器(附C#代码)
- 推荐几个好玩的手机游戏
- 什么是着色器/Threejs如何使用着色器/Threejs使用着色器实现平面网格的动态效果案例
- Java之访问修饰符
- TridentNet