我的1998年軟體版本的3D



這是後來移植到pda的軟體版本
找到以前的程式碼, 是1998年寫的. 記得還是DOS時代.
那時全部3D的書 就只有一本叫做computer graphics.
那時純軟體的3d game 印象中只有三套, quake2 tomb raider. descent.

那時才是3D程式的黃金時代, 那時就有 voxel的技術出來了.
現在寫3D已經很幸運了. 顯示卡威力夠強, dx9也成熟, 書本網路資料更是多到爆.
而你卻還不想進入3D, 還真是奇怪.

---------------------------------------------------------
有看到這照片 當時坐我隔壁的美術, 我現在需要圖形的資源, 看到請聯絡.
你的 e-mail 在我放yahoo的信箱被盜了以後 就進不去了.
--------------------------------------------------------

10年程式debug的技巧

10年程式debug的技巧

10年以上coding功力經驗談.
--------------------------------------------------------------------------------------------

寫程式光是debug可能就要花去你寫完一個軟體時間的30%了.(可能不止)

重不重要?

debug其實已沒什麼技巧, 就是練.

寫1年跟寫2年, debug的功力絕對有差別.

1,2年可能看不出來, 但1年跟5年絕對有差.

不管天份怎麼高, 了不起是別人的30% off就應該是天才了
(就是別人寫1年的功力 在怎麼的天才 也要寫8.4個月的意思)

你常常會看到什麼天才 不到幾歲就會怎樣怎樣,

在程式界 真的看不到天才.(有成就都要20歲以上)

(程式界的天才 doom的作者是在22歲才寫出來的, 我也不相信 有人12歲就可以寫出來 )

因為debug就是經驗, 練愈久的人當然經驗愈豐富.


--------------------------------------------------------------------------------------------

看一個寫程式的功力 其實看debug的功力是最準的.

看到一堆白痴公司, 包括MS, 面試應徵人員不考程式 卻考些奇怪的問題.

難怪MS的軟體bug滿天飛.

不然就是考些自己公司軟體實做上的問題, 軟體即使都是同一種語言寫出來, 但範圍太廣.

隨便跨個領域 就不一樣. 這又如何考的出實力?

最簡單看出一個程式員的功力, 就是給他一電腦(有很多面試 連電腦都沒給你 靠個紙筆能幹什麼? )

給個1,2千行的程式, 告訴他這裡面的功能, 但有幾個bug, 叫他找出來.

還可以順便考 閱讀程式碼的功力.

這種鑒視度最高, 能力差別大的 很快就能區分出來.

--------------------------------------------------------------------------------------------

開始debug.

1.千萬不要精神不好 就想要debug, 先去睡覺 比較實在.

如果精神不好 都可以讓你找出bug, 那你精神好時 怎會寫出一堆bug?


2.千萬不要自己要做什麼都不曉得 就開始寫程式==>就進入complier 開始實做.

等你想清出自己要做什麼, 要增加哪個功能, 要做哪些細節, 等想清楚, 再寫code.

當然你可以弄個notepad 打打字, 把要做的多少打些出來. 但還是不要進入complier.

等想清楚了再來做. coding只是要驗證想法的正確與否.


看到一堆自以為是的笨蛋 老是以為coding 沒什麼, 反正出一張嘴, 就只要這樣這樣 不就出來.

你想的 我也會想. 不過我做的出來 你卻做不出來. 光只會打嘴炮 不如去當政客不要coding比較實在.

小東西要是實做能力不夠, 等到處理複雜的東西, 光是debug就會 debug到哭, 覺得人生無望, 我看可能會跳樓.

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

以目前3D程式的複雜度, 我認為是2D程式好幾倍. 要是連簡單的2D都練不好, 3D沒多久就會放棄了.

2D是精確的整數, 了不起 位置 int (x,y), 顏色 byte(r,g,b), 再加個寬高int(w,h), 大概就處理完了.

3D光是一點就是 float(x,y,z), float可不是精確的數字. 只有0.333333, 沒有1/3.

更要命的: 運算結果不會出現1這種東西, 而是出現要命的0.9999999

(1.f/ 3.f) *3.f 電腦絕對不會出現1(也許有利害的complier會出現1)


float還有要命的範圍問題, 就是誤差. 數值範圍可能從200000~ -0.0000001這種東西.

要命的出現了, 參數0.01跟0.001 在3D裡面出來的結果就是會不一樣.

(我認為這是3D裡面最難debug的東西, 就是怎麼畫面沒出來, 看半天都沒問題啊 邏輯都正確,

結果只是設0.1跟設0.01的寫作不同 結果就不一樣)



float精確的問題 最明顯的表現在3D的z-fighting, 這幾乎是很難解的問題,

要解決這種看起來像是小問題, 反而要讓繞一大圈.

當然構成3D圖形不只要一個點, 還要面的資訊 int(f,f,f), 還要貼圖資訊float(tx,ty). 大概這樣.

在3D世界 說穿了 已經進入模糊的世界. 沒有精確度 只有近似度. 就是到達誤差可以容忍的範圍.


------------------------------------------------------------------------------------------------------------------------------

debug的技巧:

造成程式致命的bug, 就是那種跑一跑會當掉, 就是死掉 死當.

通每每個變數都有他的範圍, 變數初始止是很基本的技巧===>所有的變數都要被初始值.

