« 民可使由之 不可使知之 | 返回首页 | 新闻从业者的素质 »

《游戏之旅——我的编程感悟》勘误建议

今天拿到了出版社的样书八本,瞬间被分完 :)整个装订还算满意,随手翻了一下,发现了一些印刷错误。当时没有在意,现在回头想一下,应该有个地方列出来,方便读者。下次重印时也好更正。请大家赐教。

我在个人 Wiki 上整理了 勘误表

如果读者发现了错误,可以在这里留言,我会整理到勘误表中。

相关连接:

Douban 上的书评

China-pub 上的书评

Dearbook 上的书评

Comments

感謝前輩的回覆。

我動手實測了一下,EnterCriticalSection 的方法的確會消耗比較多的時間。
您寫的玩具代碼還是很有參考價值的~更希望有機會能看到您新重構的版本。

關於多進程建構系統的書籍,不知道前輩有沒有推薦的呢?

@xzx

谢谢信任。

我目前在休假中,手头没有书,所以无法核对。代码也是很久很久以前写的了。

从记忆中,我想那个锁是有必要的。不过要看过代码才能确认。

不过那段应该是段玩具代码,记得我前年重读过一次,很是汗颜。写的很糟糕,如果今天再写,应该是不一样的东西了。

其实当年主要是阐述 free list 的优化方案。记得代码也是写书的期间(04 年底)为书稿而写的,故而没有维护。我现在项目中用到的版本,是 05 年用 C 语言重新编写的一个版本。

锁的问题,EnterCriticalSection 的开销会略高一点。只是这几年,我更主张用多进程而不是多线程方式来构建系统,很少再考虑锁的问题了。

雲風前輩你好,我是您這本書台灣的讀者,有個部份有點疑惑不知道能不能在這裡提出。

由於我是繁體中文版,頁碼編排方式好像和您上面勘誤的編排不同,在繁體中文版是 9-25 頁,我估計大約是您的 260 左右的頁面,您介紹 smallobject_allocator 這個類別的 alloc_chunk(size_t idx) 函式,我看了許久,還是不明白這裡面為何要有一行 thread_guard guard(&_chunk_guard) 的動作? 看起來 _chunk_guard 要保護的應該是 _chunk_list,而這函式中好像並不需要操作 _chunk_list, _free_list 的保護不是在外層的 allocate() 就已經鎖上了嗎?在這函式中同時操作不同 idx 的 _free_list 應該是無妨吧?

另外在這函式中有一行 「for (size_t i = 0;i<=chunk_size_-node_size_*2;i+=node_size_)」這好像在 vc 2005 上面執行會有問題,在 chunk_size_ 和 node_size_ 都等於 16384 的時候,chunk_size_-node_size_*2 會變成很大的一個數字(應該是因為 size_t 不能小於 0 的關係),繼續跑下去程式會壞掉,似乎改成 i<chunk_size_-node_size_的話語意不變,但是不會有這問題,還請雲風前輩指導一下。

最後就是雲風前輩這裡使用的鎖是 spin 的方式,想請教一下如果使用 windows 的「::EnterCriticalSection()和::LeaveCriticalSection();」的方式,效能上會有什麼不同嗎?

谢谢云风回答~ 您的那段内存分配器代码,虽然我花了几周时间才完全弄懂,但是感觉这个分配器很有意思,也希望以后能与您交流。

@seefront,

让 chunk_size 是 node_size 的整数倍。

有个问题,260面最下面 cons size_t chunk_size=_min(chunk_limit/node_size*node_size, node_size*max_number);

为什么是chunk_limit/node_size*node_size ? 而不是直接 chunk_limit? 这里难道有什么讲究?

1.126页 倒数第五行,方面了程序员(正确:方便了程序员)
2.88页 如果位(未)压缩的信息是这样

你真是太懒散了,这个帖子也不留买书的链接

终于买到了你的书了,虽然这本书是你几年前写的~但是我也希望我也能够领悟到你的编程感悟~

终于比我发现左呢度,哈哈

无意中闯到你这来了。

不错啊,你对编程还是这样的专注。
还记得老同学我吗?
我现在还在学校,
但书念完了,
下个月要去新加坡了。
隆志力

多谢云风大哥的书和你的经历,说句实话,我真的很嫉妒你的尽力,还有您的父亲,我真的很难想象怎样的动力驱使大叔花费多年全部的积蓄买个“电脑”。你确实有常人没有的环境,当然,我更佩服你很好的利用了这个机会。
我从初中就决定我将来要做游戏,虽然我甚至不知道怎么去做,直到现在大二也没有改变初衷,看到你的这本书更加确定了我的信念。再一次的感谢

