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++会让我们非常痛苦,强迫我们在非必要的场合使用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#版,旧版有部分地方还是坑爹~),并且增加了一些示例源码(如下图所示,两款镇场用的未包括,等正式发布时再加):