那些日子(五)
今天已经开始上班了,最近很忙很忙。在调游戏的数值,很繁琐的事情,还要写程序去模拟。整个项目也需要人去照看。
这个系列,我想会坚持写下去。但是不想成为自己的负担,我想这样才能写的自然。因为都是写一些真实发生的事情,和身边的朋友,按记忆按自己的理解去写就好了。不像写小说,会担心有逻辑上的漏洞,会困扰于故事中每个人的结局该怎么安排。所以,挖了坑不知道该怎么填上这种事情多半不会发生的。
已经开始有朋友写 email 跟我聊这几天我写的这几篇东西了,有人抱怨为什么没写谁谁谁 :) 。这个问题其实上次解释过了,我是个不善于回忆和叙述的人,每次从记忆深处挖点东西出来,都会涌出一大堆的人和事。精力有限,只能挑选几个来写。
与其说这是我自己的故事,不如说是国内游戏圈中大家的故事。带着大家从我的眼睛,去看周遭的人。也有朋友抱怨,写的人太多太散,理不清头绪。其实,我也尽力去单独的一段一段描写那些熟悉的朋友,顾而不一定顺着时间的次序让他们入场。
关于国内游戏圈早年的一些事情,有兴趣的朋友可以 google 一下“北外隐形人”写的“中国游戏年代记”。是我读过的最全面的一个记录。从叙事角度看,猜想这个“北外隐形人”是游戏媒体圈子里的人。对于制作圈子来说,有一点点距离。有些东西写的有点偏差,比如 99 年时庞鑫大学还没毕业,不可能结婚的 :) 。同样,我的回忆也可能失实,尽量少写道听途说来的故事吧,呵呵。
一直以来写东西比较随性,有时候节奏慢点,有时候快点,跟心情有关。写这些基本不打稿子,想到哪写到哪。读的朋友得多加忍受了。记下这些往事,不是因为我喜欢缅怀过去,只是发现若再不总结一下,都快分不清好多事情的先后因果了。同时,也是帮身边的朋友们留下点滴,大家一起分享这小段美好的时光。
好了,以下是今天的正文,谢绝转载:
四月的广州,天气不错,甚至有点夏天的感觉。几年后,一个毕业实习生也是这个季节来到网易,住在我的家中。记得他曾感慨的说,知了怎么这么早就开始叫了,这里连空气里都充满着夏季的味道啊。我想那时我也是这个感觉,到处都是湿湿的,身上有点腻。和北方那种干燥真是截然不同呢。
网易的办公室在写字楼的顶楼,从卫生间门口的通道走出安全门,可以顺着外墙铁扶梯爬上天台。我很喜欢那里,吹着风,俯瞰繁华的广州。偶尔也有人出来抽根烟,我从不抽,但也不用担心吸二手烟。大家偶尔聊上两句,很惬意。
办公室里很拥挤,我想是因为新加入一大帮人的缘故。虽然额外租下了楼下第 18 层,但是没有多少改善。按网易一贯的风格,大家都坐在敞开的大办公区里,隔板不高,方便交流。我被安排在一角,前后都是原天夏工作室的程序。
micro 对于我能再次回到广州很高兴。兼职期间我写的那些模块尚未用上,因为毕竟那些是我自己的一些新想法,还没有和其他人沟通。client 的程序定下来三人,古越、我和果子。
果子,以我当时的眼光去看,是天夏的程序中编程水平最高的一人(不过他不是天夏的股东)。跟着天夏进入网易。第一天我们似乎讨论的是游戏中 UI 的问题。除了“天下”,大家都没有做过游戏,不知道游戏里的 UI 该怎么实现。果子给我看了几个用 gdi 写的 UI 小 demo ,做的不完整,也没有什么头绪用到游戏里。
接下来一两个月,UI 的问题也困扰着我。如果 engine 是由我负责的话,这种 client 的基础设施就理当给出一个解决方案。而我只有一点单机游戏的经验,在我的头脑中,游戏的 UI 都不复杂,简单的硬写出来就够了(比如古越在“天下”中干的那样)。但是直觉又告诉我,网络游戏会不一样,UI 的复杂度会高上一个数量级,不能简单对待。事后证明,我的直觉是正确的。大话西游 client 后期工作一半以上都是围绕 UI 展开的。
我在北京时,自学过一小段时间的 javascript 和 css ,曾惊叹于 web 页面可以达到如此的描述能力。虽然那个时候还不曾听说日后日趋成熟的 ajax 技术,但是我想,总有一天 web 页面上也会出现相当于传统客户端程序那样复杂的应用的。
网易有的是做这方面的技术人才,比如郭斌。我发现这个家伙对 javascript 很熟时,就老是跑过去缠着他问些相关的东西。比查 msdn 好用多了 :) 。郭斌这个人不错,听说对丁磊很是崇拜。所以很想安心在网易做一番事业。据说他入职网易后,立刻就结婚买房,在广州安家落户,一心做下去了(听人转述的)。
接触了好些新同事,以及评估了我们的进度计划日程后,我下了一个决定。这个日后反复被丁磊拿出来损我,当作是人都会犯错误的样本来教育新程序员的决定,我至今不认为它是个错误。那就是,在 client 中内嵌一个 IE ,实现游戏中的 UI 。
当时的计划是在 2001 年 9 月 15 日推出游戏。虽然我不认为 5 个月可以完成,但是我想我们的时间终归不是太多。一群没有多少经验的人做这样一个项目,没有多少头绪的情况下,找到任何一个可以分割项目,让它成为独立子项目的方案都是可行的选择,即使有技术难点,也是可以独立克服的。何况网易有许多做 javascipt 的熟手,甚至有成熟的 web 聊天服务,这些都是可以尽量利用的。
软件项目并不是人多就可以做的更快,《人月神话》里已经讲的够透彻了。让更多的程序员可以参入项目并做出贡献是非常困难的,比跨过特定的技术门槛更难。大多数情况下,增加人手只能帮倒忙。而这次,我们可以拉郭斌甚至更多网易的同事(后来做这一块时还加上了刘国斌)来做。而我们 client 组原有的三个人,可以专心于更小的一块工作。
为了嵌入 IE ,我花了不少精力做研究。那段时间读了 COM 的书,看了 ATL ,学到不少知识。不过最终问题并没有很好的解决。在那些紧张的日子里,留给我的时间不多,我不知道怎么做这些。不知道怎么从程序中直接拿到 HTML 页面上的鼠标键盘事件。最后是果子想了一个我们都公认很愚蠢的办法。写一个额外的控件注册进系统,在 javascript 里向这个控件发消息,然后由控件转发进我们的主程序。这个方案明显不符合大家的审美观,但是我有更多的事情要做,其他人也是。它可以工作,那么就那样了。
同期,我做了一件影响了后面很多年网易游戏 client 开发的事情。那设计游戏地图的数据格式,以及开发期这些数据的构建方式。
之前,几乎所有的游戏,都需要做一个场景(地图)编辑器。被业内简称为“地编”的工具,往往担负了超过一半的程序工作量。在我大学还没毕业的时候,曾经去珠海金山拜访朋友。剑侠情缘2 的主程王炜给我展示过他做的地图编辑器:游戏即编辑器,编辑器即游戏。发行给玩家的版本只是一个屏蔽掉编辑功能的编辑器而已。
这种方式并非不好,我也曾想这么做一个。但是时间不允许。所以我想到了另一个方法,直接出整图。
整图的方案不是没人干过,但是很多人做的不好。因为出整图是需要占用运行期大量的内存资源的,在当时的机器配置下,就不可能把场景做的太大。而且场景上一样有许多素材会和人发生前后遮挡,也需要编辑器去编辑他们。
我的思路很简单,能不做的工作我们就不做。如果只是描述一个 2d 场景,那么 photo shop 可以干的足够好,而且美术人员习惯用。遮挡关系的处理,我发明了一种简易的方法,用一个 mask 罩住背景图片,当角色需要绘制在后方时,engine 把背景上 mask 罩住的部分扣出来重新盖在角色图片上。这样,我们只需要做一张整图就够了。mask 也只需要用 2bit 描述一个像素(如果单单需要把场景上的一颗树这样的图素扣出来,mask 只需要 1bit 。但还需要一些额外信息描述前后关系,细节这里不展开介绍了),这些信息还可以很方便的压缩。我们需要额外设计的是,如何在 photo shop 里表达出这种 mask。最终的方案是为每个遮罩物创建单独的图层,选用黑红蓝等颜色区分出来。
这套方案是我在家时就想好了的,兼职期间也一直在做这种特殊 mask 的实现。来到广州后,果子帮我研究了 psd 文档的格式,并写程序提取出相应的 psd 文件中每个图层里的数据。
当每个人都可以专心做特定的一件事,比如美术人员可以专心用他熟悉的工具制作一张大的图片时,工程才能合理有序的进行下去。额外需要做的事情是有专人去勾勒出遮罩,分出图层,按事先约定的规则起好名字。
关于内存占用的问题,如果把整个场景的图片全部载入内存显然是不合适的。假设游戏场景有 6400 * 4800 像素那么大(实际上我们后来设计出的游戏场景比这还要大),单单一张背景高彩图片就要占掉 58M 内存。而我们的设计目标是让 64M 内存的机器也可以流畅的运行游戏。况且,60M 的数据加载也是个大问题,我个人作为一个玩家,非常痛恨游戏中缓慢的加载进度条。
最后,我决定尝试分割游戏场景数据,采用运行时动态加载的方式工作。经过测算,为了达到目标,为场景数据预留的内存不应该超过 12M 。我把图片和其它数据拆分成 320 * 240 的小块,当玩家操作主角奔跑于游戏场景中时,engine 根据他的移动方向,预估 client 即将需要显示的场景,最多会把 5 块预读到内存中(游戏的分辨率被固定在 640 * 480 高彩模式)。
为了提高加载速度,我权衡了 IO 速度和压缩图象的解码时间。结论是,如果直接保存未压缩的图片在硬盘上,以当时普通的硬盘,绝对做不到流畅的无缝读取(玩家移动于存在于内存和外存中场景块之间的缝隙)。如果使用高压缩比的压缩格式,比如 jpeg ,又会占用太多的 cpu 时间,同样会影响游戏感。最终我稍微改造了 jpeg 的数据格式,并简化了解码流程(牺牲了一点图象质量),使用大学期间自己用汇编写的一个 jpeg 解码器解决了这个问题。
地图加载这一块使用的多线程技术。不知天高地厚的我,没有任何多线程实战经验的情况下,开始编写这块代码。多线程编程出现的各种问题把我折腾的头昏脑胀,难度远远超过预想。前后花了 1 个半月时间才基本稳定下来。事实上,还遗留了一些 bug 。当程序崩溃时,地图加载的模块会蹦出一个对话框,标题栏上是我挑选的最喜欢的几句《大话西游》电影中经典台词中随机选出的一句。如果还有大话1的第一批老玩家读到这里,应该能想起早期那时不时蹦出的对话框,“悟空,你又调皮了”。
不少玩家曾经猜想过那些句子背后的含义,甚至有人投诉过网易,程序出错还蹦个对话框羞辱玩家 。哈,借唐僧的口我自嘲而已。
当这段代码最终稳定下来,已经惨不忍睹。后来很多年,我们几个产品轮替,大多数代码被重写。但一直没人敢把这块东西推翻。据说这两年做大话 3 的同事终于下决心重新弄了一遍,不简单啊。不过也有一定原因是,我们现在不再需要那么精心推敲内存的占用,硬盘的加载速度了。当硬件上升一个档次,程序员们就可以站的更高,在更高的层面考虑优化问题,反而让系统工作的更好。
当年 windows 95 就是一个例子,微软为了能让它在 4M 内存的机器上跑起来,颇费了一番工夫。结果也严重的制约了操作系统的发展,windows 98 ,windows me 走了不少弯路。直到 windows 2000 才回归正轨。
那段时间,感觉新加入网易的众多人都处于一种复杂的心理中,不知道未来,焦躁,不安……
这与大环境有关。nasdaq 股市爆跌,网易生死不明。高层似乎也发生了几起人事变动。刚进网易时,我参加过一个大型的会议,CTO 给大家讲话,抚慰大家的不安,我刚刚去,不知道是些什么。
后来传出一些谣言,说是公司会被并购,中华网或是金山,具体是哪家公司我已经不记得了。那几天,nasdaq 上的 ntes 涨到了 2 美金。似乎古越和 micro 都挺高兴,还说要出去喝酒庆祝一下。我想是因为他们手头上卖掉天夏得到的一些网易股票。我没去跟着庆祝。不久以后,股价又跌了。
公司有 7000 万美金的存款,但市值已不到这个数字。也就是说,如果有人肯掏上几千万,就可以立刻拥有银行里超出他付出的现金额。但是这是个赔钱的公司,每一分钟都在花钱,7000 万看起来很多,可总有花完的一天。
记得刚去网易没多久,美术的负责人刘琪曾经去我家坐过,随便聊聊。虽然没明说,但我能感觉到他的一丝不安。刚换公司的人大多这样,内心不安定。如果这个团队散了,如果游戏做不出来,如果游戏做不好,大家需要一条退路。我不需要退路,我只是做我应该做的事情,尽可能做好,这就够了。如果尽了全力却失败,非人力所能阻挡。
人的能力有限,其实每个人能做到的事情都差不多。就看你投入多少。如果你全心投入也做不了,那么换一个人基本上也不可能做到。
我想我要做的是解决团队里暂时无人有精力去解决的一些技术问题。还有有些问题大家觉得无所谓(比如运行效率,比如内存消耗),但是我却认定它们会对未来游戏运营起来有影响,默默的去做。不需要别人知道你做了些什么,但求以后没有人指责你做错了什么。
我们总把一些问题归咎为“历史原因”,以表达一种无奈。其实当时再多花那么一点时间,就没那么多“历史原因”了。
项目的成功正在于:少犯错误。
我的想法就这么简单。所以身再累,心不累。每天还可以很有规律的干些别的事情。比如爱上了飞镖运动。跑遍了广州买到了镖盘和钢制的飞镖,挂在屋子里。每天晚上练习。没过多久,就能连续投中 20x3 的那块小区了。
后记:
这一篇本来预备了很多内容,甚至连项目定名都没写(下篇补上)。因为在项目筹备期,有很多的人和事应该记录下来。大话西游是个很多人合作的大项目,不是哪一个人或几个人的功劳。我在这段不长的时间也解决了好几个技术问题,鉴于写太多技术上的东西会让故事过于枯燥,我想,还是分开成几篇来记述,一次提一点,同时可以留下篇幅写一些人,一些朋友,一些我的生命中的匆匆过客。
前面有朋友留言说,故事节奏太慢;又有朋友跟我说,还可以写的再慢一些。我比较偏向后一种观点,多记录些细节吧,可能更有趣。对喜欢快节奏的朋友只好说声抱歉了。
希望能够写完写清楚,又不至于太过冗长。
Comments
Posted by: 北外隐形人 | (31) February 21, 2021 12:04 AM
Posted by: cat | (30) March 16, 2010 05:25 PM
Posted by: leeonix | (29) October 2, 2009 05:00 PM
Posted by: Jack | (28) May 12, 2008 08:26 PM
Posted by: Jack | (27) May 12, 2008 08:16 PM
Posted by: lee | (26) May 7, 2008 05:04 PM
Posted by: Siney | (25) May 6, 2008 12:16 PM
Posted by: 亮 | (24) May 5, 2008 11:36 PM
Posted by: Maya | (23) May 5, 2008 09:42 PM
Posted by: ablmf | (22) May 5, 2008 08:20 PM
Posted by: chinainvent | (21) May 5, 2008 07:24 PM
Posted by: 果子 | (20) May 5, 2008 04:27 PM
Posted by: oyang | (19) May 5, 2008 03:54 PM
Posted by: standing | (18) May 5, 2008 01:43 PM
Posted by: pt | (17) May 5, 2008 01:29 PM
Posted by: nothanks | (16) May 5, 2008 01:18 PM
Posted by: chinetman | (15) May 5, 2008 01:02 PM
Posted by: chengjie | (14) May 5, 2008 11:49 AM
Posted by: xyz | (13) May 5, 2008 11:15 AM
Posted by: nothanks | (12) May 5, 2008 11:12 AM
Posted by: david | (11) May 5, 2008 10:37 AM
Posted by: zen_yue | (10) May 5, 2008 10:34 AM
Posted by: kingx | (9) May 5, 2008 10:04 AM
Posted by: sjinny | (8) May 5, 2008 09:16 AM
Posted by: 开心 | (7) May 5, 2008 09:09 AM
Posted by: chinetman | (6) May 5, 2008 09:06 AM
Posted by: cat | (5) May 5, 2008 09:05 AM
Posted by: 江心 | (4) May 5, 2008 07:51 AM
Posted by: alexandercer | (3) May 5, 2008 03:29 AM
Posted by: 张沈鹏 | (2) May 5, 2008 02:38 AM
Posted by: DD | (1) May 5, 2008 01:56 AM