简介: 在非游戏环境中将游戏的思维和游戏的机制进行整合运用,以引导用户互动和使用

本文作者:淘系前端团队-Eva.js作者-明非

背景

现在越来越多的公司和 App 开始使用游戏化的方式去做产品了,所谓游戏化,是指在非游戏环境中将游戏的思维和游戏的机制进行整合运用,以引导用户互动和使用的方法。

支付宝里面的蚂蚁庄园、蚂蚁森林,通过游戏和公益的结合实现用户的留存和活跃。淘宝支付宝的芭芭农场、京东的东东果园、拼多多的多多果园、美团的小美果园...无一不是通过游戏化的方式去提升用户留存的方案。

本篇文章,我们会列出一些游戏化互动类的游戏,然后对一个案例进行拆分,带大家学习一些2D互动最基础的知识,让大家能够快速上手写互动游戏。

能做什么

我们来看几个2D互动项目,目前,大多数的互动都是以游戏的形式展现,通过游戏的玩法和精致的效果,让用户有更好的互动体验,我们通过养成,采集,塔防,抓娃娃等类似游戏的形式,结合业务属性,达到更好的业务效果。

基础学习

2D互动常用能力

首先,我们看一下2D互动游戏所用到的常用能力,第一部分是前端知识,主要包括渲染所需的绘制工具,游戏循环,资源加载的能力。

然后是基础的绘制和动画能力,也就是前面提到的一些游戏基础元素。在游戏开发中,会涉及到很多数学相关的知识,比如让游戏中的物体模拟真实的物理效果,或者像一些游戏中的人机对战中的机器人,是使用游戏 AI 来实现的,在本文中不会过多讲解数学类知识。

互动游戏是如何运行起来的

互动游戏是如何运行起来的呢?

首先,我们知道,目前很多前端项目都是通过数据带动视图的,游戏也是这样的,比如说,我们在游戏里面有一个飞机,那么,我们需要定义飞机的尺寸,以及他在游戏中的位置,和他对应的飞机图片,这些属于游戏数据,我们将数据提交给渲染引擎,渲染引擎根据这些数据内容将对应的内容渲染到画布上。

游戏是动态运行的,为了实现一些动画/真实物理效果效果,我们通过动画,AI,物理引擎等工具控制数据的变化,然后通过循环来持续修改数据,并且渲染到画布实现游戏的运行。

循环

我们知道,通过循环来实现游戏的运行效果,接下来我们来看一下在前端浏览器环境下,游戏循环是如何实现的。

浏览器提供了 requestAnimationFrame 方法,要求浏览器在下一次绘制之前,调用制定的回调函数,这个方法一般是用于更新动画的。

浏览器在的每一次重绘我们叫做1帧,浏览器默认的绘制频率是60帧,也就是说,正常情况下,浏览器一秒会刷新60次。

通过下面的方法,我们可以保证每一帧渲染之前,我们可以进行数据的计算以及调用渲染方法:

const loop = () => {
requestAnimationFrame(loop)
// 计算数据
// 绘制图形
}
requestAnimationFrame(loop)

因为requestAnimationFrame方法只会在下一次绘制前被调用,所以,我们需要在每次调用方法的时候去调用一次这个方法保证游戏继续运行,所以在loop方法里面会重复调用这个方法。

一般情况下,我们会把这个方法放在函数的最前面,因为,如果在计算数据和绘制图形的过程中报错了,会导致程序无法执行到这个方法,游戏也就停掉了。

画布

在 html 中,我们一般使用 canvas 标签来绘制图像,它本身没有绘制能力,使用 getContext 获取绘制上下文,调用上下文上面的方法进行绘制。

常用的绘制上下文有 Canvas API 和 WebGL,一般 CanvasAPI 来绘制2D图像,WebGL 可绘制 2D 和 3D 图像,他的性能更高。

canvas 提供了一些比较基础的 API,但是在互动游戏中的元素是比较复杂的,所以一般都会有渲染引擎和游戏引擎来承接这些元素。

本文不会详细讲解 Canvas,可以到 MDN 等平台学习。

基础渲染

接下来我会介绍一下,在2D游戏化互动游戏中,我们经常用到几种渲染方案。

  • 图片
  • 文本
  • 图形
  • 精灵
  • 九宫格
  • 遮罩

图片和文本就不用说了,是视图开发中最常用到的。我们从图形开始说

图形

