【30分钟学完】canvas动画|游戏基础(5):重力加速度与模拟摩擦力
前言
解决运动和碰撞问题后,我们为了让运动环境更加自然,需要加入一些环境因子,比如常见的重力加速度和模拟摩擦力。
阅读本篇前请先打好前面的基础。
本人能力有限,欢迎牛人共同讨论,批评指正。
重力加速度
【科普】重力加速度是一个物体受重力作用的情况下所具有的加速度。也叫自由落体加速度,用g表示。方向竖直向下。通常指地面附近物体受地球引力作用在真空中下落的加速度,记为g。为了便于计算,其近似标准值通常取为980厘米/秒的二次方或9.8米/秒的二次方。
真实的物体是有质量的,所以其重力加速度是由于重力产生,而我们计算机中的抽象物体并没有质量,所有也不存在重力一说,我们这里说的重力加速度只是借用了物理上的概念,实际上是人为定义的一个方向指向y轴正半轴的加速度。
其实实现起来很简单,就是设定一个为正的加速度,每次绘制都加到物体的y轴速度上。
下面的示例是一个ball,它会受重力加速度gravity而自动下落,你可以使用键盘的上、下、左、右改变其四个方向上的加速度。核心代码如下:
完整示例:重力加速度演示
(function drawFrame() {
window.requestAnimationFrame(drawFrame, canvas);
context.clearRect(0, 0, canvas.width, canvas.height);
vx += ax;
vy += ay;
vy += gravity;
ball.x += vx;
ball.y += vy;
ball.draw(context);
}());
模拟摩擦力
【科普】阻碍物体相对运动(或相对运动趋势)的力叫做摩擦力。摩擦力的方向与物体相对运动(或相对运动趋势)的方向相反。一个物体在另一个物体表面发生滑动时,接触面间产生阻碍它们相对运动的摩擦,称为滑动摩擦。滑动摩擦力的大小与接触面的粗糙程度的大小和压力大小有关。压力越大,物体接触面越粗糙,产生的滑动摩擦力就越大。
之前的例子中有一些非常不自然的场景,比如跟随鼠标的箭头,由于加速度始终存在,导致运动永远不可能停止,而在现实中(太空例外),由于存在各种摩擦力的关系,这是不可能发生的情况。
计算机中没有摩擦力,我们只是借鉴物理中的概念模拟一个模拟摩擦力,请记住这个并不是物理意义的力。
【定义】模拟摩擦力是人为规定的值,定义和滑动摩擦力相似都与运动方向相反的量,将物体速度削减到0为止,不会改变运动方向。
注意:根据定义只能将物体的速率减去与一定大小的值,而不能分别在x, y轴上减小速度向量。如果物体正沿着某个角度运动,就会出现物体在某条轴的速度降为零,而继续在另一条轴上运动的奇怪现象。
正确做法
我们将模拟摩擦力用变量friction表示,示例会演示随机速度的ball从运动到停止的过程,核心代码如下,基本思路:
【科普】速度和速率是两个不同的概念。速度是矢量,具有大小和方向;速率则纯粹指物体运动的快慢,是标量,没有方向。
- 将vx与vy平方后求和,再开方求出速率;通过计算Math.atan2(vy, vx)获得角度;
- 从速率减去模拟摩擦力,但不要让速率变为负数;
- 通过正余弦函数将和速率分解为x轴和y轴上的速度。
完整示例:模拟摩擦力正确计算
(function drawFrame() {
window.requestAnimationFrame(drawFrame, canvas);
context.clearRect(0, 0, canvas.width, canvas.height);
// 先求速率
let speed = Math.sqrt(vx ** 2 + vy ** 2);
// 算出角度
const angle = Math.atan2(vy, vx);
// 判断运动是否停止
if (speed > friction) {
// 没有停止则减去模拟摩擦力
speed -= friction;
} else {
speed = 0;
}
// 重新分解为x轴和y轴上的速度
vx = Math.cos(angle) * speed;
vy = Math.sin(angle) * speed;
ball.x += vx;
ball.y += vy;
ball.draw(context);
}());
简便做法
正确的做法十分繁琐,是个合成分解再合成的过程,这样对计算资源的消耗是比较大的,但我们也许并不需要这么精确的做法,只要每次将各个方向的速度乘以一个0~1之间的数就能简单模拟出摩擦力的效果。因此我们定义了模拟摩擦力系数。
【定义】模拟摩擦力系数是人为规定的值,会在物体运动时不断比例减少各个方向上的速度,使各个方向的速度无限接近于0。
示例由上面的正确做法改造而来,friction被定义为模拟摩擦力系数,指为0.9,只要运动都将x轴和y轴方向的速度乘以这个值即可,减少了大量操作。核心代码如下:
完整示例:模拟摩擦力正确计算
注意:这里有一个细节,速度不断乘以系数会导致速度无限接近但不等于0,为了避免做无意义的计算,可以先判断速度是否已经小到肉眼不可见的值,以提高性能。
(function drawFrame() {
window.requestAnimationFrame(drawFrame, canvas);
context.clearRect(0, 0, canvas.width, canvas.height);
// 判断速度大小以减少不必要的计算
if (Math.abs(vx) > 0.001) {
// 减少速度
vx *= friction;
ball.x += vx;
}
if (Math.abs(vy) > 0.001) {
vy *= friction;
ball.y += vy;
}
ball.draw(context);
}());
回顾前面的示例
【30分钟学完】canvas动画|游戏基础(5):重力加速度与模拟摩擦力的更多相关文章
- 【30分钟学完】canvas动画|游戏基础(2):从零开始画画
前言 上篇主要是理论的概述,本篇会多些实践,来讲讲canvas的基础用法,并包含一些基础三角函数的应用,推荐没有canvas基础的朋友阅读,熟悉的朋友可以跳过. 本人能力有限,欢迎牛人共同讨论,批评指 ...
- 【30分钟学完】canvas动画|游戏基础(1):理论先行
前言 本文虽说是基础教程,但这是相对动画/游戏领域来说,在前端领域算是中级教程了,不适合前端小白或萌新.阅读前请确保自己对前端三大件(JavaScript+CSS+HTML)的基础已经十分熟悉,而且有 ...
- 【30分钟学完】canvas动画|游戏基础(7):动量守恒与多物体碰撞
前言 一路沿着本系列教程学习的朋友可能会发现,前面教程中都尽量避免提及质量的概念,很多运动概念也时刻提醒大家这不是真实的物体运动.因为真实的物体运动其实跟质量都是密不可分的,而且质量的引入自然必须提及 ...
- 【30分钟学完】canvas动画|游戏基础(4):边界与碰撞
前言 本系列前几篇中常出现物体跑到画布外的情况,本篇就是为了解决这个问题. 阅读本篇前请先打好前面的基础. 本人能力有限,欢迎牛人共同讨论,批评指正. 越界检测 假定物体是个圆形,如图其圆心坐标即是物 ...
- 【30分钟学完】canvas动画|游戏基础(6):坐标旋转探究
前言 本篇主要讲坐标旋转及其应用,这是编程动画必不可少的技术. 阅读本篇前请先打好前面的基础. 本人能力有限,欢迎牛人共同讨论,批评指正. 坐标旋转 模拟场景:已知一个中心点(centerX,cent ...
- 【30分钟学完】canvas动画|游戏基础(extra1):颜色那些事
前言 本篇主要讲解关于计算机颜色系统的概念,后续结合一些canvas的应用.因为是"你不知道也没关系"的边缘知识,所以作为本系列教程的扩展,没有兴趣的同学可以跳过. 开始我们万紫千 ...
- 【30分钟学完】canvas动画|游戏基础(extra1-1):美图我也行
前言 本文是接续系列教程的extra1,主要是介绍颜色系统在canvas中的应用. 本来是与extra1一起成文的,因为segmentfault莫名其妙的字数限制bug只能分割放送了. canvas操 ...
- 30分钟学玩转RabbitMQ
最近在学习RabbitMQ,在网上找了不少资料发现都特高端.动辄集群部署,分布式架构什么的,对于一个初学者实在不够友好.心想求人不如求自己,为什么不自己整理一套资料呢?于是<30分钟学玩转Rab ...
- 3分钟学完Python,直接从入门到精通
作为帅气小编,我已经把python一些模块的甩在这儿了qwq,只要你拿到这些干货,包你玩转python,直接冲向"大佬"的段位,如果已经学了C或者C++或者说如果你需要你的一段关键 ...
随机推荐
- [LC] 451. Sort Characters By Frequency
Given a string, sort it in decreasing order based on the frequency of characters. Example 1: Input: ...
- 吴裕雄--天生自然C语言开发:指针
#include <stdio.h> int main () { int var1; ]; printf("var1 变量的地址: %p\n", &var1 ) ...
- centos设置上网代理
假设我们要设置代理为 IP:PORT 1.网页上网网页上网设置代理很简单,在firefox浏览器下 Edit-->>Preferences-->>Advanced-->& ...
- Vscode 下 PlantUML 插件的安装(windows and ubuntu)
目录 Windows 下安装 JAVA 安装环境配置: 测试 Ubuntu 16.04 下安装 Windows 下安装 Vscode graphviz PlantUML JAVA(推荐长期稳定版本,官 ...
- rest framework-认证&权限&限制-长期维护
############### 自定义token认证 ############### 表 class User(models.Model): name=models.CharField(ma ...
- OpenCV 亚像素级的角点检测
#include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc.hpp" #i ...
- Redis为什么会比MySQL快?
1.Redis是基于内存存储的,MySQL是基于磁盘存储的 2.Redis存储的是k-v格式的数据.时间复杂度是O(1),常数阶,而MySQL引擎的底层实现是B+Tree,时间复杂度是O(logn), ...
- python3下scrapy爬虫(第六卷:利用cookie模拟登陆抓取个人中心页面)
之前我们爬取的都是那些无需登录就要可以使用的网站但是当我们想爬取自己或他人的个人中心时就需要做登录,一般进入登录页面有两种 ,一个是独立页面登陆,另一个是弹窗,我们先不管验证码登陆的问题 ,现在试一下 ...
- window server 2012+apache+django
一.apache下载安装 https://www.apachelounge.com/download/VC10/ ***注意*** 本人用的是window server 2012 64位版本云服务器, ...
- webpack中使用ECharts
npm安装ECharts 引入ECharts 通过 npm 上安装的 ECharts 和 zrender 会放在node_modules目录下.可以直接在项目代码中 require('echarts' ...