《自學遊戲開發·程序篇一——了解計算機的世界》
想法創意都有了,就差一個程序員了?有沒有想過:也許你配不上一個程序員。
成為一個獨立遊戲開發者,我認為他自己首先應該成為半名程序員。
這裡是知乎專欄《自學遊戲開發》,在上一篇文章《一個遊戲是如何被設計和開發出來的》中,我們已經概覽了一個大型遊戲的開發過程。但是由於程序方面的內容不便可視化展示,所以那篇文章主要是展示了設計和美術製作流程。現在我們需要來講一講的程序方面的事情。首先,我們需要認識到:
1、掌握編程技能的重要性
如果你想成為一個獨立遊戲開發者,不會編程幾乎是不可能的事情。就像一個廚師不會用刀案鍋鏟。 「電子遊戲」是一個什麼?我們這裡不談玩法設計,它的物理本質就可以說是一個計算機應用程序(程序是一串CPU指令、指令是一串代表01的電磁信息集合;請勿再溯源)。開發遊戲其實就是開發一個程序(軟體)。而開發程序的過程,我們把它叫作 編程。只有學會了編程、掌握了一款遊戲引擎,我們才會真正明白:遊戲,作為一款軟體來說 它的本質是怎樣的,它是如何運作的。你不知道汽車是如何工作的,你就製造不出一輛車。了解程序,就是了解遊戲在電腦上工作的原理。掌握這些知識,不單單是程序員的立身之本,也應該是每一位遊戲設計者的基本素養。再者,如果你從未接觸過遊戲開發,現在開始學習任何其他遊戲開發知識,你是不可能在兩個月之內自己動手製作出一款可玩的遊戲的。但是,你學習編程與遊戲引擎的使用,你便能做到。群友真實經歷,@小小故事匯 在我的引導下從職業廚師開始學做遊戲,經歷兩個月的學習之後已經能夠獨立做出「飛機大戰」那樣可玩的小遊戲了。你若學習美術、或是「設計」,這都不可能實現。這是編程的強大之處。
作為一個專職的「遊戲設計師」(遊戲策劃),並不是只會拍腦袋出主意就行了。我認為一個合格的「遊戲設計師」至少應當能夠編寫邏輯腳本,把自己設想的主意用代碼實現出來,不要把任何細小的事情都塞到專業程序員的待辦事項里。職業的程序員會為設計師提供底層的服務,讓設計師不用操心計算機底層的事務,只要把精力放在遊戲邏輯本身上。事實上,現在各大遊戲引擎的設計思路都是如此,比如 Unreal Engine 4 強大的Blueprint系統和CryENGINE推出的Flowgraph和Schematyc系統,都是為設計師們服務的,讓他們不用敲任何代碼就能編寫出基本的遊戲邏輯(基於可視化編程)。 為了讓設計師們能夠自己動手豐衣足食,程序員們已經做出了許多努力,想成為設計師的你,有什麼理由不學習一下基礎編程呢?千萬不要想:程序的事情就交給專業的人來做吧。「我」就不需要學了。這種人,就是那種常常說「就差一個程序員了」的人;這種人,也常常是那種只會空想,給團隊製造試錯成本的那種人。因為他們不懂程序,但要讓別人來為他的想法買單。他們不知道他們臨時冒出的一個「好主意」可能要讓一整個團隊忙活好幾個月。所以,我建議,每一個想要成為遊戲設計師的朋友,都接觸學習一下編程。
你只是想靜靜地畫圖,做一個安靜的美術人員?如果你只是想平靜地度過這一輩子,順便在遊戲製作領域出一些力,貢獻一些藝術力量,那麼你只需要專註於升華自己的藝術上限就好了。如果你想對這個領域搞點事情,比如說優化一下美術資源的製作流程,提升遊戲畫面的行業標準,那麼你就不能只是會用Photoshop畫畫圖、用3Ds max建建模,你需要知道Photoshop這款軟體是怎麼被開發出來的,它的每種圖層混合模式採用了什麼演算法,這些演算法用代碼如何實現,如果我要擴展它的調色盤功能應該從哪裡開始編寫。一個能回答這些問題的藝術家,和一個只會用PS畫畫的藝術家,對於工具的理解是完全不同的(假設他們的藝術修養一樣高)。而前者,更有可能推動整個數字繪畫領域向前步進。為什麼那些藝術創作軟體都出自於國外的開發者呢?開發一款藝術創作軟體,不僅需要專業的程序員,更需要具備編程素養的藝術家們來領導。而我國的藝術從業者們,有幾個具備紮實的編程能力? 而往往一說到這些,那些「大師」們就會開始貶低工具的重要性,轉而強調藝術本身。從「從藝動機」層面,許多選擇藝考的人其實就是因為文化成績太差;從思想層面,幾乎少有藝術家會想去改進他們所用的工具。如果你不是這樣的人,如果你想要成為一個推動數字藝術領域進步的人,有機會的話,你就應當認真了解一下計算機的世界。另外,回到遊戲美術本身,一個遊戲最終如何展現你畫的圖、你做的模型,這完全是由渲染管線和Shader腳本來控制的,這些都是代碼寫出來的。所以你認為遊戲美術只是畫畫?那只是其中的一個小環節。當然了,說這些只是希望你能對遊戲美術具備更多的認識。至於初學,我還是不會給你徒增痛苦讓你去學編程的。別緊張,從窗戶上下來吧朋友。
包括做音樂也是,現在編曲軟體之強大,無不是具備音樂素養的程序員們的功勞。奧巴馬說每一個現代人都應該學一下編程,不是隨便說說的。寫到這裡,我希望每一位讀者都已經在心裡提升了掌握編程能力的重要性。
在後文中,我們開始來認識一下計算機與編程的世界,再之後是編程與遊戲製作的關係,最後是編程學習路徑。我會力圖讓每一個高中生看到下面的文字時也能夠理解我在說什麼,你不用具備什麼前置知識,嗑著瓜子順序看下去便好。
2、計算機與編程的世界
是先學C還是C#?還是JAVA?還是Python?還是Unity?還是OpenGL?首先你都知道這些是什麼嗎?每一個想學遊戲編程的人都經歷過這樣的問題:入門編程語言該學什麼?我在知乎問答想要自己做一款遊戲,需要學習哪些知識?中明確說明了先學C#再學Unity。但是仍然有無數人私信問我到底該先學C還是C#。這不是因為他們沒有認真看我的回答,而是他們不知道為什麼要這樣安排,以及很多其他前輩建議他們要先學這樣或那樣。道聽途說,隻言片語的回答是解決不了大家心中的困惑的,因此在本篇文章中我想為大家介紹一下計算機和編程語言的世界,這可能會花費一些功夫,因為從來沒有人能夠在一篇文章的篇幅內完整地介紹整個計算機的世界。我也只能儘力嘗試,讓大家了解那些語言各是什麼,之間是什麼關係。在此章節完成之後,我再會解釋我們學習安排是如何設置的。
請注意,我現在要開始裝逼了:這件事情如果要溯源的話最早可以追溯到亞里士多德開創出「邏輯學」;19世紀的喬治·布爾(George Boole)在此基礎上發展出「數理邏輯」(如果你已經開始學編程的話一定會知道關鍵字:bool;3ds Max里也有「布爾」運算。就是以此人之名。);20世紀克勞德·艾爾伍德·香農(Claude Elwood Shannon)在「數理邏輯」基礎上發展出「邏輯電路」。「邏輯電路」就包括了我們高中所學的:繼電器、與門、或門、非門、異或門等等。利用這些工具,我們就能夠製造出會計算加法、減法的邏輯電路。(還有非常重要的「觸發器」、「振蕩器」等等。後來的一系列發明,比如說:電子管、晶體管、集成電路可以統統看成是對前面技術的升級和替換。)我們得到了會計算的邏輯電路,又經歷了一系列的升級和優化,那麼現在我們的計算機是如何運作的呢?首先可以分為兩個層,一層是CPU&存儲器的電路實現,一層是0與1的世界。如果我在這裡講電路設計的問題,我想很多只是單純想做遊戲的人可能會瘋掉(其實是我講不來)。有一本很好玩的書,叫《穿越計算機的迷霧》,作者以閑談扯淡的方式,從電與磁的發現一直講到了CPU的實現,作為計算機硬體入門是一本不錯的興趣書。關於硬體,我們業餘選手可以不用知道那麼多,只要知道:CPU會執行我們的一些命令,我們的命令是存在「存儲器」里的0101010110101001010…這樣的數字來代表。
作為常識我們知道,計算機只認識0和1(至少你現在知道了),那麼我們就來看一下它是如何運用0和1來工作的。
彙編:
請注意為了方便講解我就自己創造例子了,可能和實際情況有出入,但是更容易幫助理解。先看一下這一行代碼:
00000001 00001100 00001010
看不懂?普通人類當然看不懂,但是機器看得懂,而且機器就只能看懂這種形式的信息。這個叫做機器語言,也是二進位碼。二進位碼是構成如今計算機世界的基礎,我們電腦里的任何文件、應用程序歸根結底的都是以二進位碼的形式存在的。比如:我們常常能夠在電腦的文件夾里看到這樣一個文件夾:
這其中「Bin」就是單詞「Binary」的縮寫,意思是二進位文件。打開bin文件夾,我們會看到各種.exe和.dll文件。對於我們來說,.exe就是一個應用程序嘛,比如說:QQ.exe、LOL.exe。
大家難道沒有好奇過:為什麼應用程序的的後綴是「exe」呢?原因:「exe」是英文片語「Executable File」的縮寫,意思就是可執行文件。「可執行文件」的意思是:可以被CPU執行的文件。我們前面說過,CPU只能執行0101001這樣的指令。所以「可執行文件」其實就是這種指令的集合,也就是是一堆二進位碼 「00001111 01010011 00100110 00001111 01010011 ……」。所以它才會常常被放在bin(binary)文件夾里。(有沒有發現,那些曾經我們看不懂的文件夾結構、文件名後綴,其實設計得都是有道理的)
我們玩的每一個遊戲,它們的本質都是這樣的二進位文件。所以編寫一個遊戲,其實最終最本質就是編寫出這樣的文件:0101010101110010101010101001010101……可是……
我知道這也太特么為難人了!鬼看得懂這些01是什麼意思啊!(鬼:我也看不懂啊~)但沒有辦法,現代的計算機只能識別這種簡單的機器語言。(即便是量子計算機也是玩01這樣的量子比特) 為了讓這些機器語言更容易被我們人類所理解,先驅們發明了彙編語言。(對,就是那個大家都說最難寫的編程語言「彙編-Assembly Language」)但其實彙編語言很簡單,有了彙編,我就能跟你解釋前面的0011是怎麼回事了。再來看之前的那行代碼:
00000001 00001100 00001010
請注意這不是一串隨便瞎寫的0和1,它是有規律的!你們看,以八個0或1為一組,每組中間有個空格。這其中,每一組我們叫做一個「位元組」(byte),每一個0或者1,我們叫做一個「比特」(bit)。第一個位元組:00000001,假設我們規定,它代表一個命令:加法(ADD)。我們再規定,如果CPU遇到「加法」命令,它就把後面兩個位元組相加,把結果存到前一個位元組所在的地方。於是我們的CPU就能夠計算加法了。規則是給它這三個數:
第一個是表示加法命令的「00000001」,第二個A和第三個B是兩個加數,每次都不同,所以我用x表示那些比特位。同樣的道理我們能夠制定出減法命令、乘法命令、複製命令等等。比如複製命令:我們規定「00001111」代表複製命令,如果CPU遇到「00001111」,它就把後面第二個位元組的數據,複製到後面第一個位元組的數據所表示的位置上(注意這些位元組里的二進位數不僅可以當數字用,也可以當命令用,也可以用來表示儲存位置)。於是我們就有了複製數據的功能了。
這些功能,都是CPU中的邏輯電路為我們提供的,我們只需要發送規定好的指令便能使用這些功能。注意,指令的本質是一串0和1代表的信息,但是我們很難去記憶和區分00010011和01001101這樣的數字,所以我們就用「ADD」代表00000001(加法指令),用「COPY」代表00001111(複製指令)。Add和Copy在英文里本來就是加和複製的意思,這就很好記。而「ADD」、「COPY」等這些指令集合起來就形成了彙編語言。它實際上就是把機器語言(一串0和1)直譯成了英文單詞。一般CPU認識的指令不多,就那麼十幾個(加上變種一般也就幾十個)。所以彙編語言中的指令一一對應也不多,大致分為三種:
- 數據傳輸類:複製、載入、存儲……
- 算數/邏輯類:布爾運算、加法運算、自加運算……
- 控制類:轉移、停止……
就這麼幾個指令能幹啥?你別說,我還真有辦法能讓你親自見證一下,就這麼幾個指令,可以讓CPU幹些什麼事。首先,下載《Human Resource Machine》這個小遊戲。然後開始玩吧。我已經讓群友們驗證過了,不管有沒有學過編程都可以玩幾下。而遊戲的主體內容,其實就是以一種有趣的方式在寫彙編代碼。在過關這個遊戲之後,你會發現你自己用這幾個最簡單的指令,讓計算機實現了一些簡單的功能,諸如:比較兩個數字的大小、判斷一個數字的正負、讓計算機數數、用加法實現了乘法運算、從一組數中找到最小的數……如果你在遊戲里過五關斬六將實現了這些功能,那麼你就相當於解決了上個世紀計算機科學早期那些先驅們所面對的問題。給自己一個獎勵吧,點擊文章末尾的「賞」就會看到編程學習大禮包!額,你說你沒有通關?沒關係,最後幾關是比較難,而且這個遊戲只是為了讓你體驗一下彙編編程的感覺。
現在你會發現,彙編語言其實沒有多複雜,而且比起那些0011的代碼,真是太好識別了。但是那還不夠,比如我要計算一個:
X=Y*Z+(Q/10.5)+P-2
這個自然的表達式人人都能看懂吧?但是用彙編語言寫出來就不那麼好看了:
Mov X, YMul Y, ZDiv Q, 10.5Add Y, QSub P, 2Add Y, P
一眼看上去不知道是在幹嘛。而且彙編語言也不夠「自然」,比如我要做一個賦值操作:
X=Y;
上面這種寫法很自然,我們在學數學的時候就是這麼寫的,但是在彙編語言中它是這麼寫的:
Mov X, Y
直譯就是:把Y移動到X的存儲位置(這是計算機硬體能夠實現的操作)。再比如:
if x<y then x=y else y=x如果x<y那麼x=y否則y=x
這幾行命令,我們用自然語言就能讀懂它在幹嘛:比較兩個數的大小,然後把大的數賦值給小的數。用彙編語言寫就是這樣:
Cmp X,YJLE LessCaseJmp SkipCaseLessCase:Mov X,YSkipCase:Mov Y,X
用自然語言寫很簡單的三行命令,用彙編寫就需要這麼多行才能實現。
還記得當初我們為什麼需要彙編嗎?因為機器只能識別0和1構成的指令,但是那種數字指令對我們人類來說很難識別和記憶,所以我們用英文單詞來一一對應那些數字指令,那些英文單詞構成的指令集合就成為了彙編語言。新的知識點:當我們寫出彙編代碼後,在真正交給CPU運行之前,我們得把彙編代碼翻譯成機器碼,因為CPU只認識0和1構成的機器語言。(因為機器指令和彙編指令是一一對應的,所以翻譯過程很簡單,就像把簡體字翻譯成繁體字)。
先驅們嘗試把彙編語言簡化的過程中,想到:既然要翻譯,那麼我們能不能創造一種更簡潔的語言,然後把它翻譯成相對複雜的彙編呢?就像把文言文翻譯成語素成分更複雜的現代文。
"私見張良,具告以事"———翻譯為———>"私下會見張良,把事情詳細地告訴了他"
從這個想法出發,C語言誕生了。(實際上C語言是在B語言的基礎發展出來,B語言是在BCPL的基礎上發展出來的,BCPL是在CPL的基礎上發展出來的。在CPL之前還有個十幾種其他編程語言。不要管辣么多,靜靜聽我吹就好。)
(在這兒停頓,看到這裡,新手朋友們可能已經費盡了許多腦細胞了,如果你已經閱讀/思考疲勞的話,可以在這兒停頓,起來走一走看看窗外。也許你並不能全部理解上文的內容,那沒有關係,那不會影響你學習編程,但如果能理解的話,對今後學習將會有助益。我能保證後面的內容將會越來越簡單。你大可以帶著疑問先閱讀完全文,再回過來讀一次。)
C語言
你們看,彙編語言多複雜,因為它和機器硬體實現的指令一一對應,所以光改造它而不改造機器指令的話毫無意義。所以我們不如創造一種新的語言,然後把它翻譯成彙編吧!C語言幫助我們實現了設想。C語言有許多強大的優點。但是在此,(頂著老師和同行們的壓力)我想讓新手知道的是:函數。
函數是什麼?當我們在寫代碼的時候,可以想像為我們寫的每一行都是一個指令。我們寫十幾行指令來實現一個乘法運算,用二十幾行寫一個排序操作。程序猿是世界上最懶的物種,他們不想每次要做乘法時都寫十幾行代碼。能不能用一行指令代表十幾行指令?就像:
指令集A和指令集B所描述的就是完全同樣的事情。但是A用了7個指令,B用了5個指令。如果你要在這件事件上偷懶,你是願意以A的形式還是B的形式來寫這個指令集呢。我不知道你的選擇是什麼,但是作為世界上最懶的物種來說,程序猿在編程的時候,能少寫一行就不會多寫,能少敲一個字母就絕對不會敲兩個。所以在碰到上面這個問題時,採用B的寫法無疑。那麼如何實現呢?假設指令集A中的每條指令都是計算機能夠識別的指令,指令集B中的第3條「把大象裝進冰箱」是計算機不能識別的,是我們自己虛構的。但是我們要使用這條指令,因為它對於我們來說很省事。現在很簡單,只要規定:我們每次寫「把大象裝進冰箱」這條虛構指令,就自動把它翻譯成「打開冰箱、把大象塞進去、關上冰箱」這三條原生指令。翻譯過程不用擔心,前人們已經寫好了各種翻譯器能夠現實這種效果。
那麼,上面我們虛構出來的那條指令:把大象裝進冰箱。其實就是我們所謂的函數!下面展示的是在C語言中創建一個函數的形式。
把大象裝進冰箱(大象x){ 打開冰箱; 把 大象x 塞進去; 關上冰箱;}
下次想干這件事件的時候,就只要寫一句:把大象裝進冰箱(大象巴拉)。括弧里寫哪頭大象,就裝哪頭。 那麼把大象裝進冰箱()就是一個函數。
有了函數這個東西,世界上任何複雜的任務都可以被拆分成最簡單的單個任務。當我們學C語言的時候,一定要把函數的用法學好。我認為這也是新手學習C語言的主要任務。
更高級的編程語言
按照學院派的編程學習路線,計算機專業基本都是先學C語言,然後學C++,(然後學數據結構),然後學C#/Java/Python/JS....,然後回去再學彙編呀、電路呀什麼的。想必大家都熟悉這套方案。
其實學習一個東西,從根源開始了解接觸,從底層學到頂層是一個自然的遵循邏輯的學習方式。在計算機世界中,如果說從真正的根源開始學的話,估計真得從邏輯電路開始了,然後學到彙編語言,再學到C語言,再學C++。但是為什麼學院們都選擇從C語言開始呢?一是因為相比起彙編語言,C語言更能夠學以致用,使用起來更方便;二是因為,現在許多流行的編程語言,比如C++、JAVA、C#、Python都是類C語言的,首先是語法上都是仿照C語言的風格來設計的,其次它們的一些技術原理是建立在C語言的基礎之上的。它們之間的關係就好比「漢語」與「北京話」、「四川話」、「重慶話」、「廣東話」之間的關係,其中C語言就是漢語。所以C語言作為廣大語言的根基,把它當做入門編程語言來學習是沒有問題的。再以它為中心,向高層語言和底層原理來擴展學習,往往計算機專業的同學到大三就能把整個計算機體系打通。
編程語言發展史
剛剛我們才講到了C語言。並且說了遊戲領域中比較重要的幾種語言與C語言的關係。從這張圖中我們應該能夠更清晰看到這幾種語言的發展脈絡。每一種新的語言誕生,都摒棄了一些前者的弊病,加入了自己優秀的特性。但無論怎樣,每一次編程語言的發展和進步都是在前人的基礎之上進行改良和創造,很少有幾個語言是凌空出世的。正因為這樣,所以編程語言之間的差別,並不是天差地別。並不是我選擇了學習JAVA,就意味著放棄了C#;也並不是我如果不先學C語言,我就學不懂C++。編程語言之間都是觸類旁通的,只要先掌握了其中一種,那麼其他的語言就能很快掌握。
再看一眼上面的圖,接下來我來講講C、C++和C#、Java、JS、Python的關係。
C++
首先經過我們上面一頓瞎BB,已經知道了C語言是怎麼來的,而且知道了C語言的語法比較接近我們的自然語言,更容易讀懂了。C語言寫的代碼,在被CPU運行之前,需要翻譯成彙編代碼,再翻譯成機器碼。我們對這個設計很滿意,使用了好多年。後來在使用中,特別是開發一些大型項目,比如用C語言開發一個計算機操作系統時,發現有問題處理起來很麻煩,先輩就對C語言進行了改進。有一次改進後新增了一個叫「類(class)」的功能,這個功能很牛逼,導致那個版本的C語言直接脫胎換骨。這種與眾不同的牛逼需要在名字上體現出來,所以他們學習iPhone的起名策略,在名字後面加了個「Plus」。「C Plus」=「C+」。一個不夠,那就兩個「C Plus Plus」=「C++」。(順便劇透一下C#的起名策略:「C#」=「C Plus Plus Plus Plus」=「C++++」。)所以!C++是C的升級版,多了一個核心功能:類。語法沒有變,本質的東西沒有變,還需要被翻譯成彙編,然後翻譯成機器碼,再交給CPU執行。所以學校里安排先學C語言,再學C++,其實這種說法是有點狗屎的,就好像是說:我們先學習「浮水」,再學習「游泳」。本來我們學習游泳的過程中就會學習浮水,但是就要把學習「浮水」先說一遍,讓人誤解為這是兩個差別很大的東西。所以懂了嗎?我再說明白一點:學習C++就是學習一個高級版本的C語言,學C++的過程中,就會先把C語言的那些東西學到。所以不存在:如果不學C語言打基礎,就學不好C++。如果再有人問這個問題,就把這一章節貼到他臉上去。
另外補充:C++從C發展出來後,C語言也沒有閑著,自己還是在不斷發展,比如後來發展出了Objective-C。嚴格意義上來說,「學習C語言」和「學習C++」確實是不一樣的,因為要去研究它們不同的語言特性。但是!對於沒有學過任何編程的初學者來說,最開始就是學習個語法認識幾個關鍵字而已,根本到不了研究語言特性的程度,所以兩者說法對他們來說幾乎沒啥差別。
C#(和其他高級語言)
我們知道現在CPU廠商Inter和AMD兩方對峙,操作系統是Windows、Mac OS和Android三足鼎立(我們不知道Linux)。 可是你們知道上世紀八九時年代,計算機市場是繁花綻放,各種各樣的硬體、操作系統充斥在矽谷整條小吃街。那個年代的碼農,隨手寫一個程序,並不是寫完就能到處用的啊。就算現在也不是啊。原因很多,可能CPU不一樣,操作系統不一樣....那怎麼辦?先輩們想到了一個膽大包天的方法:我寫一個軟體,這個軟體去模擬CPU硬體,然後再寫其他的程序,把這些程序編譯成這個虛擬CPU能夠執行的機器碼,然後讓虛擬CPU去執行程序。(請再讀三遍)
這樣,只要所有的電腦都提前裝好我這個虛擬CPU軟體,那麼其他那些雜七雜八的軟體統統都在我上面可以運行了!完美解決跨平台問題。
有了這個想法之後,先輩們就開始動手去寫這個牛逼哄哄的虛擬CPU軟體了。他們用C語言或C++來寫這種後來被稱作「虛擬機」的軟體。這種事情都能幹得出來,他們就順便又為自己的「虛擬機」發明了專門的編寫程序的語言(真實因果關係是先發明語言,從而開發對應虛擬機)。Java語言對應JVM(Java Virtual Machine),C#語言對應 .NET Framwork(你們玩遊戲的時候肯定裝過這個),Python對應Python Virtual Machine......
看到這裡,聰明的你已經看破了真相,原來C#、Java、Python編寫的程序都不是直接交給真正的CPU運行的,而是交給了一個模擬CPU的軟體運行的!把我們的程序交給了另一個程序來運行!把我們的程序交給了另一個程序運行!明白嗎,為什麼那些程序猿都說C#沒有C++快。因為C#寫的程序交給了C++寫的一個程序來運行!Java寫的程序也交給了C++寫的程序來運行!Python寫的程序也交給了C++寫的程序來運行!再重複一遍就瘋了……
到現在為止,我們解開了一個新手十大困惑之一:為什麼C++比其他語言更快。現在我們還在章節「計算機與編程的世界」中,接下來,我們要聊一聊那幾種高級語言的不同點,以幫助我們搞清楚新手十大困惑之首:我應該選哪個語言開始學編程!
不同高級語言使用感受
這麼說吧,當年我才大二的時候,只學過C++。從沒有專門學過一天其他語言。在那個背景下,我能夠用C#在Unity寫小遊戲,我還用Java在Android Studio里寫過一個貪吃蛇。我可是一天的C#和Java都沒學過。為什麼我能做到呢?因為主流編程語言的語法基本都一毛一樣,根本就不用怎麼學啊。那種差別就像東北話和天津話的差別一樣,大家都是從漢語出來的,誰聽不懂啊。為了證明幾種語言語法上真的很像,我寫了一段偽代碼,並翻譯成不同語言版本,請找不同:
看,這三份代碼是在干同樣一件事情,是用三種語言所寫的。除了第6行比較特殊,其他部分你們能看出什麼區別嗎?是不是真的很像?如果掌握了其中一中語法,另外兩種有什麼難的呢?無非就是注意一些細節不同點。總有些人問第一個編程語言學什麼,我通常回答「都行都行」,看看上面這張圖,我不是瞎說的啊,對於學習些基本語法,了解基本概念,先學哪個真的都行(反正都一樣)。如果把我們學做遊戲比喻成學做飯,語言吶、環境吶這些東西,就可以看做是廚具廚房。學做飯的時候,重要的是學習菜肴怎麼做,烹飪方法心得,廚具工具的用法是基本的也是次要的。我們隨便選個廚房開始學做飯,一旦學會了,那麼在另一個陌生的廚房裡難道就做不出飯菜了嗎?不會的。就算是另一個廚房,就算那個廚房裡的鍋、碗、灶、鏟奇形怪狀從未見過,習慣習慣也不影響我們做飯呀,因為工具畢竟還是那些,變其形式而不變其本質。
那麼在這種情況下,我們應該選那個語言開始學習呢?總要有一個選擇。這個選擇就是C#。為什麼是C#呢?說一個很簡單的理由,因為Unity是用C#寫代碼(不考慮JS)。而Unity是我最推薦新手學習的遊戲引擎。所以學了C#就直接去用Unity咯。如果有人問:「我想用Unreal4或CryENGINE,我能不能從C++開始學呢?」 當然可以呀。你掌握了C++之後,如果又轉變想法想用Unity來開發,也能很快上手。但是我不推薦這樣,因為C++細節非常多,更繁瑣一點。學起來沒有C#輕鬆。而Unreal4和CryENGINE呢,用起來也更麻煩一點,也不建議新手拿這兩個引擎來考驗自己的自信心。
下次繼續……
作者並非職業程序猿,也不是計算機科班出生,若文中有任何錯誤,望先輩們在留言中指出,以幫助我修正文章、傳播正確有用的知識。
擴展閱讀:
1.《穿越計算機的迷霧》
那麼,下一節再見。
這裡是知乎專欄《自學遊戲開發》第三篇文章:《自學遊戲開發·程序篇一——了解計算機的世界》。我是 竇月汐 。如果你是第一次看到本專欄,建議你跳轉到自學遊戲開發--關於本專欄進行了解。如果這篇文章和本專欄對你所幫助,希望你在看到其他遊戲人需要幫助時 也能把本專欄推薦給他,向每一個遊戲人致敬。
我公開了我的一個興趣交流群,群號為:474891082。(為避免無聊人士,設置了5元 群費)
推薦閱讀:
※(可能是長文警報):守望先鋒英雄設計問題:為什麼玩家認為天使比盧西奧更有趣?
※彈幕遊戲的碰撞檢測一般是怎麼實現的?
※離散與連續:輸入方式對遊戲體驗的影響
※致旗艦評論「從《惡魔之魂》到《仁王》:兩個遊戲類型的重構史」一文