中国游戏技术资源网
 

HalfLucifer 

 

淺談遊戲程式設計入門 - [進階篇]


Show Me Demo

        讓我們把焦點轉回遊戲程設的核心工作上:也就是 Graphics API DirectGraphics OpenGL 的學習上。無論是學習何種 API,一開始免不了都是需要熟記很多很多的函式名稱、呼叫方式、傳入參數等等繁複的東西。然後還需要把整個繪圖 API 的程式設計流程架構,從頭到尾的徹底瞭解;在學習 API 時很重要的一件事,就是要用心去思考繪圖 API 設計者的想法,盡可能的掌握住這個繪圖 API 的「設計思維」,以其思維模式來學習。如果能夠掌握住了這個重點,則我相信不管是在學習繪圖 API 的理論,或甚至是記憶函式的名稱等等,都會變成是很自然而然的容易理解。記得試著多問自己「why」與「why not」。

『學習,應該是一種主動性的思考,而非僅止於被動性的知識填充而已。』

當你確定自己已經建立起正確的觀念與思維模式時,就該開始來寫寫小程式囉。對於初學者來說,從無到有,往往是最難跨出的一步;如果想自己從零開始,一行行的撰寫程式碼,可能到最後才發現辛苦的結果,全部變成不解的程式 bug。如果覺得自己可能還沒辦法,獨立完整的完成一個程式,那麼比較好的方法就是:先參考別人的程式碼。無論是 DXG OGL,在各種書籍與網站中,都有為數不少的範例程式存在。藉由 trace 一個範例的完整程式碼,可以因此而學到很好的程式寫作方式。如果已經把整個範例的程式碼都瞭解的差不多了,或者還有疑惑不明白之處,可以試著改變程式中的一些變數或函式呼叫,看看程式的結果會有什麼變化,這也是一種很不錯的學習方式。 

『學習 Graphics API 最重要的是什麼?熟記函式和參數?搞懂整個理論架構?』

都不是。最重要的是:動手做。如果所謂的學習,只是腦袋裡記了一大堆不知所以然的東西,而很少真正動腦去想、動手去做,那麼所有的一切,可以說都是白費功夫。沒有實際踏實的程式寫作經驗,幾個月後,記憶裡只會剩下一堆不連續的殘片碎影罷了。很多寫程式時要注意的小地方或小技巧,我們稱之為 tip trick;一般的書籍或網站多只提供概略性的教學,對於實做上細節的一些小技巧,就需要自己親身經歷過,才能真正體會到的。簡而言之,就像是一種經驗值的累積囉;現在很辛苦的練等級,到了真正要面臨大陣仗、大魔王的時候,才不會臨場怯陣、紕漏百出。

        如果對整個 API 已經有了相當程度的瞭解,加上時間經驗的累積之後,就可以開始動腦想一些有趣的點子來做囉。有三角形、有燈光、有材質,可以做些什麼?讓燈光的顏色隨著時間變化如何?還是改變材質的座標讓物體外表有變化?還有透明度也可以做很多變化!工具在你手上,創意在你腦中;魔法人人會變,巧妙卻各有不同。之前經歷過這麼長的學習曲線,一路篳路藍縷、披荊斬棘的到了這裡,終於是可以自由揮灑的時候了,快把自己腦中存積已久的所有點子都壓榨出來吧! : )

        『嗯?有什麼地方不對勁嗎?』

