前言

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

何为动画/游戏

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

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

【PS】顺便一提,常有疑问为什么电脑玩游戏卡,看电影不卡呢?
因为所谓的数字版电影,不论是三维动画还是二维动画,都是已渲染好的画面,也就是数据是一帧帧的图片,而计算机只需要按顺序换图片就能播放。但游戏的画面是实时计算出来的,如果计算机性能不行,也就是无法在下一帧完成渲染,画面自然就会卡顿。在PC和主机性能低下的年代,将部分游戏画面预渲染后放入游戏也是常见的提高性能的做法。

H5相关技术概述

canvas

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

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

用户交互

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

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

  1. utils.captureMouse = function captureMouse(element) {
  2. const mouse = {
  3. x: 0,
  4. y: 0,
  5. };
  6. element.addEventListener('mousemove', (event) => {
  7. let x;
  8. let y;
  9. if (event.pageX || event.pageY) {
  10. x = event.pageX;
  11. y = event.pageY;
  12. } else {
  13. x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft;
  14. y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop;
  15. }
  16. x -= element.offsetLeft;
  17. y -= element.offsetTop;
  18. mouse.x = x;
  19. mouse.y = y;
  20. }, false);
  21. return mouse;
  22. };

动画循环

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

基于帧的动画(requestAnimationFrame)

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

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

基于定时器的动画

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

  1. if (!window.requestAnimationFrame) {
  2. window.requestAnimationFrame = (window.webkitRequestAnimationFrame ||
  3. window.mozRequestAnimationFrame ||
  4. window.oRequestAnimationFrame ||
  5. window.msRequestAnimationFrame ||
  6. function timeout(callback) {
  7. return window.setTimeout(callback, 1000 / 60);
  8. });
  9. }

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

基于时间的动画

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

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

弧度(radian)与角度(degree)

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

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

坐标系

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

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

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