我没做过 console 平台的开发。

好,对于您的著作有一点比较不明:为何Console开发会一笔带过,仅仅用一个开发类似作为原因,而且文中屡次提到Console开发都浅尝辄止,不会深论。

其实作为客户端程序技术来说,Console开发与网游开发也是有比较大的不同的,而且Console开发在常用技术方面处于绝对的领先地位。

用大量时间去谈2D,谈解析度等等,而丝毫没有出现一流的Console游戏开发论述,引擎介绍等等,是不是有点“坐井观天”。

我觉得这里写“计算机的分辨率”并无大碍,如果要严谨一点的话,可以写计算机的显示分辨率。

当年的个人电脑跟今天的不太一样,正如现在说游戏机的分辨率时,也默指游戏机的显示分辨率。

P11,原文:
“找出了坐标纸...比如计算机的分辨率,就是指...”
建议把“计算机的分辨率”改成“显示器的分辨率”

感觉这书不怎么好
看了一下
里面讲的内容根本不适合这个年代的开发.
知识比较旧.
还是期待John Carmack出本书....

云风能不能写一本初学者看的懂的书了!!!这本看了很费力。。。

原意是指 C++ 虽然是一门独立的语言,但继承了 C 的许多设计理念。

49页最后一句觉得不通顺,好象有问题。不知云风的原意是什么。

刚想起来,win下绘图内容很多。。。可以的话,单说GDI就行

谢谢。
我在学习win32汇编,对于windows下的绘图无法理解,自己写过一些程序,不是画不出画来就是画出来都是黑白的,没有概念,书看了2本,似乎没人能从基础开始说透彻明白清晰的(可能是本人理解力差点),不知道你工作有多忙,如若有闲有兴,望写一篇(出书也行,呵呵)

“编译期指令”指程序在编译期间执行的指令。

P291.段1最后行:主要依靠宏和编译[期-->器]指令来控制.
不知道是不是这么改。。。

不会出错的,请仔细读一下。

第261页代码段(倒数 15 行左右):
你新修正的代码中,如果

if(chunk_index(sizeof(chunk_list))==idx){
chunk_node=reinterpret_cast <chunk_list*>(new_chunk);
new_chunk=new_chunk->next;
}

那new_chunk己经再不是::malloc返回的地址了,如果把这个地址放到
chunk_node->_data=new_chunk;
中,那到~smallobject_allocator()释放内存块时就会出错了

那个是不同的锁。guard[idx] 是一个数组,在不进入 `alloc_chunk` 时,不同大小的内存块之间可以相互不影响的。

但是一旦进入 `alloc_chunk`
后,必须有唯一的互斥了。

在allocate里不是有一个thread_guard guard(&_guard[idx])
这里不是把想要修改的_free_list锁住了吗?(因为alloc_chunk()是在allocate里被调用的,所以这把锁在整个alloc_chunk里都应该有效)

那261第一行的功能是什么?我一时没看出来,请云风指教

261第一行的锁,是因为有可能把 free list 的指针修改掉。

在书中第261页中第8行
`for (size_t i=0;i<=chunk_size-node_size*2;i+ = node_size)`

意思是该新内存块必须至少有两个节点,因为最后一个节点的`_next`为NULL(头4个字节),用于提示`alloc_chunk`函数分配新的内存块
但当要分配的内存很大,大于`chunk_limit/2`时,就无法用最后一个节点记下NULL,而且`chunk_size-node_size*2`是永远都不可能为负的

另外261第一行的代码可不可以不用
`thread_guard guard(&_chunk_guard);`因为好像不要,也不会对`_chunk_list`产生不良影响

DIB 的 Bitmap 描述可以自己控制是 565 还是 555 格式。(当然有些显卡一般只支持其中一种格式,这就依赖系统转换啦)

关于 GDI 下 555,565 的问题,在书中 P128 有简略叙述。

这本书,这么说呢?真的是,我在迷茫大海中的一柱灯塔,之后就只有Andre Lamothe的书可以这么说了,无奈身边无这样的人,真是渴望羡慕有共同语言的朋友.赞美之言,多则生腻.

同时还有一个问题,555格式是与显卡有关还是和GDI有关??因为SetDIBitsToDevice这个函数用565格式的怎么显示不正常??

