« May 2007 | Main | July 2007 »

June 29, 2007

一道初等几何题

triangle.png

前两天看书的时候看到这道题:三角形 ABC 是一个等腰三角形,顶角 20 度。角 EBC 为 60 度,角 DCB 为 50 度。求角 DEB = ? 度。

由于是躺在床上看书,身边没有笔和纸,脑子里想不清楚,就用手机上的计算器把答案算了出来。当然,用了三角公式。结果是一个整数,这也预示着这道题很可能存在一个初等几何的解法。

一不小心把书翻了一页,看到了答案,觉得乐趣少了很多。当时觉得这是道有趣的题,就记了下来,第二天带到公司。果然,几个同事花了很长时间都没做出来 :) 到第三天才有人找到初等几何的解法。

各位观众,如果还有谁有兴趣可以一试。只需要具备初中(或仅需要小学高年级?)平面几何的知识就够了。

按书上的说法,这是一道颇为著名的初等几何题。我 google 了一下,只找到一篇相关论文:Adventitious Angles , 可惜没权限进去看。

如果实在做不出来,可以去书店在《蚁迹寻踪及其他数学探索》中找答案。这里就不公布了,否则会坏了许多人的兴致 :D


为避免 spam, 此贴于 2007 年 11 月 7 日关闭评论。想发表意见的朋友请移步留言本。

June 21, 2007

平台无关的游戏引擎

一直以来,我们的新引擎一直以跨平台为设计目标。这倒不是说,我们有多重视非 Windows 平台的用户。只是我觉得,一个好的设计一定是很容易做到平台无关的。对于做跨平台开发这件事情,公司里支持的人寥寥。光老丁都几次三番劝我不要把精力花在无谓的地方。

唉,怎么说呢。写了这么多年程序,我一直把编写代码和设计软件作为一件很有趣的事情在做。所以我并不认为我做的一切是一种工作,它是我的玩具。早就不需要担心后半辈子的生活问题,所以没有人可以阻止我做想做的事情,更何况我认为良好的设计造就优秀的产品。今天看似多花的精力,日后慢慢的会给出回报。

回想当年做西游的客户端,我固执的把内存的占用量控制在 64M 左右,让低配置的机器也可以流畅的运行。为了达到这一点,当年多花了好多的精力。做内存中的精灵压缩,做地图的动态加载,做图象数据的 cache 和主动交换,改动许多我认为会更多占用内存的数据结构,阻止美术的一切可能过于消耗内存的设计。

这些在我离开西游的开发后的这么多年里,配合硬件的发展,往日做的那些,得以让后来的不断扩展玩法和美术资源可以稳定的进行。后期的开发维护人员可以用足够的东西来“浪费”。前期的种种约束和正是为了后期的无拘束扩展,直到这些项目顺利的走完生命期。

我希望几年之后,依旧有人感谢我当下做过的努力。

这两个月从对 X 的一无所知,到略有所成,还是颇花了点精力的。google 上关于 X 系统的编程相比 Windows 少的可怜,更别说我在 glx 上遇到的问题,那些更是很难直接获得答案。

一直以来一个人摸黑在 X Window 上摸黑写了好多代码,昨天同事写的另一部分关于 3d 方面的一些代码完成,我惶恐不安的放到 freebsd 上运行。虽然理性上我相信我们的跨平台架构是没有问题的,但是感情上还是不太相信一点问题都没有。

结果,除了一些文件名上的小问题之外(*nix 上对文件名是大小写敏感的,一开始没有重视),居然一次运行通过。看到 X 上显示的 3d 画面,格外欣喜 :D 这种感觉大部分来自于我们的设计小小的被检验了一次。因为另外的程序员在写他的代码的时候,丝毫不用考虑跨平台的问题,仅仅只是在遵循我们一起指定的一些标准罢了。

这次还是二进制跨平台的。

后来试了一下 openGL 的远程渲染,我在 Windows 上装了 XMing ,昨天晚上第一次用。glx 方面还是出了一点小问题。XMing 的 server 只支持 glx 1.2 ,而我起先是用 glx 1.3 做的,这让我花了点时间改过来,并且找到了另一些小问题,最后也顺利通过运行了。虽然这种远程渲染对 3d 游戏这样交互性和性能要求比较高的应用程序来说意义不大,但当个玩具玩玩还是很有趣的。特别是远程使用 DDD 调试的感觉很不错,这样就可以换掉难用的 insight 了。

