Quake3是Idsoft的大作,属于差不多20年前的东西,大神John Carmark所在团队的作品,之前分析了一下著名的平方根求倒算法,研究了一段时间源码,算是小有所成,这篇文章主要泛泛的介绍一下下,谈一下自己的心得体会。
首先谈一下编程风格,用的是C语言写的,加上少量汇编,应该标准C,完全没有c++,没有stl,没有模板等;
甚至连动态数组都没有,所以所用到的数据结构基本都是独立实现的...
由于用的是C,连类都没有,因此通过类似全局结构体加上函数的方式来实现类似类的功能
这也充分证明了一点,面向对象编程并不是必须的,即使没有对象也可以写出好代码,这和我的观点是一致的
整体来看,代码还是比较清晰的,不算特别难读吧
内存管理部分独立实现了一个内存池。。。 用的是链表的形式实现的,代码不是特别难懂,基本看明白了,此前从来不知道内存池该怎么实现,现在终于知道怎么实现了。
大概思路就是申请一大块内存,有一个指针指向空闲区域,前面一小段存着一个定长的头信息,后面给用户分配数据,然后头信息指向后面一块空闲地址的头,整个构成一个双向链表结构,每次分配内存时,从空闲地方开始向后迭代,找到符合的大小就分配,更新链表,如果是释放内存,会把相邻的合并起来,由于这里不想写的太细,就写这么多,回头博主有机会会用c++实现一个内存池,贴给大家看
有用到hashmap,也是独立实现的。。。
我当时看这段代码看了半天不知道在干啥,代码并没有告诉我这个hashmMap,看到最后发现貌似是个hashMap啊,然后一分析,果然是的,好吧,这下知道hashMap怎么实现了。。
其实也很简单,还是一块buf,每个格放一个链表结构,再加一个hash函数,ok,hash函数也是独立实现的,比较简单的一个实现
从某种意义上来说,quake3的代码有些过时了,毕竟用的是c,c++11的unordered_map就是个hashmap,现在已经不需要自己去实现了,不过quake3的作者信手拈来就是个hashMap。。有点犀利。
作者经常进行各种位运算,看着晕,不过仔细一分析,还挺有道理, 可能是比较追求效率吧,整个代码风格都有追求效率的倾向,这个和一般的编程极客差不多,都有这个特点。
至于代码注释方便,比较关键的函数会有一段注释,其余基本没有,额,这个和人现代编码风格比较接近....
架构方面,看了一些,总体感觉还是挺牛的,大概这样
quake3.exe,这是引擎,主要干两件事:
1,收集服务器客户端传来的消息以及系统消息;然后根据自己是服务器还是客户端转给相应的vm处理
你可能要问我vm是什么,vm是虚拟机的意思。。。 也就是作者实现了个虚拟机在引擎里面,好吧,真是什么都有。。
而且还实现了编译器。。。好吧。。
不过因为vm有很多汇编代码,超出博主能力范畴了,看不懂,也就没怎么看,但是vm有一个替代解决方案,就是dll,
代码里有一段大概意思是根据情况选择vm还是dll,所以不深究的话可以把vm理解为一个高级dll即可,我们下面就针对dll来说明
2, vm有3个,一个是服务器的vm, 客户端有2个vm,一个是ui,一个是cgame(游戏逻辑吧)
3,quake收集了消息之后,就会调vm接口 VM_Call,(对于dll来说其实就是调导出函数),
4,然后vm也可以和quake发消息,因为quake和vm互传了一个函数指针,
一般流程如下:
quake收集各种消息 调用VM_call,vm处理逻辑,如果需要什么信息,通过system_call去quake拿,渲染也是通过system_call触发,然后quake绑了个renderer.lib,主要负责渲染和opengl打交道,当然游戏是少不了opengl的。。
quake调vm通过VM_Call vm调quake通过system_call,然后各自分工,大概就这么回事
这么设计个人感觉还是不错的,引擎主要负责事件收集分发和渲染,客户端和服务器只处理逻辑,这样与系统打交道的部分就全在引擎,相当于引擎把脏活累活全干了,客户端和服务器专注于业务逻辑,挺好,这部分设计很有参考价值。
quake3最经典的就是BSP了,貌似doom,还是quake3(反正一家的就不区分了)第一次在游戏中实现了bsp,
bsp的代码我看懂了也没看懂,因为有多个bsp(作用不同)。。
不知道那个时候没有z-buffer还是啥的,渲染是用的bsp,(不过我在代码里看到了一个z-buffer的单词...)
这个bsp算法也是独立写的,其中用于渲染的bsp我看明白了,不过貌似还有两个bsp没看明白
bsp就是2叉空间分割树,主要用于提升渲染效率或者是碰撞检测,这里不展开了,可以百度谷歌
当然游戏少不了AI,quake3实现了一套机器人AI. bot.lib,连AI也有。。。。这部分有一篇论文专门介绍,论文很长,还没怎么看,这部分就先略过
bot.lib是由服务器调用的,和客户端没关系;
quake的网络部分貌似也很牛,这部分代码没看,看了下介绍,用了一个snapshot机制,大意是做增量补偿的意思,减少数据传输量,客户端有做延迟补偿,这里具体逻辑还没看明白
感觉quake里基本上你能想到的东西都有了,确实无愧一代传奇代码,总的来说虽然代码量很多,但是相对于游戏引擎来说还不算太复杂,属于性价比 比较高的那种,很有学习的价值
之前我一直觉着c++不错,但有它的局限性,有些东西实现起来不方便,库比较少,其他语言如火如荼兴起的,go,python,让我认为有些东西可能是c++做不了的,或者实现比较麻烦的,因此我觉着每种编程语言各有优缺点;当时就想把所有主流编程语言全学会,不过看了quake3的代码之后我觉着没必要了,因为整个游戏全是用C语言实现的,
AI,图形引擎,服务器,客户端,网络,编译器,所有一切都用c和汇编搞定了,连c++都没有,面向对象编程都没用
这既说明了c语言的强大,也说明了如果你觉着一门编程语言不够好,可能是。。。
现在我相信C和C++可以做任何事,因为20年前就有人做到了,并把这些代码展现在了我面前。