隨著自己寫的小程式數目一直累積下來,或許你已經發覺到一件事實:「其實根本不用每次都從零到有的一行行程式碼撰寫,對吧?」沒錯,一般來說都會存在有一部份的程式碼是重複的、不變的;例如:視窗程式的初始化、繪圖 API 一定會做的初始化之類的動作。那應該怎麼做比較好?需要的時候再從之前的程式 “copy-paste”?不,這絕對是既沒有效率又存有風險的方法。什麼是最好的做法?最好的做法,就是把每次都會重複使用的程式碼,寫成一個骨幹架構 (framework)。所謂骨幹架構部分,通常是一個程式中變異性很小的程式碼;例如視窗程式的繁複初始化動作,動輒數百行程式碼以上,但卻有很大的固定性,所以就非常適合寫成骨幹架構。如果我們把骨幹部分的程式碼,獨立在一個 source file 中,而把真正相關繪圖部分的程式碼抽離出來到另一個 source file 中;把所有不相關的閒雜人等,寫成一個 source file 一次解決,從此不需要再煩惱那些不相關的東西,只要我們把主要繪圖部分的程式碼撰寫完成後,再和以前就寫好的骨幹程式做編譯連結,就可以讓專案 (project) 的整體架構看起來更清楚易懂,也大幅增加了專案的結構性。

        『除了最基本的 framework 之外,還覺得需要什麼嗎?』

        沒錯,你需要自己的圖書館 (library)。什麼是 library?讓我舉個例子來說明:如果你所學習的 API OpenGL,你可能會發現,不管是 BMPTGA JPG 等等所有的圖檔格式,都需要自己撰寫程式碼來讀取。OK,那就寫吧。The same as old,你會發現到,無論所需讀取的是哪一種格式的圖檔,我們的目的都是很相近類似的:就是做為多邊型的材質 (texture)。那我們何不以 C++ 的物件導向模式,寫出一個專門處理相關 texture 大大小小事務的類別呢?把讀取每一種圖檔的 function 寫在 texture class 的成員函式中,並且一樣的把它獨立成一個 source file;如此一來,只要每當需要處理 texture 相關程式時,就把已經寫好的 texture source file 和我們的專案做編譯連結,夠簡單又結構化,看起來很棒吧?

        同理可證,除了處理 texture 的類別外,還有文字的輸出呢?計時器的控制呢?鍵盤滑鼠的操縱?………別忘了還有最基本的矩陣和向量!把所有你能想到的基本功能,都寫成一個個的獨立 source file,只在需要的時候才和它編譯連結;如此不但程式碼易於維護除錯,未來的擴展性也相對的寬廣許多!而這一個個的 source file 集合起來,就是所謂的 library 囉。就像是自己家裡有座圖書館一樣,架上擺著分類齊全、功能眾多的各種書本,可以依照自己的需求而選取不同的書本來運用;而不是把幾萬行的程式全都濃縮在一本書 (source file) 中,時日一久,如果生了臭蟲,恐怕連原作者都不認識書的內容了!

        『所以,在寫小程式賺取經驗值的同時,最重要的工作就是要開始建立起自己的 library。』

        其實不管是在網路或書籍範例中,都可以看到很多別人寫的 library;有一些 library 甚至還具備了很強大的功能。但是我並不建議在自己的程式中使用別人的 library。有什麼壞處?以學習者的立場來看,使用別人的 library 所能學到的知識遠遜於自己辛苦寫出來的。參考別人的 library 寫法,或許是個不錯的主意,但是要記得:自己的 library,自己應該要看得懂才行。否則別說是擴充功能了,就連善加利用可能也沒辦法做到。在寫 library 的過程中,就可以看出之前學習的成果如何了;如果程式語言、資料結構的基礎沒有學好,現在肯定會是最痛苦的一刻。在撰寫自己的 library 之時,也未必要一次就寫出功能非常齊全的物件類別;如果使用物件導向設計模式來撰寫 library,就可以利用其可擴充的彈性,在有需要的時候才寫新出的功能,並加入相對應的成員函式;如此又可減輕了初始設計的負擔。

 

Hardcore Stuff

        經過漫長的旅程,寫過幾個小 demo,擁有一些自己的 library 之後,應該可以感受到一點遊戲程設的樂趣與魅力了吧?但是這樣的知識,可能還是不足以達到設計你心目中理想遊戲的能力,對吧?基本知識有了,繪圖 API 熟了,接下來呢?讓我們更進一步來看看比較深入的遊戲程設世界。

        Ok, let’s talk something seriously.

        我想,只要是對於遊戲設計稍有興趣的人,在玩一款遊戲的時候,多少都會問自己:「這個遊戲是怎麼做的?」是的,如果你是一路踏實努力走來的學習者,你現在更應該認真思考這些問題。除了以玩家的身份體驗一款遊戲的樂趣之外,更要以設計者的角度來看這款遊戲。在此,網路上的許多網站,就扮演了很重要的學習媒介角色。相信你在學習過程中偶爾都會聽過一些奇怪的名詞術語,像是:BSPPortalOctreeLODLightmapRay tracing ………等等。這些就是遊戲設計的相關技術名詞。你知道這些技術和遊戲程式有什麼關連性嗎?你好奇這些技術如何應用在遊戲程設中嗎?在此,你的英文能力 (或翻譯軟體 :p) 就十分的重要了。

        『你想知道的一切,網路上都找的到答案。』