ps. 如果有 X Window 或是 Mac OSX 的编程达人看到我这篇 Blog ,可否留个联系方式,大家以后多多交流 :D

June 19, 2007

最近有点忙

旅游回来后,突然觉得有一大块的时间可以用。就仿佛新启动的进程,一下子可以申请到上 G 的连续地址空间那样;感觉很爽。每天可以只做睡觉和写程序两件事。中间累了尽可以来点放松的小活动,但不会干扰主流程。

自从上次引擎的第三次的设计改动已经冻结下来,似乎只需要向上面添砖加瓦了。既然怎么做应该想好,完成它应该只是时间问题。

另一个附带的项目经过了一年,终于可以看到结束的曙光。虽然行百里路半九十,但毕竟一个半成品的出现还是让人欣喜的。

做这些事情的同时,往日坚持的一些业余活动就很久没有进行了。每周两次的抱石没有去碰,现在力量下降了太多,只能指望过段时间再有个恢复期;琴没弹了,太花时间,不适合现在时间紧张的状态。桥牌没打,三缺一(有时候是缺二)。

不过还是做了不少别的事的。比如读书:

卢梭的这本《论人类不平等的起源和基础》放在床头一年,终于读完了最后一页。我开始有点喜欢这个老头了,过段时间可能还会再买一些他的书看。

深入解析Windows操作系统:第4版》有着令人畏惧的近千页的厚度;但是其内容对一个 Windows 程序员的重要性,让我已经翻过了十分之一。

还有一些时间,就是打打游戏:

travian 的确是个好游戏,很符合我的需求。这两天正在确立对周边死羊的独家保护权:)有玩三服的人可以跟我联系。

MHP2 挑战麒麟中。

玩了一下 C99 ,觉得现在已经可以在项目中用了。

周末写了个将 C 的结构(联合)映射到 Lua 用的 lua 扩展模块,支持结构嵌套,感觉还不错,挺方便的。

目前正在公司内部物色好的美术人员,争取在公司内“挖墙角”:D 既然公司的内部招聘制度已经成文了,就该好好利用一下。结果公告一发, popo 和 email 里塞满了简历和作品。大家都好有热情啊。为这个会专门做了个 php 留言本做交流。

还有、还有,一些琐碎的事情耗掉了我几个晚上。公事,不宜公开。

ps. 老妈写了封信来,读完了想回,但又不知道从何写起。暂时搁着了。

June 17, 2007

如何在 Lua 注册表中选择一个合适的 Key

Lua 提供了一个注册表(REGISTRY)让我们的 C 扩展可以安全的把一些运行时数据放进去,而不被 lua 代码碰到。为了让各个 C 扩展库之间可以相安无事的工作,并且对注册表的操作又有较高效率。Lua 大神 Roberto 在神作 Pil 里给出了一个简洁的方案:用 static 变量的地址作为 key

静态变量在当前进程中一定拥有惟一的地址,且 lightuserdata 作 key 非常高效。这无疑是一个好方法。

但是,当模块的源码规模变大了以后,我们将代码分散到不同的源文件中。或者几个子模块需要相互协作时。这个方法就有了一定的缺陷。那就是,必须将这个静态变量暴露出来供大家蹂躏;或是写一个内部函数来取得它(其实没有本质区别)。

如果你也碰到这类问题,不妨看看下面的解决方案。

我们可以在子模块间约定一个字符串,比如 "foobar" 。如果能保证字符串惟一,直接用这个字符串做 key 当然也可以。不过效率稍微低了一点。(字符串压栈要多做一次 hash)。但是 lua 的虚拟机可以保证,只要字符串还有人引用,那么字符串对象就永远只有一份放在内存中,且不会被移动。

所以,只要保证这个字符串从未被回收,lua_tostring 的结果就永远是一致的。

明白了吗?每个子模块只要在初始化的时候,顺着调用:

lua_pushstring(L,"foobar");

key=lua_tostring(L,-1);

就可以保证得到的 key 是惟一地址了。

当然,你依然得谨慎选择字符串防止冲突。并且要自己在一个绝对安全的地方对这个字符串做至少一次引用。

June 13, 2007

贴两张前段去度假时拍的照片

