SmallGameLib是我自己这两天学习silverlight,通过对昨天编写的“气球人”游戏代码重构及解偶,开发出一个超级轻量级的小游戏开发包,
现在功能还非常薄弱,不过架构已基本形成,可以使用它进行一些超小型游戏的快速开发。
本文主要对该游戏开发包进行架构介绍与分析,为广大尚未入门的游戏开发者提供一个构建属于自己的游戏框架的思路。与此同时,我将继续完善这个框架,并且使用这个框架开发更多的示例游戏。
1。 为什么需要开发包?
为了提高代码复用率,使得游戏开发更为迅速。试想一下,每次一个游戏都完全从0做起?No——其实同类型的游戏中有很多地方是相同的,比如资源载入,资源分配,各种调度等等。一个提供基本功能和框架的开发包,能让我们开发起游戏来更加迅速。
为什么不叫游戏引擎,而叫开发包?其实两者是一个概念,由于我这个规模实在太小,功能实在太少,所以尚未上升到“引擎”级别。
我们游戏开发包的使命就是使得编程人员能更加专注于业务逻辑的实现,而尽量分离底层代码,并且需要有易用性,试想一下开发一个小游戏来让人学习一个相当复杂的开发包及其框架,谁会干呢?还要有易扩展性,一个好的开发包应该不是尝试为使用人员做一切事情,而是为他做他需要的事情,当他不需要该功能、或者要修改该功能的时候,应该易于替换、扩展。
2。 游戏主循环
所有的游戏都是一个循环的过程,在循环中触发各种逻辑、渲染。写成伪代码大致如下所示:
while(1)
{
logic();
render();
}
介于silverlight开发小游戏可以使用强大的Blend进行界面开发,所以我将整个循环设成可中断,一些界面可由 Blend开发,在游戏中把控制权交给Blend开发的界面,而后再根据特定情况重新返回到游戏主循环中来,然后游戏的主逻辑进行过程中再将循环打开。(此处抽象的说有些不好理解,可以结合之后的示例)
3。 架构设计
看到这四个字,先别慌~
介于我们的游戏引擎定位——超小型游戏开发包,我们的架构一定要能多简单就多简单,最好能一眼就看明白的。
我们来分析一下一些经典的小游戏。
游戏一般都是多个层,每个层中有各种物体或者元件(比如血条,分数,属性栏等)。然后结合游戏开始、游戏结束等各种选择、配置画面。就可以组合成一个完整的小游戏了。
于是设计成如下架构
如上图,GameEngine就是我们的核心引擎负责处理状态机、游戏循环以及一些渲染的控制。
在这之上是Layers,也就是我们游戏中的各种画面层,(比如背景层,主层)
在层之上我们有Objects,也就是游戏中的各种物体,(比如主角、敌人)
与此同时,我们在tools中提供一些经常可能用到的工具方法或者工具类。比如一些数学方法(MathTools)、一些图片处理方法(ImageTools)
此外,游戏还需要有整体配置,我们写在Config中。
需要有游戏资源,比如各种图片,我们放在Resource中。
然后整个游戏逻辑凌驾于这个底层框架上。
4。 逻辑派发机制
在我们的具体游戏中,每一帧各种物体都需要有自己的策略。比如吃豆子游戏中,怪物需要来抓主角,而主角需要获取玩家的操作,去吃豆子。。如何在保证每个角色都能有自己的“思考”呢?——我们需要在一定时间中调用每个角色的“思考”方法。
一种很朴素的机制是,给每个角色都分配一个定时器(线程),到时间就自己决定自己下一步该做什么。这样的好处是保证了每个角色逻辑业务的独立编写,缺点是使用了一堆定时器,造成资源的大量浪费,而且还很不好同步游戏整体逻辑。(比如你要判断一颗子弹是否打中了主角,你是在子弹逻辑中判断,还是在主角的逻辑中判断?怎么保证你在子弹判断过程中,主角又没有移动?……诸如此类问题,会在编程过程中造成大量麻烦)
于是,我在SmallGameLib中使用最朴素的遍历派发机制,在每个逻辑帧中,游戏引擎将调用所有的层(Layer)逻辑,然后用户可以在层逻辑中编写程序调用属于该层的物体的逻辑的代码(当然,你也可以不调用,比如这个物体是一颗 静止不动的树,它不需要逻辑)。
5。开发包代码结构介绍
SmallGameLib不会为你做一个完整的游戏出来,它仅仅为你提供一个思考和最基本的底层框架及工具集,这距离我们具体开发出一个游戏还有很“遥远”的路程。
BaseLayer :层(Layer)基类,抽象类,继承自Canvas,在你的游戏中需要派生这个类来创建游戏层。它是一个抽象类,你可以重载它的logic方法(默认为向属于该层的物体派发逻辑),以及reset方法(默认为清空该层物体)。
BaseObj :物体(Object)基类,抽象类,继承自Canvas,在你的游戏中需要派生这个类来创建游戏物体(角色),你必须实现它的logic方法,可以重载getMyBounderRect方法来设置该物体碰撞的包围盒。
GameEgine:游戏主引擎基类,抽象类,在你的游戏中需要派生这个类来创建游戏核心引擎,必须实现 TickGameFrameLoop方法(用于处理帧逻辑),在该方法中你可以调用 layersLogic方法向各帧派发逻辑。如果你的游戏需要引入状态机的话,也应该在此方法中实现各状态的分发。
ImageTools、MathTools:工具类,提供静态方法。
在下一篇文章中,我们将根据此开发包实战编写Hello world!敬请期待。