同程旅游616邀請函——一款你沒見的3d html5游戲
第一次接觸webgl還是去年的天貓活動,記得當時網上好多人瘋狂轉載,因為是國內第一次出現,所以大家覺得挺新鮮的,后來我了解到原來使用的是threejs的第三方庫。去官網看了現有的示例,當時深深地被其3D效果所震驚,原來web還能做到主機和客戶端的3D效果。作為一名交互設計師,除了日常產品對接體驗優化工作外,自己業余時間也在學習threejs。不得不吐槽,threejs文檔真心難用,學習成本還是比較高,但是多看看官網示例,多看看源碼還是有不少進步的,順便讓我的Javascript的基礎知識更牢固了。廢話不多說了,進入今天的主題吧。先放幾張截圖和體驗地址
首先說一說需求來源,同程旅游市場中心品牌組要搞一個616運營活動,主要是以游樂場為場景,突出616活動氣氛,以H5的形式出現。產品找到我們UED,本來是讓我們這邊出交互和設計稿,我們UED leader峰哥說可以嘗試不一樣的,可以試試我們最近研究的Webgl,產品看了兩個demo后,欣然同意我們的想法(Demo更厲害,留著以后放大招)。期限為兩周,包括搭場景、開發和測試,說真的,第一次做壓力不是一般大,時間比較緊,難度有點高,而且要做那種漫游的感覺。
做的時候我和峰哥兩人分工的,我負責coding,峰哥負責建模搭場景。這時不得不佩服我們leader的綜合能力,場景是3dmax做的,包括建模,貼圖,烘焙,AO等。這東西我只是了解,這部分交給峰哥了。Webgl基本環境和場景搭建我就不介紹了,這個太簡單了,主要包括相機、燈光、場景等,大家可以去Github上看我源碼
我首先要解決的問題是路徑問題,飛機要沿著一定的路徑飛行,因為場景不能太大,如果單純繞圈或者沿著某一方向飛行一會就結束了,沒有趣味性,飛機要飛得忽上忽下,有種漫游的感覺(PM原話)。要沿著某一固定曲線路徑,首先要生成曲線即SplineCurve,查看document文檔,發現只能生成二維的,找到幾個示例才發現CatmullRomCurve3才是生成三維曲線(寫在了對象里,為了“再玩一次”重新初始化)。
第一個問題花了一天左右解決后,其他問題就簡單了,主要就是模型的導出和導入,以及一些細節的處理。模型基本上都是導出json文件,然后調用ObjectLoader或JsonLoader導入。導出Json有好幾種方法,例如網上用Blender導出Json,這種方法自己試過跑通的但是不方便,得要一個一個導出,還有就是Blender界面超難用,果斷放棄。后來自己和峰哥探索出了Maya,3dmax導出Json的方法,但是穩定性有待提高,等我學好了python再優化。我們現在使用最穩妥的就是3dmax導出obj文件,導入到threejs官網的editor里編輯后導出Json,但是只能導入靜態模型,動畫模型還是要用到3dmax或者Maya導出,但對于這個項目是足夠的。
第二步就是模型導入后大的背景搭建了,比如天空盒和海水,天空盒就是在建個Box,六張貼圖貼在六個面(前后上下左右),代碼參考github;大家看到海水很真實,這個海水就比較麻煩了,用的是threejs示例里的Mirror.js和WaterShader.js,可以參考下官網的例子,調下參數就OK了
第三步就是加入金幣和紅包了,金幣和紅包要分布在固定曲線路線的兩側,而且朝向得跟曲線方向一致,不然就吃不到了,所以得要再次用到上續的代碼
第四步就是導入飛機和控制飛機,飛機拆成了螺旋槳和機身是為了螺旋槳的動畫,通過var delta = clock.getDelta(); rotatescoller.rotation.z+=delta*50;兩行代碼讓螺旋槳旋轉起來。最難的就是控制飛行了,可能你會說不就是利用陀螺儀控制左右移動嘛,剛開始就是這樣的,半小時搞定了;但后來發現存在一個問題,飛行時左右移動是漂移的,就是太tm假了,沒有物理飛行的效果。好吧,在leader的重壓之下搬出了高中的物理知識,利用JS的if…else寫出了物理運動效果,當時也想過調用第三方庫,但是提醒的大家是要想做出好的Webgl作品,盡量要克制使用第三方庫,不然渲染時肯定會卡,就用原生的JS寫,這樣你才能有所提高。代碼如下,有點傻瓜但是實用。
function controlUpdate(tt){
var actualV=0.5;
var angleLR=0.02;
group.position.x+=flymove;
group.rotation.z=flyangle;
if( moveLeft&&group.position.x>-10){
if(flyangle<0.2){
flyangle+=angleLR;
}
flymove-=actualV*tt;
}else if(moveRight&&group.position.x<10){
if(flyangle>-0.2){
flyangle-=angleLR;
}
flymove+=actualV*tt;
}
else {
flymove=0;
if(flyangle<-0.04){
flyangle+=0.02;
}
else if(flyangle>0.04)
{
flyangle-=0.02;
}
else{
flyangle=0;
}
}
}
飛機弄完后就是檢測碰撞了,離成功只有一步之遙了,能否吃到金幣和紅包得要利用threejs里的Raycaster,Raycaster就是射出一道射線,類似于雷達波一樣,檢測到物體則返回值,從而判斷是否碰撞到物體。大家看到代碼里有一個對象ParticlesHolder,這個就是碰撞后的粒子,就是碰撞的一個反饋,也是純JS手寫,高中物理沒白學…..
最后一步就是動畫了,場景要實時渲染的,包括螺旋槳,飛機軌跡,場景、海水都是要一直渲染的,加上function animate(){requestAnimationFrame( animate );render();}就可以了。
除了上續的threejs核心代碼外,還有一些流程上其他的工作,比如預加載,再玩一次,分享等。說一下預加載,因為是我第一次寫這個預加載,所以去國內網站上看了一些例子,只能說很坑,new image()預加載圖片還行,Json文件根本沒反應,后來用了XMLHttpRequest()就可以了。
總的來說,這次收獲還是蠻大的。期間遇到各種各樣的問題,坑肯定不止以上這些問題,但是我們沒有放棄,堅持在兩周內解決了。但是整個游戲流程還是有點問題,比如吃完金幣和紅包沒有任何獎勵,這點體驗很不好,但快上線了已經來不及了,這次也算是一個教訓,遺憾總是有的。這算是我們市場中心UED的第一次嘗試,由于本人只是個業余開發,學代碼也才一兩年,未來還有很長的路要走,感謝峰哥和小伙伴的幫助和鼓勵,希望以后會帶給大家更多更好的作品,也希望大家多給些建議,大家互相學習。
github地址:https://github.com/fangkai0802014232/616-Anniversary
評論
評論
推薦評論
暫無評論哦,快來評論一下吧!
全部評論(0條)