網路資源的利用可以說是學習過程中非常重要,並且不可或缺的一環。以國外的三大遊戲設計網站 GamasutraFlipcode Gamedev 來比較:Gamasutra 通常會提供相當深入、內容充實的研究主題,包含了遊戲程設、美術,甚至音樂與企畫管理,非常適合想對某一特定主題深入探討的人;此外,Gamasutra 也是 Game Developer 這本著名遊戲設計雜誌的相關網站。Flipcode,也會不定期有教學文章的更新,主題多數都蠻具實用性的;並且 Flipcode Image Of The Day 區域提供大家一個展示程式的地方,在此往往可以看到不少有意思的作品,絕對是這個網站不可不看的部分。Gamedev 相較於另外兩者,在業界新聞及教學文章的更新速度都比較快,並且文章的數量很多、分類詳細,不過其所提供的教學文章多以概論為主,少有比較深入的探討。

        『到此為止,才算是真正開始逐步踏入遊戲程設殿堂的時候。』

        只要稍微瀏覽過國外遊戲設計網站的話,應該不難發現,其中的文章數目及種類實在太多太多了。其實對一個初學者而言,這個樣子反而不見得是一件好事。可能會不知從何開始學習,文章裡充斥著一大堆看不懂的專業術語,甚至可能搞不清楚自己想要學習什麼。萬事起頭難,剛開始或許一整篇文章,從頭到尾仔細的閱讀了兩次,還是只懂得其中的兩三成內容;這個時候就需要踏實的投注時間與精力,點點滴滴的累積知識的廣度。文章看得多了,程式寫得勤了,漸漸的就可以瞭解七、八成以上的內容囉。每篇文章所講的主題,就像是一個個的「點」,如何找出點與點之間的「關係」,將這一個個的「點」連成「線」,進而化成一個知識的「面」,也是學習中值得思考的一件事。

        除了每個網站的教學文章之外,附屬於網站之下的討論區也是一個非常重要的資源。試著用英文表達你的誠懇、發出你的問題,即使文法不是百分百正確、即使找不到合適的詞彙表達你的意思,你會發現總是有許多熱心的人很樂意幫助你的。在國外討論區回答問題的人,往往都很願意幫助別人解答疑惑,就算是自己不熟悉的問題,也會提出自己的經驗和想法,甚至連程式碼的展示也毫不吝嗇;所以只要你問的問題夠好 (我相信唯有好的問題才能導引出好的答案),往往可以得到遠超過你所想像的豐富收穫、學到很多有用的知識。在發問前,也可以先搜尋看看該討論區有沒有類似的討論,或許你的問題早已有人問過了。記得不要再問「DirectX and OpenGL, which one is better?」這種問題囉! : )

        『網路的資訊是學習新知技術最好的一條途徑,那如果想對基礎的原理有更深的認識呢?』

        別無二法,就是書本。書本可以說是學習知識最紮實的 (也或許是最痛苦的 :p) 途徑。其實真正學習的最好最好方法,就是找到一個好老師加上一本好書。不管任何知識,如果有了好老師的授業解惑,絕對有事半功倍之效;很可惜的是,一位稱職的好老師真的很難找,特別是在遊戲程設這個怪領域中。所以靠人靠天,最後還是靠自己最實在;書本,就是閉關練功的武林密笈、不二法門。或許你會懷疑,已經學會了程式語言、視窗程式、繪圖 API,為什麼還要看書?書裡寫的不都是一堆無聊的理論加上複雜的數學式嗎?正如在之前的文章所提到的,瞭解理論並不見得會帶來什麼立即的效益,也不一定能增強寫程式的功力;但是書本的知識,能夠幫助你更確實的掌握住事物的本質基礎與思維模式。特別是在日趨複雜的遊戲程式設計中,如果沒有深厚穩固的理論基礎所建構起的法則做為地基,恐怕難以負擔起越來越龐大複雜的遊戲程式架構。

        還是那句老話:「想創造規則的人,必先瞭解規則。」每一本好書,都是前人以無可計數的時間經驗所得來的心血結晶,集英薈萃之後以文字的形式傳諸於世,讓所有有心學習知識的人都能因此受惠。從書本中,我們可以輕易的學到前人的知識經驗與心血結晶;原來可能自己要花費數年時間才能領悟的道理,現在只需要從閱讀書本中的知識就能輕易習得。以 3D 電腦圖學來說,瞭解其背後的許多理論基礎,更能幫助你更快的學習並吸收新的知識。例如在瞭解了 Phong reflection model 的定義之後,就可以很容易的理解為什麼光源的組成要分成 ambientdiffuse specular 三個成分了;如果瞭解 3D 電腦圖學的發展歷史,就不難理解為什麼目前的 3D 繪圖主流方式還是以 polygonal mesh 為主了;諸如此類,太多太多的例子可以舉。理論知識這東西,不會是你一時的飯碗;卻會是你一輩子的財富。

 