最近半年工作太忙,通宵多了,没空健身,瘦的不行了。打算突击把程序写完,下半年恢复健身。

前段时间去了普吉岛,还真是蓝天白云、水清沙幼啊 :D 看见沙滩上的大礁石就忍不住去爬。没带岩鞋,光脚上的。发现只要忍忍痛还是很有优势的,那就是大脚指可以发挥很大的作用。比穿鞋时爽很多。必要时可以勾住石头,等于多了俩指头控制平衡。

其实回来有一段时间了,只不过我出去玩都不喜欢拍照,也不带相机。今天在同事的共享目录下发现了这两张,觉得还不错 :)

June 12, 2007

魔兽世界的影响力

晚上一个小朋友在 gtalk 上问我编程语言专注哪一门好。当然这不是一个简单能回答的问题。尤其对刚上大学的小朋友不太好解释清楚。

不过睡觉前我还是八卦了一下当今世界编程语言的流行程度排名。查了下 TIOBE 的排行榜。首先映入眼帘的加黑的头条:Lua only 0.003% away from top 20 position

不得不感叹魔兽世界的影响力啊。(同事语: wow 让阿猫阿狗都开始写 lua 程序了)回想 05 年的时候,Lua 可是排在 70 多位的。

我们在 01 年底为大话西游2 选择一门嵌入式脚本语言的时候,考察了 lua python java javascript ruby 等许多开源动态语言(java 是个例外,而且 java 不开源,但还是可以找到一些 JVM 的开源代码)。最后定下 lua ,其中一个原因就是它不太为人所知。反逆向工程可能可以方便一点,真没想到今天会是这个局面。(当然,那个时候 python 和 ruby 在国内用的人也相当的少)

是金子总会闪光的 :D

ps. 语言之争总是火药味十足的。lua 在游戏开发圈子的影响力倒不完全是来至于魔兽世界。GDC2004 的一个 round table 上,lua 和 python 哪个更好的争论就是相持不下。第一天吵完了,第二天继续吵 (._.!)

GDC 2005 时,lua 的相关节目多了好多,不过我就没去瞎参合了。想来那时有了魔兽世界,lua fans 的腰板该是硬了许多。

June 10, 2007

看到一句话,心有戚戚

语法层面的(nontrivial的)错误往往预示着语意层面的错误。例如,循环依赖导致的语法错误往往暗示抽象设计存在问题。

-- 转至 http://fanfou.com/statuses/uiT9IzmuonQ

我一直想好好写写循环依赖的问题,但不知如何下笔。只是在前段时间的 Blog 末尾提了一下。 (见 良好的模块设计 的最后两段。)

这些是我最近用 C 写了很多代码后悟到的。

C 往往允许程序员省略函数原型声明,只需要你把被依赖的函数实现列在前面即可。

刚学写 C 程序的时候,我老喜欢把各种函数的声明列在一起放在一个头文件中。后来明白了应该尽可能隐藏实现细节这个道理,转而把内部函数的声明放在独立的内部使用的头文件中。

今天,我发现,如果能保证没有循环依赖,所有非接口的函数都不必另外写一个声明;这一点可以反过来促成更好的设计。

在用 C++ 的日子里,我对这些一直没能有太清晰的认识。想来是因为 C++ 提倡每个类都预先写好类声明有关。

当然,间接递归并不等同于循环依赖。递归正是利用将实现和接口分离的方法,从而消除循环依赖。但解决掉眼前的问题就够了吗?我有点理解为什么当年 Fortran 不支持递归了。

当人们手中的工具越有威力,就越不把跟前的问题看在眼里。能力越大,越难 KISS 。

June 09, 2007

修复了留言本的 Bug ,翻出几篇旧文

主页的留言本 是我为数不多了 PHP 作品之一。

今天发现原来程序写的有点 bug ,一直点下一页翻不到底。这样会导致正常的浏览方式永远访问不到一些老帖子。晚上花了点时间改过来。同时还找到一些以前写的旧文,留个链接在这里存档 :) 也方便那些搜索引擎的蜘蛛来爬。

树表结合的一种映射表实现 2005-09-25 01:08:19

在 vector , map , list 间取得平衡 2005-09-22 05:08:58

关于 DXT1 格式的解码优化 2005-05-24 03:14:20

乌龟赛跑, 一道简单的概率题 2004-07-20 01:02:17

