[游戏入门基础]淺談遊戲程式設計入門 - [基礎篇] 

2007-01-08 10:33 发布

引擎学习交流 /[参考文档]
4294 0 0
『首先,請開始學習C++。』

 

        嗯?什麼?你說你會VB、會C語言?還有JAVAASPSQL?讓我再說一次:「請開始學習C++。」無論你之前學習過什麼樣的程式語言,請記得,現在我們談論的是最適合用來開發遊戲程式核心的程式語言。C++無庸置疑是目前功能最強大、效率最好、操作彈性最佳,也是最複雜難懂的語言。因此,C++用來開發遊戲程式核心,至少在PC平台上,是最最合適的不二人選。

        『OKOK,我已經聽到很多不以為然的聲音了;請給我一點機會解釋一下。』

 

 

        C++是一個具備良好物件導向設計模式的一種語言,能相當完整的以「物件」為設計的著眼點來完成整個程式的分析及架構。在這裡舉一個實際應用上的例子:大家都知道,在3D的程式設計中,「向量」的使用是非常廣泛且多面的,如果我們能以「物件導向」的觀點設計出一個「向量物件類別」,那麼在之後的使用上將會帶來許多的便利性。怎麼說呢?如果我們使用傳統 structure-based 的設計模式來建立一個向量的新類別,我們通常會這樣宣告:

        typedef struct {

                float x, y, z;

} Vector;

以此來表示一個自己定義的新類別 Vector,其內結構由 xyz 三個類別為浮點數的變數所組成。

「看起來還不錯?」但是今天如果有需要做兩個 Vector 類別的加減乘除呢?對不起,你必須一步一步的自己來做:

        Vector vec1, vec2, vec3;

        vec3.x = vec1.x + vec2.x;

        vec3.y = vec1.y + vec2.y;

        vec3.z = vec1.z + vec2.z;

 

 

「有沒有更直覺的做法呢?」有的,在C++中,你可以自訂類別的「運算子」來幫你更直覺化的完成這件事,例如:

        operator+(Vector vec1, Vector vec2) {

        vec3.x = vec1.x + vec2.x;

        vec3.y = vec1.y + vec2.y;

        vec3.z = vec1.z + vec2.z;

}

如此一來,以後在做 Vector 類別之間的加法時,只要簡單的寫:

        vec3 = vec1 + vec2;

所有的工作,就由自訂的加號運算子來幫助你完成,就像使用預設的加法運算子一樣的直覺。在C++的語法中,你還可以為自訂的「物件類別」,增加更多的「成員函式」;我們可以把「成員函式」看做是去定義一個「物件」的某種「行為」或「方法」,藉此來達成物件與外界的溝通橋樑。例如一個 Vector 常有可能會需要使用內積、外積或向量長度的計算;而其他加減乘除的運算,也都是 Vector 這個物件的「行為」或「方法」。當我們把這些功能寫成 Vector 的成員函式之後,我們就能更加直覺的瞭解並使用這些方法,同時也在無形中增加了程式碼的可重複利用性。

 

 

物件導向及C++語言的威力還不僅止於此,在物件類別中所定義的各種函式都可以做到虛擬與多型的機制拓展,更進一步的提供了「繼承」這項嶄新的設計思維。何謂繼承?所謂的繼承,即是指物件架構的繼承體系。如「人類」是屬於「靈長類」下的一支,而「靈長類」又是屬於「哺乳類動物」下的一支;於是我們可以說,所有靈長類的動物必定具備有哺乳類動物的特質,而所有的人類必定具備有靈長類動物的特質。這就是一種「繼承」的架構。當我們在寫程式時,若能依照架構由上而下的來定義物件類別,則必定能夠節省很多的時間和力氣,寫出更好的程式。

舉一個例子來說明:如果今天我們要設計一個有關「質點」(particle) 的類別,要能夠描述所有質點可能具備的特質及可能發生的行為,用C++的觀點該如何來做?假設我的世界中會有三種質點:雪、火、雨。於是我們開始設計「雪」的物件類別…… 再來是「火」,…………… 最後還有「雨」。然後,我們可能會發現,其實這些質點會有許多共通的「本質」存在;不管是任何一種質點,我們都需要它存有:質點位置、質點大小、質點速度等等之類的資料。既然如此,我們何不把所有質點的共同特質抽離出來,成為一個抽象的 Particle 物件類別?如此一來,所有繼承自它的物件類別 SnowFireRain 都可以擁有和 Particle 相同的「屬性」及「特質」。然後再依不同質點的不同「行為」,個別去定義各自的成員函式。以後如果還需要定義其他種類的質點,只需要先從 Particle 繼承而來,再來定義這個質點的不同之處就可以啦。

 

 

