Layabox小游戏试玩小结

Posted by csy on 2019-03-13

一、试玩历程

随着微信小游戏的大热,我们组的运营也坐不住了。从18年9月份的时候开始接触Layabox游戏引擎,当时看了一篇文章对比了各大游戏引擎,作者用各种数据安利Layabox,说是目前全球性能最高的HTML5引擎之一。那就来试试吧。

  • 第一个小游戏《玩个锤子》,用TypeScript + Layabox进行开发。

    当时layabox官方已经发布了LayaAir1.0,但是想起大学课上用Dreamwearver的体验。 :sweat:感觉这种IDE拖控件生成代码的方式,过程比较无聊还耗时,而且生成的代码也比较冗余。考虑到需求算比较简单,不需要用到物理引擎,入门开发尽量轻量级,省去学习IDE的时间成本,所以没用官方的IDE。

  • 第二个小游戏《旋转吧胖胖》,用JavaScript + LayaAir1.0。

    需要用到物理引擎,而且之前尝试了TypeScript + Layabox,要写很多的代码,比较辛苦,代码的可读性比较差。开发第二个小游戏就打算玩一玩LayaAir1.0,用的是JavaScript。嗯,真香。:neutral_face:

  • 第三个小游戏《牙牙跳跳》,JavaScript + LayaAir2.0。

用Layabox实现的其中一个游戏地址如下

js+Layabox

二、解放F8、F5

LayaAir有一套已经配好的gulp文件(.laya/compile.js),开发过程中如果想预览效果,需要先后按F8(编译)+F5(调试),而且有数秒的等待时间。然后chorme就会自动打开一个页面如下:

demo

这个访问路径,好像没办法Hybrid?果断抛弃。用webpack配置开发环境。重新配置后 npm run dev +(ctrl+s)即可完成编译。

三、常用的全局参数配置

1.设置网络基础路径 Laya.URL.basePath

通过basePath属性可以设置网络基础路径。如果不设置,默认为当前网页的路径。最终地址将被格式化为basePath+相对URL地址,适用于静态资源替换cdn地址。 在入口文件Main.js里的constructor设置,这里需要注意,一定要写在初始化引擎之后,也就是Laya.init(GameConfig.width, GameConfig.height, Laya["WebGL"]);,因为初始化的时候会重置。

2.取消音效播放后自动删除
1
Laya.SoundManager.autoReleaseSound = false;
3.自适应全屏

设计稿是750 * 1334,为了自适应移动端各种尺寸的分辨率,我的实现是编辑模式Scene场景宽高设置750*1334方便开发,代码模式this.height = Laya.stage.height设置Scene高度为stage舞台高度。首页底部的内容用bottom定位,其余部分用y定位。

1
2
3
4
5
GameConfig.width = 750;
GameConfig.height = 1334;
GameConfig.scaleMode ="fixedwidth"; //场景适配模式
GameConfig.alignV = "middle"; //垂直对齐模式
GameConfig.alignH = "center"; //水平对齐模式

矮肥屏和高瘦屏的效果图如下。

ts+layabox js+layabox

四、移动物理世界

Laya的2D物理引擎,是使用Box2d(一个用于模拟2D刚体物体的C++引擎)驱动的。默认世界根容器为stage。移动时是整个物理世界移动,实际需求中一个界面上一部分物体需要跟随人物的移动而移动,另一部分比如分数栏,血条等需要固定。可以将所有需要移动的Sprite放在同一个容器中,然后改变物理世界根容器,根据此容器作为物理世界坐标世界,进行坐标变换,就可以整体位移物理对象,保持物理世界不变。

1
2
const _mapBox = this.owner.getChildByName("mapBox")
laya.physics.Physics.I.worldRoot = _mapBox

设置完之后,动一动,效果如下。咦,明明改变了物理世界根容器,为什么物理辅助线显示碰撞体的位置和想象中的不一样?不用担心,是用于调试的物理辅助线出问题了,实际碰撞体的位移是正确的。:sweat_smile:

当时开发第二个小游戏时,查文档反复确认使用的方式没问题,不知道问题出在哪里。纠结了很久只好弃用移动物理容器的方案,改其他方式实现。第三个小游戏再把这个问题拿出来看看,才发现原来如此…

移动前 移动后

五、地图的生成

all

拿到设计稿,地图居然是纯色的,那可以愉快的用代码写地图的生成算法啦。用drawPoly画多边形写地面。

道具的生成

斜坡上的刺如果直接算坐标点好像有点复杂,可以先画出平行于x轴的刺,再旋转。通过斜坡的最低点和最高点的坐标算出斜边长,算出刺的数量。在三角函数中,两个参数的函数atan2是正切函数tan的一个变种。atan2(y,x)所表达的意思是坐标原点为起点,指向 (x,y) (x,y)的射线在坐标平面上与x轴正方向之间的角的角度。当y>0时,射线与x轴正方向的所得的角的角度指的是x轴正方向绕逆时针方向到达射线旋转的角的角度;而当y<0时,射线与x轴正方向所得的角的角度指的是x轴正方向绕顺时针方向达到射线旋转的角的角度。这样就可以算出刺需要旋转的角度。解决了刺的生成,其他的弹簧和火堆都比较简单就不一一记录了。

1
2
3
let z = Math.sqrt(x*x+y*y) //斜边
let num = parseInt(z/thornW) //刺的数量=斜边/刺宽
let deg = Math.atan2(y,x) / (Math.PI/180) //倾斜角度

然而,写完demo之后,需求方说后续的版本可能会换肤,也就是说地图的图案会变。:sweat_smile: 只好心疼的删掉代码,改用几个size的矩形精灵+RigidBody, ChainCollider来实现地图的拼接,在生成时,随机调用。

ground

拼接的效果底部会有空隙,从上面地图的底部开始平铺填充,尽量节省Sprite的数量。 ground2

1
2
3
4
5
6
let path = []
path.push(0,bottom)
path.push(0, h)
path.push(w, h)
path.push(w, bottom)
block.graphics.drawPoly(0, 0, path, "#79ab69")

六、碎碎念

1、人物跳跃

思路是给人物一个力,让他跳起来,于是搜API找到这个方法applyForce:对刚体施加力。这里需要注意,要本身就有速度,施加力之后才会起作用。人物一开始是静止站立的,所以 applyForce、applyLinearImpulse施加速度冲量都没有效果,要setVelocity设置速度后才可以,比如setVelocity({x:10,y:-10})。

2、Skin、Texture傻傻分不清

在代码模式,换肤的时候需要注意图片资源有的是用Skin,有的是Texture。比如button是Skin、Sprite是Texture。

3、open(url:String, closeOther:Boolean = true, param:* = null) 加载打开场景并传递参数param

laya.display.scene文档 onOpened(param:*):void 场景打开完成后,自动调用此方法。 试了一下,场景打开完成后没有调用onOpened,不知道是哪里出问题了,暂时还未解决。

七、最后

对于前端开发来说,开发小游戏需要换一个思路,游戏和通常的web页面不太相同,框架和目前流行的三大框架也大不相同。 还没有体验过其他游戏引擎,但是感觉Layabox还是非常适合前端进行开发H5小游戏、微信小游戏等。