Drum Machine
An amazing game,u can roll the ball to destination,but it's difficult. Just try it.
ps.I never imagine shockwave can make such 3D effects.Go figure!
They say we all lose 21 grams at the exact moment of our death.
Life has to go on with or without god.
找工作就跟找女人一樣,前面那個(gè)女人要求高,我某方面達(dá)不到要求,就被拋棄了。所以,我還得再找工作。
前面那個(gè)女人能給我我想要的那么多,是否還能找到出的起同樣價(jià)錢的呢,我不知道,說真的,沒信心。
高 德 納 的 二 十 年 計(jì) 畫
8123033 穆信成
高德納已經(jīng)五十八歲了。 他打算再花二十年的時(shí)間繼續(xù)他的著作,
The Art of Computer Programming. 大家知道 Donald E. Knuth
是資訊科學(xué)界公認(rèn)的大宗師, 知道他以他的重量級(jí)著作 The Art
of Computer Programming(以下簡(jiǎn)稱TAOCP)[2,3,4] 聞名於世,原計(jì)
畫要出七冊(cè),但目前只完成了三冊(cè)。但也許並沒有很多人知道他還有
個(gè)中文名字:「高德納」。
* * *
TAOCP 這套書的名氣這麼大,敢去碰它的人反倒不多。寒假我因?yàn)橐?br>些原因,讀了高德納的另一本書 "The Stanford GraphBase"[1]。大
師的書到底是什麼樣子呢?
高德納在序言裡說了寫這本書的原因:在寫 TAOCP 的第四冊(cè)前, 他
想要用一個(gè)叫做 ladders 的遊戲當(dāng)作貫穿全書的例子。 於是寫了不
少相關(guān)的程式和龐大的測(cè)試資料,最後集結(jié)成了一個(gè)程式/資料庫。
他想這套 GraphBase 可以作為大家測(cè)試 graph 演算法的基礎(chǔ),讓那
些 「街上混的程式員們 (programmers-on-the-street)」 知道電腦
科學(xué)家們也會(huì)做實(shí)際的事。另外,這套程式庫全部用他鼓吹的 liter-
ate programming 方式寫成,也可以當(dāng)成一個(gè)活生生的例子。
最後一個(gè),但卻是最重要的原因是,"to have fun".「的確,快樂是
這一路上最主要的原因,但我不敢承認(rèn)。電腦科學(xué)家們總是得裝出一
副咬牙工作的樣子,讓別人心甘情願(yuàn)付給他們高薪水。但遲早這個(gè)社
會(huì)得承認(rèn), 有些工作仍然值得尊敬 --- 即使它們比任何事情都要來
得有趣?!?br>我不禁笑了。高德納在辦正事的途中岔出去做別的事情,一做就是好
幾年已經(jīng)不是第一次。TeX 這個(gè)現(xiàn)在大家都在用的排版系統(tǒng)不就是他
嫌 TAOCP 被排得不好看, 因此自己捲起袖子研究電腦排版的產(chǎn)物嗎?
Tex 耗去了他十年的光陰,而這本 Stanford GraphBase 則可以追溯
到二十年前。高德納好像永遠(yuǎn)不怕老?
Ladders 這個(gè)遊戲是這樣的:挑兩個(gè)五個(gè)字母的英文單字,試試看一
次一個(gè)字母,把一個(gè)字變成另外一個(gè)。但是在過程中它必須仍然是一
個(gè)英文單字。比如說把 black 變成 white 的方法是這樣的:
black -> brack -> brace -> trace -> trice -> trite
-> write -> white
大家看得出來,如果把每個(gè)單字當(dāng)作一個(gè) node, 兩個(gè)單字如果只差
一個(gè)字母,就連一條 edge, 那麼這個(gè)遊戲可以想成在兩個(gè) node 中
找一條 path .
但 GraphBase 有趣的地方卻是資料。 高德納收集了一個(gè)含 5757 個(gè)
單字的資料庫。他參考了 1971 年以前 Beeler 為了這個(gè)遊戲?qū)iT編
的一部字典,刪去老的字,加入新的單字。高德納花了很大篇幅解說
他選字的標(biāo)準(zhǔn):姓名不選,所以 Knuth 就沒有了;但是 gauss 已經(jīng)
是一個(gè)電磁學(xué)單位,所以受錄了進(jìn)去。他很耐心的等到 e-mail 終於
被大家寫成 email, 以便把他收集到資料庫中。
接下來就開始玩這個(gè)資料庫囉。高德納發(fā)現(xiàn) 5757 個(gè)單字中,有 774
個(gè) degree 是 1 的(只有一根接出去的 edge),位居第一。Degree
= 2 的也有 727 個(gè)。株連最廣的單字是 "bares" 和 "cores" , de-
gree = 25,而 "cores" 的 25 個(gè)鄰居都是 degree 大於 9 的。 De-
gree = 1 的單字中有 103 組根本就是孤零零的兩兩成對(duì),如 alpha-
aloha, gonad-monad. 跑一個(gè)找 connected component 的演算法,
發(fā)現(xiàn)大部分的單字都在同一個(gè)有 4493 個(gè)單字的大 component 裡面。
高德納自己定了一個(gè)方法橫量單字在文章中的出現(xiàn)頻率。 在這 5757
個(gè)單字中, "which" 是最常出現(xiàn)的, 其次是 "there" 和 "their"。
"often" 果然常出現(xiàn),比出現(xiàn)("occur") 還要常出現(xiàn)。
看來高德納真的是玩得不亦樂乎呢。"to have fun", 於是我們可以
想像高德納出這本書的真正原因,是他自己建了這些資料後,發(fā)現(xiàn)越
玩越有趣,終於忍不住想出書了。
玩過了單字,想知道美國(guó)大學(xué)足球隊(duì)誰比較強(qiáng)嗎?高德納已經(jīng)把 120
支隊(duì)伍的 638 場(chǎng)比賽建成 graph 了。 他又參考資料, 找出美國(guó)的
128 個(gè)城市之間的最短距離,並且在發(fā)現(xiàn)前人的資料明顯錯(cuò)誤後自己
寫程式來修正。把蒙娜麗莎的微笑掃描起來後,高德納示範(fàn)了如何運(yùn)
用 bipartite graph matching 的技巧,用骨牌重新拼出這幅名畫。
高德納的文筆親切而幽默。CWeb 是他大力推廣的 literate program-
ming 系統(tǒng),他認(rèn)為每個(gè)人都應(yīng)該有一套。 「但是今天已經(jīng)沒什麼人
能永遠(yuǎn)跟上新軟體的發(fā)行,所以如果你沒有 CWeb,也不用覺得太有罪
惡感?!?接下來他解釋如何安裝 Stanford GraphBase, 這一段的
makefile 可以給想學(xué) make 的同學(xué)們做很好的參考。 如果裝不起來
呢?高德納問,你有沒有好好祈禱呀?最後,他希望大家能像他一樣,
多用這些程式庫和資料檔做些實(shí)驗(yàn),「也許有天你也會(huì)迫不及待地想
出本這樣的書呢!」
瀏覽了全書,我想:高德納到底是太閒,還是有用不完的精力?將近
六十歲的他,仍舊充滿著旺盛的活力和赤子般的好奇心,而這一切又
以他深厚的功力做為基礎(chǔ)。
* * *
四月號(hào)的 Dr. Dobb's Journal 做了一篇高德納的專訪[5]。 為什麼
寫書寫到一半, 卻花了十年的時(shí)間在 Tex 上? 他說, Niklaus
Wirth (Pascal, Modular-2 和 Oberon 的設(shè)計(jì)者)一直想設(shè)計(jì)飛機(jī),
但他發(fā)現(xiàn)他需要夠好的工具,於是他設(shè)計(jì)了一個(gè)個(gè)的電腦語言,造了
自己的電腦。高德納也希望他的書能夠不因科技的進(jìn)步而被淘汰,希
望即使製書的科技進(jìn)步,他的書仍舊是用領(lǐng)先的方式製作的。
談到另一位大師 Edsgar Dijkstra, 他說 Dijkstra 的力量來自於他
不妥協(xié)的拗脾氣?!腹馐窍胂裼?C++ 寫程式就會(huì)讓他病倒!」Dijk-
stra 的拿手技巧是鉅細(xì)靡遺地用 formal 方法推導(dǎo)、檢驗(yàn)程式, 這
和工業(yè)界不斷產(chǎn)生數(shù)以 mega 計(jì)的軟體, 但使用者卻無時(shí)不負(fù)擔(dān)著
bug 的風(fēng)險(xiǎn)的實(shí)際情況顯然有段差距。高德納則認(rèn)為自己位於兩種極
端的中間。一方面他贊同 formal 方法提供的可靠性,但他也知道在
大系統(tǒng)中這種方式的極限。他盡力維持他的軟體的品質(zhì),因此他願(yuàn)意
提供賞金給在 TeX 中找到新 bug 的人。
* * *
由於高德納已經(jīng)不用 email 了,他有一個(gè) Web page[6],
http://www-cs-faculty.Stanford.EDU/~knuth/
裡頭還有個(gè) FAQ, 可以看到他中文名字的圖章。大家劈頭要問的當(dāng)然
是:第四冊(cè)什麼時(shí)候出來呀?
他說,TAOCP的第四冊(cè)將會(huì)分成三部份,4A : Enumeration and Back-
tracking, 4B : Graph and Network Algorithms 和 4C : Optimiza-
tion and Recursion. 從 1997 年開始,他會(huì)以大約每 128 頁為一
個(gè)單位( 高德納好像很喜歡用 2 的乘冪做單位,他付給找出 TAOCP
中錯(cuò)誤的賞金也是 $65536 分)把第四冊(cè)的部份散發(fā)給大家,聽取各
方的意見。如果一切順利,第四冊(cè)將在 2003 年正式完成。第五冊(cè)的
完成時(shí)間則定在 2009 年。第五冊(cè)告一段落後,他會(huì)重新整理 TAOCP
的一到三冊(cè),更新內(nèi)容。再下一步,他將把一到五冊(cè)的重要內(nèi)容全部
濃縮在一本書裡。之後才著手進(jìn)行六和七冊(cè)。
所以,高德納至少得活到 2020 年囉....
為了完成 TAOCP, 高德納已經(jīng)退休,過著半隱士的生活。 他不用 e-
mail, 不怎麼會(huì)見訪客, 取消大部分的演講和旅行。 他說,他得用
batch 方式工作,而不能把事情 swap 來 swap 去的。他託人在家裡
造了一座管風(fēng)琴,空閒的時(shí)間裡,他就會(huì)彈彈琴自娛。如果你會(huì)彈琴,
他很願(yuàn)意和你見個(gè)面,來個(gè)四手聯(lián)彈。
為什麼那麼賣力呢? 在DDJ的專訪裡, 當(dāng)被問到他是否能從 Tex 和
Metafont 圖利時(shí), 他說,一旦一個(gè)人能夠餵飽自己,能夠有個(gè)安身
之所,剩下的就是他能為別人做些什麼,如何能為群體做出一些貢獻(xiàn)
了。
因此他很希望程式創(chuàng)作者們不要把演算法當(dāng)作自己的私產(chǎn)。程式應(yīng)該
容易閱讀和了解,因?yàn)樵蕉嗳四軌蛄私馑?,它才能夠發(fā)揮越大的影響
力。
也許他也是基於這個(gè)想法繼續(xù) TAOCP 的寫作吧? 在他的 web page
中,對(duì)於他的這件「此生的大事」,他下了這樣的註腳:「我嘗試著
盡我所能的去學(xué)習(xí)電腦科學(xué)裡的一些領(lǐng)域,然後把這些知識(shí)摘要成大
家比較容易了解的方式,讓沒有那麼多時(shí)間做這種學(xué)習(xí)的人也能夠吸
收他們」。
為了這個(gè)目的,他必須閱讀超過二十萬頁的文件,然後把它們濃縮到
兩千頁裡頭。他寫的東西並不是最流行的,但他希望他能從日新月異
的新技術(shù)中,萃取出值得存活到下個(gè)世紀(jì)的東西。
不禁想起前陣子同學(xué)討論到的話題:專家是訓(xùn)練有素的狗嗎?我們?cè)?br>不該成為專家?高德納毫無疑問地是個(gè)專家,但他的大師學(xué)養(yǎng)和風(fēng)範(fàn)
也許能給我們不少啟發(fā)。
Reference
[1] Donald E. Knuth, The Stanford GraphBase : A Platform for Combinatorial
Computing, Addison-Wesley, 1993
[2] Donald E. Knuth, The Art of Computer Programming, Vol 1 : Fundamental
Algorithms, Addison-Wesley, 1973
[3] Donald E. Knuth, The Art of Computer Programming, Vol 2 : Seminumerical
Algorithms, Addison-Wesley, 1973
[4] Donald E. Knuth, The Art of Computer Programming, Vol 3 : Sorting and
searching, Addison-Wesley, 1973
The Art of Computer Programming 有日文,俄文,西班牙文等許多國(guó)的版本。
其中,中文版資料如下
Chinese translation by Guan JiWen and Su YunLin, Pei Xue He Cha Zhao,
Beijing: Defense Industry Publishing Co., 1985
[5] Jack Woehr, An interview with Donald Knuth, Dr. Dobb's Journal, April
1996, p16-p22
[6] Donald E Knuth's WWW Page : http://www-cs-faculty.Stanford.EDU/~knuth/
http://www.geekchic.com/repliq6.htm 也有一篇小小的訪問。高德納最喜歡的
語言是 CWeb, 最喜歡的運(yùn)動(dòng)是棒球,認(rèn)為有許多人是他值得崇敬的。
高德納將在最近將他的論文以更淺顯的方式整理過後,重新集結(jié)出版。
這套書的預(yù)定讀者並不是電腦科學(xué)的專家,似乎很值得一讀。這套書
將有八本,前兩冊(cè)已經(jīng)出版:
[7] Literate Programming, Stanford, California: Center for the Study of
Language and Information, 1992
[8] Selected Papers on Computer Science, Stanford's Center for the Study
of Linguistics and Information and Cambridge University Press, spring,
1996
[9] Selected Papers on Analysis of Algorithms, to be published
[10] Selected Papers on Computer Languages, to be published
[11] Selected Papers on Design of Algorithms, to be published
[12] Selected Papers on Digital Typography, to be published
[13] Selected Papers on Discrete Mathematics, to be published
[14] Selected Papers on Fun and Games, to be published
下面的是學(xué)C++時(shí)要注意的。絕對(duì)經(jīng)典。?。?
1.把C++當(dāng)成一門新的語言學(xué)習(xí)(和C沒啥關(guān)系!真的。);
2.看《Thinking In C++》,不要看《C++變成死相》;
3.看《The C++ Programming Language》和《Inside The C++ Object Model》,不要因?yàn)樗麄兒茈y而我們自己是初學(xué)者所以就不看;
4.不要被VC、BCB、BC、MC、TC等詞匯所迷惑——他們都是集成開發(fā)環(huán)境,而我們要學(xué)的是一門語言;
5.不要放過任何一個(gè)看上去很簡(jiǎn)單的小編程問題——他們往往并不那么簡(jiǎn)單,或者可以引伸出很多知識(shí)點(diǎn);
6.會(huì)用Visual C++,并不說明你會(huì)C++;
7.學(xué)class并不難,template、STL、generic programming也不過如此——難的是長(zhǎng)期堅(jiān)持實(shí)踐和不遺余力的博覽群書;
8.如果不是天才的話,想學(xué)編程就不要想玩游戲——你以為你做到了,其實(shí)你的C++水平并沒有和你通關(guān)的能力一起變高——其實(shí)可以時(shí)刻記住:學(xué)C++是為了編游戲的;
9.看Visual C++的書,是學(xué)不了C++語言的;
10.浮躁的人容易說:XX語言不行了,應(yīng)該學(xué)YY;——是你自己不行了吧!?
11.浮躁的人容易問:我到底該學(xué)什么;——?jiǎng)e問,學(xué)就對(duì)了;
12.浮躁的人容易問:XX有錢途嗎;——建議你去搶銀行;
13.浮躁的人容易說:我要中文版!我英文不行!——不行?學(xué)呀!
14.浮躁的人容易問:XX和YY哪個(gè)好;——告訴你吧,都好——只要你學(xué)就行;
15.浮躁的人分兩種:a)只觀望而不學(xué)的人;b)只學(xué)而不堅(jiān)持的人;
16.把時(shí)髦的技術(shù)掛在嘴邊,還不如把過時(shí)的技術(shù)記在心里;
17.C++不僅僅是支持面向?qū)ο蟮某绦蛟O(shè)計(jì)語言;
18.學(xué)習(xí)編程最好的方法之一就是閱讀源代碼;
19.在任何時(shí)刻都不要認(rèn)為自己手中的書已經(jīng)足夠了;
20.請(qǐng)閱讀《The Standard C++ Bible》(中文版:標(biāo)準(zhǔn)C++寶典),掌握C++標(biāo)準(zhǔn);
21.看得懂的書,請(qǐng)仔細(xì)看;看不懂的書,請(qǐng)硬著頭皮看;
22.別指望看第一遍書就能記住和掌握什么——請(qǐng)看第二遍、第三遍;
23.請(qǐng)看《Effective C++》和《More Effective C++》以及《Exceptional C++》;
24.不要停留在集成開發(fā)環(huán)境的搖籃上,要學(xué)會(huì)控制集成開發(fā)環(huán)境,還要學(xué)會(huì)用命令行方式處理程序;
25.和別人一起討論有意義的C++知識(shí)點(diǎn),而不是爭(zhēng)吵XX行不行或者YY與ZZ哪個(gè)好;
26.請(qǐng)看《程序設(shè)計(jì)實(shí)踐》,并嚴(yán)格的按照其要求去做;
27.不要因?yàn)镃和C++中有一些語法和關(guān)鍵字看上去相同,就認(rèn)為它們的意義和作用完全一樣;
28.C++絕不是所謂的C的“擴(kuò)充”——如果C++一開始就起名叫Z語言,你一定不會(huì)把C和Z語言聯(lián)系得那么緊密;
29.請(qǐng)不要認(rèn)為學(xué)過XX語言再改學(xué)C++會(huì)有什么問題——你只不過又在學(xué)一門全新的語言而已;
30.讀完了《Inside The C++ Object Model》以后再來認(rèn)定自己是不是已經(jīng)學(xué)會(huì)了C++;
31.學(xué)習(xí)編程的秘訣是:編程,編程,再編程;
32.請(qǐng)留意下列書籍:《C++面向?qū)ο蟾咝Ь幊蹋–++ Effective Object-Oriented Software
Construction)》《面向?qū)ο筌浖?gòu)造(Object-Oriented Software
Construction)》《設(shè)計(jì)模式(Design Patterns)》《The Art of Computer
Programming》;
33.記?。好嫦?qū)ο蠹夹g(shù)不只是C++專有的;
34.請(qǐng)把書上的程序例子親手輸入到電腦上實(shí)踐,即使配套光盤中有源代碼;
35.把在書中看到的有意義的例子擴(kuò)充;
36.請(qǐng)重視C++中的異常處理技術(shù),并將其切實(shí)的運(yùn)用到自己的程序中;
37.經(jīng)?;仡欁约阂郧皩戇^的程序,并嘗試重寫,把自己學(xué)到的新知識(shí)運(yùn)用進(jìn)去;
38.不要漏掉書中任何一個(gè)練習(xí)題——請(qǐng)全部做完并記錄下解題思路;
39.C++語言和C++的集成開發(fā)環(huán)境要同時(shí)學(xué)習(xí)和掌握;
40.既然決定了學(xué)C++,就請(qǐng)堅(jiān)持學(xué)下去,因?yàn)閷W(xué)習(xí)程序設(shè)計(jì)語言的目的是掌握程序設(shè)計(jì)技術(shù),而程序設(shè)計(jì)技術(shù)是跨語言的;
41.就讓C++語言的各種平臺(tái)和開發(fā)環(huán)境去激烈的競(jìng)爭(zhēng)吧,我們要以學(xué)習(xí)C++語言本身為主;
42.當(dāng)你寫C++程序?qū)懙揭话雲(yún)s發(fā)現(xiàn)自己用的方法很拙劣時(shí),請(qǐng)不要馬上停手;請(qǐng)盡快將余下的部分粗略的完成以保證這個(gè)設(shè)計(jì)的完整性,然后分析自己的錯(cuò)誤并重新設(shè)計(jì)和編寫(參見43);
43.別心急,設(shè)計(jì)C++的class確實(shí)不容易;自己程序中的class和自己的class設(shè)計(jì)水平是在不斷的編程實(shí)踐中完善和發(fā)展的;
44.決不要因?yàn)槌绦颉昂苄 本筒蛔裱承┠悴皇炀毜囊?guī)則——好習(xí)慣是培養(yǎng)出來的,而不是一次記住的;
45.每學(xué)到一個(gè)C++難點(diǎn)的時(shí)候,嘗試著對(duì)別人講解這個(gè)知識(shí)點(diǎn)并讓他理解——你能講清楚才說明你真的理解了;
46.記錄下在和別人交流時(shí)發(fā)現(xiàn)的自己忽視或不理解的知識(shí)點(diǎn);
47.請(qǐng)不斷的對(duì)自己寫的程序提出更高的要求,哪怕你的程序版本號(hào)會(huì)變成Version 100.XX;
48.保存好你寫過的所有的程序——那是你最好的積累之一;
49.請(qǐng)不要做浮躁的人;
50.請(qǐng)熱愛C++!
這篇文章幫了我大忙,不過現(xiàn)在還是不知道消除MFC預(yù)設(shè)的背景色,前兩種方法如何實(shí)現(xiàn)?我對(duì)MFC的框架還不是很了解
無閃爍刷屏技術(shù)的實(shí)現(xiàn)(文章來自:http://www.vchelp.net)
在實(shí)現(xiàn)繪圖的過程中,顯示的圖形總是會(huì)閃爍,筆者曾經(jīng)被這個(gè)問題折磨了好久,通過向高手請(qǐng)教,搜索資料,問題一基本解決,現(xiàn)將文檔整理出來以供大家參考.
1. 顯示的圖形為什么會(huì)閃爍?
我們的繪圖過程大多放在OnDraw或者OnPaint函數(shù)中,OnDraw在進(jìn)行屏幕顯示時(shí)是由OnPaint進(jìn)行調(diào)用的。當(dāng)窗口由于任何原因需要重繪時(shí),總是先用背景色將顯示區(qū)清除,然后才調(diào)用OnPaint,而背景色往往與繪圖內(nèi)容反差很大,這樣在短時(shí)間內(nèi)背景色與顯示圖形的交替出現(xiàn),使得顯示窗口看起來在閃。如果將背景刷設(shè)置成NULL,這樣無論怎樣重繪圖形都不會(huì)閃了。當(dāng)然,這樣做會(huì)使得窗口的顯示亂成一團(tuán),因?yàn)橹乩L時(shí)沒有背景色對(duì)原來繪制的圖形進(jìn)行清除,而又疊加上了新的圖形。有的人會(huì)說,閃爍是因?yàn)槔L圖的速度太慢或者顯示的圖形太復(fù)雜造成的,其實(shí)這樣說并不對(duì),繪圖的顯示速度對(duì)閃爍的影響不是根本性的。例如在OnDraw(CDC *pDC)中這樣寫:
pDC->MoveTo(0,0);
pDC->LineTo(100,100);
這個(gè)繪圖過程應(yīng)該是非常簡(jiǎn)單、非??炝税?,但是拉動(dòng)窗口變化時(shí)還是會(huì)看見閃爍。其實(shí)從道理上講,畫圖的過程越復(fù)雜越慢閃爍應(yīng)該越少,因?yàn)槔L圖用的時(shí)間與用背景清除屏幕所花的時(shí)間的比例越大人對(duì)閃爍的感覺會(huì)越不明顯。比如:清楚屏幕時(shí)間為1s繪圖時(shí)間也是為1s,這樣在10s內(nèi)的連續(xù)重畫中就要閃爍5次;如果清楚屏幕時(shí)間為1s不變,而繪圖時(shí)間為9s,這樣10s內(nèi)的連續(xù)重畫只會(huì)閃爍一次。這個(gè)也可以試驗(yàn),在OnDraw(CDC *pDC)中這樣寫:
for(int i=0;i<100000;i++)
{
pDC->MoveTo(0,i);
pDC->LineTo(1000,i);
}
呵呵,程序有點(diǎn)變態(tài),但是能說明問題。
說到這里可能又有人要說了,為什么一個(gè)簡(jiǎn)單圖形看起來沒有復(fù)雜圖形那么閃呢?這是因?yàn)閺?fù)雜圖形占的面積大,重畫時(shí)造成的反差比較大,所以感覺上要閃得厲害一些,但是閃爍頻率要低。那為什么動(dòng)畫的重畫頻率高,而看起來卻不閃?這里,我就要再次強(qiáng)調(diào)了,閃爍是什么?閃爍就是反差,反差越大,閃爍越厲害。因?yàn)閯?dòng)畫的連續(xù)兩個(gè)幀之間的差異很小所以看起來不閃。如果不信,可以在動(dòng)畫的每一幀中間加一張純白的幀,不閃才怪呢。
2、如何避免閃爍
在知道圖形顯示閃爍的原因之后,對(duì)癥下藥就好辦了。首先當(dāng)然是去掉MFC提供的背景繪制過程了。實(shí)現(xiàn)的方法很多,
* 可以在窗口形成時(shí)給窗口的注冊(cè)類的背景刷付NULL
* 也可以在形成以后修改背景
static CBrush brush(RGB(255,0,0));
SetClassLong(this->m_hWnd,GCL_HBRBACKGROUND,(LONG)(HBRUSH)brush);
* 要簡(jiǎn)單也可以重載OnEraseBkgnd(CDC* pDC)直接返回TRUE
這樣背景沒有了,結(jié)果圖形顯示的確不閃了,但是顯示也象前面所說的一樣,變得一團(tuán)亂。怎么辦?這就要用到雙緩存的方法了。雙緩沖就是除了在屏幕上有圖形進(jìn)行顯示以外,在內(nèi)存中也有圖形在繪制。我們可以把要顯示的圖形先在內(nèi)存中繪制好,然后再一次性的將內(nèi)存中的圖形按照一個(gè)點(diǎn)一個(gè)點(diǎn)地覆蓋到屏幕上去(這個(gè)過程非常快,因?yàn)槭欠浅R?guī)整的內(nèi)存拷貝)。這樣在內(nèi)存中繪圖時(shí),隨便用什么反差大的背景色進(jìn)行清除都不會(huì)閃,因?yàn)榭床灰?。?dāng)貼到屏幕上時(shí),因?yàn)閮?nèi)存中最終的圖形與屏幕顯示圖形差別很小(如果沒有運(yùn)動(dòng),當(dāng)然就沒有差別),這樣看起來就不會(huì)閃。
3、如何實(shí)現(xiàn)雙緩沖
首先給出實(shí)現(xiàn)的程序,然后再解釋,同樣是在OnDraw(CDC *pDC)中:
CDC MemDC; //首先定義一個(gè)顯示設(shè)備對(duì)象
CBitmap MemBitmap;//定義一個(gè)位圖對(duì)象
//隨后建立與屏幕顯示兼容的內(nèi)存顯示設(shè)備
MemDC.CreateCompatibleDC(NULL);
//這時(shí)還不能繪圖,因?yàn)闆]有地方畫 ^_^
//下面建立一個(gè)與屏幕顯示兼容的位圖,至于位圖的大小嘛,可以用窗口的大小
MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);
//將位圖選入到內(nèi)存顯示設(shè)備中
//只有選入了位圖的內(nèi)存顯示設(shè)備才有地方繪圖,畫到指定的位圖上
CBitmap *pOldBit=MemDC.SelectObject(&MemBitmap);
//先用背景色將位圖清除干凈,這里我用的是白色作為背景
//你也可以用自己應(yīng)該用的顏色
MemDC.FillSolidRect(0,0,nWidth,nHeight,RGB(255,255,255));
//繪圖
MemDC.MoveTo(……);
MemDC.LineTo(……);
//將內(nèi)存中的圖拷貝到屏幕上進(jìn)行顯示
pDC->BitBlt(0,0,nWidth,nHeight,&MemDC,0,0,SRCCOPY);
//繪圖完成后的清理
MemBitmap.DeleteObject();
MemDC.DeleteDC();
上面的注釋應(yīng)該很詳盡了,廢話就不多說了。
4、如何提高繪圖的效率
實(shí)際上,在OnDraw(CDC *pDC)中繪制的圖并不是所有都顯示了的,例如:你在OnDraw中畫了兩個(gè)矩形,在一次重繪中雖然兩個(gè)矩形的繪制函數(shù)都有執(zhí)行,但是很有可能只有一個(gè)顯示了,這是因?yàn)镸FC本身為了提高重繪的效率設(shè)置了裁剪區(qū)。裁剪區(qū)的作用就是:只有在這個(gè)區(qū)內(nèi)的繪圖過程才會(huì)真正有效,在區(qū)外的是無效的,即使在區(qū)外執(zhí)行了繪圖函數(shù)也是不會(huì)顯示的。因?yàn)槎鄶?shù)情況下窗口重繪的產(chǎn)生大多是因?yàn)榇翱诓糠直徽趽趸蛘叽翱谟袧L動(dòng)發(fā)生,改變的區(qū)域并不是整個(gè)圖形而只有一小部分,這一部分需要改變的就是pDC中的裁剪區(qū)了。因?yàn)轱@示(往內(nèi)存或者顯存都叫顯示)比繪圖過程的計(jì)算要費(fèi)時(shí)得多,有了裁剪區(qū)后顯示的就只是應(yīng)該顯示的部分,大大提高了顯示效率。但是這個(gè)裁剪區(qū)是MFC設(shè)置的,它已經(jīng)為我們提高了顯示效率,在進(jìn)行復(fù)雜圖形的繪制時(shí)如何進(jìn)一步提高效率呢?那就只有去掉在裁剪區(qū)外的繪圖過程了??梢韵扔胮DC->GetClipBox()得到裁剪區(qū),然后在繪圖時(shí)判斷你的圖形是否在這個(gè)區(qū)內(nèi),如果在就畫,不在就不畫。
如果你的繪圖過程不復(fù)雜,這樣做可能對(duì)你的繪圖效率不會(huì)有提高。
終于完成了A階段,下面可以進(jìn)入B階段了,主要集中在程序的UI上,另外考慮如何提升速度。
我的臨時(shí)文檔,看起來好亂,程序里的標(biāo)識(shí)符也沒完全按文檔里的來,真是亂套了,明天好好修改修改。
放入MyDefine.h,MyDefine.cpp文件
1. 河的邊線
Doc里放入:
//num of ctrl pnt,nodal pnt,display style,
//wave speed wave distance and wave num
int ctrlNum,ndlNum,style,wSpeed,wDistance,wNum;
//the pnt array represent ctrl pnts and nodal pnts.
CArray <CPoint,CPoint&> c_PntsL,c_PntR,n_PntsL,n_PntsR;
視圖類和文檔類都要引用MyDefine.h,用#ifndef吧
以下內(nèi)容放在視圖類里的OnCreate函數(shù)中,先為CView的派生類聲明一個(gè)圖元文件的數(shù)據(jù)成員HMETAFILE m_hMetaFile;
CArray <CPoint,CPoint&> initL,initR;
//預(yù)先輸入的控制點(diǎn),自定義
Int const Max=60;
//CArray <CPointPartner,CPointPartner&> init_CPntPtr,final_CPntPtr;
//CPointPartner作為TYPE有問題,還是用數(shù)組
//改為:
CPointPartner init_CPntPtr[Max],final_CPntPtr[Max];
//最后的點(diǎn)對(duì)數(shù)組final_CPntPtr給CCurve類用
While(i<Num)
{
CPointPartner temp_CPntPtr (initL[i],initR[i]);
init_CPntPtr.Add(temp_CPntPtr);
i++;
}
//鼠標(biāo)點(diǎn)擊或預(yù)先指定控制點(diǎn),即一些點(diǎn)對(duì)
//以及處理后得到的點(diǎn)對(duì)
CSpline spL (initL);
CSpline spR (initR);
//兩邊的樣條曲線
CArray<CPoint,CPoint&> finalL,finalR;
//處理后得到的樣條曲線上的點(diǎn)
spL.GetPoints(finalL);
spR.GetPoints(finalR);
Count=finalL.GetSize();
For(int i=0;i<count;i++)
{
CPointPartner Temp_finalP (finalL[i],finalR[i])
Final_CPntPtr[i]=temp_finalP;//重載=運(yùn)算符
}
//將樣條對(duì)象spL,spR里的點(diǎn)放入finalL和finalR,之后又放入點(diǎn)對(duì)數(shù)組final_CPntPtr;
//共count個(gè)點(diǎn)對(duì)
CMetaFileDC metaFileDC;
metaFileDC.Create();
這里畫出邊線(通過finalL和finalR)
m_hMetaFile=metaFileDC.Close();
5.23晚19:30以上程序的調(diào)試已完成(未加鼠標(biāo)控制)
2. 一道道波紋(CCurve類)
在視圖類中聲明數(shù)據(jù):CArray<Points,Points&> mPntsCurve;
在OnDraw里
先確定水波位置:
WavePL[i]和WavePR[i]
For(int i=0,i<WaveN;i++)
{
CCurve tempCurve (final_CPntPtr[i]);
tempCurve.ComputePnts(mPntsCurve);
連這些點(diǎn)成線
}
詳細(xì)設(shè)計(jì):
Doc里定義兩個(gè)點(diǎn),
View里定義一個(gè)函數(shù)BOOL ComputePnts(CArray<CPoint,CPoint&>& m_Pnts,CPoint m_LPnt,CPoint m_RPnt)
OnDraw里給兩個(gè)點(diǎn)賦值,調(diào)用ComputePnts,再繪圖
與MFC的聯(lián)系
//用圖元文件保存邊線,中間的curve即時(shí)畫出來
//要描繪的點(diǎn),每?jī)牲c(diǎn)畫條線連接LineTO
或者將點(diǎn)集的計(jì)算都放在文檔類中,給文檔類新建兩個(gè)函數(shù)
數(shù)據(jù)的放置位置還得琢磨琢磨
5.21 晚12:00此文檔完成
Spline的計(jì)算在CDoc里,Curve的計(jì)算在CView里
5. 29 晚1:47 添加(明天再修改)
5.30
Q: Spline里的temp值使得數(shù)組越界問題
A: 精度造成的,兩個(gè)float型變量t和T1[j1+1]都為0.90000,但t>T1[j1+1]為true,
Tips:
1. 查找類型強(qiáng)制轉(zhuǎn)換以及精度丟失的知識(shí)
2. 看林銳的《高質(zhì)量C++編程》,注意這些細(xì)節(jié)。
5.31
已完成:位圖作為背景。
Q:鼠標(biāo)控制的問題