一般在开发中会经常使用一些简单的图形,图片不仅会用在直接展示内容,也会用在对渲染内容的遮罩,例如一张图片只显示图形内的内容,也会用在按钮区域判断、物理引擎碰撞的形状等等地方。

精灵

精灵图也是我们在 CSS 中接触的精灵图,就是将多张图片合成在一张大图中,在使用时渲染其中某个位置,通过精灵图的方式,我们可以提高网络加载效率以及渲染效率。一般精灵资源是由两个文件组成,一个是图片文件,另外一个是位置信息文件。一般使用引擎进行渲染时,只需要关心对应小图的名称。

九宫格

我们经常会遇到一些尺寸不固定,但是周围或四遍样式不变形的图片,也就是 .9 图,例如消息气泡,如果直接设置宽高会将整个气泡图片拉变形。

使用九宫格的原理进行解决:

一般渲染引擎也会提供方便的方式实现。

遮罩

通过遮罩可以实现渲染内容的遮罩效果,是不是很像给div设置 overflow:hidden 呢

基础动画

过渡动画

例如一个物体经过3秒,从100px的地方移动到500px。我们可以通过以下方法计算。
startTime 是动画开始的时间。

如果一个物体向右做匀速运动,我们可以使用公式 s = v * t

一般情况下,我们都会使用现成的动画库,类似 Tween.js 实现,当然在实现复杂的动画逻辑时,还可以使用一些工具,类似 Lottie,我们还是需要手写动画的。

逐帧动画

骨骼动画

骨骼动画可以模拟实现一些比较复杂有一定关节逻辑的动画,比起帧动画而言,所使用的图片更少,占用内存更小。

骨骼动画主要以下几部分组成:

骨骼动画贴图

骨骼设计以及动画

贴图+骨骼+动画

所以骨骼动画资源一般由三个文件组成,常用的骨骼动画设计软件是 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 会继续专注于前端,专注于游戏化项目,让游戏化项目开发更简单。我们也希望大家能够参与到前端游戏化领域的建设中来,我们也会陆续分享相关的技术,输出游戏化项目开发能力。

原文链接
本文为阿里云原创内容,未经允许不得转载。

所有前端都要看的2D游戏化互动入门基础知识的更多相关文章

  1. XML 新手入门基础知识(复制,留着自己看)

    如果您是 XML 新手,本文将为您介绍 XML 文档的基础结构,以及创建构造良好的 XML 需要遵循的规则,包括命名约定.正确的标记嵌套.属性规则.声明和实体.您还可以从本文了解到 DTD 和 sch ...

  2. web前端学习(三)css学习笔记部分(1)-- css入门基础知识+基本样式

    1.介绍及语法 1.1CSS概述: CSS指层叠样式表 CSS样式表极大地提高了工作效率 如果值大于一个单词,需要加上引号(意思是值只有一个的时候可以不加引号) 1.2CSS高级语法 1.选择器分组 ...

  3. Unity 2D游戏开发教程之精灵的死亡和重生

    Unity 2D游戏开发教程之精灵的死亡和重生 精灵的死亡和重生 目前为止,游戏项目里的精灵只有Idle和Walking这两种状态.也就是说,无论精灵在游戏里做什么,它都不会进入其它的状态,如死亡.于 ...

  4. Unity 2D游戏开发教程之摄像头追踪功能

    Unity 2D游戏开发教程之摄像头追踪功能 上一章,我们创建了一个简单的2D游戏.此游戏中的精灵有3个状态:idle.left和right.这看起来确实很酷!但是仅有的3个状态却限制了精灵的能力,以 ...

  5. Unity 2D游戏开发教程之为游戏场景添加多个地面

    Unity 2D游戏开发教程之为游戏场景添加多个地面 为游戏场景添加多个地面 显然,只有一个地面的游戏场景太小了,根本不够精灵四处活动的.那么,本节就来介绍一种简单的方法,可以为游戏场景添加多个地面. ...

  6. Unity 2D游戏开发高速入门第1章创建一个简单的2D游戏

    Unity 2D游戏开发高速入门第1章创建一个简单的2D游戏 即使是如今,非常多初学游戏开发的同学.在谈到Unity的时候.依旧会觉得Unity仅仅能用于制作3D游戏的. 实际上.Unity在2013 ...

  7. Unity 2D游戏开发教程之2D游戏的运行效果

    Unity 2D游戏开发教程之2D游戏的运行效果 2D游戏的运行效果 本章前前后后使用了很多节的篇幅,到底实现了怎样的一个游戏运行效果呢?或者说,游戏中的精灵会不会如我们所想的那样运行呢?关于这些疑问 ...

  8. Unity 2D游戏开发教程之使用脚本实现游戏逻辑

    Unity 2D游戏开发教程之使用脚本实现游戏逻辑 使用脚本实现游戏逻辑 通过上一节的操作,我们不仅创建了精灵的动画,还设置了动画的过渡条件,最终使得精灵得以按照我们的意愿,进入我们所指定的动画状态. ...

  9. Unity 2D游戏开发教程之游戏精灵的开火状态

    Unity 2D游戏开发教程之游戏精灵的开火状态 精灵的开火状态 “开火”就是发射子弹的意思,在战争类型的电影或者电视剧中,主角们就爱这么说!本节打算为精灵添加发射子弹的能力.因为本游戏在后面会引入敌 ...

  10. Unity 2D游戏开发教程之游戏中精灵的跳跃状态

    Unity 2D游戏开发教程之游戏中精灵的跳跃状态 精灵的跳跃状态 为了让游戏中的精灵有更大的活动范围,上一节为游戏场景添加了多个地面,于是精灵可以从高的地面移动到低的地面处,如图2-14所示.但是却 ...

