双人打飞机项目经验分享

前段时间前期后后断断续续大概花了4个月的时间去完成我的双人打飞机游戏,我做这个游戏的初衷是为了给自己一个机会去探索html5的canvas和nodejs的使用,最后坚持把游戏写出来了。
Screenshot_2013-12-30-21-09-15
刚开始我只是想做一款在电脑上用html5实现的一款打飞机的单人游戏:
做游戏很重要的一个事情是要有素材。打飞机的素材在哪里找?别在网上找了,直接下载微信的apk包,解压缩,png就在里面。QQ图片20131230123136
之前用ps慢慢扣图傻逼死了.
找到图片之后先解决一个问题:碰撞问题。
html5没有类似flash那样提供hittest的方法,所以要检测2个物体直接的碰撞是很困难的。
一般的方法比如矩形和圆形都是比较容易检测的,如果遇到不规则图形,这就比较难处理了,就比如这个飞机的形状。
解决这个不规则的问题有我找到4种方法
1:box2d 这个html5的版本我还没用过,不过内置的aabb算法可以很容易的构造一个多边形的刚体达到检测部规则图形的目的。
2:像素覆盖法 记录位于某个图的某个像素的相对坐标的RGBA,只要检测到这个RGBA值发生变化时,就发生变化。
3:aplan值判断法 如果两个图所在的矩形相互碰撞,则js新建一个canvas把2个图贴在上面逐个像素检测,如果某一个图的a值变成非1,则发生了碰撞.

  •         context.drawImage(this.img, this.x, this.y);
  •         var data1 = context.getImageData(minx, miny, maxx – minx, maxy – miny).data;
  •         context.clearRect(0, 0, 550, 400);
  •         context.drawImage(sprite.img, sprite.x, sprite.y);
  •         var data2 = context.getImageData(minx, miny, maxx – minx, maxy – miny).data;
  •         for(var i = 3; i < data1.length; i += 4)
  •         {
  •                 if(data1 > 0 && data2 > 0) return true;
  •         }
  •         return false;

4:原理同上。不过相较的属性要改为globalCompositeOperation =”xor,source-over ,然后检测到2个图是否有存在这个透明点,如果存在则发生了碰撞;

  •         /*第二种方法
  •         context.drawImage(this.img, this.x, this.y);
  •         context.globalCompositeOperation = ‘xor’;
  •         context.drawImage(sprite.img, sprite.x, sprite.y);
  •         var data = context.getImageData(minx, miny, maxx – minx, maxy – miny).data;
  •         context.globalCompositeOperation = ‘source-over’;
  •         for(var i = 3; i < data.length; i += 4)
  •         {
  •                 if(data == 0 ) return true;
  •         }
  •         return false;*/

QQ图片20131230124825
第1,2个方法都是比较高效的,第一个方法要加载box2d库,使游戏体积变大,大概 100K
第2个方法比较麻烦,要自己写一个复杂的类,而且有时候很不精确,比如碰撞物体颜色一样的时候。
第3和第4个方法原理类似,不过就太低效率了,需要每个像素遍历。
我觉得选择第一种是最好的方案,尽管加多了100K,当时没想到先用了第2个方法,太复杂了,再用第3个方法。目前游戏采用的是第3个方法。
然后就是画布处理的问题,可以选择多个部件一个png,也可以一个png里面放多个部件,这是写HTML的常用方法。这里尽量选择后者,及时会遇到很多兼容的问题,貌似在

context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);

里面后面4个参数不支持
当我把单人打飞机做出来之后,这大概花了1个月时间吧。我觉得自己打太没意思了,于是想到了双人打的模式,在用户角度双人打其实也不是很有趣,仅仅从技术角度出发,双人打是一项困难重重的工作,尤其是手机端。我决定在PC浏览器上先实现双人打的功能。
难点分析:服务器怎么写?对于我这个前端工程师,入门最快的就是nodejs了,虽然它不是运行最高效的(理论上c++会更快),服务器该用什么?如果你有一台linux服务器,建议你用linux,如果用windows也可以,只是会有很多未知的限制。如果你企图使用新浪或者百度的nodejs服务,我建议你死心,因为他们不提供socket长连接服务。
关于安装nodejs的方法就不说了。只要做到类似聊天室的功能,就可以自己写一个类做出双人飞机同步了。
又过了大概半个月,我把电脑版的双人打飞机做出来了,可是电脑上的屏幕大小并不适合玩飞机大战,如果换到手机上玩会不会体验好一点。手机上的兼容问题是比电脑还麻烦的问题,幸好目前主流的手机浏览器都兼容html5,但兼容程度各不相同。至于如何兼容呢?
IOS 的safair 限制多多,相对比较统一。
android 的内置webket 算是比较好,没多大限制。
但是android屌丝机居多,很多垃圾android玩游戏都会卡,这一卡就会引起很多问题。
比如敌人飞机每一帧运行需要30ms 如果手机卡可能是50ms 如果敌人飞机是运行速度是5px 那么实际速度会比这个小,导致2个人手机对战的敌人位置不一致,就会出现bug。
再说一下屏幕问题,很多手机的分辨率大不一样,我还发现了一点 电脑上的1像素的大小,其实跟手机的大小是不一样的,有个名词叫dpi,手机的dpi是电脑的3倍,为了达到画布占满圈屏幕的效果,可以这样 给canvas标签一个css的属性width和height这个宽高是手机浏览器的宽高,需要用javascript去动态改变。
加上这些标签告诉浏览器不要缩放.
<meta name=”viewport” content=”width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no”/>
<meta http-equiv=”X-UA-Compatible” content=”IE=edge,chrome=1″>
<meta name=”apple-mobile-web-app-capable” content=”yes” />
<meta name=”apple-mobile-web-app-status-bar-style” content=”black” />
 
