斜视角图形引擎的设计(下)

本文围绕游戏图形引擎展开,介绍了精灵的定义、分类及处理方法,包括静止和运动精灵的绘制、遮挡处理与运动控制。还探讨了让场景更生动的特效实现,如天气、光亮和阳光表现。此外,深入分析了物体精灵的轮廓处理,提出消除锯齿的方法。

复杂的精灵控制

特别感谢八爪鱼工作室 为本文提供精灵图案,及为我设计中的引擎提供测试用精灵动画

在游戏设计方面的英文资料中,经常看到 Sprite 一词,表示游戏中的运动的物体. 我暂时使用这个词的直译"精灵"来表述问题;-)

这里,我使用了更广泛的定义,凡是在这个引擎里,运用多帧位图来表现的同一单位对象, 都将其称之为精灵.所以玩家操纵的是精灵,NPC 是精灵,而地面上燃烧的火堆及墙上等火把, 远距离攻击的武器,比如箭(如果游戏中有此设计的话)都是精灵.在这个精灵的范畴, 我们可以再将其细分:

  • 静止的精灵:指相对游戏世界位置不变的对象,但又可以和其它对象之间发生遮挡关系, 不能作为地表处理.
  • 运动的精灵:指有自己的运动规律,或是由外界因素所影响其运动的对象

关于静止的精灵,比较好处理,只需要在每次刷新屏幕时,按照正确的位图重画它即可.至于遮挡问题, 和运动精灵一起处理.

需要仔细分析的运动的精灵,暂时我只写精灵的遮挡处理和简单的运动.更复杂的超出了图象引擎的范畴, 属于战斗引擎.当然我喜欢 Diablo 的战斗形式,那样,战斗引擎和图象引擎是没有明显得划分的.

精灵绘制时的遮挡处理和上篇讲述的物体绘制基本相同,问题也是集中在判断对象前后的问题. 不同的是,精灵的处理后于物体的绘制,所以绘制方案有略微不同. 同层次之间的处理可套用上篇的做法,先对屏幕上所有精灵位置排序,然后从后向前对每个精灵进行处理. 对具体的精灵,我们可以先将其画在应该在的位置,检索出剪裁矩形的屏幕坐标在其下方,且与之有相交部分的物体.设定精灵的剪裁矩形为绘图时的剪裁框(所有落在剪裁框外的点不绘制). 依次绘制上一步找出的可能遮挡精灵的物体,由于设置了剪裁框,所以重新绘制的物体不会破坏屏幕的其它部分, 具体步骤可以见图中详解.

两个物体 (2994字节)绘制精灵 (5061字节)重画物体 (4765字节)最终效果 (4585字节)

精灵的运动是比较复杂的,因为在坐标移动时还伴有位图的变换,这里先做初步讨论.更多的工作, 比如动作的切换,行走路径的搜索...留在战斗引擎部分实现.

精灵可能作出不同的动作,要得到生动的效果,连行走,跑动,站立,及其这几种状态之间的过渡, 都需要不同的动画表现.更不提复杂的战斗动作.我的做法是,处理每一类动作,设计一函数, 和相关的数据结构.精灵在同一时间只有一种动作状态,将对应的函数指针及结构指针在游戏主循环中赋予精灵,然后循环处理屏幕上等所有精灵. 而象跑动到停止这样的过渡动作的处理函数里能自己修改精灵的运动状态值,从而达到自动处理.

行走的精灵 (16698字节) 以最基本的行走动作为例,为了使精灵能全方向运动,至少要设计 8 组动画, 使用时, 由运动方向最接近哪个设计好的角度来决定使用某组画面.(这里再次感谢 八爪鱼工作室 为我调试这个引擎而设计的精美的精灵行走动画)
btw,按我的观点,行走动画至少要有 5 帧画才能有说得过去的效果, 可惜许多 RPG 都是用 3 帧画来表现这个 :-( 而八爪鱼工作室寄给我的几组动画,设计都非常精良, 无论从人物制作,还是从动作设计上来讲 ;-) (我很喜欢,这里放一组给大家欣赏) 据说这是他们将于明年春节左右推出的 RPG《杀气》中敌人之一的造型, 相信那将是个美工一流的游戏,明年的国产游戏定会给玩家一些新的感受.

让场景更生动

