背景
现在越来越多的公司和APP开始使用游戏化的方式去做产品了,所谓游戏化,是指在非游戏环境中将游戏的思维和游戏的机制进行整合运用,以引导用户互动和使用的方法。支付宝里面的蚂蚁庄园、蚂蚁森林,通过游戏和公益的结合实现用户的留存和活跃。淘宝支付宝的芭芭农场、京东的东东果园、拼多多的多多果园、美团的小美果园...无一不是通过游戏化的方式去提升用户留存的方案。
本篇文章,我会列出一些游戏化互动类的游戏,让大家看一下阅读本文后,我们可以做的项目是怎样的。
然后对一个案例进行拆分,带大家学习一些2D互动最基础的知识,让大家能够快速上手写互动游戏。
能做什么
互动案例
我们来看几个2D互动项目,目前,大多数的互动都是以游戏的形式展现,通过游戏的玩法和精致的效果,让用户有更好的互动体验,我们通过养成,采集,塔防,抓娃娃等类似游戏的形式,结合业务属性,达到更好的业务效果。
案例分析
我们进行一个案例分析,先来看一下,在一个互动项目中,我们需要用到哪些互动游戏的元素,首先,我们可以看到整个场景里面有背景和前面的猫动画,背景是使用了图片展示,猫动画是用了骨骼动画实现的,在招财猫的钱袋中,有时间进度条信息,进度条是使用两个圆角矩形实现的,进度变化是使用过渡动画实现的。在互动项目中,我们还会用到一些帧动画、精灵图、事件的能力。对于普通的前端开发来讲,有一些概念我们并不常用,接下来就让我们开始了解一下这些基础知识。
基础学习
2D互动常用能力
互动游戏是如何运行起来的
互动游戏是如何运行起来的呢?首先,我们知道,目前很多前端项目都是通过数据带动视图的,游戏也是这样的,比如说,我们在游戏里面有一个飞机,那么,我们需要定义飞机的尺寸,以及他在游戏中的位置,和他对应的飞机图片,这些属于游戏数据,我们将数据提交给渲染引擎,渲染引擎根据这些数据内容将对应的内容渲染到画布上。
游戏是动态运行的,为了实现一些动画/真实物理效果效果,我们通过动画,AI,物理引擎等工具控制数据的变化,然后通过循环来持续修改数据,并且渲染到画布实现游戏的运行。
循环
浏览器提供了requestAnimationFrame方法,要求浏览器在下一次绘制之前,调用制定的回调函数,这个方法一般是用于更新动画的。
浏览器在的每一次重绘我们叫做1帧,浏览器默认的绘制频率是60帧,也就是说,正常情况下,浏览器一秒会刷新60次。
通过下面的方法,我们可以保证每一帧渲染之前,我们可以进行数据的计算以及调用渲染方法
const loop = () => {requestAnimationFrame(loop)// 计算数据// 绘制图形
}
requestAnimationFrame(loop)
因为requestAnimationFrame方法只会在下一次绘制前被调用,所以,我们需要在每次调用方法的时候去调用一次这个方法保证游戏继续运行,所以在loop方法里面会重复调用这个方法。
一般情况下,我们会把这个方法放在函数的最前面,因为,如果在计算数据和绘制图形的过程中报错了,会导致程序无法执行到这个方法,游戏也就停掉了。
画布
常用的绘制上下文有Canvas API 和WebGL,一般CanvasAPI来绘制2D图像,WebGL可绘制2D和3D图像,他的性能更高。
canvas提供了一些比较基础的API,但是在互动游戏中的元素是比较复杂的,所以一般都会有渲染引擎和游戏引擎来承接这些元素。
本文不会详细讲解Canvas,可以到MDN等平台学习。
基础渲染
接下来我会介绍一下,在2D游戏化互动游戏中,我们经常用到几种渲染方案。
图片
文本
图形
精灵
九宫格
遮罩
图片和文本就不用说了,是视图开发中最常用到的。我们从图形开始说
图形
精灵
九宫格
我们经常会遇到一些尺寸不固定,但是周围或四遍样式不变形的图片,也就是 .9 图,例如消息气泡,如果直接设置宽高会将整个气泡图片拉变形。
使用九宫格的原理进行解决:
一般渲染引擎也会提供方便的方式实现。
遮罩
通过遮罩可以实现渲染内容的遮罩效果,是不是很像给div设置 overflow:hidden
呢
基础动画
过渡动画
例如一个物体经过3秒,从100px的地方移动到500px。我们可以通过以下方法计算。
startTime 是动画开始的时间。
如果一个物体向右做匀速运动,我们可以使用公式 s = v * t
一般情况下,我们都会使用现成的动画库,类似 Tween.js 实现,当然在实现复杂的动画逻辑时,还可以使用一些工具,类似Lottie,我们还是需要手写动画的。
逐帧动画
Texture Packer
来实现逐帧动画资源,一般是由设计师逐帧绘制,然后导入 Texture Packer 后导出资源文件,开发者直接使用资源文件即可。骨骼动画
骨骼动画可以模拟实现一些比较复杂有一定关节逻辑的动画,比起帧动画而言,所使用的图片更少,占用内存更小。
骨骼动画主要以下几部分组成:
骨骼动画贴图
骨骼设计以及动画
贴图+骨骼+动画
所以骨骼动画资源一般由三个文件组成,常用的骨骼动画设计软件是 Spine 和 Dragonbones,一般是由设计师或者动画设计师进行设计。开发者只需要使用软件导出的资源即可。
项目实战
了解到以上的内容,我们就可以开发互动项目了,工欲善其事,必先利其器,这里我们推荐由淘系技术部开源的 Eva.js,它是专门给前端开发者提供的开发游戏化互动项目所设计的。目前淘宝、天猫、支付宝、优酷、阿里妈妈、AliExpress、Lazada、考拉等很多产品都在使用,2020年双11养猫猫项目也是使用 Eva.js 实现的。
接下来我们拿一个最简单的 Demo 来学习使用 Eva.js。
这是一颗心做左右移动动画,点击后弹出一个alert。
Eva.js 的游戏是由游戏对象和组件构成,游戏对象代表游戏中的一个物体,组件代表物体的能力,在这个例子中,只有一个物体,他的能力有三个:
显示成一个心的图片
有一个左右的过渡动画
点击事件
我们刚刚分析了这个 Demo 所需要的能力,接下来我们要做 Eva.js 开发游戏的四步操作
Step1 添加资源&创建游戏
import { resource, Game } from '@eva/eva.js'
import { RendererSystem } from '@eva/plugin-renderer'
import { ImgSystem } from '@eva/plugin-renderer-img'
import { EventSystem } from '@eva/plugin-renderer-event'
import { TransitionSystem } from '@eva/plugin-transition'resource.addResource([{name: 'imageName',type: RESOURCE_TYPE.IMAGE,src: {image: {type: 'png',url:'//gw.alicdn.com/bao/uploaded/TB1lVHuaET1gK0jSZFhXXaAtVXa-200-200.png',},},preload: true,},
]);const game = new Game({systems: [new RendererSystem({canvas: document.querySelector('#canvas'),width: 750,height: 1000,}),new ImgSystem(),new EventSystem(),new TransitionSystem()],
});
addResource
传入了一个资源的里面,这里不一定只有图片资源,还可以有帧动画、骨骼动画等等资源,这里以图片资源举例子。更多Demo可以进入 Eva.js 官网 中查看。
在添加资源之后,我们也创建了一个游戏实例,这是运行游戏的主要运行时, 因为 Eva.js 只有一个最核心的游戏运行时,所以我们所有的功能都是要自己安装的哦~所以我们要安装这个游戏所需要的系统,图片、事件、动画。
RendererSystem
是用来将游戏渲染出来的系统,所有渲染的能力都依赖这个系统,里面设置了宽高以及所要渲染的canvas对象。ImgSystem
是用来画图片的系统EventSystem
是用来触发点击事件的系统TransitionSystem
是用来做位移动画的系统
Step2 创建对象,并设置定位
import { GameObject } from '@eva/eva.js'const heart = new GameObject('heart', {size: { width: 200, height: 200 },position: {x: 0,y: 0,},origin: { x: 0, y: 0 },anchor: {x: 0,y: 0,},
});
GameObject 的第一个参数为对象的名称,第二个参数为对象的位置信息,其中 size
设置对象大小, position
设置位置,其他的可以后续参考文档学习哦~
Step3 添加所需要的组件
刚刚我们在 new Game
的时候添加了实现视频功能所需要的系统,这些系统是为了读取组件上面的数值然后实现功能的,所以,我们需要给对象添加组件以后,才能够让对象实现对应的功能。
我们目前所需要的功能是图片渲染、点击事件、位移动画,所以我们要添加三个组件
图片渲染
import { Img } from '@eva/plugin-renderer-img'heart.addComponent(new Img({resource: 'imageName',}),
);
调用 heart 的 addComponent
方法既可添加组件,这里我们添加 Img
组件, Img
组件有个 resource
参数,该参数是图片资源的名称,其实对应了 Step1 中添加的图片资源的名称。当然雪碧图、骨骼动画也是同样的原理,需要在 resource 中添加资源,在添加组件的时候使用。
点击事件
import { Event } from '@eva/plugin-renderer-event'const evt = heart.addComponent(new Event())
evt.on('tap', () => {alert(1)
})
给游戏对象添加一个 Event 组件,并通过 on
方法绑定 tap
事件, on
的第二个参数为 tap
事件所触发的函数,当然,Event 组件还有其他事件,我们可以通过 Eva.js 文档查看。
位移动画
import { Transition } from '@eva/plugin-transition'const transition = heart.addComponent(new Transition())
transition.group = {idle: [{name: 'position.x',component: heart.transform,values: [{time: 0,value: 0,tween: 'ease',},{time: 1000,value: 400,tween: 'ease',},{time: 2000,value: 0}]}]
}
transition.play('idle', Infinity)
上面的代码中,我们创建了一个动画组,名字叫做 idle
当前动画组里面,我们对 heart.transform
组件的 position.x
属性进行数值变化,0->1000ms,数值从0->400,1000ms->2000ms,数值从400->0,然后使用 Transition 组件的 play
方法,让动画执行 Infinity
次。
Step4 运行
一般游戏都是自动运行的,所以做完以上工作后,游戏会自动开始运行。
总结
未来会有越来越多的游戏化产品,开发互动类游戏将成为前端工程师的必备技能,通过本篇文章,我们可以了解到一些基础的游戏化互动技术,也通过 Eva.js 学习了如何实现一个最简单的互动游戏。如果想对游戏化、互动技术更加深入,我们需要去深入学习游戏引擎、渲染原理、动画、物理、音效等技术,对于互动业务开发来说 Eva.js 目前能满足大部分需求。
前端领域中游戏化方向刚刚起步, Eva.js 是专注于开发游戏化项目的游戏引擎,也处于刚刚起步的状态,未来 Eva.js 会继续专注于前端,专注于游戏化项目,让游戏化项目开发更简单。我们也希望大家能够参与到前端游戏化领域的建设中来,我们也会陆续分享相关的技术,输出游戏化项目开发能力。
人人可开发、处处有互动
我们团队的使命是“人人可开发、处处有互动”,基于这样的目标,Eva.js 会最大化的减少互动游戏的开发成本,让每一个前端工程师都可以低学习成本开发互动游戏。
Eva.js 将于 4 月 22 日举办开源技术专场,欢迎扫海报上的二维码入群, 也可以点击阅读原文扫码进群,群内大佬云集!