后来我尝试给手机版本的打飞机加上声音,结果不尽人意。
1 ios的audio需要在用户事件后面触发的,比如在服务器返回同伴的飞机死亡了,发出爆炸的声音,IOS是没办法播放的
2 不支持多声道 意思是同一个音乐,没办法在同一周期内播放2次,比如我在同一时间发生2次爆炸,则爆炸声音只有一次。
3 声音不同步,某些屌丝android由于cpu很烂,播放声音后总是延迟才能发出声音,这对于即时对战的游戏是很恶心的。
4 android上的audio突然播放不了.郁闷了,查不到原因.
以上问题都没有得到一个很好的解决方案,我只能把声音播放放弃了。
当我把手机版的双人对战模式做好以后,发现如果他有了社交关系链之后容易在朋友圈之中传播,但是做起来并非易事。
我在微信的内置浏览器中打开我的游戏,发现屏幕变得很小,iphone4s根本被压缩得很扁,幸好微信提供的接口把底部栏隐藏掉。

document.addEventListener('WeixinJSBridgeReady', function onBridgeReady() {
WeixinJSBridge.call('hideToolbar');
});

关于社交链,简单的说就是微信的名字,如何能获得到呢?
1:普通的公众是不可以的,只有经过认证的工作平台才有资格获取用户数据,即使是服务号也不行,为此居然花了50块钱去淘宝买了个服务号,如果要认证的话要800元,风险有点高我就放弃了。
2:除了微信认证,有没有其他方法呢?答案是有的,我觉得使用QQ登陆的开放接口,这样就可以获得用户数据,但是这样的用户体验很差,有一次我拿给同事玩,他以为我要盗取他的QQ账号,不管如何,这功能上算是实现了,也加深了我对登陆的oauth2.0的认识。
Screenshot_2013-12-30-20-48-48
3:如果说一定要获取用户信息,那除了以上两种,我没有其他方法了。微信确实是一个很严谨的平台。至此我只能把排行榜的功能放弃了。
接下来要思考的问题是如何连接2个人一起对战呢?我想到了4种方法
1:陌生人模式,进入房间,随机匹配
2:连接发送模式,将url发送给朋友,适合远方的朋友
3:二维码扫描,适合在身边的朋友
4:微信顶部的好友分享
第1种方法,不好不坏,凑合使用。
第2种方法,我曾经想让用户直接复制url给QQ或者微信,但是这样做不现实,用户不懂的
第3种方法,遇到了阻碍,通过二维码扫描进入的网址,会被微信过滤掉JS
第4种方法,可以直接发送链接给微信好友,并且不需要关闭浏览器。
无奈之下我只能选择了第1种和第4种方法。
微信并不提供JS的好友圈分享接口,我只能引导用户提示右上角进行分享。不过我估计没有人会分享的了 哈哈
Screenshot_2013-12-30-20-51-09
在设计期间,我考虑到游戏对通信要求很高,否则会涌现很多bug,比如双人模式,网络不够好的话,根本玩不起来.为了有一个良好的体验,我只能在游戏开始时做网络检测.延迟低于80ms才能进入游戏.虽然微信有提供网络状态接口,但是wifi和3G都不能完全保证延迟足够低.所以只能跟服务器做时间判断.
Screenshot_2013-12-30-20-49-27
在开发期间,我曾经想过把游戏包装成APP接入给微信开放平台,我想到了使用phonggap,几经折腾终于把phonggap搞定了,不过这个平台确实有很多限制,就像给浏览器套了一个外框。并不能充分发挥性能优势,只适合web程序员使用。
至此为止,此游戏并非是一个可玩性高的游戏,但是对于我而言这段时间学习到了很多。关于手机上的html5游戏的各个方面都有所认识。
总结:目前手机上写HTML5游戏不靠谱。

发表评论