[後註]:其實這裡所舉的「質點」這個例子,在實做上並不完全合適如此的繼承架構。)

雖然它不是萬靈藥,但以物件導向的思維模式來寫作程式,在多數的情況下,都是相當有利於每一個程式設計者的。而C++,正是包含了物件導向設計模式,目前最合適應用於PC平台遊戲設計的程式語言。

 

 

        『嗯?聽起來好像真的很不錯吧?』

 

 

        很可惜的是,天下沒有這麼容易吃的午餐。既然C++有這麼多的優點和這麼強大的功能,那也就表示:C++是一種很難學習的程式語言。著名的作者侯捷在 Effective C++ 一書的譯序中就曾提到:「C++是一種難學易用的語言!C++的難學,不僅在其廣博的語法,以及語法背後的語意,以及語意背後的深層思維,以及深層思維背後的物件模型;C++的難學,還在於它提供了四種不同(但相輔相成)的程式設計思維模式:procedural-based, object-based, object-oriented, generic paradigm。」

 

 

        因此在C++語言的學習曲線上,相較其他語言自然來的漫長許多。這通常是初學者真正第一個需要用力跨越的門檻。程式語言,並不是一種很直觀的思維模式。沒有人與生俱來就熟悉這種語言,要親近它、學會它、熟練它,一步一步都是需要灌注時間和心力下去累積的。閱讀真正值得一看再看的好書、做各種程式的寫作練習、找個好老師學習,各種方法都是不能省略的。雖然在學習程式語言的過程中,會稍嫌單調無趣了些,但真正到了進階的部分時,就會發現這個部分功力的重要性。無論寫的是哪一種的程式,程式語言就是最重要的「內功心法」;如果內功未臻成熟,就急著練些花俏的武功招式,最後的結果就是程式 bug 連連,使出來的招式總在意料之外發生破綻。不可不慎之。

 

 

        在學習程式語言的過程中,也應該熟悉一些基本的「資料結構」,如各種 linked listqueuestacktree 等等的用法;如果能夠懂一些基本的「演算法」概念,對以後程式的設計也會有不小的幫助。關於程式編譯器 (compiler) 的選擇,其實在目前這個階段使用什麼編譯器都是沒有差別的;而在之後學習「視窗程式設計」及各種 Graphics API 時,就需要從 MS Visual C++ Borland C++ Builder 兩者中擇一了。我的建議是使用 MS Visual C++。畢竟是在 Windows 上開發程式、畢竟將來可能用到 MS 老大的 DirectX,在一開始的時候先用 MS 的編譯器,可能比較不會碰到太多非預期內的麻煩問題。

 

 

 

 

 

