hilo,一套html5跨终端的互动游戏解决方案。hilo支持了多届淘宝&天猫狂欢城等双十一大型和日常营销活动。内核极简,提供包括dom,canvas,flash,webgl等多种渲染方案,满足全终端和性能要求。支持多种模块范式的包装版本以及开放的扩展方式,方便接入和扩展。提供对2d物理,骨骼动画的内建和扩展支持。另外,hilo提供丰富的周边工具及开发案例。下文来自一位云栖社区新的朋友,天猫事业部-产品技术部江成的分享。
目前,hilo已经开源,并入到hilo team中。开源地址 https://github.com/hiloteam/hilo (欢迎star)
hilo的特点:
极简内核: hilo核心模块极精简,保留了2d游戏引擎最必要的模块,同时采用模块化管理。
完善接入&扩展: hilo 支持多种模块范式的包装版本,包括amd,cmd,standalone多种方式接入。另外,你可以新增和扩展需要的模块和类型。
多种渲染方式:提供dom,canvas,flash,webgl等多种渲染方案,可以做到跨全端,高性能的要求。
完善的周边工具:提供动画编辑器 ,yeoman脚手架及典型案例产出的辅助开发工具。
案例丰富: 支持天猫,手淘多次大型和日常活动,如双十一,年中大促等。代表产品如狂欢城。
hilo采用极简的内核。核心模块包括基础类工具(class),事件系统(eventmixin),渲染(render)和可视对象(view),如下图所示。

