小小游戏程序员四个月工作总结
分 3 部分写,工作内容及其解释,实际我做的事,我获得的经验。
1、windows下的错误捕获及Dump。(Error report and dump)
内容:事实上是程序未处理异常的捕获及minidump。
我做的事情:这是我在公司除了看代码干的第一件事。总监很给时间。让我用大半天的时间看完了
经验:光这个小事情,我懂了一大堆东西,从windows SEH到函数调用,dump的机制,到dump文件的使用。更是对
2、windows&Linux下的底层文件系统(FileSystem):
内容:事实上这个文件系统牵扯很多,主要包括一个类似MPQ的文件打包系统将大量的小文件全部打包成一个大文件,并通过哈希表,块表来索引,以减少文件的I/O时间,并方便统一的加解密。
我做的事情:最开始用了半周的时间去弄清楚了MPQ的源代码,不得不佩服一下
整个文件系统差不多也就完成了。中间值得一提的就是windows本身的文件读取机制很奇怪。读取普通文件的效率起伏很大,有时很快,有时慢的要死,而且切换目录对于文件读取的效率有很大的影响。并且出人意料的是一旦你用了seek,那么整个文件的读取效率都会奇低,这是我开始没有注意到而导致序列化速度奇慢的原因。
经验:二进制数据,计算机的所有数据不就是二进制的数据吗?没有什么大不了的,经过文件系统的设计及实现,深深的懂得了什么叫关心效率,什么叫代码的健壮。听了太多的现在计算机速度越来越快不需要关心效率的话,在这里完全都不适用,不关心效率,还做这么多工作干什么??
3、文件更新包
内容:实际包括普通文件的比较更新和打包格式文件的比较和更新。更新包(patch)的制作,自解压运行模块。
我做的工作:更新包(patch)格式的设计及编码,自解压运行模块的设计及编码。因为打包系统里面有比较包的接口,所以我做的主要就是patch包的格式设计了。本来想套用打包系统的,后来因为老总想让此系统更加通用,被老总否定。于是重新设计了一套文件系统,包括索引表和文件内容,相当于一个简单的打包系统了。说明一下的是我仅确定了patch的格式和提供了patch制作的接口,实际的patch制作过程由工具组的兄弟调用接口完成。而自解压模块有开源代码,我实际也仅仅做了点修补工作。实际工作1周左右。
经验:又见二进制数据,又一个文件格式,在制作patch时用了序列化函数,自己写了一套内存序列化的类。使用起来的确方便。比起以前的打包格式中全靠底层接口来write,read要方便许多,对序列化的理解深入了不少。不过这里有个疑问就是公司的序列化为什么不用C++的stream系统来完成,而是全用C语言那一套,靠函数而不靠重载«操作符呢?我个人感觉上,«,»操作和序列化就类似于序列化,也可能是从序列化发展过来的。
4、游戏界面(gameui)相关
内容:为游戏制作一个与游戏主窗口并行的外部聊天的窗口,和让游戏最小化到系统图标(TrayIcon)的功能。TrayIcon状态还能出现相应的提示信息。
我做的工作:其实不多,外部聊天窗口就是利用交换链来渲染,共用游戏中窗口的XML配置文件来确定框架。TrayIcon状态完成也很容易,难得就是提示消息窗口的出现和消息的响应。和正确的显示半透明的PNG图。为了达到需求还得要求点击提示窗口确定位置,游戏中有相应动作的发生。实际工作完成用了近两周。
经验:了解了公司游戏的框架,包括gameui,消息订阅模式的使用等。最主要的了解来自于让3个消息提示窗口正常的响应消息。要知道,这些全部要求用win32程序完成,不是MFC,所以消息的响应全部靠我自己维护的外部的map完成,深刻的理解了总监所说的MFC消息分配发送机制。
5、游戏性能的优化相关
内容:分析游戏中显示tooltips速度过慢的原因,分析对比3种XML解析器的效率,并确定使用哪一种XML解析器。(tinyXML,expatXML,XerceXML)
我做的工作:分析tooltips为什么速度过慢,最简单不过了,不过是大片的插入时间检验,最后得出结果。最后对游戏中底层分配创建框架窗口的方式进行了优化。原程序是大面积的if else string对比,优化成类工厂创建方式。效率提高不少。接着分析XML解析器,这可是个难工作,因为我不仅要分析对比他们的效率都要求放到游戏中实际的检测,所以我还得负责写此XML解析器在游戏中使用的接口,另外还由于游戏中现有的XML解析文件都是utf8的,还要求我换到unicode去,最后还需要了解每个XML解析器的接口,然后测效率。有意思的是,tinyXML(游戏中现有XML解析器)写出来的XML文件有的地方不够规范,其他两个XML解析器不能正常解析,还是我手动调整了不规范的地方(主要是少空格)然后才能正常解析。这些工作都花了我1周多的时间。
经验:检验程序效率的方法,实践中体会2-8原理,在实践中应用工厂模式,体会其在C++中的使用方式(太多的宏),在实践中进一步确定了重复工作时,正则表达式非常复杂替换的应用效果。这次有近80个类,不是靠替换,我会吐血的。了解XML文件解析器的接口,了解了XML文件解析器的一些相关信息,现在忘了不少-_-!。
6、游戏的脚本系统(lua)
内容:为游戏中添加新的脚本系统,了解脚本系统在游戏中的应用,并设法为游戏UI编辑器添加脚本管理功能。
我做的工作:了解脚本系统与游戏现有内容的结合接口设计。理解lua代码中C++程序的运行时调用。(利用tolua++)。学习了lua语言:)。用了一周多的时间其中有3天公司什么工作都没有给我分配,就让我好好的学lua。。。。太感激了最后这个工作做了一周多就转向下一项工作,这个工作没有任何成果就废弃。
经验:真正的算是了解了一门脚本语言lua,对lua的嵌入式应用感受颇深。为了达到这个目的,lua的设计之简洁让我佩服不已,使用起来的确非常方便,除了与C语言的调用接口虚拟堆栈有点复杂外,lua为C语言设计库,C语言为lua设计模块都是非常之简单。让我对脚本语言产生兴趣,开始重拾python。边看边实践的看完了整个一本
7、游戏日志服务器
内容:将游戏中需要记录的所有事件全部写入mysql数据库。
我做的工作:首先熟悉了现有的ODBC框架,并将其应用于mysql数据库,后又因为ODBC效率偏低而改为纯mysql C API的调用。仿照原有ODBC框架,写mysql CAPI的封装,用了两层连接池以支持多数据库,多连接。以udp通信收包,收到即写入mysql数据库。根据需求,设计了5个通讯包,在公司原有的服务器框架上,构建日志服务器。并写了一个自动创建相关库的辅助程序。实际现在正在做的工作。
经验:进一步的了解了网络及多线程编程。重新熟悉了SQL语句(中途学过n次,因为工作中不用又忘了n次)。了解了mysql这个数据库的使用及其API。了解了公司的服务器框架,(真是精巧啊)。更加感激这个实际上有正则表达式和vim这个东西,没有他们,60多个字段的包会将我写崩溃的。
其他:
-
因为从lua产生的兴趣,开始回顾以前学习的python,并开始认真的对待。以前的确学过一些时间,但是因为后来还是去学C++了,没有太在意。现在重新学习的感觉是python的库实在是#@%#@$%$#@^丰富的太夸张了。
-
因为学习lua没有太好用的编辑器,重拾vim,第一次用vim是在大学用linux的时候,学了一下有个初步印象。没有好好用。后来再学vim是后来学win32汇编的时候的确没有合适的编辑器可以用,当时想到的就是使用vim这个万能编辑器。那时才算能将vim做一般的编辑器来用的水平了。后来在做filesystem到linux的移植的时候,又重新回顾了vim的一些用法,到了写lua程序的时候,已经驾轻就熟了,vim的确属于c++一类,没有学会百般难用,学会以后受用无穷。
这里特别谈一点我感觉特别受用的vim的使用经验: :)
1. u转换小写,U转换大小特别好用,普通模式配合g来使用
2. CTRL-A,CTRL-X配合q的记录功能简直可以实现你想要的任何复杂重复性操作。
3. vim有很大一组命名的寄存器,你可以指定使用。用@
4. 在windows下希望能和外部的CTRL-C,CTRL-V共用剪贴板,使用设置
set clipborad=unnamed。
5. map一族学会怎么使用以后,你可以实现你想要的n多功能,比如我就喜欢普通模式下enter,backspace,space按键不仅仅是移动,也是和插入模式一样的操作。那么可以这样:
" 添加空格
nmap <Space> i<Space><Esc>l
" back删除
nmap <BS> i<BS><Esc>l
" 回车向下移动
nmap <CR> i<CR><Esc>
我还喜欢能有个全部选择的功能,可以这样:
" 全选
nmap <C-Q> ggVG
6. << >> 操作很好用:)特别对于python这种不能自动排版的语言来说。
好了,其他的就不多讲了,自己体会体会吧:)
- 正则表达式的应用我可以说是感觉非常之好,可以实现很多很多你本来需要大量重复性机械运动才能实现的功能。(以下以VS2005windows的语法为准,并且我仅仅是回顾和介绍,不一定还准确。)简单的说一下,比如我有一次忘了在所有的日志输出后面加\n表示换行,一个一个寻找那可就费事了。可以这样:用{LOG("。#}{");\n}查找,用\1\n\2匹配,就相当于在最后的”前加了一个\n符号,这样你先替换一两个看看对不对,直接就可以来个全局的替换,很有效率的完成了需要大量且容易遗漏的操作。
再说个更复杂的例子,这个例子中我综合了vim和正则表达时的使用:
比如:在确定包的时候,有60多个字段,我需要绑定60多个参数才能完成一个SQL语句,大量的操作都是bind[n]。xx = yy;类似的操作,但是每个n,xx,yy都需要你手工填写,因为都是不一样的。n的自增长,你可以通过C++语言的i++来代替,但是那会带来不直观的效果,因为你编写代码时无法与相应的字段一一对应。手工填写每个n,写60多次,会很痛苦,这里用vim的q记录,下一n行,CTRL-A增长1,q结束。[count]@执行那么多次,一次完成:)至于后面的xxx是包中的一个字段,可以通过正则表达式的匹配来完成,首先我利用的是生成表的SQL语句,我当时写的时候是一行一个字段,去掉CREATE TABLE等头尾字段,类似于
ValueLv TINY NOT NULL,
ItemID INT NOT NULL,
以mySQL绑定参数的语句为例:
最主要的是类似下面的两条:
bind[n]。buffer_type= MYSQL_TYPE_LONG;
bind[n]。buffer= (char *)&int_data;
首先类型,类型这一句可以通过查找TINY,INT这个字段来匹配。
其次int_data这个,需要的是包中的实际一个字段,这里我投机取巧的地方在于
表名正好就是包中的去了前缀mi的实际成员变量名。
于是可以通过
{:w+} {:w+} NOT NULL,\n
来匹配一行SQL语句,mi\1就是变量名,由于INT在buffer_type中叫LONG,所以只
能分两次来生成,首先找到所有的TINY,再找到全部的INT。类似下面这样
匹配 {:w+} TINY NOT NULL,\n
替换: bind[n]。buffer_type = MYSQL_TYPE_TINY;
bind[n]。buffer = (char *)&mi\1;
一个全局替换以后,所有TINY类型的SQL语句全部编程你想要的参数绑定语句了,
INT和其他类型操作类似:),当参数的确多的时候,比如我需要操作的是100多个
字段,那这样的操作简化的可就不是一点点啊:)。
-
看完了原版的<Effective C++>,真的感触挺多,的确感觉自己对c++的理解上升了一个层次,感受最多的是4,5,6三章,基本上自己慢慢去适应Meyers提出的建议,在碰到一次析构函数没有正常调用时,第一时间反应正确,基类没有虚析构。。。。
-
看了半本booch的<面向对象分析与设计>,感觉自己还没有到工程领域高度那个阶段。。。。放弃。本人目前毕竟还是个单纯,简单的IT工人,小程序员而已。其实不是不想看。。。学术性太强,看的摸不找边际。面向对象分析与设计>
再其他:
-
老总要的是什么?大局观,思路清晰。不得不说一下,我们老总的技术实力实在是够强的,从服务器到客户端无所不管,无所不通,而且无所不思路比我们清晰。他说的做事要讲究方法,首先要思路清晰的教训一直牢记脑海,在公司,我感觉自己更像是在学校,做个学习的学生而已。
-
程序员是什么?要先满足需求(游戏里面是策划),还要围着运维转。的确是,老总说了原因,程序的开发就算有难度,但是开发就是一下的事,开发完了就算完了,而别人的使用是长时间的,有一点点别扭也是别扭很长时间,累计起来就是很不方便。不过我确得承认老总的话的确是对的,难得是其作为研发的头还能有这样的认识。自叹不如。
-
关于策划,常听策划的头教训手下,本人似乎也挺受教。。。。呵呵,还是思路问题,策划也需要思路,不仅仅是文字工作而已。”人物的血加了,怪不加?像话?一开始的引导让人卡了,怎么做的?”游戏任务的引导是此时我才有了清晰的认识。以前光就玩,从来没有从开发层次来想过。
“开始应该让人上手啊,难的东西给高级玩家去玩,不能一开始就难倒普通玩家。”
真理。。。。。
“策划为主还是美工为主?怎么能因为美工这样画的,策划就去迁就美工?”
这才叫真正的思路。。。。与老总的运维,策划为主如出一辙。。。。。
够了。。。。等再过几个月再来总结吧。。。。。呵呵
By 九天雁翎
2008年08月31日 | 九天雁翎的博客