Handle Your Window

 

 

        有了程式語言的基礎之後呢?在你急著想學些3D的程式設計之前,先等一下,我們還得先拜拜碼頭:「先學會和我們可愛的 Windows 溝通溝通囉!」和 Windows 老大打好人際關係後,以後我們做起事來才會順利的多。誰也不希望程式執行到半途,老是跑出「此程式執行無效,即將關閉」的蔚藍畫面吧?

 

 

    『寫程式歸寫程式,又關它 Windows 老大啥事了勒?』

 

 

        話,不是這麼說滴。我們要知道,所有電腦中的應用程式,都是建構在「作業系統」上面動作的;我們在 PC 上所寫的遊戲當然也算是應用程式的一種。而 Windows 正是扮演著「作業系統」這個角頭老大的角色。由它來分配每個應用程式所可以使用到的記憶體以及 CPU,還有一般的鍵盤滑鼠訊息也都是經由它來傳送資訊給應用程式的。所以囉,想在 Windows 上寫作程式,當然需要先過這關囉。 

 

 

        『所以,現在有充分的理由開始學習 Windows SDK 囉。』

 

 

        不,即使會使用 VB 來設計視窗應用程式,也並不代表真正瞭解視窗程式設計的意涵。我再說一次,直覺化如 VB BCB 的拖拉點放「視窗元件」設計介面,也只是在你熟悉了視窗程式的核心概念之後,才能應用得宜、加速程式開發的。在那之前,好好的從基本的視窗程式寫作開始學習起,才是最正確並且合適的做法。

 

 

        對一個習慣了在 DOS 上開發寫作應用程式的人來說,在學習視窗程式設計的過程中,一開始最無法適應的就是找不到 main() 這個程式的起始點;在 Windows programming 中,都是以 WinMain() 取代 main() 了。除此之外,還有很多一開始比較難以接受的新概念:什麼是訊息迴圈?不可或缺的 WndProc() 又是做什麼的?怎麼輸出文字?………… 相當多在 DOS 上的程式用法或函式,到了 Windows 上卻不管用了。如今,要在 Windows 上寫出一個最簡單基本的 “Hello, World” 小程式,也約略要寫 100 行左右的程式碼。不過也不用擔心太多,只要找到一本好書做為學習的教材,就能夠很快的進入狀況、熟悉環境了。在此當然不得不推崇 Charles Petzold 原著的 Programming Windows 這本書,內容真可謂是鉅細靡遺,書中還包括了每一個範例程式的完整程式碼,不論是書的厚度或內容,都是相當地具有「份量」;目前此書也已有中譯本。

 

 

        『那麼,SDK 的學習大概要到什麼程度呢?』

 

 

        Programming Windows 這本書為例,我想真的很少有人能夠有足夠的耐性與時間,完整的啃完厚達 1500 頁的內容吧?何況其中的內容雖然非常豐富可觀,但如果僅是以「遊戲設計」為目標的話,倒也不需要懂這麼多東西。那麼至少,要學到什麼程度?我想,至少的至少,要學會如何鍵盤及滑鼠事件的操控,才能算是及格了。如果對如何使用 SDK 寫出一些進階功能的視窗有興趣的話,例如像子視窗、功能表、加速鍵、對話盒、文字字體、多工多緒之類較進階的課題,就可以再往這本書後面的章節繼續學習。如果在此時不學習這些進階的程式功能也是可以的,未來我們可以選擇學習 SDK 之外的其他方法,如 MS MFC,及 Borland VCL,來實做一個進階的視窗程式。有了以上的基本概念之後,才能再往下一個領域探索學習;如果在學會程式語言之後,沒有先具備視窗程式的設計概念,就急著想學 DirectX,到後來只會形成不得要領、四處碰壁的學習窘狀罷了。

 

 

 

Let's Rock'n Roll 

 

 

        馬步紮穩之後,就可以開始來玩玩真正有趣的東西囉!

 

 

        『Graphics,是一個遊戲的程式設計中,相當重要的一個部分,也常常是一個遊戲的程式設計師的最主要工作。當然,也可以說是程式設計中,最有趣的一件事。』

 

 

        「那麼要從哪裡開始?」首先,我們必須瞭解,要去寫一個3D的程式,並不是全部從無到有的從頭做起、一個一個輪子的造出來;而是去使用一組別人已經做好的基本功能,像堆積木一樣的一步步堆砌出我們夢想中的城堡。我們無須去在意每一塊積木的內部構造是什麼、或從何而來,而是應該學習如何利用這些不同積木的不同特性,建造出最合適的目標。轉換成程式的觀點來說,就是世界上的某幾個大頭,制訂了一組標準的3D繪圖函式以供其他人使用;而一般的程式設計師,就只需要去瞭解該函式的介面及使用方法就可以了。如此的一組函式及介面,也就是常被人稱做 API (Application Programming Interface) 的東西。

 

 

        或許你已經聽過,目前主流的3D繪圖 API 由兩大流派分庭抗禮 分別是  DirectGraphics 以及 OpenGL。那應該學一個比較好呢?是的,相信這也是困擾著很多初學者的問題之一。「網路上好像關於 OpenGL 的資源比較多耶?」……「可是遊戲業界好像都是用 DirectGraphics 居多耶?」…………

 

 

        『我的建議是:兩者都學。』

 

 

        唯有兼容並蓄、納百家之長於一身,才能在遇到問題時,提出最合適的解決方法。OpenGL DirectGraphics 可說是各有優缺點:OpenGL 的程式介面固定性很大,操作方式簡單、易於學習;但它只提供一些基本功能的函式,並且它的版本更新太慢,若遇到新的技術出來,往往只能以 extension 的附加標籤功能來加強。而 DirectX 的使用方法則較為繁雜,但它也提供了更多進階功能的函式可供使用;而它的版本幾乎每年更新,是好事也是壞事,往往新版 DirectX 的程式介面都會和舊版有不小的相異之處,特別是從 DX7 DX8 的轉變更是劇烈;這對所有的程式設計師來說,都是一場又一場「程式引擎重寫」的惡夢。

 

 

        『然而,對一個對沒有3D圖學背景、初學3D程式設計的人來說,我建議從 OpenGL 開始。』

 

 

        理由如下:OpenGL 的使用方法較 DirectX 簡易且直覺,可以讓初學者專注於真正重要的3D圖學基礎的學習上。包括書籍、教學網站、原始碼,OpenGL 擁有相當多的資源可供學習及參考。並且 OpenGL 的介面固定、很少變動,新版本的 OpenGL 通常都能夠和舊版本完全相容;不用擔心學了之後,或甚至還沒學完全,每過一年就要再重新學習一次新的函式介面。OpenGL 只提供基本繪圖功能的 API 函式,想讀取一張點陣圖進來?想秀出一些簡單的 model?抱歉,這些全都得自己來完成;因而可以藉此來磨練自己的一些基本程式能力與觀念。

 

 

        我認為,只要確實的掌握住了3D圖學的原理,所謂的 OpenGL DirectGraphics 的差別,也不過是函式的呼叫介面不同罷了。學習 3D 程式設計,不是要去死背一大堆函式的用法及參數的使用;而是應該要真正踏實的瞭解 3D 的理論基礎與架構。觀念融會貫通之後,自然也就能觸類旁通了。學會程式的使用方法,往往只是最容易的事;而真正困難,並且值得去深入思考學習的,應該是其程式的設計思維模式與程式背後所建構的理論基礎。

 

 

        我個人相信,OpenGL DirectX 各有它們的一片天空與其支持擁護者;雖然說其實這兩者有越來越相像的趨勢。畢竟它們就像是一對異卵的孿生兄弟一樣,雖然外貌有些許的不同,可是骨子裡的血液精髓,還是出自同一個父母的根源。或許未來五年十年內也會一樣,兩者繼續保持分庭抗禮的姿態;有人發明了一個新的理論,想立即找一個簡單又好用的繪圖 API 來做驗證,又不想侷限在 MS 的作業系統平台上,OpenGL 仍然是不二人選;有人想開發一個功能強大、各方面都最佳化、將硬體的效能發揮到極限的超強 3D 引擎,DirectGraphics 可以表現的非常亮眼。所以,一個能依據不同的發展需求,而選擇不同的工具來達成目的的人,才會是一個最稱職的程式設計者。

 

 

 

