【30分钟学完】canvas动画|游戏基础(1):理论先行

前言

本文虽然说是基础教程,但这是相对动画/游戏领域来讲,在前端领域算是中级教程了,不适合前端小白或萌新。阅读前请确保本身对前端三大件(JavaScript+CSS+HTML)的基础已经十分熟悉,并且有高中水平的数学和物理知识。demo采用ES6编写,遵循Airbnb规范,不依赖第三方框架或库,请在现代浏览器里运行。
大部分例子来自《Foundation HTML5 Animation with JavaScript》,感谢这本书做者的辛劳和启发。本教程也能够算是该书的精(tian)简(you)优(jia)化(cu)版,既是个人我的读书笔记,也是经验总结,方便没空看书的忙人阅读。
本人能力有限,欢迎牛人共同讨论,批评指正。javascript

何为动画/游戏

【科普】动画是指由许多帧静止的画面,以必定的速度(如每秒16张)连续播放时,肉眼因视觉残象产生错觉,而误觉得画面活动的做品。为了获得活动的画面,每一个画面之间都会有细微的改变。而画面的制做方式,最多见的是手绘在纸张或赛璐珞片上,其它的方式还包含了运用黏土、模型、纸偶、沙画等。

使用H5技术实现动画原理跟传统动画是同样的,都是利用“视觉暂留”现象,计算机经过必定的规则运算获得一个画面(像素数据),而后以必定速度连续播放就造成动画。但也有些许不一样,传统动画的重点是绘画技法的表现,也就是每张图画得漂亮,而计算机动画更关心的是如何确立运算规则,这也是数学和物理知识的运用。
在计算机领域,动画和游戏界限并不明显,他们的差异就是是否有交互性,若是玩家有必定的改变更画的操做,再加上一些游戏规则,那就能够称得上是游戏了。html

【PS】顺便一提,常有疑问为何电脑玩游戏卡,看电影不卡呢?
由于所谓的数字版电影,不管是三维动画仍是二维动画,都是已渲染好的画面,也就是数据是一帧帧的图片,而计算机只须要按顺序换图片就能播放。但游戏的画面是实时计算出来的,若是计算机性能不行,也就是没法在下一帧完成渲染,画面天然就会卡顿。在PC和主机性能低下的年代,将部分游戏画面预渲染后放入游戏也是常见的提升性能的作法。

H5相关技术概述

canvas

【科普】 <canvas> 是 HTML5 新增的元素,可用于经过使用JavaScript中的脚原本绘制图形。例如,它能够用于绘制图形,制做照片,建立动画,甚至能够进行实时视频处理或渲染。

做为上世代flash的升级替代品,简单来讲就是浏览器提供一个画布,你的工做就是用js操做画笔在上面画画,不断重复画画和擦除的工做,就能够实现动画。
canvas相关文档前端

用户交互

交互是游戏的根本,H5上的交互不外乎鼠标、触摸和键盘这几种,其实就是DOM标准的事件流。咱们在事件中拿到屏幕上的坐标或键盘的键位代号,执行相应的操做。这不是本教程重点,不懂的右转HTML相关基础,这里就不细说了。
这里有些简单例子,能够在控制台看到效果:java

demo中为了方便使用封装了这些交互方法,放在工具库utils.js里,这里以获取鼠标事件,触摸事件同理为例。git

utils.captureMouse = function captureMouse(element) {
  const mouse = {
    x: 0,
    y: 0,
  };
  element.addEventListener('mousemove', (event) => {
    let x;
    let y;
    if (event.pageX || event.pageY) {
      x = event.pageX;
      y = event.pageY;
    } else {
      x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
      y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
    }
    x -= element.offsetLeft;
    y -= element.offsetTop;

    mouse.x = x;
    mouse.y = y;
  }, false);

  return mouse;
};

动画循环

这是计算机动画在代码层面的核心,简单来讲就是一个循环调用(不断递归)的过程,每次循环都是一帧画面的产生,实现方式大致能够概括为三类。github

基于帧的动画(requestAnimationFrame)

【科普】在视频领域,电影、电视、数字视频等可视为随时间连续变换的许多张画面,而帧是指每一张画面。

通常来讲1秒15帧就可以让人眼不发觉黑暗的间隔,25帧就可感受流畅,每秒钟帧数 (fps) 愈多,所显示的动做就会愈流畅。W3C所建议的刷新率是1秒60帧,大部分浏览器是遵循这一标准的。
requestAnimationFrame是H5加入的函数,用法相似于setTimeout,用于告诉浏览器下一帧的时候该干什么,好比一个物体每1帧要移动多少距离。它提供基于浏览器的优化实现,是实现H5动画的首选,全部demo都有使用。至于它优化了什么,下面会提到。
requestAnimationFrame文档连接web

基于定时器的动画

在requestAnimationFrame还未出现的时代,通常是用setTimeout和setInterval实现动画,也可使用他们模拟requestAnimationFrame,只需把时间间隔设为1000/60毫秒,也就是大约16.7毫秒执行下一个循环,固然你也能够定义本身须要的帧率,达到游戏中常见的锁帧效果。
所谓模拟,另外一层意思就是不可能相同,咱们的程序在浏览器沙盒中运行是不知道显卡和显示器硬件实际是否在刷新的,但浏览器是能够知道的,因此浏览器才能够真正的知道何时屏幕会刷新,更好的配合硬件工做,这也是requestAnimationFrame优于定时器的缘由。
基于此咱们能够创造一个polyfill放到工具库utils.js里。canvas

if (!window.requestAnimationFrame) {
  window.requestAnimationFrame = (window.webkitRequestAnimationFrame ||
    window.mozRequestAnimationFrame ||
    window.oRequestAnimationFrame ||
    window.msRequestAnimationFrame ||
    function timeout(callback) {
      return window.setTimeout(callback, 1000 / 60);
    });
}

特别注意:js中给定时器规定的时间间隔仅仅表示最少的时间,而非确切的时间,对于过复杂须要超过期间间隔才执行完的程序,执行时间就会被延后。浏览器

基于时间的动画

其实不管是requestAnimationFrame仍是定时器,都不能保证以特定速率播放。也就是说复杂的动画在性能较差的计算机上播放,会比它设计速度慢。这个在游戏的体验上是十分不友好的,因此就有了游戏里常见的跳帧作法。
其实就是使用真实的时间来度量每一个物体的运动变化,而不是依靠每帧的变化。将物体每帧移动距离,转变为物体每秒移动距离。
因为demo都是简单动画,因此暂时不会使用这个操做。框架

计算机中一些数学概念与标准的差别

弧度(radian)与角度(degree)

平常咱们使用角度会比较多,应该没有人不知道一个圆是360度吧(笑)。但计算机中不使用角度概念而是使用弧度。学校也有说过,这里就不讲解他们的关系了,只要明确一圆周是2π弧度,二者的转换用代码表示就是:

let radians = degrees * Math.PI / 180;
let degrees = radians * 180 / Math.PI;

坐标系

计算机里的坐标系也不是平常使用的标准坐标系,能够说是标准坐标系的颠倒版本,以下图,越往右x轴值越大,越往下y轴值越大,反之亦然。

【科普】这个坐标系有必定的历史背景,由于“大屁股”显示器里的电子枪是从左往右,从上往下扫描屏幕的。

坐标系

这个坐标系还致使了另外一个问题,就是角度的正负值是与标准坐标系相反的,以下图,顺时针角度才是正值,逆时针为负值。

角度

相关文章
相关标签/搜索