【30分钟学完】canvas动画|游戏基础(1):理论先行的更多相关文章

  1. 【30分钟学完】canvas动画|游戏基础(2):从零开始画画

    前言 上篇主要是理论的概述,本篇会多些实践,来讲讲canvas的基础用法,并包含一些基础三角函数的应用,推荐没有canvas基础的朋友阅读,熟悉的朋友可以跳过. 本人能力有限,欢迎牛人共同讨论,批评指 ...

  2. 【30分钟学完】canvas动画|游戏基础(7):动量守恒与多物体碰撞

    前言 一路沿着本系列教程学习的朋友可能会发现,前面教程中都尽量避免提及质量的概念,很多运动概念也时刻提醒大家这不是真实的物体运动.因为真实的物体运动其实跟质量都是密不可分的,而且质量的引入自然必须提及 ...

  3. 【30分钟学完】canvas动画|游戏基础(4):边界与碰撞

    前言 本系列前几篇中常出现物体跑到画布外的情况,本篇就是为了解决这个问题. 阅读本篇前请先打好前面的基础. 本人能力有限,欢迎牛人共同讨论,批评指正. 越界检测 假定物体是个圆形,如图其圆心坐标即是物 ...

  4. 【30分钟学完】canvas动画|游戏基础(6):坐标旋转探究

    前言 本篇主要讲坐标旋转及其应用,这是编程动画必不可少的技术. 阅读本篇前请先打好前面的基础. 本人能力有限,欢迎牛人共同讨论,批评指正. 坐标旋转 模拟场景:已知一个中心点(centerX,cent ...

  5. 【30分钟学完】canvas动画|游戏基础(extra1):颜色那些事

    前言 本篇主要讲解关于计算机颜色系统的概念,后续结合一些canvas的应用.因为是"你不知道也没关系"的边缘知识,所以作为本系列教程的扩展,没有兴趣的同学可以跳过. 开始我们万紫千 ...

  6. 【30分钟学完】canvas动画|游戏基础(extra1-1):美图我也行

    前言 本文是接续系列教程的extra1,主要是介绍颜色系统在canvas中的应用. 本来是与extra1一起成文的,因为segmentfault莫名其妙的字数限制bug只能分割放送了. canvas操 ...

  7. 【30分钟学完】canvas动画|游戏基础(5):重力加速度与模拟摩擦力

    前言 解决运动和碰撞问题后,我们为了让运动环境更加自然,需要加入一些环境因子,比如常见的重力加速度和模拟摩擦力. 阅读本篇前请先打好前面的基础. 本人能力有限,欢迎牛人共同讨论,批评指正. 重力加速度 ...

  8. 30分钟学玩转RabbitMQ

    最近在学习RabbitMQ,在网上找了不少资料发现都特高端.动辄集群部署,分布式架构什么的,对于一个初学者实在不够友好.心想求人不如求自己,为什么不自己整理一套资料呢?于是<30分钟学玩转Rab ...

  9. 3分钟学完Python,直接从入门到精通

    作为帅气小编,我已经把python一些模块的甩在这儿了qwq,只要你拿到这些干货,包你玩转python,直接冲向"大佬"的段位,如果已经学了C或者C++或者说如果你需要你的一段关键 ...

随机推荐

  1. Eureka 源码分析之 Eureka Server

    文章首发于公众号<程序员果果> 地址 : https://mp.weixin.qq.com/s/FfJrAGQuHyVrsedtbr0Ihw 简介 上一篇文章<Eureka 源码分析 ...

  2. FastDFS分布式文件服务器

    5.分布式文件服务器FastDFS(阿里巴巴) 5.1什么是FastDFS FastDFS 是用 c 语言编写的一款开源的分布式文件系统.FastDFS 为互联网量身定制,充分考虑了冗余备份.负载均衡 ...

  3. [多校联考2019(Round 5 T2)]蓝精灵的请求(二分图染色+背包)

    [多校联考2019(Round 5)]蓝精灵的请求(二分图染色+背包) 题面 在山的那边海的那边住着 n 个蓝精灵,这 n 个蓝精灵之间有 m 对好友关系,现在蓝精灵们想要玩一个团队竞技游戏,需要分为 ...

  4. Scrapy 教程(四)-命令

    scrapy 没有界面,需要命令行来操作. 非常简单,总共也就十四五个命令,分为全局命令和项目命令. 全局命令 在哪都能用 常用命令 scrapy startproject name 创建项目/工程 ...

  5. linux 环境 Xshell操作数据库

    一:采用sqlplus连接登录(确保安装了sqlplus) 1:先登陆进入到oracle的数据库的服务器环境下 2:切换到sqlplus操作:  sqlplus /nolog 3:conn /as s ...

  6. spring boot配置分页插件

    在springboot中使用PageHelper插件有两种较为相似的方式,接下来我就将这两种方式进行总结. 方式一:使用原生的PageHelper 1.在pom.xml中引入依赖 <depend ...

  7. 使用mysql的source批量导入多个sql文件

    需求: 有一个文件,文件里面包含100多个sql文件,想要把这些sql文件都导入到mysql中 做法: 使用 mysql 的 source 可以将文件导入到 mysql 中,但是一次只能导入一个 sq ...

  8. C++实现简单的日志记录

    C++实现简单的日志记录 //dlogger.h #ifndef DLOGGER_H #define DLOGGER_H #include <iostream> #include < ...

  9. Java web项目搭建系列之二 Jetty下运行项目

    在项目pom.xml文件中添加Jetty运行配置 在pom.xml文件project节点下插入如下代码: <build> <plugins> <plugin> &l ...

  10. Zabbix--05 Grafana、percona、自动发现和自动注册

    目录 一. Grafana自定义图形 1.安装grafana 2.安装并激活zabbix插件 3.数据展示 4.自定义图形仪表盘 5.自定义图形饼图 二. percona模版监控mysql 1.安装p ...