因為3D處理的數值範圍太大, 隨便float一運算, 從3434343~0 -0.2323都有.

重要變數範圍都要做檢查, 就是你的程式只處理你要的範圍, 其他沒處理的都要直接把錯誤印出來,

提示出來, 讓你知道. 不然死當的機會很高.

這不是簡單的什麼陣列index範圍檢查, 而是float數值範圍檢查.

最常見的數值範圍在-1~1之間, 超出就會錯誤.

除以0也要檢查.

這些即使出現錯誤 也不會當掉.

關於那些3D遊戲宣傳, 只有美美的動畫宣傳 我是不大相信的.

還要實際試玩, bug還有操控性 都是很重要. 一款遊戲也可能被操控性給毀掉.

現在3D遊戲突然多起來了, 說穿了只是顯示卡的進步, 而造成的畫面好看而已.

很多問題 還是一樣沒有進步. 這當然就成為缺乏遊戲性的原因了.

-----------------------------------------------------------------------------------------------------------------------------

用你擅長的語言功能:

c++用了10年, 我還是只用基本的class封裝功能, 其他什麼繼承 虛擬有的沒有的, 我都沒用.

STL也只用vector.

用你不熟悉的語言功能 只會增加你的負擔, 增加程式的bug.

(你大腦要記住這麼多語言的功能 還要把功能發揮 沒那麼容易)

一堆軟體工程寫的書, 看看就好. 反正是打嘴炮.

去看看人家真正實做出來的程式碼, 長的什麼樣子, 比較實在. 那是真正能跑的東西.

quake3程式碼都出來了, 自己去看看, 純C. 連基本的class都沒有.

bug會比較多嗎? 直接打死一堆書 一堆老師. 也直接打死什麼c++, java...一堆奇奇怪怪語言的發明者.


以最基本的UI按鈕的事件回應, 照我看來 windows的switch case 結構最經典, 最好用 好學 好懂.

你自己去實做一個類似的按鈕radio list.... 有的沒有的.

當然會用到什麼虛擬 繼承....

事實上 通通不用到, 改用windows的switch就很好用了.

java還搞出一堆奇奇怪怪的函式: 什麼addLister...說穿了就是函式指標.

寫出一堆奇奇怪怪的程式碼, 故弄玄虛. 結果做出來的功能也是一樣的.

但程式碼卻更多行, 那可是會多出上百行, 只會弄個什麼繼承 虛擬?

畫蛇添足 多此一舉. 程式碼愈多行, bug愈多, 閱讀 整理 就愈困難.

同樣的事件功能, win32 switch case程式碼數量 遠比那些什麼奇怪的 亂七八糟的 怪物件設計好上好幾倍.

我告訴你: 最直覺的程式設計 就是一行一行 有序的執行, 不止符合邏輯思考, 閱讀上也方便多了.

軟體上 一堆只是理論 理想. 聽聽就好.

----------------------------------------------------------------------------------------------------------------------------------------

只用class 就可把程式碼的整理給簡化很多了.

把data跟函式包在一起, 說穿了 就是一種程式碼的整理而已.

因為絕大部分都是函數只要一個就好, 函數是最基本的封裝.

每次需要就是傳的函式參數. 但參數一多 函數一多 就很難整理.

可能用個檔案把gobal變數 跟函數再放同一個檔案.

但這又不整潔. 所以class的發明 本身就夠偉大了, 資料要很多份, 函數只要一份.

a.GetPos(); b.GetPos(); 這樣多整潔.

如果不這樣寫, 只是單純的c, 光是a,b裡面的一大堆變數 就不知要放哪裡了.



對於奇怪的UML也無法認同 那是什麼鳥東西.

所有說明文件 只要寫的好, 好的函式說明: 傳入什麼 傳回什麼, 給個sample 都比奇怪的UML好多了.

好的class 說穿了 就是哪些是重要的變數 跟重要函數 讓你知道 就可, 只需看那些重要的變數函數.

其他都不用管. 簡化多了. 不然每個變數函數都一樣重要的話 那真是浪費時間.


--------------------------------------------------------------------------------------------------------------------------------------------

匈牙利命名法:

我認為這大概是MS對整個軟體業最大的貢獻.

只要一接觸到windows程式設計 一定會提到的變數命名法.

雖然有些人不以以為然, 但我認為這是相當好用的.

另外不需要用到那麼複雜.

m_, s_, g_, m_nPlayer, m_szName[30],....凡是陣列我也是用sz. m_szPlayer[10]

其他有需要 就自己加.

這說穿了 就是針對變數 給出範圍, 到底這變數是哪裡來的, 有沒有注意到: 匈牙利命名法 是針對變數不是什麼函數....

最基本的封裝是函式.

但一個函數會用到很多變數

void House::FunHouse(int a, int b )
{
int i, x. name;

w = myName(x );
}

w是什麼鳥東西?

照道理而言, w根本是個bug. 莫名其妙就冒出來.

結果找半天 不知道w在哪裡, 還要find in file, 結果跑出一堆w.

但如果只增加個 多寫m_w. 或是g_w. 一目了然.

m_w一看就知道是 class House裡面的變數, 馬上就可找到.

g_w 就知道這變數很重要 要小心 會在很多檔案裡用到.

這對debug有很大的幫助.

就是你寫的東西 到底在哪裡, 要能很快的找出來.