病了
周日晚喝了点红酒,然后开始头痛。
周一没有食欲,继续头痛。
周二开始咳嗽。
今天出现轻微的流鼻涕这种症状,头痛有所缓解,继续干咳。
我想是感冒吧,估计要到下周才能好。
没休息,工作中。比上周稍微效率高点,今天还写了百多行代码,和一篇设计方案的文档。因为病了,所以可以早睡早起,比平常休息的好。
今天母亲大人驾到,有人照顾 :)
« December 2006 | Main | February 2007 »
周日晚喝了点红酒,然后开始头痛。
周一没有食欲,继续头痛。
周二开始咳嗽。
今天出现轻微的流鼻涕这种症状,头痛有所缓解,继续干咳。
我想是感冒吧,估计要到下周才能好。
没休息,工作中。比上周稍微效率高点,今天还写了百多行代码,和一篇设计方案的文档。因为病了,所以可以早睡早起,比平常休息的好。
今天母亲大人驾到,有人照顾 :)
昨天跟老丁喝酒,听说了些坊间流传的谣言,真是让人哭笑不得。我本还以为只是别人说着玩玩,没几个人信的。今天早上一来居然就有人问我这个事了。
以下摘至于我的聊天记录:
这个可是大新闻啊~
看来 csdn 真是个谣言集散地 (._.!) 鉴于上次的事情(三人成虎),这次我提早辟一下谣,或许有用。
顺便说个有趣的段子:
许多人喜欢 google 自己的名字。前段时间我一个高中同学也这么玩了一下。本来他的名字并不多见,不太会 google 到陌生人的。结果居然在许多娱乐八卦新闻中查到许多条记录,而他的名字被放在记者名单里。原以为纭纭众生,有个同名同姓的娱乐记者并不稀奇。可神奇的是,每篇新闻落款都有两个记者名,而另一个记者名却是我那同学的同事。
我拿这个事情调侃那老同学时,他倒是很委屈。一个闷声做 IT 的技术人员,连同他的同事,怎么就变成娱乐小报的记者了。我们分析了一下,原来他有一个同事的老婆就职于某八卦网站做文字编辑。估计有时候编新闻不知道该怎么落款。写个张三李四吧,又太假,只好在生活中找名字了。
最近装了个 google 分析 ,满有意思的。
因为用的时间不长(两天半),数据量采集不大。但是已经让我看到许多有趣的现象。
其中有一项可以查到用户都是用什么关键词检索到这个网站的,昨天的记录中,有两组关键词非常接近。"云风blog"(中间无空格)这个词被人搜索并点到我的网站 7 次;“云风 blog”(中间有一个空格)是 6 次。
我个人的习惯是加一个空格,或许是出于程序员的习惯吧。我认为分词这件事,如果人脑可以做的话,顺手做了不仅可以减轻电脑的负担,而且往往更加准确。如果我来搜索,会偏向于“云风 blog”这种形式。而且,对于中英文混用的时候,潜意识我也会在英文单词前后多加一个空格方便阅读。
我自己更喜欢用 google 而不是 baidu ,事实上,除非 google 访问不了,我才有很小的几率试一下 baidu 的。如果在 google 上搜不到的东西,我也几乎不会求助于 baidu 。
不知道是不是 google 用户的共性,在 6 次对“云风 blog”(人为空格分词)的搜索中,有 5 次来源于 google (这 5 个人平均每人访问了我的 blog 6.6 页;只有 1 次来源于 baidu (他访问了 3 个页面)。而在 7 次“云风blog”的搜索中,有 5 次来源于 baidu (平均访问页面 2.6 个);另两次来源于 google (平均访问页面 3.5 个)。
看来,喜欢我这里的人跟我的习惯更相近一点 :D
ps. 无论是在 google 还是 baidu ,加不加中间的空格,搜索“云风 blog”的结果,我这里都被列在第一位。所以以上结果跟排名无关。
设计有 UI 的软件,Command 模式可以说是可能用到的设计模式中最常用的一种了。它隐藏了关于命令发起者的相关对象以及命令处理过程的细节。也就是建立一个第三方的对象,用来解耦发送者和接收者的联系。
Command 模式最常用的用途就是给软件做 undo/redo 的功能。只用维护一个链表放置命令序列,就可以方便的记住发出的命令。每个 Command 对象实现一个乒乓开关(或者实现一对 undo/redo ),在对象内部保留住相关对象,自己执行 undo 或 redo 操作即可。
在动态语言里,一个 Command 对象,往往用一个 closure 来实现。closure 天然的具有封装参数和过程的能力。而 C++ 中,我们必须实现一个单独的类。这不仅使代码冗长,而且因为这个类往往和命令操作的对象栖息相关。不想写过多的供外部使用的方法的话,最直接的方案是 friend 一下所有的相关 Command 类。可无论怎样,一大堆代码或是难看的宏是避免不了了。
由于 C++ 没有 gc 的能力,所以在命令执行中构造和删除对象要十分小心。因为带 undo 功能的软件,即使你删除一系列对象,也不能真正从内存中释放掉。转而应该保留在 Command 对象内部。
典型的需求是向一个 TreeView 中删除节点的操作,只能是从 TreeView 上摘除(unlink)而不是删除,否则无法 undo 。当然还有一种实现方法是:从命令序列的头开始从头执行所有的指令,效率极低且不总是有效。只要命令序列中有涉及外部数据的读取,由于我们无法保证外存数据的不变,所以就不能保证 undo 的有效性。
智能指针是一种折中的解决方法。而一般在 C++ 中更高效的使用 Command 模式的方案是:任何的对象的诞生和消亡都由 Command 对象来负责,而 Document 中的对象之间只用指针记录其关系。这在设计角度,实在是没有支持 gc 和 closure 的动态语言来的简洁。
今天同事在调试一个 win32 程序的时候,希望从 console 输出一些调试信息。他威胁说,否则,就要动用邪恶的 MessageBox 了。
我们以前的库倒是提供了一个 console 模块,可以从 win32 程序中创建出一个 console 。然后把标准输入输出定向到上面。这并不麻烦,就算不用翻出以前的代码重用一下,查下 MSDN 自己写上几句也可以解决。
今天突然想到,其实还有一个更 kiss 的解决方法。那就是直接开一个 console ,再在上面执行需要调试的程序。只不过直接运行是不会得到任何输出的,需要多做一步的是使用管道操作。
例如,需要调试的程序是 test ,那么只需要写 test | more 就可以把 test 的标准输出导向 more ,那么 more 就能捕获所有 test 的标准输出并显示在控制台上了。
我们的游戏引擎已经开发了一年半了,其中 3d 引擎部分也做了近一年。
一个好的引擎,渲染部分总是容易做的。因为面对的问题比较单一,资料也很丰富。需要克服的问题很有针对性,即使短期解决不了的问题,放在那里也关系不大。我们团队有两个同事拥有完整 3d engine 开发经验,所以在渲染引擎接口设计部分也不会走太大弯路。(不过事实上,因为基础构件的重写,渲染引擎也是几经修改的)
最近 3d engine 部分又面临一次大的重构。起因是这样的:
整个 client 引擎的最初构架中,我们并没有把嵌入式脚本语言放在一个首要的地位。我在项目开始半年后,才正式开始嵌入式语言的工作。而之前一直是在做更底层的构架。3d engine 的起步也在这个时期。
可以说,脚本语言和 3d 部分在整个游戏引擎中处于相同的层次在做。
最近的一些想法的改变,以及游戏逻辑开发启动,让我深刻感受到了其中的不足。以前做的游戏项目,一则是因为 2d 的比较容易控制,二则我参与的部分以图象引擎以及 UI 方面的基础设施为主。在做完整游戏引擎上,思考不足。或者说,以前完成的几个游戏,都没有一个特别完备的游戏引擎。
最大的问题是,游戏逻辑和渲染引擎作为两个不同的层次,之间还有没有别的东西?目前的想法是,应该有一个粘合层。但准确定义这个中间层的功能是个难题。
我们项目早期的做法是,让脚本可以直接控制 3d engine 的渲染。这样可以有足够的灵活性。按这个方法,我们在一周内堆砌了一个 3d demo :) 但是到现在,这个思路不想延续下去了。毕竟游戏不是 demo ,而且我们期望的游戏逻辑又是非常的复杂。
我想一个合理的中间层,应该有动态语言做粘合剂,而用 C 做渲染底层。中间层不应涉及游戏逻辑层的东西,比如角色的 HP 等。它解决的是对象于对象之间的空间关系,逻辑归属,消息转发,资源管理等等。良好的这个中间层应该尽量的隐藏渲染层的信息,可以很方便的把 3d 渲染层换成 2d 的,甚至换成文本交互的界面。
按这个思路,前段时间我重新写了一个简陋的中间层框架,并做了一个简单的 2d 渲染层于之吻合。然后尝试让 3d 渲染的部分可以配合上这个框架。一切都是摸索阶段吧,目前看起来,2d 的那个部分工作的满好,3d 的部分尚未竣工。和以前做的许多东西不同,这次嵌入的动态语言深入到了引擎的更底部,放弃用 C++ 做模块的粘合剂而换用纯 C + 动态语言的组合,可以算是我近一年来最大的编程思想变革吧。
这个周末去逛了下书店。(原计划是去买新手机的,结果没有找到满意的。苹果的 iPhone 又刺激了我的神经,最后决定不换了)
在书店买书,一般从经济上不划算。大多数大书店,书都不打折。所以逛书店纯粹是为了发现一些平时不太关注的东西。如果有一早就有目标的话,在网上邮购是个更好的选择。
随便逛了下,没有什么收获。发现书城一角有台计算机可供查询。就掏出手机,登陆上 douban 打开 我想读的书的页面 ,逐个输入搜索。结果发现了几本想买的书,如《1688年的全球史》和《当中医遇上西医》。直奔指定书架取了下来。
我对这台手机虽然百般不满意,看在它可以跑 opera 的份上也就一直忍着没换。这种时候还是可以发挥点作用的 :)
可惜更多想要的书还是没有。但也没多大遗憾。反正遇见喜欢的书还是需要机缘的,像我这样不常逛书店的人更是如此。
大老远跑一趟,只买两本有点不甘心。仔细转了一下,有所发现。
角落里插着一本《相对论的意义》,是爱因斯坦写的,很小的册子。前几天睡觉的时候,没来由的想弄清楚相对论到底是什么。高中的时候读过一点,有点似懂非懂。上大学后上课也没好好听讲。就这么巧让我遇到了这本书,马上买了下来。
接着顺手买了本《一生受用的公式》,里面的活泼可爱的插图吸引的我。前段时间跟同事讨论过一些能源的问题。做一些简单的心算时,发现自己一些物理公式记得不太清楚了。收藏这么一本书看来还是有意义的。
另外还取了本《昆虫图鉴》。小时候玩蚂蚁玩多了,蝴蝶,蛐蛐,螳螂什么的也抓过不少。这种科普读物现在读的少了,让我的百科知识至今停留在《十万个为什么》阶段。想想都挺惭愧的,要补习啊。
最后临走的时候俗了一把,从收银台前拿了本《长尾理论》。
除了这些,还买了些城市设计方面的书。原本没有这个计划的,但这段时间设计游戏时,越来越觉得知识匮乏。世间万物都是学问,面对几书架的城市规划专柜,我觉得自己很无知。虽然我不做美术工作,但是规划游戏中的城市布置的时候,也总想给点意见。这个领域也是很广阔的,读点专著充实一下也好。另外,谁叫我曾经是 simcity 的 fans 呢。
周末还有另一项重要工作就是打游戏。本周翻出了一个 ps2 上的老游戏玩—— demento 。
运气还不错,这是一个好游戏。除了有点血腥镜头外,别的都还好。我对恐怖游戏没有特别的爱好,这一款也不是以恐怖见长的。它更像我喜欢的 ico 。精美的画面加上难度适中的迷题。游戏节奏控制的很好,玩起来有一气呵成的感觉。不会在某个地方卡太久,又不至于简单到觉得在侮辱自己的智慧。
我居然从周六的晚饭后一直玩到了周日早上天亮。好久没有通宵打游戏了,感觉还是满爽的 :D
ps. 《当中医遇上西医》是一本好书,作者是一个在香港的医生,接受的是正统的西医教育。作者著书的态度严谨,这本书的观点中立客观。我花了三个多小时,一口气读完。相比较前段时间读完的《人体使用手册》,我认为更能让我了解中医。
无论是想批判中医的人还是拥护中医的人,都值得读读这本书。
今天俗一把,掺乎近期网上最热门的这个话题:C语言已经死了,5个需要忘却它的理由。大家驳来、驳去 的。这的确是一个不值得一驳 的问题,我这里也没打算驳斥那些观点。只是写点别的:
C 并不是对机器模型的完整抽象,就是说把 C 作为一种 portable assembly language 是有缺陷的。即使是做底层,光有 C 也是不够的 (IMHO) 。
C 语言的卫道者们最喜欢举的一个例子是:某某语言的 VM 都是用 C 的;或是某某语言都是先编译成 C 再编译成本地码等等,以示 C 的重要性。没错,现今的事实如此,这是历史选择的结果。我最近在读一本翻译的很糟糕的书,《游戏——自然规律支配偶然性》 。如果有人耐着性子读下去,就可以从书中列举的小球游戏看到选择一般怎样发生。
今天看来 C 并不太适合写 VM ,也非做别的语言编译成本地代码的中间语言之最佳选择(尤其对函数式语言来说)。选择 C 只是没有更好的选择而已。
我最近读了一些关于 C-- 的 paper ,C 对 gc 支持的不足可以说是最大的一个缺陷。这一点是语言的不足,用库去解决是不太现实的了。对于函数式语言来说,函数尾调用的堆栈优化也使 C 在性能表现上相形见绌。到了 C++ 解决了一些,不仅外观是拙劣的(大量的 inline 函数的使用),性能依然有欠缺。可悲的是,许多 C 程序员对这些不屑一顾(尤其是对 gc 的错误认识)。
其实即使是机器语言上的编程,到了具体流行的系统上,也有强烈的历史选择的痕迹。比如堆栈的设计,对于冯诺体系来说并不是必须。但是大家都这么设计了,CPU 也按这个做了优化(提供堆栈寄存器、优化堆栈指令的速度),导致了最终我们都得选择这种结果。别的设计并非不存在,比如 forth 语言就依赖双堆栈来工作。btw ,forth 这种小语言,至今也未能消失。它的大量使用甚至鲜为人知。比如在 boot firmware 领域的地位就无可取代。
C 在静态语言中没有太大的竞争者其实也是 C 的悲哀。造成了在 C 能力临界点上的领域,它依旧成了最好的选择。这造成了大家在低阶开发上把 C 当万能药来使。今天看来,没有 C 是万万不能的,这也是一个历史选择的结果。假若当年 pascal 战胜了 C ,现今所有用 C 写的代码都用 pascal 来实现也未尝不可。
C 在历史的选择中走到了今天,当然还会一直存在下去。
今天收到通知说,年收入 12 万以上的高收入人士今年起需要自行申报个税。据说申报和单位代缴是两回事。比如股票收入这些,现行法律是不要求纳税的,但是却在申报范畴。
总的来说,我支持税收改革。个人的一些观点,这几年经常在闲聊时和许多朋友议论。
刚才 google 了下,发现自己要放在成都,就是一富豪了 :D 。(成都3000富人 2007年1月1日起单独报税)
据说这次为了迎接新事务,共建和谐社会。公司已经着手协助需要自行申报的员工计算收入和填写申报表格。
我个人收入计算似乎还比较麻烦。因为除了工资所得,我还有一些不多的版税,以及投资在股票基金上的些许收入。后者是不需要纳税的,而前者出版社已经帮忙代缴足了。当时也是我嫌麻烦,没有伪造一些共同写作的人员名单(用来避税),这下也更方便我计算收入了 :) 。不过计算这些非工资所得却也是很麻烦的。
相对而言,银行里的利息所得,拜招商银行方便的电子银行所赐,计算起来非常方便。
唯一的疑问是,我在国外的一些股票的增值,不知道算不算在年收入之内?
我已经前后为我在 263 的电子邮件信箱支付了七年的费用。但是我已经不打算使用它了。
在此声明:如非必要,云风不再回复发往 cloudwu AT 263.net 的信件。不过如这几年一惯所为,我会继续不定期的检查那里的邮件。
本人的主要私人邮件信箱为 gmail 上的一个,地址放在 www.codingnow.com 首页。在 163.com 的私人信箱以及公司分配的公务邮箱同样保证经常查收。
email 为本人的第一联系方式,其下依次为网页留言、电话、IM 、短信和明信片。
元旦这几天没啥心情做项目,老是胡思乱想。
有个问题我一直没弄清楚,那就是静态语言如何提供一套合理的 gc 机制。目前,给 C/C++ 硬加一套 gc 库,显然有超 C 语言的能力。这种库,也不是没有。A garbage collector for C and C++ 这儿就有一个。但是它的内存扫描,是基于一种对指针的猜测。这并非完美的解决方案。
D 语言 支持了 gc ,但跟我想象的不太一样。前段时间读了好多 D 语言的资料,还是不太了解它怎么实现 gc 的。
这几天想走另外一条路子:如果自己写一个 C 语言的前端,好象当年 C++ 干过的那样。该怎么实现最为合理呢?
想来想去,最麻烦的是 C 语言本身对局部变量(即堆栈上的数据)的布局无法控制。这是 gc 在做根扫描时的最大障碍。而全局变量和用户自定义结构中的指针查找,都可以通过前端生成的数据和代码轻易解决。
我想了一个方案是采用双堆栈。系统堆栈只用于函数调用的返回地址,而堆栈数据则分配到另一个自己控制的数据堆栈上。前端去生成每个函数用到的局部变量的内部布局结构。当然物理上放在一个堆栈上也可以,只是实现稍有不同。
这两天查了一些资料,经同事提醒,我翻到了一个不新的玩意,C-- 。以前留意过没深究。今天仔细的读了它的一篇 paper C--: a portable assembly language that supports garbage collection 感觉满有意思的。其中谈到了几点 C 语言的局限性深得我心。
如果真要做这么一个前端的话,port 到 C-- 会是一个比 C 更好的选择。
可惜目前项目压力太大,就算做一次思想实验罢了。
零七年来的这么快,让我措手不及。
十年了。九七年我刚刚接触互联网,做了自己的主页:以游戏制作为主题的第一个中文网站。
也是那一年,我用自己编写程序的技能赚到了平生第一笔钱。一个现在都不好意思拿出手的小共享软件,靠盗版光盘的传播,收到了来至祖国各地邮寄过来的注册费。
似乎还是在那一年,我决定做自己的游戏。结果岁月飞逝,今天仍旧是感觉一事无成。
十年前,网易这家小公司成立了。十年后的今天,我掰着手指数,居然已经为这家公司服务了六年。还真是难得啊。零零年的时候我可没想过自己会如此稳定。
席德梅尔果然不愧为大师,席德梅尔的铁路已经让我着迷了几个晚上了。
游戏贵在规则简单而变化无穷,铁路就是这样一个好游戏。花了大约十五分钟过了一遍教学模式,我就会玩了。这是一个非常纯粹的游戏,就是修铁路,规划火车路线。相比之下,模拟城市等系列的最新版本我就提不起多大兴趣了。
这几天和同事一起琢磨怎么修铁路,越玩越觉得乐趣无穷。原来铁路的学问这么大的,对于各种交通的处理不琢磨出点模式出来的话,肯定一堆火车头堵在那里。玩了几天后,终于可以修出像模像样的铁路了。