同程旅游616邀请函——一款你没见的3d html5游戏

数英评分
我的评分
收藏 评论
举报 2017-06

 第一次接触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

 


同程旅游
 
数英评分
5
我的评分
谢谢
数英评分
5
我的评分

    专业评分

    专业评分已截止

    参与评论

    文明发言,无意义评论将很快被删除,异常行为可能被禁言
    DIGITALING
    登录后参与评论

    参与评论

    文明发言,无意义评论将很快被删除,异常行为可能被禁言
    800

    推荐评论

    暂无评论哦,快来评论一下吧!

    全部评论(0条)