Build Up Toolbox 

        熟悉了一些遊戲的核心技術之後,就可以開始建立自己的工具箱了。何謂工具箱?一般常見的講法就是「編輯器」(editor)。編輯器大致上有兩種用途:一是做為程式的測試工具,二是做為遊戲開發的編輯工具。以第一種用途來說,例如你想用之前文章提過的質點系統 (Particle System) 來做一個施放魔法時的特效場面。要怎麼要才能知道所寫出來的程式碼有沒有符合需求呢?這個時候就可以寫一個質點系統的編輯器工具,把所有可以調整的變數全部列在編輯器的面版中,可能會包括質點大小、位置、顏色、速度及運動法則等等要素。然後就可以在編輯器的面版上,直接調整變數的值,即時的觀察質點系統的變化情形如何。使用這種方法,就能夠很便利的以各種不同數據測試程式的結果,而不是每次都要在程式碼中更改數據後,再重新編譯連結整個程式。更大的好處,就是可以讓不懂程式碼的人,也能直覺性的調整並控制程式的呈現結果。所以建立編輯器之後,就算是複雜的交叉數據測試,也會變得容易、而且直覺許多。

        編輯器的第二種用途呢?舉個例子來說,Quake 3 Arena 中宛如藝術品般驚為天人的美麗場景是如何製作的?如果你對遊戲設計的核心技術已經具備有基本概念,就應該能夠瞭解,它的場景不可能是由幾位程式設計者,一個一個物件的撰寫程式碼而完成整個複雜場景的。那應該是用什麼樣的方式來建立複雜的遊戲場景呢?就是依靠所謂的編輯器。一般來講,一個完整的 3D 場景就稱做一個 level,而編輯場景用的就叫做關卡或場景編輯器 (level/map editor)。通常編輯器是由程式設計者,將所有可能會使用到的功能先設計完全,並做出一個易於操作的使用者介面;如此一來就可以讓專門負責場景的設計者 (level designer) 來完成所有的關卡與場景。只要編輯器的功能夠強大齊全,甚至不用懂得任何程式碼,也可以設計出非常棒的場景;而這正是編輯器的真正威力。

        編輯器的真正目的應該是化繁為簡的能力。最理想的狀態應該要做到,不需要任何說明文件與教學,任何稍具遊戲設計概念的人都可以輕易上手才是。編輯器的產生也使得遊戲開發的分工變得更合理可行;只要程式將人物的對話編輯器寫好之後,就可以交給企畫負責編撰人物的文案;如果程式開發出夠強的場景編輯器,就可以讓美術來負責整個場景的建模與成形了。所以編輯器往往是遊戲的製作過程中,相當重要的一個部分。如果說一個遊戲的開發時間,有百分之五十投注在設計開發編輯器的過程上也不為過!

        『我知道你在想什麼。』

        到了這裡,又要再次面臨類似的問題:Borland C++ Builder MS Visual C++,到底要選擇何者做為開發工具用的編譯器?我的答案還是一樣的平凡:兩者都學了再說。在之前的文章提過,要寫出比較進階的視窗程式,可以用 Win32 SDKBorland VCL 或是 Microsoft MFC。其實編輯器就是屬於一種進階的視窗程式設計,因為它會包含很多複合性的元素,如繪圖 API 的呈現、對話盒、控制面版與檔案的儲存載入等等。在各大程式設計討論區,BCB MSVC 的批評比較,絕對不亞於 OpenGL DirectX 的情形。如果用另一種方式來比喻的話,BCB 就像是家裡的萬能老媽一樣,會幫你把所有想做的事情都打理的很好;只要用「拖拉點放」的方式,就可以完成大部分的視窗元件設計。而 MSVC 就像是精打細算的老婆一樣,所有要完成的事情都要跟她報備,照著規矩一項一項的來做;雖然有一些便利的設計精靈可以應用,可是大部分還是要用「手工打造」的方式,循序漸進的來完成。

        而兩者的缺點呢?BCB 常被人所詬病的,就是其不佳的程式編譯效率及執行效能;而 MSVC 則是 MFC 的學習曲線太長,龐大複雜的 MFC 結構,往往使初學者望之卻步。我的建議還是相同,不管別人的說法如何,還是只有自己親身用過之後才能體會其優劣勝敗之處。兩者都學習之後,或許才會發現在別人眼裡是優點的地方,自己不以為然;而在別人眼裡是缺點的地方,自己卻不以為意。不論是 BCB MSVC,都只是一種工具,為了達成某些目的而被造出來的工具;所以,能因地制宜,選擇合適的工具,看何者用的比較順手就使用何者,或許才是比較好的方式。

 