不是不是,one two的问题
如果画个图
横坐标是alpha值,不管纵坐标是one的还是two的dou是开口向上的二次曲线,这个作何解释??
1~31逐渐下降了,但是32又完全的100%.
那个mark值是我算时算错了,造成blit的时候色差问题,但是从31到32的突变没有任何疑义.我只是在编程的突然发现而已.

内部是有几个物理上的队列的


内部有几个物理上的队列


又见“是……的”句型

alpha 一般可取 [0,32] 而不是 [1,32]
你的 mask 设置有错。通常 555 的设置为 0x03e07c1f

至于是你说的反了的问题,取决于你传递 one 和 two 的次序。

这个算法很简单,理解了再写出来。只是照书上的来改恐怕学不到东西。

书中的关于alpha blend的那一章中有点问题,是565格式的,我在自己的文件中引用如下:

//the alpha blend thanks cloudWu for this algorithm (in RGB555)

WORD AlphaBlend16(UINT one,UINT two,const UINT alpha)const
{

const DWORD mask=0x03e0741f;

one=(one|one<<16)&mask;
two=(two|two<<16)&mask;
UINT re=((((one-two)*alpha)>>5)+two)&mask;
return (WORD)((re&0xffff)|(re>>16));
}
是555格式的,但是问题是这样的:它不是从1~32递增,而是递减,然后32时没有blend,1的时候也有问题。
您知不知是什么问题??

是一本学习指向的书。读前几章时,很羡慕 云风 有那么好的学习条件。
总之是一本适合向这方面发展的人看的书,找到方向才能用力么。

^_^

您在书中提到断言的一些正确以及错误的用法,但有一点我一直想的不是太明白。一般来说,我们不希望程序在发行版中死掉,而在开发阶段发行并解决所有的错误又非常困难,这样就不得不使用if/else暂时回避一些错误,哪怕最终程序的运行会有一些逻辑的错误。所以很多时候我们不得不采用先断言,后if/else这种很怪异的办法,知道这样很不好,不过没有找到神秘解决的办法。不知道您怎么看这个问题,谢谢!

非常感谢,书里出现这么多别字,非常惭愧。

边看边挑,呵呵。291页第一段第三行“这两个版本公用一份源代码”是不是应该是“共用”呢?

错别字:
181页第2段最后一行:“会带来十多个始终周期的延迟”应为“时钟周期”

对于技术方面的东西,很多时候应该是仁者见仁,智者见智的,就算是有错误那也是可以原谅的,请大家指出时注意措辞和语气,有些人是带着一种批评甚至是贬低的态度来指出的,对于这样的人,我本人反而是贬低他的,有本事你为什么不写一本书呢,有那么多经验你为什么没有像云风那么大方来和大家分享呢?还有很多人说这本书没有重点,没有学到什么东西,对于这些只是一位的想学表面的技术的人,我觉得你要么就再读一遍这本书要么就把读过这本书的事忘了吧,当然对于后者我个人认为在编程道路上也走不远。最后对云风大哥给我们带来这样一本有思想深度的作品表示感谢!

我认为你们老师对ShowWindow 的理解是错误的。

当然到底谁错了,你应该自己做实验来验证,并对其原理做出思考。

书中第118页第1和第2段关与ShowWindows的解释是不是错了啊?我们老师说ShowWindows函数是把窗体画出来的啊

那个 bug 已经在这里修正了,印刷版的第 2 刷里也修正过来。因为书的排版不是我做的,所以编辑在直接向 word 里贴的时候难免有些问题。当然主要还是我自己的问题,这里表示道歉。有问题的代码被印在书上,相信任何一个作者心里都不会舒服。

注释的问题,我根据我自己的想法加。个人觉得不需要注释的地方就不会写注释了。

ps. 那段代码我觉得写的不好,如果各位需要的话,请自己实现。

请把9.5动态内存优化的源代码错误修改掉,顺便加注释可以吗?有错误的代码也往书里写。

个人认为,release 版和 debug 版的区别不在于名字,在于是否生成了调试信息。生成调试信息跟是否优化代码,或是调试信息是否生成在目标执行文件中也没有直接联系,只是被优化了的代码更难被 trace 而已(同一条代码可能被编译在不同的位置上,或是代码编译后被融合甚至消失)

本质上,调试器还是在调试汇编级的程序,但是可以根据编译时生成的调试信息找到对应的源代码的位置。

我这里指的 release 版本特指未生成调试信息的版本。