浮点数的精度控制问题 2004-07-17 01:49:15

多层地图的表述 2004-05-11 03:00:23

GDC2004 见闻录 2004-03-30 04:11:56

寓言三则 2004-01-13 01:26:03

C++对象计数 2003-12-04 04:26:23

我的爱车 2003-11-26 06:57:24

June 08, 2007

2007 年玩家主流显卡配置

本文版权归所有、谢绝任何形式的(部分或全部内容)转载

花了两天和同事一起做了一次数据挖掘工作。

前几天拿到了大量的显卡标识串统计数据(百万条级别),开始做数据分析。因为数据不太规则,所以颇花了些工夫。我想数据的来源和分析结果未得到公司允许前,都不能公开。不过我想在这里透露一些大略信息,对从事游戏开发的朋友(尤其是商业 3d 游戏)会有不小的帮助。

目前,NVidia 、ATI 、Intel 三家几乎垄断了玩家的显卡市场,市场份额超过了 95% 。如果你硬要考虑一些小厂商的话,不妨关注一下 VIA(包括其收购的 S3)和 SiS 。算上这两家已经涵盖了 99% 以上的玩家机器了。

一些若干年前风光过的显卡,如 Voodoo Trident 等现在依然有人用,但如今已经非常稀少。当然,还有人用一些更为稀少的专业显卡,或是我没听过的品牌的垃圾卡(疑是电子垃圾)在玩游戏 :D

N 卡是绝对主流显卡,占据市场份额大约六成(请原谅我不公布详细数值);而 A 卡则只有 3 成(比我预想的低一些,因为我们办公室配的机器以 A 卡居多)。

不过 N 卡的用户中,性能比较差的卡有相当的比例,尤其是 MX440 。而 A 卡中则无相应档次产品。

一些非常低端的产品,如 N 卡的 TNT 系列,A 卡的 Rage 128 系列。都还有一些用户,比例已经非常稀少了。

对于支持 DirectX 10 的显卡,即 N 卡的 8 系列,已经有一些玩家购买,但属于凤毛麟角,不足千分之一。而 A 卡的对应产品如 2900 等,推出比较晚,未能在我的源数据中出现。

可喜的消息是,玩家的显卡配置情况超过我的预料。而且,玩家购买新显卡的动力高于我的预期。以 N 卡为例,虽然 7 系列,6 系列,5 系列的用户数量不相上下,但其绝对数量是 7 系列略高于 6 系列,而 6 系列则略高于 5 系列。这或者也因为配置新电脑的用户逐年增多的缘故吧。

以此类推:2009 推出的游戏可以考虑采用 DirectX 10 档次显卡作为推荐配置。

玩家似乎偏向于选择成熟且廉价的卡。比如 N 卡的 6600 的用户数量远高于 6800 。

最后,给做 3d 游戏的程序员一个简单的清单,我想会有用的。

游戏建议测试用卡:

N 卡: MX440 FX5200 6600 7300

A 卡: 9200 9550 X300/X550 X1300

其它(如 Intel, S3): 不给建议 :)

June 04, 2007

无欲则刚

最近洗澡的时候,发现了右额处多了一大缕白发。平时被表层的头发盖着看不出来, 掀起方能察觉。看到觉得有趣。我一直有少白头,小学时就有白发,应该是遗传。不过长出这么大一缕还是第一次。(我知道父亲大人也有看这里。不必担心, 妈妈知道我的, 一直很注意保养身体。)

我想这也不是累的, 可能是前段想的事情太多的缘故吧。

独立带团队已有两年了, 这里每个同事都是经过我招聘来的。甚至办公场所也是自己敲定的, 装修方案都亲自改过。两年还前兼过财会,前台,网管。好在不久就找到了得力的行政mm, 可以心无旁骛的做开发了。总之, 我对周遭的一切人与物都深有感情。

一直以来, 都有所谓猎头和我联系。我不是一个容易被人说服的人, 只因为相信自己在芸芸众生有自己独立的思想。一个问题在两年前就有了答案, 而这两年不断添加着注解。为什么选择一直留在网易,而没有自己创业?或是去谋求一个更好的发展空间。

经历过寻找投资,融资这些流程的人都应该明白,谋求创业资金并不难。只要你真的有想法,想做点事,而不是只想赚点钱, 那么接触到投资方后, 会发现大家其实很平等。就我所知, 大票的人握着大笔的资金不知道该怎么投掉呢。

