动画-物体运动需要用到的力

一个正在运动的物体,会有一个速度,且是一个指定方向的速度(速度向量),它可以是匀速或者加速。 除了速度,还可能会有阻力/摩擦力,比如空气的阻力,阻力会让速度逐渐变慢直到物体停止运动。 当物体碰撞到墙壁或者其他物体时,会有一个弹力。 物体由于地球的吸引而受到的力叫重力,它的方向总是竖直朝下的。

速度向量 vx / vy

与速度的区别是,速度向量会有一个方向,就是朝哪个方向运动的速度,在 canvas 的坐标轴里,往左边的速度向量为负数,右边为正数。

// 公式
let vx = 10
let vy = 10

ball.x += vx
ball.y += vy
// 模拟一个物体朝右边匀速运动
let canvas = document.getElementById('canvas')
let ctx = canvas.getContext('2d')
let ball = new Ball()
// 设置速度为每次移动10像素
let vx = 10

ball.x = 0
ball.y = canvas.height / 2

;(function drawFrame() {
  window.requestAnimationFrame(drawFrame)
  ctx.clearRect(0, 0, canvas.width, canvas.height)
  // 每次都加上 vx
  ball.x += vx
  ball.draw(ctx)
}());

加速度 ax / ay

在速度 vx / vy 的基础上每次累加。Demo

// 公式
let ax = 0.5
let ay = 0.5
let vx = 0
let vy = 0
vx += ax
vy += ay
// 模拟一个物体朝右边加速运动
let canvas = document.getElementById('canvas')
let ctx = canvas.getContext('2d')
let ball = new Ball()
// 初始速度为0
let vx = 0
// 加速度为0.5
let ax = 0.5

ball.x = 0
ball.y = canvas.height / 2

;(function drawFrame() {
  window.requestAnimationFrame(drawFrame)
  ctx.clearRect(0, 0, canvas.width, canvas.height)
  // 让速度加上加速度
  vx += ax
  ball.x += vx
  ball.draw(ctx)
}());

阻力/摩擦力 friotion

让速度与摩擦力相乘即可。Demo

// 公式1
let vx = 10
let vy = 10
let friotion = 0.95
vx *= friotion
vy *= friotion

// 公式2
let friotion = 0.1
// 通过勾股定理求速度
let speed = Math.sqrt(vx * vx + vy * vy)
// 获得弧度
let radians = Math.atan2(vy, vx)
// 从速度中减去摩擦力,摩擦力大于速度则速度为0
if (speed < friotion) {
  speed = 0
} else {
  speed -= friotion
}
// 再通过正余弦函数将角速度转换回vx vy
vx = Math.cos(radians) * speed
vy = Math.sin(radians) * speed
// 利用公式1模拟一个物体的摩擦力
let canvas = document.getElementById('canvas')
let ctx = canvas.getContext('2d')
let ball = new Ball()
let vx = 10
let vy = 10
// 摩擦力
let friotion = 0.95

ball.x = canvas.width / 2
ball.y = canvas.height / 2

;(function drawFrame() {
  window.requestAnimationFrame(drawFrame)
  ctx.clearRect(0, 0, canvas.width, canvas.height)
  if (Math.abs(vx) > 0.001) {
    // 速度与摩擦力相乘,因为摩擦力是小数,所以速度会越来越小
    vx *= friotion
    ball.x += vx
  }
  if (Math.abs(vy) > 0.001) {
    // 速度与摩擦力相乘,因为摩擦力是小数,所以速度会越来越小
    vy *= friotion
    ball.y += vy
  }
  ball.draw(ctx)
}());

重力 gravity

让速度 vy 与 gravity 相加。Demo

// 公式
let vy = 0
let gravity = 0.5

vy += gravity

弹力 bounce

让速度与 bounce 相乘。Demo

// 公式
let vx = 10
let vy = 10
// 值为负数
let bounce = -0.5

vx *= bounce
vy *= bounce

利用这些知识,制作《行星》游戏里的宇宙飞船,可以通过方向键控制飞船的移动: Demo