首先,我们来看看如何接入hilo。
hilo是模块化的架构,且每个模块尽量保持无依赖或最小依赖。在hilo的源码中,你看不到一般的模块定义的范式:
取而代之的是,hilo的每个模块都会有这样的注释定义:
我们使用注释标签<code>@module</code>来标记模块名称,用<code>@requires</code>标记模块的依赖。
在编译阶段,我们会根据这些标记获取模块的相关信息,然后编译生成符合不同的模块范式定义的代码。比如:
我们除开提供一个独立无依赖的版本外,还提供amd、commonjs、cmd、commonjs、kissy等多种模块范式的版本。开发者可以根据自己的习惯,下载hilo的不同范式版本使用。
接下来,我们来看看hilo如何做扩展。
<code>class.create</code> 是hilo里创建类的主要方法,如下:
其中:
<code>extends</code> - 指定一个父类。
<code>mixes</code> - 指定混入对象。可以是一个object或array。
<code>statics</code> - 指定静态属性。
<code>constructor</code> - 创建类的构造函数。
此外 hilo 使用 <code>class.mix(target, [mixinobject])</code>,可以为target混入属性和方法。
代码示例:
再以扩展hilo的可视对象的基础类view为例。view在表现上就是一个个矩形,无论图片还是文字都可以使用一个最小的矩形包裹。在这些可视对象上做平移,旋转,缩放,透明处理等操作就可以实现普通动画的绝大部分。
如上图所示,view解决了可视对象展示的基本问题。
利用hilo提供创建类和扩展类的方法,我们可以扩展出可视对象所属管理的container类:
添加和删除可视对象
可视对象排序
位置对换,可视对象的所属包含判断
由坐标系的位置获取可视对象
根据位置、索引、id来添加和删除可视对象
类似地,根据不同view的其他展示特性,hilo扩展出舞台stage,位图bitmap,画图graphic,精灵动画sprite等类型。
我们知道一个游戏运行的核心流程——在一个loop循环内,接受输入并完成对所有可视对象的游戏属性更新,然后渲染。下面是单个可视对象的一个循环过程:
作为一个可视对象,包含了位置,大小,缩放,旋转等自然信息,如下图所示:
update是个计算过程,后面赛车案例会讲通过update我们可以做一些特殊的效果出来。在这之前,我们先看看渲染,即如何根据可视对象的自然信息来把他们 “画”出来。那么如何实现view的render函数呢?如上图所示,在render函数中主要解决两个问题:
位置,尺寸,旋转等变换(transform)
渲染(背景样式,图片,颜色,透明度等)
hilo首次提出了特别的渲染方案——即提供dom 、canvas、 flash或者webgl 四种渲染的方式来实现render,目前该方案已经申请专利。这四种渲染方式是和view独立分开的,view在做自身属性更新时完全不需要考虑怎么被“画”出来,同样,拿到view后我们可以使用不同的“画笔”把它描绘出来。如果你有更好的绘制方式,也可以扩展出更多的渲染方案。如下图所示:
view可以粗略分为普通类的view,文字类view(text)和画图类view(graphic)几种类型。不同类型的view“长相”不尽相同,在做update和render时也要针对处理。
普通类的view,如bitmap,container,button,sprite,在渲染层面主要处理图片的展示问题。单从图片展示的技术实现上讲,dom渲染可以通过设置元素的background样式实现,canvas也有绘图方法drawimage,webgl则可以通过shader做纹理绑定。
特别地,在flash的渲染模式下,hilo首先将view所有和绘图相关的方法通过jsbridge的方式交由适配器flashadapter,flashadapter来翻译成对应flash工程实现绘制的方法,如下图所示:
由于flash在pc浏览器上的广泛支持,特别是ie的支持,使用flash渲染额外好处就是跨终端,这个终端包括所有主流pc浏览器(包括ie 6,7,8)在内。
另外,在一些低端的手机浏览器上,可以选择dom渲染模式来代替其他的渲染方式。在canvas支持不好的机器上或者互动游戏场景本身比较耗性能情况下,dom渲染模式可以很好地胜任渲染的工作。2015年天猫年中大促的赛车互动,我们就在android机器上使用dom渲染的方案。
除了多种渲染模式,hilo还提供给一些其他衍生能力。这些衍生能力或者来自每次项目的技术改进,或者来自对其他优秀引擎的能力的吸收。例如hilo支持主流骨骼动画和自建骨骼动画系统(tahiti),狂欢城多图片下高性能优化,主流物理引擎无缝支持和一些特殊物理效果实现。
相比较精灵动画(sprite animation),骨骼动画(skeletal animation)使用一套资源就可以完成千万种动作变化。
目前做骨骼动画比较成熟的产品有spine和dragonbones 。两者在功能上已经接近,考虑dragonbones免费,可自由使用,hilo实现了对dragonbones的支持。
hilo也实现了自己的动画编辑器(目前仅内部使用)——tahiti。tahiti通过flash插件的方式实现,目前可以支持css3 animation,dom,canvas,hilo动画导出。
骨骼动画将可视对象进行分解,得到一个个可视组件。很显然,这些一个个可视组件本身就是一个个view,只要调整相应的时间片内调整这些view的transform属性,把他们组合起来就是一套完整的动作。
tahiti将分离出的可视对象扁平化管理,各个部件处于同一层级。借助我们自己实现flash 插件就可以导出如下的动画数据格式:
tahiti实现了对导出数据的解析,再借助hilo的渲染,就可以把设定的动画运行起来了。特别地,tahiti不仅对接了hilo的渲染,还可以对接了css3 animation,独立js模式(canvas)的渲染。
hilo 骨骼动画 demo 点这里
一年一度的双十一狂欢城是检验性能的大考。以2015年双十一狂欢城为例,在性能方面主要面临的挑战:
多图:100多商家,每个商家都有品牌logo
动画:大部分商家需要动态展示logo,至少3帧精灵动画
单屏:所有的动画需要在一个页面里分屏展示(iphone 6 plus 下为8屏)
狂欢城预估图片总数为200张 ( 252*296),为了优化性能,我们首先对整体画面做了三个分层:
地图部分:此层的资源绝大数为静止画面,内容更新概率低。
logo展示部分:商家品牌的动态展示区域,一般为3帧的精灵动画。
ui 层:导航,操作ui等。
下面主要看看地图部分的优化。
地图部分多为静止画面,为tiledmap的拼块。由于canvas大小有限制,同时为了性能考虑,我们把8屏狂欢城界面按512*512分解成多个块,分解方式如下图:
把这些分块独立成一个个canvas,他们只在首次加载时和内容更改时(比较低的频率)进行渲染,渲染结果保存在这些cache list中。这个list同时被图示地图container管理,每次更新时只需要对这些缓存在内存中的list做一次整体渲染即可,这样就避免了成百个view单独渲染的问题,大大的降低了draw的次数。
此外,这些分块在有内容更新时,如上图的脏矩形更新所示,view 2在某一帧有内容更新,那么先找出和view 2 所有相交的view,然后把这些view按照z轴次序从远及近更新,且只更新其相交部分。这样,便可以最大限度的只渲染需要渲染的部分。
概括地说,我们首先从结构上保证性能,大的方面上做了分层,抽出那些“动”和“不太动”的。其次,我们把view做了分块,把多个的view 更新渲染变成了一个512*512 大小的view 渲染,组成cache list,然后在交互范围内把cache list里需要输出的对象渲染到手机真实物理屏。与此同时,在更新cache list时,为了避免cache list 内 view对象的全部更新,我们尝试了更新引起变化的最小矩形块。
考虑到性能和库的精简,hilo选择chipmunk 作为自己的默认2d物理引擎。
我们知道物理世界非常丰富,不可能通过一个物理引擎就把物理世界全部展现的。不同材质,刚体或非刚体,流体或者布料这些在物理表现上差别巨大。物理引擎帮助我们解决一些基本问题,就像hilo里的基础类view解决可视对象的基础问题。
面向业务,我们可以扩展出更多的物理效果。如2015年天猫年中大促的赛车项目,我们自己实现了一套赛车漂移的效果,改写的就是view update计算方式。具体实现在后续介绍文章中推出。
以上,从动画,性能,物理三个方面案例阐述了hilo可以做更多的事情,相信在业务支持和技术推动下,hilo可以更加完善,非常希望对互动感兴趣的同学加入到hilo开源队伍中,完善hilo能力,提高hilo开发效率,同时产出更多令人欣喜的作品。
hilo 从阿里前端委员会建议立项到开发完成,得到许多关注和帮助,也同时支持到共享、阿里通信、手淘、天猫、城市生活、国际ued、阿里妈妈多个bu。因技术推广这里就不一一感谢。 留下两位主要作者的花名 @正霖 @墨川
hilo github 开源地址 https://github.com/hiloteam
hilo 官网: http://hiloteam.github.io/
特别开设了微博:阿里hilo(欢迎感兴趣的朋友联系)