因为对现实中的利益不太所谓, 所以工资或别的经济回报无法打动我。人活着的是为什么? 这个问题我想很多人都想过, 我也没有答案。但我知道活着并不是为了更好的活着。如同魔兽世界中无休止的组团副本, 打来更好的装备为了更有效率的副本一样, 毫无意义。钱这个东西, 满足生活需求后, 最终总会落到一个用途: 以自己的意愿,借助它作为媒介改变周遭而影响其他人。而钱不是能做这些事的惟一工具, 只要想通这一点, 自然也就无所谓了。

前段有个同事专程来找我谈起程序员的前途问题。我知道他是真的迷茫,也很感谢他对我的信任。长谈中我也借机梳理了自己的想法。其实,能以写程序为生真的是很幸运的一件事。这意味着你可以单纯而快乐的活着, 并不断的发掘出美妙的东西。世俗点说, 这一行当还可以提供平均水平以上的生活质量。当然一切的前提是你真爱编程这件事。我相信无功利的爱是成就优秀程序员的前提,而优秀的程序员永远都是行业内的稀缺物。从经济学上来看, 这种稀缺性保证了其价值。

选择一直留在网易工作,是因为这里有一个成型而熟悉的环境。公司有丰厚的现金储备, 而没有乱花钱的人(许多人了解到我们公司居然把上亿资金,以活期形式存在银行里好几年,都觉得不可思议)。这可以让专心搞开发的人看的见长远的保障。

因为在公司工作了很多年的关系,我没有担任重要职务,但却可以接触到管理层中许多人。也了解到公司许多管理问题。许多人为此忧心忡忡。但我明白, 大多数可以左右管理政策的人都发至内心的想把公司做好,并在不断努力。很多事后看似错误的决定依旧无法证明走另一条路会更好。这些年,我也出谋划策过, 但也没有答案。管理好上千脑力劳动者真的很难, 即使自己从头创业, 走到这一步时, 同样不会立刻得到答案。那么, 若选择创业,最多是享受一下奋斗初期的欢快罢了。该面对的问题还是会面对, 那种选择只是将未来的困难像鸵鸟把头埋在沙子里一样对待罢了。

躺在床上休息时,有时也想想死亡的问题。偶尔觉得自己想通了,死亡这一人人必然的归宿便不那么可怕。剩下来的问题就是坦然面对人生。

写程序或是做游戏, 我不敢肯定是我一生的追求。总觉得人生才开始不久,追求会变,不变的是真善美。 当下我觉得所作之事中蕴涵着这些。既然事情已经启动,当尽力为之。慢慢的参与的人多了,顺带也多了些责任。大家为各自的目标去努力,领头的人如我有责任把人们带向同一个方向。那目的地不是个人的,而是在行进的过程中不断修正的集体目标。领头人需要做的只是让 1+1 大于2 。

当初跟老丁要了三年时间。时光飞逝, 如今已经过了大半。感谢公司信守承诺, 我从未受到任何外来的压力。也凭着程序员的执念,单单出于美感上的原因,把 engine 重构了三次。我想这次以后就不再大改了。争取从下半年,也就是七月开始正式启动游戏项目。

过去的日子中,做错了不少事,但我依旧不知道怎样正确。尤其是错过了原本唾手可得的感情,最终只好在心里请求那个女孩的原谅。人生就是这样有得有失吧, 要得到一样, 就需要相应的付出代价。未来的路,要好好的走。

似乎有不少同事会来这里看到这些文字。为感到迷茫的朋友多写几句:能在一起工作是一种缘分。对于一起奋斗的人,一直想说,我对身边的人都充满感激。希望大家能一起继续努力,把想做的事做好。信任我的人请相信我:事在人为,既然都真心在努力,总能得到好的结果。

壁立千仞、无欲则刚。大家共勉吧。

ps. 刚刚结束了一周的长假。普吉岛的风光和海水真是不错。上周出发前恰逢公司公布财报,帐面上不算好看,接着股价连跌两天。临走时我在17.17 的价位买进两千。昨天回来一看, 已经涨回 18.2 了。等交易窗口关闭我就放着了,有什么投资比投资自己正在做的事情更让人放心的呢?