淺談Java遊戲引擎在智慧機領域的發展
1.為什麼專注於Java而不是C/C++?
一、首先,Java人討厭C/C++
對任何一名忠實的Javaer來說,我們都不會喜歡複雜的C++程式碼結構,都不會喜歡解決那些因繁瑣的指標、引用所衍生的神奇Memory問題,更難以接受程式碼和資源稍微多些,重新編譯一次工程就要耗費數分鐘乃至數小時的恐怖煎熬。
儘管Java語法脫胎於C/C++,且現階段在執行上也離不開C/C++構建的JVM。但我們卻真的不喜歡直接用C/C++程式設計,否則,也不會選擇這條與C相似,卻不盡相同的道路。
坦率地說,絕大多數Java人對於C/C++有著本能般的排斥,就連JNI開發方式,我們也會盡量少的使用。
強迫我們使用C/C++會讓我們非常痛苦,強迫我們在非必要的場合使用
比如,小弟在Libgdx論壇“潛伏”時,就曾看到有Javaer對某C系遊戲引擎大聲疾呼:I hate it!
小弟在此敬告所有專職搞C的女同志:多年後,我若搞Java,你若玩C/C++, 讓你閨女還有你在路上注意點(╯^╰)。
二、其次,C/C++在遊戲開發上也有其侷限性
雖然從執行效率上看,C系語言編寫的遊戲會比Java語言編寫的遊戲執行效率為高。然而,這卻是以單純C/C++開發的低相容性,高難度,漫長開發週期為代價的。
可能有人會說:別扯了,張嘴你丫就胡說!C/C++不是能“一次編寫,到處編譯”嗎?怎麼會扯到相容性問題上呢?
——拜託,有腦子的話,請讓它稍微運動一下好嗎?
如果C++真的能“一次編寫,到處編譯”,當年Sun為又憑什麼讓Java一舉成名,最高市值達到2100億美金的巔峰?如果C++真的能“一次編寫,到處編譯”,那蘋果如今又為什麼要搞LLVM這個“特殊的虛擬機器”出來(雖然對外僅僅是“資助”關係),補足IOS系統呢?
關鍵原因就在於,單純C/C++開發對系統底層的依賴實在太高,太高了。以至於,只要底層稍有變動,單純的C/C++專案就隨時可能癱瘓死掉。
遠的不提,就說當初Android 4.1升級那麼一次,頃刻便幹躺下一片C/C++遊戲引擎,他們的作者一直要耗到數週乃至數月後升級引擎程式碼才勉強解決了相容問題。然而,基於Dalvik的Java應用們,則普遍不存在這種困擾,甚至對此事根本毫無覺察。
對Java來說,無論系統底層如何修改,只要上層虛擬機器的API不換,應用都可以準確無誤的執行下去。退一萬步講,即使部分後臺原始碼被更換了,對我們而言通常也就是換個類,甚至換個函式名的事。然後C/C++卻不一樣,C/C++在開發上牽一髮而動全身,一個指標的錯誤使用,都可能讓你的程式在莫名其妙的時刻莫名其妙的崩掉。更何況是不知牽扯到何處的底層變動了,將遭遇到的種種問題,遠比Java使用者所能遭遇到的問題要多得多。
或者有人會說,我用的C/C++引擎很高階,是源自YYYY的ZZZZ,或者山寨自OOOO的XXXX,他們有數十人的專業團隊,有上千萬的資金支援,所有可能的問題都已經被他們解決了,用他們的C/C++引擎——絕對不存在任何相容性問題。
那麼,小弟只反問您一句,就一句話。
就算他們能做到,您確信,您也可以做到嗎???
事實上,即便你所使用的C/C++引擎本身沒有任何相容問題,但作為C/C++引擎使用者的你,在C/C++開發中,也能做到絕對不產生相容性問題嗎?
要知道,用C++開發時,只要稍不留神,手輕輕那麼一滑,就可能寫出在這個平臺能用,那個平臺不行的程式碼來,而你書寫的程式碼量越大,這種可能性也就變得越高。
小弟愚見,在這世上號稱可以多平臺執行的語言中,有兩種最為悲劇,一者為C/C++,一者為JavaScpirt。
讓這兩個傢伙跨平臺執行的代價,在寫過一定數量的跨平臺程式碼後恐怕都會印象頗深吧?雖然他們在最終的最終,確實可以實現所謂的“跨平臺執行”,但這中間的艱辛困苦,又有幾人明瞭?真是“光看見賊吃肉,沒看見賊捱打”啊!
仔細說來,為什麼C/C++遊戲引擎大多會青睞於Lua,AngelScript這些指令碼引擎?為什麼即使C/C++的功能已經十分完善,還要將它們引入其中,就像生怕你們使用C/C++而非指令碼來進行開發一樣呢?
這裡的潛臺詞恐怕是“大哥,大姐們,兄弟好不容易才搞定這個C/C++引擎支援多平臺執行,你們玩玩指令碼就好,可千萬別改我的C/C++程式碼啊!千萬別改!你們一改,一改,就該改崩了~”
所以,即使你程式碼寫的再好,只要使用C/C++開發,一旦所在平臺底層程式碼有了變動,就絕對逃不出“一次編寫,到處編譯,平臺升級,編譯失敗,重新編寫,重新編譯,平臺又改,迴圈重來……”的變態連鎖,這無疑是其低相容性的體現。
總之水很深,不提也罷(-____-)。
再者,C/C++編譯之耗時大家有目共度,而且程式碼越多耗時越大,對於程式碼量小的簡單專案還好說,您大可以做會眼保健操什麼的等待它結束。而一旦處理程式碼和資源都較多的中等以上規模專案(比如搞個怪物獵人4之類),您又偏偏喜歡按下【重新編譯】而非【編譯】按鈕。那麼,您真的可以扭頭回家,等明天再來看有啥編譯結果吧(結果第二天一看,一萬多個編譯錯誤,十幾萬個警告之類(° ?°)~)
小弟經常在想,如果Windows7或8是某個人單獨負責的專案,而他又將所有開發資源都引入一個Project中,那麼他每次按下重新編譯,是不是公司都會給他放一次大假呢?\(╯-╰)/
由此可見,C/C++作為遊戲開發語言,遠非大家想象中那麼十全十美。
三、最後,指令碼語言才是遊戲開發的王道,而Java本身就是很棒的指令碼
通過前文的論述,大家可以發現,即便在今天,大多數C/C++開發的遊戲引擎若沒有像lua這類指令碼引擎相配合,也很難製作出多麼複雜的遊戲來。
也正因為有了Lua,AngelScript之類的指令碼引擎,才讓C/C++的遊戲開發週期由【數年】縮短為【數月】,才有效減少了C/C++程式設計師對程式碼的反覆編譯除錯,才可以讓指令碼動態呼叫C/C++寫成的基礎類庫,從而拓展出嶄新的高階功能,而不必考慮一改就不相容的問題……
可以說,有了指令碼語言,才區域性解決了上述所涉及的純C/C++開發問題。
指令碼引擎的誕生,縮短了C/C++遊戲的開發時間,提高了程式碼的重用可能,使得大中型C/C++遊戲能夠較為輕鬆的實現。對於C/C++開發的遊戲引擎而言,lua這樣的指令碼引擎真的至關重要,更可以說是無可替代。
然而,如果我們用Java來製作遊戲引擎呢?我們還需要這樣的指令碼引擎輔助嗎?
——答案,當然是,不需要了!
顯而易見的,對於Java開發者來說,Lua肯定沒有對於C/C++那麼重要。或者說,Java在某種程度上講,本就是和Lua平級的東西(Java有編譯過程,產生Bytecode,但同時又使用虛擬機器解釋Bytecode執行,解釋執行是指令碼語言的特性,故此嚴格意義上說Java等於解釋+編譯共存,單純把它當指令碼用沒什麼)。
譬如我們以Java開發時,哪怕重新編譯上萬個class,也不過是一瞬間的事情,這是編譯CPP的速度所無法比擬的,指令碼才有這種優勢。而Java語法又比C/C++簡潔很多,只要掌握一些基本方式,任何人都能用它輕易開發遊戲(Java遊戲存世量少,是最初Java開發偏向JavaEE造成的,而不是Java不適合做遊戲,否則就不能解釋海量JavaME遊戲的存在(另,拆過一些工程發現,有些排行很高的IOS遊戲純是JavaME遊戲換圖移植|||))。
我們完全可以說,以Java程式碼充當遊戲指令碼,和使用lua指令碼是沒有本質區別的;即使偏要說有,也只是lua+java可能會讓開發變得更慢,而非更快,畢竟很多面向物件的特性lua並不具備。
現實中的例子也是這樣,著名的Unity3D引擎當前總共支援三種開發語言:JavaScript,C#,Boo,而其最常用到的C#,在各種意義上都和Java平級。更進一步講,只要Unity3D願意引入IKVM,它便可以立刻支援Java開發(Unity3D基於Mono,所以能憑藉IKVM做Java支援)。
假如您認為Unity3D在設計上不算腦殘的話,那麼使用Java做為遊戲開發語言便同樣是最正常不過的選擇。
——當然,有兩種特殊狀況存在:一是您要移植已經使用lua引擎的遊戲專案,二是您需要和他人分工開發,但對方卻只會lua指令碼。那就另當別論。
但Java世界中還有Groovy和Scala等更加易用的動態語言專案存在,就算有人認為新一代動態語言相比老舊的Java更為高效,也大可用它們直接補上,而不必藉助lua。
綜上所述,利用Java充當遊戲指令碼,充當遊戲開發語言絕不是什麼奇談怪論,而是非常容易做到,也必將做到的事情。
2.Java遊戲引擎前進的道路上面臨著哪些障礙?
有優勢當然也會有劣勢,在智慧機領域中,Java遊戲引擎所面臨的問題也真不少,否則早該由Java語言一統天下,而論不到C/C++逞強撒野了。
一、Oracle不給力,標準Java目前不能支援任何一款知名智慧機平臺
假如Oracle提供多智慧機平臺支援,讓Java遊戲爆炸式增長,根本就輕而易舉。MonoTouch就放在那裡,Java多平臺支援根本不會存在技術障礙,真做不了還可以買下MonoTouch換殼嘛。
真正的大問題是,Oracle似乎對移動領域根本就沒有興趣(至少在行動上),以至平白錯過了智慧機發展時代,還懵懂未明。
悉數目前最有發展潛力,也最知名的三大智慧機平臺,莫過於:IOS、Android、WP(我是Blackberry、MeeGo、Bada腦殘黑)。
拋開Oracle主觀意圖不談,我們只說憑藉Oracle多年來積累下的“江湖地位”, Java究竟能部署到哪一個上呢?
Google的Android?100%不可能。
世人皆知,Google已經讓埃裡森得罪苦了(猶太人別打猶太人啊~),標準Java想上Android不說是做夢,但除非Oracle和Google全體員工同老闆一起嗑藥,然後一起滾床單高喊Yooooooo。否則,這也算得上天方夜譚了(何況Google自己的Dalvik還活著呢)。
Microsoft的WindowsPhone?90%不能實現。
至於WP平臺,額滴神啊,人家Microsoft有自己的.Net,怎麼輪得到Java插手。假如我是埃裡森,倒很可能拼著丟個幾億$出去買下Mono,然後閉源C#部分,讓它徹底淪為Java專案再開源,同時免費MonoTouch三年,真不信搞不定WP(三年後考下Oracle認證的可以免費用,考不下的一年99$使用費~)。
可惜,埃裡森成不了我,我也成不了埃裡森,所以,全是做夢。
Apple的IOS?聽說埃裡森和天國的喬布斯,當年私交好到兩人老婆都妒忌啊。
仔細斟酌下,小弟發現以Oracle的人緣+江湖地位,Java現階段唯一有可能上的知名智慧機平臺(個人愚見,Blackberry真心不算智慧機,沒有911這貨不可能成功),似乎只剩下Apple的IOS了。
尤其在很多年前,當JavaFX 2.0剛剛出現之時,就有人迫不及待的上傳了下面這樣一張圖片。不得不說,當時很多Javaer都倍感鼓舞,以為Java終於能跑在IOS上了。
“歲月是把殺豬刀,喝了咖啡,黑了龜殼,收了老喬”
但接下來的JavaFX發展,卻讓人不再樂觀,儘管人們都期待著看到JavaFX跑在IOS上的颯爽英姿。但換來的,卻是Oralce一次又一次的瘋狂跳票。
從2009年-2012的JavaOne,幾乎JavaFX on IOS的字眼就從沒間斷過,如今已近2013年了(如果2012年地球不便當),傳說中的JavaFX on IOS 卻連個測試版也沒有蹤影。
此刻我們再看Oracle公佈的Java發展路線圖,連IOS的影子都找不到了。
大哥,把你手裡IPad中執行的JavaFX專案上傳先,都三年了。此刻我只能說——毫無PS痕跡啊。
Oracle啊!Oracle!你真不愧是傳說中的坑神,專注坑爹30年!畫個圈圈咀咒你(╰_╯)
二、自行開發Java多平臺支援標準不統一,各師各法
因為Oracle跪了,Javaer們不得不紛紛自謀生路,自己想辦法解決Java應用的智慧機移植問題。
不過嘛,這也沒什麼,Mono並非Microsoft官方開發,照樣可以乾的風生水起。
——我們堅信,技術宅挽救世界。
遺憾的是,目前在Java世界中,還沒有一款能同Mono並駕齊驅的專案,更缺乏一個Xamarin那樣的團隊(與Portable .NET能相較者倒有之~)。所以,當今最主流的Java跨平臺方式,居然是依靠MonoTouch,然後通過IKVM這個.Net擴充套件外掛把Java語言轉為Mono能夠接受的CIL再進行Mono特有的本地化處理(雖然IKVM對Mono的貢獻也不少,但這隻優化了Mono,並沒有產生Java自己的智慧機跨平臺專案)。
使用這種方式解決智慧機跨平臺移植的Java遊戲引擎較多,比較有名的是Google支援的PlayN,以及Mario個人主導開發的Libgdx。
MonoTouch+IKVM的最大好處在於,原版Java程式只要經過很少的修改,就可運行於多種智慧機平臺之上。
PlayN for IOS版部分原始碼:
Libgdx for IOS 部分原始碼:
從程式碼上來說,兩者都沒對Java程式碼部分進行什麼修改,僅僅以KIVM+MonoTouch提供的IOS本地Java API替換了其原本的Java本地互動部分,就讓程式正常跑在IOS環境之上了。
以效果論,這堪稱是目前最簡潔,最便利的Java智慧機平臺開發方案。
——假如,MonoTouch不要錢的話。
雖然Mono專案本身是免費的,MonoDevelop這個開發用IDE也是免費的,就連MonoGame這個仿XNA實現都同樣是免費的,但關鍵是——真正有價值的Mono衍生專案MonoTouch卻是收費的!而且,此物還是Miguel de Icaza自己搞的,鐵了心要收錢,絕對不會開源的商用專案!
上邪!企業版999(完全支援2499)美刀,個人版399美刀,至於free版的MonoTouch呢?除了能在模擬器玩一玩,再沒有其他作用。
GameMaker正版授權能跑5大平臺,不過299$;Unity3D價格不菲,其3D高質量卻擺在眼前。而Xamarin上一個Professional的MonoTouch授權便需399$,這實在讓人難以接受。試問又有多少人會花399$(普通企業版999$),只為跑個免費的遊戲引擎呢?Xamarin難道不知道,一臺iPhone的價格,便足以讓某些國家的人缺少腎臟之類的身體重要器官嗎?!
而MonoTouch,又是目前以KIVM+Mono方式讓Java支援智慧機多平臺開發的唯一手段。
My God !誰會花幾百刀就為用個開源引擎(收費引擎大多還有破解版),誰就真腦子被驢踢了。IKVM這條路,Javaer恐怕是很難走下去了(土豪請自覺退散)。
故此,小弟對Libgdx和PlayN這種開源引擎,採用Mono作為Java跨平臺解決方案的評價只有四個字。
——浪費時間。
既然Mono這個高富帥靠不住,我們只好退而求其次,找找Java系本身有沒有什麼和Mono類似,可以把Java原始碼本地化,卻不收費的窮人樂專案存在。
幸運的是,在Java世界中確實有這麼一個專案,它,就是傳說中的XMLVM。
XMLVM並不是標準的Java實現,它基於Apache Harmony的C/C++實現部分,而非OpenJDK之類。
就原理來說,XMLVM酷似Mono,都是先將原始檔案轉化為某種中間程式碼,再將中間程式碼本地化到指定平臺的交叉編譯工具。
從適用範圍上講,XMLVM其實比Mono還要廣闊,XMLVM可以將任意Java位元組碼或.NET CIL乃至Ruby翻譯成XML文件,再轉化為C,Obj-C,Java,C#等等很多種語言輸出,這點是Mono所無法比擬的。當然,它最核心,也是最常用的目地, 還是讓Java轉化為任意語言並本地編譯。
通過源自http://xmlvm.org/tutorial/的XMLVM官方描述我們可以看到,就連Oracle一直說要搞定而沒有搞定的IOS,也在XMLVM支援之列。
雖然功能上還有所欠缺,不過想把Java轉化為C或Ojb-C都可以做到(另,人家註明要拋棄Obj-C了)。
可以說,您何時願意使用XMLVM,您何時就可以讓自己的Java程式跑在IOS系統之上。
——不過XMLVM也是有缺點的。
下面,是一個XMLVM將Java轉化為C#時產生的CS檔案。
大家可以看到,Java程式碼確實被轉化成了cs檔案,而且這個cs檔案也確實是可以被編譯通過的。但是,為什麼語法看上去那麼奇怪,好像有N多冗餘在其中呢?……
原因就在於,XMLVM對於Java或C#的檔案轉化並非基於原始碼,而是基於原始碼所衍生的Bytecode或CIL指令集。
顯然,XMLVM是將比原始碼更簡單的,面向過程的指令集轉化到目標原始碼之上,而非原始碼對原始碼的遷移。但這畢竟不是彙編,無論你的初衷怎樣,用面向物件的方式,寫等價於指令集的程式碼,都會造成某些一些很不必要的冗餘程式碼。
—— 效率是硬傷。
對於結構複雜的Java程式碼轉化成的C程式碼,程式效能將會被嚴重拉低。
——低到和Java原版差別不大的程度(原本的Java程式碼畢竟是跑虛擬機器,這樣看來問題不算太大嘛,-_-|||)。
XMLVM發展到2012年,已經可以滿足絕大多數Java程式碼向IOS,Android,WP的遷移。如果能把效率問題更優化一些,減少些轉化可能引發的問題,更多地增加本地API。那麼,XMLVM超越Mono也指日可待(大部分程式碼可以轉化成功,但非100%能夠成功,在使用時也可能出現必須修改Java原始碼以適應XMLVM的情況存在。比如小弟的LGame整體可以轉化,但有個別函式無法生成可用C方法,如果替換寫法應該能解決。不過,我還是等XMLVM再成熟點自然解決吧,先搞自己的多平臺方案玩……)。
PS:另外還有CodenameOne這種基於XMLVM的二次開發專案。這貨不是單純的衍生,而是重寫了部分XMLVM實現替換以自己的類庫,而且自帶Eclipse和NetBeans視覺化外掛,做應用的話堪稱神物。比較鬱悶的是,它重寫了一堆JavaME元件,用統一的JavaME API掩蓋了本地API,讓人看著不爽,做遊戲引擎的話,有些東西我想自己改的~
對了,最近類似的專案又新增了Libgdx作者搞的Jake,這是一個J2C的轉化工具,一樣基於位元組碼向本地語言的遷移(所以翻譯過來的程式碼看上去也一樣奇葩)。
話說Javaer果然都是技術宅,寧願自己寫新的,也不願意去參加XMLVM專案(>_<|||)。
最後,我們來談談前幾天橫空出世的J2ObjC。
J2ObjC,Google搞的一神物,作用是將Java程式碼無縫轉化為Obj-C程式碼。
與XMLVM的區別在於,它並不是翻譯位元組碼,而是真的將語法做Java To Obj-C的1:1移植,這樣它所生成的.h,.m檔案將具有可讀性,也方便使用者自行改寫(Bytecode指令集是面向過程的,而Java原始檔的書寫方式是面向物件的,有編碼習慣在起作用,轉化Java指令集比轉化Java原始碼翻譯簡單的多,因為複雜原始碼是很難按面向物件翻譯準確的)。
比較遺憾的是,Google已明確表示J2ObjC不提供UI介面以及一切與本地API互動的功能,只保證語法的遷移。需要介面之類的,那部分還得自己手寫原生代碼去(這是在逼人發展J2ObjC的衍生專案啊)。
不過嘛,這對小弟來說已經足夠了,因為小弟目前已經在做特定範圍內的Java功能再現與自有UI集(就是LGame Java版到其它版本的轉換器,話說這貨快調完了,Java版API目前已經凍結,正向其它版本遷移)。因為我原先做的已經有J2C#,J2C++加上Google的J2ObjC,徹底省事了……
總之,Java作為智慧機領域遊戲開發語言,在技術上是絕對可以實現的,前途是光明的。
__________________________
另:
在LGame的SVN中有更新(Beta20120921),目前Java版API已經凍結,只要完整像其它版本的新增類和API遷移就可以釋出了(順便我先重寫部分C#版,舊版有部分地方還是坑爹~),並且增加了一些示例原始碼(如下圖所示,兩款鎮場用的未包括,等正式釋出時再加):