On The Way

        『什麼?你是認真的嗎?這麼無聊的三篇文章你都能看到這裡了喔,真服了你耶。』

        『嗯?你說你前面的所有學習步驟都完成了,接下來呢?』

        『不,如果你會有這個疑問,表示你還沒到達這裡。』

        ………………………

        『好吧,好吧,如果你真的好奇的話,讓我們再來稍微談談之後的路。』

        其實很容易,至此有幾個簡單的選擇;一是對自己有興趣的主題繼續深入研究,往深度發展;二是再尋找其他沒學習過的主題,往廣度發展;第三,還有別的嗎?就是寫 GAME!跟我唸一次,GAMEGAME!別忘了我們一路從這漫長艱辛的路程走來,為的是什麼目的。現在你終於可以大聲的說:我有能力寫出一個遊戲了!開始激發你的創意,爆發你的潛能,構思設計一個 GAME 吧! : )

        最後再提一件事情。或許你也會常常聽到某某遊戲用了什麼「3D 引擎」之類的。嗯?你說這一系列的文章,怎麼從來沒有談過有關 3D 引擎的主題?咳咳,請記得這篇文章的主題是「淺談遊戲程式設計入門」,不是什麼「如何在 30 天內做好一個 3D 引擎」、「快快樂樂學做 3D 引擎」,或「如何在 30 歲前擁有人生第一個 3D 引擎」之類的OK……………好啦,講認真的,3D 引擎真的是非常複雜的東西,絕非像這樣的三兩篇文章可以解決的。也不是我目前的能力可以分享的。其實像之前所提到的編輯器工具,可以說就是 3D 引擎的一個重要核心;不過 3D 引擎同時還必須整合美術及音樂的部分,將一切製作遊戲所需的元素都考慮進去,才能算得上是一個完整的、真正的「3D 遊戲引擎」。不過我的建議是,就算你已經學習至此,還是先不要想太多 3D 引擎的東西;繼續充實自己,累積寫程式的經驗,利用自己現有的知識與技術,做出一個有趣的小遊戲吧!

        一向慣於以文字表達的我,到了這裡還是不禁要懷疑:這些辛苦敲打出來的文字,究竟能不能適當地表達我心裡真正想說的話呢?真正能瞭解我想表達的意思的人有多少呢?而真正能努力做到並且達成目標的人又有多少呢?…………………好吧,我承認我想太多了 (其實是已經不知道要說什麼了 ~_~)。總而言之,基本上這一系列文章的重點差不多已經告一個段落,在接下來的最後一篇文章中,我會以自己親身的學習經驗為例,和大家做個分享。還請大家多多指教。