随机推荐

  1. 学会Promise,看这里!!!

    前言 众所周知,在JavaScript的世界中,代码都是单线程执行的.由于这个原因,JavaScript中的耗时操作,如网络操作.浏览器事件等,都需要异步执行.这也导致在JavaScript中异步操作 ...

  2. 基于Rust的Tile-Based游戏开发杂记(02)ggez绘图实操

    尽管ggez提供了很多相关特性的[demo](ggez/examples at master · ggez/ggez (github.com))供运行查看,但笔者第一次使用的时候还是有很多疑惑不解.经 ...

  3. 专访OV组亚军|30岁的我,如何从码农转CG且获奖?

    "新锐先锋,玩转未来"--首届实时渲染3D动画创作大赛由瑞云科技主办,英伟达.青椒云.3DCAT实时渲染云协办,戴尔科技集团.Reallusion.英迈.万生华态.D5渲染器.中视 ...

  4. 快速上手系列:webservice

    不同公司的系统交互,用webservice可以起到安全的作用. Webservice使用方法如下:   客户端: 这个是要打成jar包,给别人的用的,里面只是接口,没有实现.   用Webservic ...

  5. FPGA之PLD的简单设计

    FPGA之PLD的简单设计 1.实验原理 PLD是可编程逻辑器件的简称,是FPGA的前身(FPGA是在PLD的基础上发展出来的).从PLD设计可以感受早期可编程逻辑器件的特点,了解FPGA在器件层的原 ...

  6. 如在 Java 中分割 Excel 工作表

    前言 在Excel中创建的大多数商业报告不是单页的文档,而是包含了多个上下文相关的信息,这些信息被存储在多个工作表中.例如我们的一些地区销售报告.按部门分类的员工记录.每家店铺的库存清单等. 然而,随 ...

  7. #莫比乌斯函数,Miller-Rabin#洛谷 3653 小清新数学题

    题目 求\(\sum_{i=l}^r\mu(i),r-l\leq 10^5,1\leq l\leq r\leq 10^{18}\) 分析 其实有一道可以算是弱化版的题目 这种类型的tricks就是枚举 ...

  8. protocol buffer没那么难,不信你看这篇

    目录 简介 定义一个消息 类型定义 字段的值 字段描述符 添加注释 嵌套类型 Map 总结 简介 上一篇文章我们对google的protobuf已经有了一个基本的认识,并且能够使用相应的工具生成对应的 ...

  9. Matplotlib绘图设置---颜色条设置

    设置颜色条 对于图形中由彩色的点.线.面构成的连续标签,用颜色条来表示的效果比较好,在Matplotlib中,颜色条是一个独立的坐标轴. 可视图形的颜色选择可参考matplotlib配色方案. Cho ...

  10. Linux之Docker搭建KMS服务器

    前言 在大规模软件部署和管理的过程中,激活授权管理是一项至关重要的任务.微软的KMS(Key Management Service)是一个广泛使用的技术,它使得大型组织能够在本地网络内集中管理Wind ...