昨天随手翻了一下, 看到关于调试的部分.
调试 Release 版的程序, 编译参数设置正确, 是可以用IDE象 Debug 版本一样调试.
也可以设断点, 观察变量.

上周在书店偶然看到本书,马上就买了一本,说实在的,对云风实在是佩服,一是他的毅力和兴趣,二是他的无私.我花了5个晚上将书籍通读了一遍,收获颇多,在很多地方很有同感,觉得真是在用心在写书.作为一个在Windows平台工作多年的程序员,书中的一些技术不是我擅长的,对比如对算法的研究和汇编的优化,这是作者比较擅长的.作者对Windows编程的基本内容的总结还是很中肯的,就是觉得对COM的讲解和使用少了点.对作者对基本调试方法的运用收获很多,特别是录像思想具有很重要的意义,可以大大加快程序的调试,开发出高度稳定的程序.作者对版本控制分析本人也深有同感,真的很重要.对作者实践的开发方法也深表赞同.总之,这是一本好书,可以给我们勇气,让我们了解了游戏开发的一些内幕,减少了神秘感,这是我最大的感受.

我终于憋不住买了一本,晚上看了三章,我觉得技术虽然涉及的广,指明了一个学习方向,谢谢你

看完你的书后,受益匪浅,谢谢。希望以后能再出几本属于自己的书。

其实关注云凤大哥已经是很早的事啦,出这本书我也是在第一时间在china_pub上买的。看了有很多人的说法,我感觉要说几句,我觉得很多人都是有点不负责任的在批评云凤,虽然也许在某些方面可能表达未必好,但是作为一个为了梦想而努力的人,我觉得你已经把自己在书中那种表达的感觉出来了。支持你。bs那些无聊的人。

122页中间,有句“内部是有几个物理上队列的”怎么读不通顺呢。

书写的很好,我买来之后花了三个晚上认真地读过,作者真地是在“用心写书”,而且“用心良苦”。

301 页 倒数第3行
void log::instance()
>>>>> void 应是 log&

我是最近才买的这本书,看来显然是比较落后了:)

作为一个即将毕业的大学生,我也谈谈我的看法。我看完了书的2/3,当然大多是不太懂的,所以如果要勘误的话我也只能找一些印刷错误了:)我更感兴趣的是云风的经历,在信息和技术那样缺失的条件下历练而成的中国游戏的一代巨匠,相对于年轻几岁的我们这一代学软件的大学生,那种肤浅、浮躁和急于求成,云风的经历让我觉得羞愧。

无论如何,在这个飞速发展的时代,求伯君们、雷军们没有出书,感谢云风毫无保留的分享。而云风的书给了我们很多想要的信息,我相信这比整篇代码的纯技术书更有意义,我相信这本书对大学生,甚至中学生的影响几年之后就会突现出来,因为我们最缺的不是技术书籍,而是怎样使用那些技术书籍的借鉴。

所以,云风大哥,希望你在精力允许的情况下多多关注一下这本书,希望在众多读者的支持下,再版的时候做的更好。谢谢你,代表我及我的同学们。

另外,关于给你写email的事我一直很忐忑,可以给你写吗?

额外的队列需要的处理时间和空间应该很小,和真正的绘制相比几乎可以忽略不计的。


还有一个问题要请教一下:
217页,让 canvas 自身保存上一帧所有对象的状态并且和当前帧比较,计算负担很大。

我想,对上一帧和当前帧的对象的状态比较,用 hash 查找算法,计算起来很快。负担不大。
这个方法我已经实现了。

额外的队列需要额外的处理时间和空间。而且正反只是观念问题,比如我现在就很不习惯从下向上思考。

ps. 3d 显卡也建议从前向后提交。

我的想法是风魂应提供一个正向绘制的接口(风魂好象只能逆向绘制吧?),以方便客户。同时还能继续支持风魂中精妙的覆盖算法。

我前面说的就是实现这个目标的一种方法。
实际上是一个预处理的过程,还没涉及到渲染。
也就是把绘图指令看成是“绘图事件”,先放在队列中。然后再逆向、正向应该都可以了。

我选择从上向下,逆向用画家算法。是因为,上面画的东西如果可以把下面的完全盖住,那么,被盖住的东西就根本不需要进入渲染队列。

花了3个晚上拜读了大作,真是棒极了。
有两处想请教一下:

1、 216页的“逆向画家算法”

风魂使用了异步绘图。因此,只要先把绘图指令存在队列里,然后倒转一次,就可以变成正向的画家算法了吧?