体现游戏整体美工/设计水平的,往往是不经意的小处.表现天气和时候的方法很多. 让地面积满白雪,哪比得上天上飘下几片雪花更能打动玩家? 所以,画面最后用些特效来修饰,虽然不是必要,但更能烘托出环境气氛.最后,这可以说是整个图形引擎中最难, 最需要技巧的地方.本文已经三易其稿.第一稿因为当时连续几天的工作,明显感到有些力不从心,引擎代码的编写开始跟不上我的思考速度,所以是在没有任何代码写出来的情况下,介绍了些想法.后来由于想到需要对自己的文字负责, 编写了具体的代码,发现了许多问题,从而写了第二稿,而大家现在看到的是第三稿, 很遗憾,刚发现,我现在的能力,及目前正在使用得机器,无法在引擎中以合理的速度, 实现下雨或飘雪的效果,所以删掉了此部分,留在以后有了新的算法或机器升级后再补充. 以后的时间,我将全力完成引擎后面还需要编写的部分及完成这个系列文章, 争取在本站周年之际,拿出我的作品

以往天气等的表现在第一人称的游戏中有所使用,第三人称得游戏中表现天气的几乎没有, 在握记忆中很早以前似乎有过一个那样的 RPG, 不过是矩形 Tile 的,似乎在斜视角的游戏中更难实现,在毫无借鉴的情况下,将各种我暂时能想到的特效的实现方法归纳起来,大约有3种:

  1. 满屏的天气表现,诸如雨雪天气
  2. 光亮表现,用颜色基调和亮度表现昼夜,黄昏,或是大雾
  3. 阳光,以光束出现的阳光

其中以第一种最为复杂,因为我们不能简单的将雨点或雪花贴在屏幕表面,那样将毫无纵深感. 如果机器速度允许,我们可以将雪花之类的物体,每片做成一个 3D 面片,给于它们自己的运动轨迹, 以 3D 方式绘制. 可惜现在还不是人人使用屁兔加五毒的年代, 就算是吧, 至少云风的鸡也没那个档次, 而设计这个引擎的动机,在很大程度上是自我娱乐用哦 ;-) 开始我的计划是用一些非常手段 2D 模拟 3D 效果, 结果发现以我正在使用得机器, 加上目前的本人的水平,无法在这个引擎中实现这效果, (单独实现它,就占据了几乎我所有的 CPU 之间) 除非使用 320x240x256 的分辨率,显示速度的确是个太大的障碍,在实现了前面讲述的所有后, 每帧画能留给天气效果使用的时间充其量只有考虑透明色后复制 1 屏画的能力. 毕竟 640x480x16bit 每帧画有 7 百多 K 的数据量啊. 除非找到一种高速算法, 不用位图操作, 而直接全速向画面上绘制雪花或雨点, 同时有很好的视角效果, 否则我宁可放弃这个环节... (第四次修改本文记录: 云风已经找到了比较快的方法实现天气表现, 引擎的初步代码早已经按期在主页周年时拿了出来, 在最后一个版本里, 初步实现了下雪的效果. 因为时间关系, 一直没有将这部分的文章补全, Sorry. 请大家期待本文第四稿)

第二种效果最容易实现, 因为仅仅是色调和亮度的变化,在 256 色的年代, 重置一下调色板就可以了, 现在 16bit 的引擎中呢, 万幸:-) 如我们前面所述, 为了减少内存的消耗量, 我们所有的图象信息同样是以调色板机制存放,所以所要做的事情仍然是正确的调整调色板而已, 当然,由于是 16bit 色, 每个位图可以拥有不同的调色板, 引擎则要对所有的调色板进行操作.

关于第三种阳光的操作,具体说来就是用 Alpha 混合产生光晕, 或光束来增强画面的表现力, 这个我是从当今众多游戏中学来的,象红线飙车中那阳光的光圈, 西风狂诗曲中透过天窗射入的阳光, 真的给人以享受, 我希望我的引擎中有这些. 具体的代码将在引擎全部写完时以源码形式公布.

装饰游戏的画面还有许多方法,假如机器的速度足够,可以实现很多,新的特效实现也留待我们大家去研究.

深入了解物体精灵


