A闪的 BLOG 技术与人文
作者:式神
原文链接:http://bbs.todoair.com/forum.php?mod=viewthread&tid=92&extra=page%3D1
开始写这篇文章时这标题让我犹豫了很久,因为这并不是关于某个编程语言或者游戏开发文章,而是如何在我们现有的平台和有限的技术上开发一款2D的渲染引擎,用制作这个词呢,让我感觉更加贴切,就像我们利用手上的卡纸和剪刀制作一个玩具一样,也希望此文是在轻松愉快的环境下献给朋友一些经验和技巧吧,本文的内容主要是介绍一些2D渲染引擎的概念,当然内容都是以我个人的开发经验总结出来的,所以他并不是一个唯一的标准和答案,有遗漏之处也请多多包涵,那么下面就来开始我们的正题。
准备:
首先,我们要制作一款2D的渲染引擎就要了解到我们是在什么平台上用什么语言来开发,那么我们现在掌握的技术能提供给我们什么,如果某些技术我们还没有掌握时应该如何去寻找去学习,下面我们就从最基本的原理来分析一个2D渲染引擎需要具备什么功能。
2D渲染原理:
不管我们在任何平台上看到的绚丽的2D画面都可以认为是一张张带透明通道的图形数据,那么,我们制作一款引擎的第一步就应该学会掌握如何在平台上用平台的语言在显示器上绘制一快图形数据,那么,绘制图形数据我在这里又把它分为4个大类,绘制模式分为,面向对象模式,,流水线模式,高级绘制,低级绘制,下面我就来解释一下他们之间的区别。
面向对象模式:通常这种模式的绘制存在与高级绘制中,由某平台提供的绘制库或者引擎支持,使用方法也大致分为创建图形数据数据,传递图形数据数据,显示图形数据.你可能无法更改他的绘制模式,绘制效率也在一定程度上受限于它。
流水线模式:这种模式更像一个面向过程绘制方式,它可能并没有对象的概念也不会自动存储你所绘制的内容,通常会存在一个画布,一个画笔,一块数据数据,和一块线程,在反复循环的线程中画布反复的清理,画笔反复重绘位图数据,所以当你只想移动一个2*2像素的图形数据时可能需要重绘整个100100的画布,当然这也是优化的一个话题,在这里我们就不讨论了,这种绘制过程可能更加贴近生活,比如你在一张白纸上绘制一个小人在点A的位置,然后换一张新的画布再绘制小人在点B,然后点C,点D 。 。 。 。 。,当然,如果你在这个过程速度够快能达到每秒24张的速度的话,那就可以形成动画的效果,当然人类无法做到,只能交给机器了,所以,如果如果我们通过流水线绘制效率显而易见就是绘制每张的图形的逻辑和内容丰富度。
高级绘制:使用某平台的绘制库或引擎来绘制图形数据,大多数又高级语言来使用,使用的流程通常为传递图形数据的URL地址或者内存地址或者引用,当某平台的绘制库或者引擎通过你传递的图形数据在内部生成可供显示器显示的数据包,当然这其中的原理你并不需要知道,,生成之后再调用某平台提供的显示接口,比如addChild(data),来显示这快图形数据,优点就是能快速的在显示器上绘制一块位图数据,使用简单,更加容易理解,学习成本较低,但是缺陷是你需要长期的关注某平台提供的绘制内库和引擎,并且绘制效率受限于它,甚至可能以后对它产生了抱怨,但这无疑是快速通过他开发游戏的一条路径。
低级绘制:使用某平台或者某组织提供的底层绘制接口,比如Opengl,DX,Stage3D(虽然stage3d比起他们来说要高级很多)或者是J2ME游戏开发库(同stage3d类似),等等,使用这些接口来绘制的图形可以尽量的做到平台无关性,不需要受限与高级绘制提供的绘制库,当然,必须你自己通过低级绘制编写的绘制库的效率或者某一优点是高级绘制目前无法提供的,低级绘制的流程通常为流水线模式,其优点就是高度自由,可以更加容易的接受其他平台的渲染方式或者移植,当然,缺点也很明显,不容易理解,有一定的复杂度,学习成本也好高,绘制效率的优化等等。
2D控制原理:
那么,现在我们了大致了解了如何绘制图形数据到我们的显示器上,接下来我们要做的就是如何去控制图形数据绘制我们想要的位置或者缩放和旋转到我们所想的状态,至于控制我也把他们分为了几块,面向对象控制,顶点控制,数据集控制.
面向对象控制:它也通常存在于高级绘制和面向对象模式中,用某平台提供的方法显示图形数据后自然也会提供给你更改图形数据的的一些方法,比如X,Y,scale,rotation等等。
顶点控制:通过某平台或者某组织提供的接口来绘制图形时,原理多数是由N个顶点形成一个平面,通过对平面的某个顶点的位移可以对图形进行拉扯,位移,缩放,旋转等等.
数据集控制:比顶点控制高级一些,把顶点的控制权和方法统一集合到一个矩阵中,用户更改矩阵的数据,然后把矩阵的数据和顶点的原始数据做一些数据交换操作比如+,-/,等等来形成新的矩阵数据,然后把新的数据矩阵覆盖原来的顶点数据,而使图形数据形成新的显示效果。
2D对象的基本控制内容:
如果我们知道如何去控制显示器上的图形数据,那么我们要知道我们需要控制的是什么,下面我列出一些最基本的控制数据
X:使某顶点或者图形数据往X轴方向移动
Y:使某顶点或者图形数据往Y轴方向移动
Scale:使某顶点或者图形数据往Scale设定值的方向缩放
Rotation:使某顶点或者图形数据往Rotation设定值的方向旋转
可喜的是我们是2D游戏开发,所以不管是在任何平台上控制绘图图形上面这些操作都是最基本的篇章,也是觉容易掌握的,如果你正在学习opengl es你就可以看到前8章就会把这些内容教会你,如果是stage3d你可以在任何好心者提供的基础DEMO学习到。
2D对象的容器:
我们编写引擎的目的在于希望能把他们往高级绘制和面向对象绘制来实现,这样能更加方便的制作我们的游戏和降低代码量,那么,现在我们能做到在显示器上绘制图形并且控制他们的状态了,但这也只是一块数据,我们不能每一块数据都会他手动的操作,而且甚至我们并不知道应该绘制多少个图形什么时候应该绘制什么时候不绘制,他们的层次关系是怎么样的,所以我们我们现在得把方向从单数转移到复数去,既然是复数我们就需要存储他们,这样我们的容器就派上用场了,根据平台的不同容器也有所不同效率也不一样,这可以视情况而定,当我们选择一款容器时首先要它提供以下的基本功能,存入,取出,交换,这样我们就能很方便的去控制我们的图形的隐藏和层次了,然后将容器的控制权交给我们的核心引擎,比如addChild()是往容器里添加一个显示对象,removeChild()是取出。
2D场景控制器
回顾一下上面的内容,我们知道如何去绘制,控制,和存储,现在我就需要一个大的控制中心来管理他们,管理中心的操作通常是对容器的操作,比如添加和删除显示对象,事件机制,鼠标坐标拾取,图层划分等等,甚至可以做一些全屏的特效比如地震,这就看自己的喜好了,
坐标系:
在不同的平台上绘制对象可能坐标系都会有所不一样,有的可能只取一个象限,有的可能是包含了4个象限,那么我们根据自己的需求在我们的引擎统一他们的坐标系,有了坐标系我们才能准确的定位图形应该显示在某点,或者是碰撞等。
辅助对象
OK,现在我们已经能在显示上绘制各种图形数据并且可以操作他们的显示状态了,但是对于要制作一款游戏来说还是不够的,我们需要再上面的基础再封装一层,等于给他们加上一个铠甲让他们更加灵活强力,下面我将介绍一些基本的辅助对象。
精灵类:
它是图形显示的最基本的对象,游戏中大多数静态图形基本上都可以属于精灵类,它也是上面所有显示内容最基本的封装。
影片剪辑类:
游戏中如果只是光有静态图形可不行,没有动画的表现很多游戏特效是无法实现的,那么我们就得再精灵类的基础上再加一层,通常情况下,如果我们的引擎是属于流水线模式那么我们就可以把图形数据存储到一个容器中,在场景控制器绘制时,再读取容器中不同的数据以形成动画的效果。
按钮:
按钮可分为5个状态,正常状态,鼠标划入鼠标划出,鼠标点击,鼠标松开,我们可以用精灵类或者影片剪辑类封装。
数字:
如果我们是基于图形开发游戏,那么文字的显示就是一个问题,不过我通常的做法是把数字转换为0~9的图片,这样就可以用我们的影片剪辑类填充,通过不同的数量的影片剪辑让每个对象停止到某一帧,这样就能形成我们的数字,当然这对于一些特效数组或者美术加工的个性数字是格外有用的,当然,某些平台他们会提供给你基本的文本组件,可以嵌入字体等等。
文本:
和数字类似,某些平台会提供相应的组件或者内库来支持,如果是英文的话,26个字母我们可以根据数字的原理来拼凑出我们想要的文本内容,如果是中文,这确实有些麻烦,我的做法如果文字是静态的则可以用图片代替。
计时器:
这是让一个游戏运行的核心组件,如果是通过计时器来控制游戏的流程,那我们就可以很好的解决游戏的播放和暂停,可以统一的管理所有数据的运算和图形的绘制,避免出现一些中断游戏的操作而影响游戏本身的数据等等。
高级辅助对象
上面的内容为基本辅助,也是游戏必须的,如果有闲暇时间可以依据自己的能力添加如下一些高级辅助对象,我这里也列出一些基本的。
UI组件:
UI和游戏是永远不分家的,一个流畅友好的UI更加能凸显游戏的特色,UI操作基本上都可以按照一定的规律封装起来,可以节省我们日后的开发工作量。
粒子系统:
当然,如果希望游戏画面更加逼真,富有趣味性,那么就可以考虑加入粒子系统,我这里可以提供最基本的粒子原理,首先,你得想办法让你的图形数据随意的更改透明度和RGBA色值,然后再让他们模糊,模糊你可以用某平台的语言动态实现或直接读取一张模糊的图形数据,然后能让多个图形数据混合,这可能需要一些算法,最后可以赋予这些图形数据一些运动轨迹,相信我,如果你能做到了上面的几点那么你就可以实现非常漂亮华丽的粒子效果了。
音效控制:
音效也是游戏很重要的一部分,音效控制得好可以让玩家更加轻松更加投入在你的游戏世界中,所以,我们得为我们的音效加入,播放,暂停,停止等功能,当然也可以加入距离感应,比如角色离游戏中的水池越近那么水池的音效就会越大。
硬件控制:
终于到了最后一部分了,我们上面所做的多是属于视觉上和听觉上的,但游戏游戏不能只让玩家光看着,或者听着就可以的,我们需要玩家通过硬件的一些控制器,比如鼠标或者键盘来动态的更改游戏的内容,下面我列出最基本的2个控制器和一些需要实现的方法,
鼠标:
通常某平台会提供接口或者内库去访问这些硬件接口,我们可以不用在这上面费多少功夫,比如你正在学习AS,它会让你侦听某个事件来获取鼠标的坐标点,如果你正在安卓上开发,则需要继承某个类来覆盖它的触点函数等等,只要我们能获取鼠标的坐标点,那么我们第一步要做的就是把鼠标的坐标点映射到我们的游戏坐标系中,然后通过计算出当前鼠标点的坐标位置下有多少显示对象,或者某显示对象被点击等等,这比起上面的绘制流程来说,应该是相当简单了。
键盘:
原理和鼠标类似,可能比鼠标更加简单,因为不再需要映射坐标系了,当然,如果你是动作游戏爱好者,可以考虑把组合按键封装到你的按键库中。
最后补充一些话,不要太依赖于外界提供的一些框架思想或者设计模式,实战永远是最好的老师,我相信你自己也一定有自己独特的设计模式,不管怎么样,先去用,只有用了你才会发现它的不足,才能更加细致的去更改或吸收他人的经验,引擎就好比我们的伙伴他也是需要不断成长的,当然,前提是你必须创造出一个属于自己的引擎。
希望本文能给一些对2D游戏富有激情,并且乐于去实现的朋友一些微小的帮助,后面的内容我会教大家如何用stage3d利用有限的学习资料来实现我们的2D引擎。