53页的setjmp/logjmp,应该是longjmp吧

今天收到一个读者朋友来信,给我指出了不少错误,现在全部整理到上面了。感谢大家。

偶买了您的这本书回去看看,网上评论很多,有好的有不好的,无论如何有人来做这件事本身就是好的,正如您书中所说一个人的修为有限所以不可能达到尽善尽美的地步,在此我很理解您的.^_^

我还没有仔细读完有一个地方印刷错误

在56页的第5段最后书中写为:

一个任天堂红白机的模拟起.

我怎么想也应该是:

一个任天堂红白机的模拟器.

希望这本书再版时可以以全新的面目呈现在读者面前.(指错误不该这么多)

不必太在意那些评论,写出本来就是一件很主观的事情,不可能让所有人满意。我永远支持你。

const 是在 C89 被加入标准的。
我不知道这里面是否有C++的原因,也或许相互作用。但是这个标准被延用的很久,应该被所有 C 程序员认可并注意。

C 里面的 const 好象是在 C++出现之后才加入的。

顺着上面的连接找到了其他的书评..

感觉搞技术的中国人都有一个共同点:别人要把最好的东西免费送给他,而且要送的好,送得不好就开骂!!

这么多年此类书籍寥寥无几,那些牛X的人怎么就没写几本出来..

以为作者对有些评论可以不用理会,按照自己的思维办事,不要被这些迷了方向!

今天终于在 china-pub 读到“骂”我的书评了 :)

<a href="http://www.china-pub.com/member/bookpinglun/viewpinglun.asp?id=27924">http://www.china-pub.com/member/bookpinglun/viewpinglun.asp?id=27924</a>

不过也骂的很对,我大部分都接受。

花了2个晚上读了一些...深为云风知识面的广博而佩服..不过现在发现里面几乎每页都会有狠低级的印刷错误.希望再版时能修正,这样好的一本书如果被那些微不足道的东西影响了实在是一件狠不划算的事情..

我也发现两个地方有印刷错误了,不过书已经不在我手上了,具体那也到也忘~~~~要不有奖励(比如免费送下一本新书)明天去催还:),不然,按经验看要想拿回书得过几个月,传一个圈...

这本书写的时候我真的没有保留了。孟岩当年阅读完书稿后也说读到精彩处不够尽兴。跟 sword007说的浅尝即止应该是一个意思。

我只能抱歉了,语言能力实在是有限,理论知识不足以开山立派。如果要写的东西没有深刻的理解我都是怕写的,但写了的东西我相信都是有沉淀的。所谓 2d 引擎的细节能写的我都写了。即使我以后再写书,也不会超出多少。这本书我觉得值得一读的章节还是有的。举个例子,比如 Windows 编程,或许大多数有多年 Windows 开发经验的朋友都直接略过,不屑一读。但是就我这几年跟许多资深程序员的交流来看,我在书中所述,并非每个人都了解的十分清楚。而我自己,也是通过写书明白了许多道理的。

Michael Abrach 的图形程序开发人员指南那本我很喜欢。但是所谓的技术细节与我也无太多用处,我更喜欢书里面透出的思路。所以这最终成我写这本书的指导方向。光是列代码和描述过于细致的技术细节的话,我想对读者是有害无益。或许真可以对少数有鉴别能力的程序员起到借鉴之用,但是从现今大多数程序员的作风来看,会助长不求甚解,只会摘抄例子的风气。

今天刚拿到书!还没来得及翻!不过来这里先赞一下!
顺便说一下关于csdn的事,可能是人在江湖,身不由己!算了吧!:)

今天在又去公司附近的书店逛了一下,终于发现了这本书. 翻了一把,说句实话,有点失望.可能不太合乎我的需求吧.里面前半部分讲了云风的历史?呵呵,对于我等从N年前就上云风网站来看的人,不太需要了.后面的技术部分,浏览了一下,感觉都是浅尝即止,真的都是感悟的笔记而已.云风什么时候出本专著,像Quake出来之后,ID soft作的那样,将大量引擎的细节公布.如果网易允许的话, :)

当然有必要啦。可不可以列出页码和行数(从上到下 base 1, 或者从下到上 base -1)
或者给出段落和行数。

我发现了一些错别字啊。这个有必要提出来么?

应该整个勘误,力争做到最好,我们这些读者发现的错误也整上来,重印时,这书就Very Good !圆满

牛人都出书了,我啥时候能牛到有人请我出书啊。

Post a comment

非这个主题相关的留言请到:留言本