轮廓处理

  游戏的画面不同别的美术作品, 它是由各个单独的小图片拼合起来的, 而让玩家感觉到屏幕上的所有东西是一个整体是我们游戏设计者的目标. 在处理这个问题上, 可见游戏画面和其他诸如广告图片/动画等的不同. 此类引擎不同 3D Engine, 光线, 对象, 都是实时计算渲染的, 画面浑然一体. 2D Engine, 所有的对象都是事先绘制好, 临时拼成场景, 单独制作单一对象时, 我们无法考虑四周环境对对象的影响, 所以环境的色调不能完全体现在对象上. 所以直接将对象贴在整个场景里时, 对象图形的边缘部分和场景交界, 可能会产生不协调. 最明显的是锯齿现象, 这个是由于屏幕上的图形是非线形造成的. 可以发现, 用 3D MAX 等对整个场景连同上面的物体/人物一同渲染, 便不会产生锯齿, 放大渲染后的图形观察可以发现, 在对象间的交界处, 有些过度的颜色点. 可惜, 过度的色彩点有可能不适合所有的情况, 边缘处理过的图形在动态的游戏中,有时过度的很自然, 有时却成了难看的轮廓线.

  负有经验的游戏美工, 在处理此类情况时可以做的相当的漂亮, 我对此没有太多的了解, 简单的推测可能是色系的选择(人眼对暗的颜色的色彩区别感觉要迟钝些), 或是图形上的点保持一定的"脏乱"的色彩干扰, 使其没有大片的纯色而更自然. 仔细研究老外的游戏精品中图象, 我想是我们的游戏美工应当多尝试的.

  当美工此方面的能力尚缺乏时,我们程序员是否应该试着去弥补呢? 诚然, 实时处理这个问题, 会给系统带来本不必要的负担 (如果我们有世界一流经验丰富的游戏美工的话... 可惜我们没有 :-( ) 但为了我们游戏的视觉秒度个效果, 我们在游戏设定这么一个轮廓实时处理的开关也未尝不可.

  消除锯齿, 比较常用且简单的方法是运用 Wu-Pixel, 这个在机械工业出版社的《高性能图形程序设计》一书中有详细介绍.点是有大小的, 假设我们在黑色背景的(100,100)处画一个点, 就可以看成是画一个 (100,100)~(101,101) 间的矩形(不包括坐标 101,101). 矩形的大小为 1x1, 即点的大小. 如果在 (100,100.5) 处画一个点呢? 这个矩形便是 (100,100.5)~(101,101.5) 可惜屏幕上做坐标不可能是小数, 常规的方法只能将点画在 (100,100) 或 (100,101) 处, 使用 Wu-Pixel, 我们将使用亮度值来表现点的位置离整数坐标的偏差. (100,100.5) 是介于 (100,100) 和 (100,101) 间的, 即要绘的这个矩形在 (100,100) (100,101) 两个点构成的矩形中间. 我们便可以在 (100,100) 和 (100,101) 上分别绘制一个亮度一半的点, 两个点来反映这个处于两个物理点间的点. 同理,点 (100,100.3) 可以在 (100,100) 上绘制亮度 70%, (100,101) 上绘制亮度 30% 的点. 将这个方法从点推广到线, 屏幕上的斜线正是因为无法在小数坐标上绘点而造成的, 使用这个思路去绘制斜线上的所有点, 我们将得到一条平缓的线条.

  线形坐标系上的所有点, 反映在屏幕坐标上都将涉及到四个点. 点的大小可以和屏幕上的一样, 但屏幕上每个物理点都应该是四个线形坐标系上的四个点构成的了. 我们应该将其融合再绘制,根据四个元素点在屏幕物理点中所占比例不同, 我们也应当做相应的混合处理. 这个就是对上面提到的黑色背景上绘制亮色线条方法的加深. 游戏中真正需要处理的是物体的轮廓线. 为了得到一个线形的物体轮廓, 我有个简单的方法, 就是将物体缩小到 1/4 在运用. 每四个点融合成一个点. (将四个点的 RGB 分别取平均值在组合起来及可:-) 如果四个点中有点是透明色, 又有点不是, 则是在轮廓上. (但反过来不对, 四个点都不透明,虽然也可能是轮廓上的点, 但不必特殊处理)我们在处理的同时, 也得到了轮廓线上点最小刻度为 0.5 的坐标值. 为过度打下基础. 处理轮廓, 我们将轮廓线上的点分为 3 级,如果四个点中有 1 个不是透明色, 则 Alpha 值为 25%; 两个不是透明色, Alpha=50%; 三个不是透明色, Alpha=75%. 在绘制这个物体时, 轮廓部分以相应的 Alpha 值背景做 alpha 混合, 即可得到满意的效果, 你将发现锯齿没有了 ^_^

  实时去计算轮廓当然不合适, 尤其使用这个方法, 需要 4 倍原图的图形, 未免浪费. 实际运用时, 应当在计算完后, 将轮廓数据和图形保存在一起.

  这个方法不算很好, 实际上, 用 3D MAX 渲染图形时, 可以同时生成一张带 Alpha 通道的图形, 实际描述的就是轮廓信息, 还包括了轮廓上点的透明度. 能够使用这些信息, 应该比上面的方法更好.

  关于程序, 我在北京时曾经用 VC 写了一个, 走时匆忙, 忘了带回来 :-( 家里的系统放假回家来一直很乱,加上换了块主板, 重装了 Win95, 没想到 VC 和我的主板 /显卡有冲突 (我一点选菜单, 不出 5 秒就 S 机, 这个 M$ 出的烂东东 @#$%!, 其它软件都运行良好) 一直头痛, 也没有再写. 如果用 Allegro 怕许多朋友没有机会编译, 就暂且搁下, 过两天一定补上, 另为此文加配插图 ^_^

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值