Explore Another World

        3D程設有了第一次的親密接觸之後,先別HIGH過了頭;還有其他你沒見識過的世界呢!

 

 

        當學習了一段日子的3D程設之後,腦子裡所累積的基本知識應該會開始逐漸成形:「開始可以把心中所想的 idea 給具現化了對吧?」「開始覺得以前的想法,可能不再只是遙不可及的夢了吧?」如果你已經具備了這樣的智識及能力,我要說聲:「恭喜你!」你已經正確的踏出了成功的第一個腳步了 :)

 

 

        『想寫一個3D,或甚至2D的小遊戲,已經不是很難的問題了。』

 

 

        等等等,先別太急。一個遊戲程式的組成元素有很多,除了即時運算的3D物件之外,要不要有美美的2D圖片呢?玩家的操作介面是要用滑鼠、鍵盤還是搖桿呢?別忘了還有遊戲中的各種音效;當然,如果有背景音樂的話就更完美了!那來個多人連線如何?....... 有太多太多的想法可以實現。

 

 

        所以呢,現在可以看自己的需要,或是自己針對哪一方面的知識比較感興趣,可以補充一些 Graphics programming 之外的其他知識。知識的累積,不僅應具有深度,更應能兼具廣度。想使用 joystick 來做遊戲的控制器,或想對鍵盤滑鼠做更進一步的掌控與回應嗎?試試 DirectInput 的強大威力吧;想在自己的遊戲中播放音樂或音效嗎?可以試試學習 DirectAudio 的使用;想寫個簡單的區域連線小遊戲嗎?可以試試 DirectPlay 的簡單網路功能;此外,如果有機會的話,能玩玩 Photo Shop3ds MaxMaya 之類的2D3D美術應用軟體也都是很不錯的經驗。

 

 

        這個部分所提到的知識都是選擇性的,站在一個學習者的觀點來看,最好是自己對某方面真的有興趣,才更進一步的深入去學習;如果不是出自於自願性、自發性的學習,往往都會變成只是三兩天的熱度、難以持久。總而言之,朝著自己有興趣的方向發展下去,才會有源源不絕的動力可以繼續往前邁進囉!

B Color Smilies

你可能喜欢

[游戏入门基础]淺談遊戲程式設計入門 - [基礎篇] 
联系
我们
快速回复 返回顶部 返回列表