当前位置: 首页 > Web前端 > HTML

[Fes]基于canvas的前端动画-游戏入门(一)

时间:2023-04-02 15:59:09 HTML

前言本系列虽然是基础教程,但相对于动画/游戏领域来说,属于前端领域的中级课程。不适合前端初学者或者萌新。在阅读之前,请确保你已经非常熟悉前端三大组件(JavaScript+CSS+HTML)的基础知识,并且具备高中水平的数理知识。demo使用ES6编写,遵循Airbnb规范,不依赖第三方框架或库,请在现代浏览器中运行。大部分例子都来自《Foundation HTML5 Animation with JavaScript》,感谢本书作者的辛勤劳动和启发。本教程也可以看作是本书的精(tian)简(you)优化(jia)(cu)版。既是我个人的读书笔记,也是经验总结,方便工作繁忙没有时间阅读的人。本人能力有限,欢迎大家一起讨论,批评指正。什么是动画/游戏【科普】动画是指以一定的速度(比如16帧/秒)连续播放多帧静止画面的作品,肉眼会误认为画面在运动由于视觉残像的错觉。为了得到动图,每张图片之间都会有细微的变化。制作图片最常见的方法是在纸上或赛璐珞片上手绘,其他方法还有使用粘土、模型、纸偶、沙画等。采用H5技术制作动画的原理与传统动画相同动画片。它利用了“视觉暂留”现象。计算机通过一定的运算规则得到一张图片(像素数据),然后以一定的速度连续播放,形成动画。但也有一些不同。传统动画侧重于绘画技法的表现,即每幅画面都很美,而电脑动画则更关注如何建立计算规则,这也是数学和物理知识的应用。在计算机领域,动画和游戏的界限并不明确。它们之间的区别在于是否有交互性。如果玩家有一定的操作改变动画,再加上一些游戏规则,就可以称之为游戏。[PS]对了,经常有人问为什么电脑玩游戏卡死,看电影不卡?因为所谓的数字版电影,不管是3D动画还是2D动画,都是经过渲染的画面,即数据是一帧画面,电脑只需要改变画面就可以了播放它们。但是游戏的画面是实时计算的。如果电脑性能不好,也就是无法在下一帧完成渲染,画面自然会卡顿。在PC和主机性能低下的时代,预渲染部分游戏画面并放入游戏中也是提升性能的常用做法。H5相关技术概述Canvas【科普】是HTML5中的一个新元素,可以在JS中使用脚本来绘制图形。例如,它可用于绘制图形、制作照片、创建动画,甚至进行实时视频处理或渲染。作为上一代flash的升级换代,简单来说就是浏览器提供了一块画布,你的工作就是用js操作画笔在上面绘图,重复绘图和擦除的工作实现动画。Canvas相关文档用户交互是游戏的基础。H5上的交互无非就是鼠标、触摸和键盘,其实就是DOM标准的事件流。在事件中,我们获取到屏幕上的坐标或者键盘的键码,并进行相应的操作。这不是本教程的重点。如果不了解右转HTML的基础知识,这里就不赘述了。用户交互的示例触摸事件需要浏览器的模拟功能有效;打印内容需要在控制台查看。所有鼠标事件演示鼠标按下坐标获取演示触摸事件演示键盘事件演示键盘上下左右交互模块封装demo将这些交互方法封装起来方便使用,放在工具库utils中。js,这里以同样的方式获取鼠标事件和触摸事件为例。(见下文)utils.captureMouse=functioncaptureMouse(element){constmouse={x:0,y:0,};element.addEventListener('mousemove',(event)=>{letx;lety;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;鼠标。x=x;mouse.y=y;},false);返回鼠标;};动画循环这是代码级别的计算机动画的核心。简单的说就是一个循环调用(continuousrecursion)的过程。每个循环就是一帧画面的生成。实现方法大致可以分为三类。基于帧的动画(requestAnimationFrame)【科普】在视频、电影、电视、数字视频等领域,可以看成是很多张随时间不断变化的图片,一帧就是指每一张图片。一般来说,每秒15帧可以让人的眼睛察觉不到黑暗区间,而25帧则可以感觉流畅。每秒帧数(fps)越多,显示的动作就越流畅。W3C推荐的刷新率是每秒60帧,大多数浏览器都遵循这个标准。requestAnimationFrame是H5新增的功能。它的用法类似于setTimeout。它用于告诉浏览器在下一帧要做什么,比如一个对象每帧应该移动多少。提供优化的基于浏览器的实现,是实现H5动画的首选,所有demo均有使用。至于它优化了什么,下面会提到。requestAnimationFrame文档链接Timer-basedanimation在requestAnimationFrame还没有出现的时代,动画一般用setTimeout和setInterval来实现,也可以用来模拟requestAnimationFrame,设置时间间隔为1000/60毫秒即可,大约为16.7millisecondstoexecute在下一个循环中,当然你也可以定义你需要的帧率来实现游戏中常见的锁帧效果。所谓模拟还有一个意思,就是不能雷同。我们运行在浏览器沙箱中的程序并不知道显卡和显示硬件是否真的在刷新,但是浏览器可以知道,这样浏览器才能真正知道屏幕什么时候会刷新,更好地配合硬件,这就是为什么requestAnimationFrame是比定时器好。基于此我们可以创建一个polyfill并将其放入工具库utils.js中。如果(!window.requestAnimationFrame){window.requestAnimationFrame=(window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.oRequestAnimationFrame||window.msRequestAnimationFrame||函数超时(回调){returnwindow0all0/setTimeout(60);});}特别注意:js中为定时器指定的时间间隔只表示最短时间,不代表准确时间。对于过于复杂,需要超出时间间隔执行的程序,会延迟执行时间。基于时间的动画,无论是requestAnimationFrame还是定时器,都不能保证以特定的速率播放。这意味着复杂动画的播放速度将低于其在性能较差的计算机上播放的设计速度。这在游戏体验上是非常不友好的,所以在游戏中出现了一种常见的“跳帧”方式。其实就是用实时去衡量每个物体的运动变化,而不是依赖每一帧的变化。将物体每帧的移动距离换算成物体每秒的移动距离。由于demo都是简单的动画,所以暂时不用这个操作。计算机中一些数学概念和标准的区别。弧度(radian)和角度(degree)我们每天都在使用更多的角度。应该没有人不知道一个圆圈是360度吧(笑)。但是计算机中不使用角度的概念,而是使用弧度。学校也说了,这里不解释他们的关系,只要明确一个圆是2π弧度就行,两者之间的换算用代码表示:letradians=degrees*Math.PI/180;让度数=弧度*180/Math.PI;坐标系计算机中的坐标系并不是日常生活中使用的标准坐标系。可以说是标准坐标系的倒版。反之亦然。【科普】这个坐标系有一定的历史背景,因为“大屁股”显示器中的电子枪是从左到右,从上到下扫描屏幕的。这个坐标系还导致另一个问题,就是角度的正负值与标准坐标系相反,如下图,顺时针角度为正,逆时针为负。