目录 V+Y%v.F
2*& ^v
2 游戏实践讨论
=4YhG;%
2.1 制作概况 A:%`wX}
2.2 模块划分 -l*|M(N\
2.3 游戏引擎 &jJL"gq"
2.4 关键讨论 6Pl<'3&
2.5 希望 F0TB<1
AO4U}?
,?%Zc$\LW
2 游戏实践讨论 b4 6~?*
+Mb.:_7'
现在有很多人对国产游戏事业是又爱又恨的。爱的是希望能够出现一批真正属于我们自己的好游戏,恨的是这些游戏制作者们太不争气,到现在也没有做出来。我非常感谢他们,因为假如没有他们,也就没有了我们。我也感到非常抱歉,因为我们的作品目前还不能让人们满意。我想多说什么都是无用的,只有实事才能说话。前面我所说的大多是理论上的内容,是我们在几年的游戏制作过程中总结出的经验。这些内容有些可能是错误的,因为我们还没有从正面证明它,有些对我们至今仍然只是个美好的愿望,我们自己还没有真正做到。所以请大家在阅读时针对自己的情况进行取舍。 Rh{f5-
下面我利用我们曾经做过的一个游戏,具体分析它的制作过程和制作方法。希望借此为那些关心游戏制作的人提供尽可能多的材料,让他们了解得多一些。也为那些有志于游戏制作的人提供一些经验和教训,让他们少走一些弯路。要说明的是,我们在处理某些问题的时候,所使用的方法很可能是非常普通的,甚至是笨拙的,别人看来可能有更好的办法。但是我不想与各位争论,假如您有什么更好的想法和办法,就把它用到你的游戏中去吧,我希望每一个喜爱游戏制作的人都能够制作出更好的游戏来。 eF$x 1|
JG rWHIsNV
2.1 制作概况 z43M]P<
<赤壁>作为瞬间工作室成立以来的第一个作品,是1997年7月上市的,这个版本称作标准版。其后增加了网络功能,修改了一些Bug,增加了一些游戏事件,被称作增强版,增强版于1997年底上市。在此期间,我们又制作了日文版,韩文版和繁体版,又为国内的OEM厂商制作了相应的版本。据说<赤壁>全部的销售量超过了十万份,其中零售量超过一万五千份。这是与前导公司所有员工的努力分不开的。 m=:9+z
x=P\qjSa
<赤壁>的策划工作开始于<官渡>制作的后期,1996年6月。而程序开始的时间要晚一些,在1996年9月。那时侯我们碰巧见到了另一部国产游戏<生死之间>的早期版本。这给我们的震动非常大,因为这两个游戏的类型比较接近,而我们才刚刚开始这个游戏的制作而已。从程序开始动工,到第一个版本发行,一共9个月,先后参与程序编写的程序员有5人,总的工作量大约40个人月。程序代码的总量约为90000行,2.6MB。大部分用C++编写,少部分由C和汇编编写。我们使用Microsoft Visual C++ 4.0编译<赤壁>标准版,Microsoft Visual C++ 5.0编译<赤壁>增强版。可执行文件大小约为500多KB。 By!o3}~g
m+[Ux{$
<赤壁>的工作进度如下: c7k~S-nU
程序设计期:1996年9月初至1996年11月底。 H/
HMm{4
底层制作期:1996年12月初至1997年2月底。 C ;W"wBz9
游戏编写期:1997年3月初至1997年5月底。 IHac:=*Q
游戏测试期:1997年6月初至1997年6月底。 rglXs
~q.F<6O
日文版: 1997年8月。 p8O2Z?\
OEM版: 1997年9月。 (y~TL*B
韩文版: 1997年11月。 mO7]9p
繁体版: 1997年12月。 +~$ ]}%
增强版: 1997年12月。 EW OVx*l
sY&IquK^
需要说明一点:那就是我们的所有程序全部都是自己完成的,没有使用任何其他人其他公司提供给我们的代码。要知道,我们公司当时还没有能力去购买国外的游戏引擎,而我个人连SoftICE都不会使用,更不要说跟踪研究别人的代码了。我们对别人的学习方式非常简单和直接,就是观察。通过观察猜测它所使用的方法,然后考虑自己如何把它实现。这可能是我想到的最笨的一种方法,如果一个程序员能力强,在制作游戏以前,详细分析了解别的游戏的算法我想一定是非常有用的,他在制作游戏时一定可以节约不少走弯路的时间。 B~ GbF*j
另外,我们对<赤壁>的测试时间也是很短的,在程序基本稳定之后,我们大概只剩下两个星期左右的时间。所以有很多Bug。 .*Y
*i%.;Z"
2.2 模块划分 5|s\*bV`
kbQ>a5`,x
赤壁的程序分成五个大的部分和19个模块: #=A)XlZMd
显示模块 )7Wf@@R'F
战场显示模块 AQvudx)@"
分为通用显示底层和游戏战场显示。 6A-|[(NS
通用显示底层是基于DirectDraw的一套函数。 /W<;Z;zk
有关内容请详见DDApi.h, DDCompo.h。 jV1.Yz(`
|u<7?)mp
游戏战场显示是根据游戏单元的类型,位置,状态,动画帧等数据将单元位图以适当形式显示在战场的适当的位置上。要显示的内容有:地形,单元(士兵/建筑/将领),攻击效果,魔法效果,远程武器物体,阴影等。 wlqksG[B
主要功能有:对图素的压缩和读取,图像的显示,单元归属颜色的转换,边界剪裁,遮挡关系,缩略图显示和响应,屏幕移动,阴影遮挡判断,攻击效果,魔法效果,远程武器物体的显示和移动。 ^6V[=!& H
有关内容请详见CBDraw.h, 显示单元的位图 yNBfUj -L
CBDrawM.h, 显示特殊效果,比如水。 &j"?\f?
CBDrawOT.h, 显示特殊物体。 db7B^|Di
CBMini.h, 显示缩略图。 oD.Cs'
CBMap.h, 图素的操作。 #q=Efn'
CBShadow.h, 阴影的计算和显示。 +a+Om73B2
CBOther.h, 特殊效果的显示和计算。 ^hM4j{|&M
dUZ
,m9u
界面显示模块 Zb>? 8
根据游戏设计需要,在显示器相应的位置上显示游戏的各层界面。 <\^8fn
它分为两个部分:界面底层部分和游戏界面部分。 f2`2,?
界面底层是属于底层部分的通用函数库。它包括按钮,对话框,滑块,检查框等界面元素的实现。 VY4yS*y
有关内容请详见DDBitmap.h, 显示位图的基类。 _]H&,</
DDButton.h, 按钮。 yvB.&<]No
DDCheck.h, 检查框。 JK5gQ3C[
DDList.h, 列表框。 n Dxz~8
DDMenu.h, 菜单。 !_)[/q"
DDScroll.h, 滚动条。 VpDbHAg
DDText.h, 文字。 h*](a_0
iqWQ!r^
游戏界面主要有:游戏主菜单,新游戏菜单,读取进度菜单,保存进度菜单,网络选择菜单,系统设置菜单,任务提示菜单,结束菜单,错误处理对话框等。 on`3&0,.
有关内容请详见Interfac.h, 提供基本的游戏界面接口函数。 <>rneHl8
Interfa1.h, 处理所有的按钮Button信息。 m;QMQeGz
Interfa2.h, 处理所有鼠标操作发出的消息。 hz@bW2S.
net_face.h, 网络部分界面。 rg!r[1c
Marco.h, 所有按钮的消息ID。 rjYJs*#
CBprompt.h, 游戏战场中屏幕右方信息的显示。 0x@
mZ
CBAarray.h, 对游戏元素的查询。 )jP1or
DDComUn.h, 针对游戏中下达命令时的命令组。 3f{3NzN
lt8|9"9<
过场动画模块 @Jw-8Q{
显示公司标志,制作群,历时回顾,片头,片尾和过场动画。 SE %pw9
它有两个部分,第一是播放视频图像,第二是调用其它进程。 M .mfw#*
有关内容请详见CBAvi.h, 视频图像的播放。 D'Q\za
Mciapi.h, 播放AVI文件的底层函数。 EaN6^S=
VCMApi.h, 高效率的播放AVI的底层函数。 N`e[:[
CBGame.h, 播放结尾。 XXa|BZ1RX
Interface.h, 程序状态的转换。 cVF"!.
3
Za} b|
单挑显示模块 AoxA+.O
武将单挑时出现的专门画面。本部分与原始设计有出入,原始设计中可以对单挑进行操作,后来删减称为只播放一段Video。有关内容请详见CBAvi.h。 h2d(?vOT
m9rp8r*e
控制模块 T_4/C2
鼠标控制模块 ,k3FRes3
根据鼠标的位置设置鼠标的形状,对鼠标的操作对响应单元发出命令。 /gP+N2o+}
主要内容有:鼠标点击检测,目的地模式,命令构造,可建造区域判定,鼠标形状转换。 S<Xf>-8w
鼠标点击检测,主要判断鼠标点击的位置是否在某个单元上或地形上。详见CBMouse.h。 4^:=xL
目的地模式,主要控制鼠标选择了单元(命令主体)后,可能对单元下达的命令的模式,根据不同的命令可能需要不同的目的地类型和命令参数。详见CBCtrl.h。 "4{r6[dn
命令构造,通过鼠标的点击选择或按下某个,命令按钮,构造出具有命令主体,命令ID和命令客体的命令,放到命令队列中,供执行。详见CBCtrl.h。 UJ
可建造区域判定,在建造建筑时需要判断哪里可以建造哪里不可以, 并且显示出来。详见CBBuild.h。 k{-Cwo
鼠标形状转换,鼠标移动到某个界面或某个单元上时,或处于命令构造阶段时,需要对鼠标的形状做一定的改变,以显示当前的操作状态。详见CBMouse.h。 vEJbA
k9L;!TH~1K
命令处理模块 ]c'A%:f<
根据鼠标和人工智能发出的命令,传送给对象单元,并将其转化成为单元的相应状态序列。 C?eH]hkZ3
根据单元状态,判断单元状况,更改单元的状态。 <Q3c[ Y
详见CBCtrl.h, 命令的构造保存和传递。 . $vK&k
CBRun.h, 命令的执行。 Q^")jPd
CBRDelay.h, 命令执行时需要的一些变量。 _oeS Uzq.
`;egv*!P
攻击计算模块 I; rGD^
根据敌我双方的攻防力量,计谋的实施和阵型计算每一次打击敌人生命的损失。 c]!V'#U
详见CBRun.h, 攻击计算。 WH^%:4
CBZhenFa.h, 阵法计算。 a\*yZlXKs
5nx1i
行军控制模块 UkFC~17P
根据单元的位置,速度,目的地和地形数据,计算行军路线,设置单元的下一步。详见March_n.h。 ,z=LY5_z)
Qo|\-y-#
网络控制模块 tKXIk9e
游戏数据在网络上的传递,纠错。模拟机的建立和管理。详见Network.h。 SE*g;Cvg1
j0q&&9/Jj
策略模块 CpTjJXb
君主策略模块 3u0RKLc\
计算机一方根据战场双方的力量对比和战斗模式计算对单元的生产,对敌人的攻击,产生命令。 l.M0`Cn-%
详见TEmperor.h。 U 6)#}
h/Y'<:
将领策略模块 sRb9`u=)
每一支部队根据将领的属性,士兵的状况调整战斗的方式或判断撤退。 1?l1:}^L
详见TGeneral.h。 YGNP53CU
N8df8=.kw
本能策略模块 )vlhN2iv
士兵单元面对周围的情况产生固定的基本反应。 rYk0
ak
详见Tai.h。 ?}Y]|c^W
Tbnbase.h, 人工智能中需要的数据结构。 p5*EA
x
CBEyes.h, 人工智能与游戏主体结构之间的接口。 x]j W<A
UJ2U1H54h
文件模块 xyXa .
资料数据文件模块 xskz)kk
地形和单元图素的图像文件,相应控制数据文件。单元的各项属性数据文件,操作用数据文件,界面位置数据文件。 VUuE T
详见CBData.h, 游戏中使用的单元属性全局数据结构。 2&cT~ZX&'
CBMap.h, 游戏中使用的地图图素,单元图素全局数据结构。
gs`q6f%(
CBGame.h, 游戏中使用的单元全局数据结构。 v`T
c}c '
qf-8<{T
存储数据文件模块 )boE/4
存盘用数据,记录战场上的所有单元的状态和思考数据。 -mh3DhJ,
详见CBGame.h, 存盘。 *{5fq_
(/$^uWj
其它模块 {P-):
~&uHbTq
文件封装模块 |Y.?_lC
为减少程序使用的文件的数量,增加程序的安全性,将大量的图像文件和数据文件封装起来,供程序调用。 {M)Nnst"~
详见L_Allbmp.h, L_Image.h, L_Save.h, L_Scan.h, L_Text.h, Tools.h。 Q/Rqa5LI:
{n=|Db~S
声音模块 8eRLy/`gd
背景音乐和音效。有混音和音量控制。 #<xm.
详见DsWave.h, 播放WAV文件。 6aj!Q*(WT
-yg7;ff
文字模块 `WS&rmq&'
在非中文系统下显示汉字,日文,繁体汉字和韩文。详见puthz.h。 "<gOzXpa
DHRlWQox
地图编辑器 -Lg
Ei3m
为使美术人员方便快捷规范地制做战场地图,提供专门的地图编辑器。同时为整个游戏的文件系统,显示系统做技术上的准备。 f6p/5]=J26
这是一个单独运行的程序,详见Mapedit。exe。 dc'Y`e
4<v&S2Yq
安装程序 }6ldjCT/,
将游戏安装和卸载。详见Setup。exe。 N$tGQ@
;9#KeA _
2.3 游戏引擎 ia?
c0xL
说到游戏的引擎,很多人都不知道它是什么,以为制作它有多么困难。引擎的概念也很混乱,至少现在我还不知道它的确切定义。但我想如果一个东西要被称作引擎,它应该具有这样一些特点: yt2PU_),
它应该是由函数组成的。 RM/ 0A|
它应该实现某项具体功能。 E?@m?@*/
它应该是完整的。 y1#1Ne_
它应该可以被重新使用。 J.%IfN
2`-Bs
从上面的要求可以看出,其实这就是作为底层程序的要求。我想没有必要把引擎认为是游戏的现成编写工具,只要2改一下美术就是另一个游戏了。只要这些程序代码将会被我们应用在以后的游戏中,我们就已经节约了很多的时间和精力。 ,]D,P
下面我会说一下在<赤壁>的代码里,哪些将被看作我们的引擎。实际上,这些部分经过一些修改后正在被我们应用到新的产品中。 2Khv>#l
=EsavN
显示底层: +w~oH =
这是一套包裹在DirectDraw外面的函数。为了简化在调用DirectDraw函数时的复杂度我们使用了一些缺省参数和内部错误处理函数。建立了一个CDDSurface类库,使得对位图的使用更加简单。详见DDApi.h @(lh%@hO
在DDCompo.h中我们有关于游戏鼠标的一套操作。在屏幕独占模式中,Windows标准鼠标有时显示会不正常。于是我们自己制作了鼠标的显示方法。方法很简单,在每帧读取鼠标的位置,然后在该位置上显示一张位图。 0+8e,
在赤壁里面,我们没有使用双缓冲区的模式,而是只更新某个特定的区域。它的优点是当需要更新哪里的时侯就更新哪里,对于哪些在每帧中都只有小面积图像需要更新时是非常高效的。比如在486上,<赤壁>的主游戏界面里的鼠标移动仍然是十分流畅的。可惜的是,在<赤壁>的战场部分,它并没有优势,因为基本上是需要全屏刷新的。 |vC~HJpuv'
在未来的游戏制作中,因为计算机的速度越来越快,所以我们当时所使用的模式恐怕变得不太适用,双缓冲区模式应该是主流方向。 E" vS $
hqdDm
多媒体底层: 1 -b_~DF
主要包括声音和视频。我们使用了MCI设备来播放AVI,WAV,MIDI,CD AUDIO等内容。那曾经是我们在做上一个游戏的时侯完成的部分。但是它有很多缺点,比如不能同时播放多个WAV文件,这对于我们制作游戏音效是很重要的内容。 pK4)yu+
所以我们又使用DirectSound来播放声音。这里的难点在于当我们需要播放很长的文件时,不能一次读入,而需要建立新的线程按时装入声音。好在现在大部分游戏都使用CD Audio作为背景音乐,不需要WAV。 1.>m@Slr>
HbIF^LeY|R
界面底层: Alq(QDs
基于显示底层之上的界面元素其实并不好做。因为我们总希望它的响应方式与Windows95中相同。而大家在<赤壁>里看到的内容就与Windows95有些不一样。比如滚动条(ScrollBar)对鼠标的响应就非常简单,按钮(Button)的反应也有所不同。但是好在它比较简单,易于使用。 @}ZVtrz
6dYMwMH
在每做完一个游戏之后,我们都习惯要把某些东西整理一下,看看它是否可以在以后被使用起来。而往往这些东西也都是需要不断修改的。因为程序运行的平台不一样了,它的用途也不一样了,而我们的编程水平也不一样了。但总之这些代码被较为完整地保留了下来,它必将是我们今后编程的基石。 "Y.y:Vv;
OZ&o:/*HM
2.4 关键讨论 ,fRq5"?
Ts x>&W