【30分鐘學完】canvas動畫|遊戲基礎(3):速度與加速度

前言

上一篇基本已經對canvas打好了基礎,本篇主要將引入經典物理概念速度和加速度,探討他們在編程動畫中的應用。
在閱讀以前請先自行了解速度和加速度的基礎知識,以及向量與向量加法。
本人能力有限,歡迎牛人共同討論,批評指正。javascript

速度

【科普】速度是描述物體運動快慢和方向的物理量。物理學中提到物體的速度一般是指其瞬時速度。速度在國際單位制中的單位是米每秒,國際符號是m/s,中文符號是米/秒。相對論框架中,物體的速度上限是光速。

在動畫編程中,速度是最基礎的要素,在本系列教程的第2篇講到三角函數時就有所體現。html

動畫編程中的速度

見下圖,咱們這裏要討論的計算機動畫中的速度跟物理學上概念類似,都是矢量,也就是既有大小又有方向,而方向的體現就是其值的正負,回顧系列第1篇中講到的座標系,沿着正半軸運動速度就是正,沿着負半軸運動速度就是負。
另一點不一樣就是單位,不必定會以時間爲單位,多是以幀爲單位,好比「像素/幀」。
也正由於速度是矢量,那任何一個速度均可以分解爲x軸和y軸上的速度,這就是編程動畫基本思想。 java

速度分解圖

實例應用

將系列第2篇的「一個會跟蹤鼠標位置的箭頭」改形成「跟隨鼠標的箭頭」。代碼很基礎,看註釋就行,基本思路:git

  1. 計算目標點與物體的夾角;
  2. 依據夾角分解速度到x軸和y軸;
  3. 分別將每條軸上的速度與物體的位置座標相加。

特別說明,由於這個例子中的動畫循環是基於幀,因此速度單位是像素每幀
完整例子:跟隨鼠標的箭頭github

/**
 * 跟隨鼠標的箭頭
 * */
window.onload = function () {
  const canvas = document.getElementById('canvas');
  const context = canvas.getContext('2d');
  const mouse = utils.captureMouse(canvas);
  const arrow = new Arrow();
  // 設定速度
  const speed = 3;

  (function drawFrame() {
    window.requestAnimationFrame(drawFrame, canvas);
    context.clearRect(0, 0, canvas.width, canvas.height);

    // 計算鼠標與箭頭的相對距離
    const dx = mouse.x - arrow.x;
    const dy = mouse.y - arrow.y;
    // 求箭頭指向鼠標的夾角
    const angle = Math.atan2(dy, dx);
    // 將速度分解到x軸和y軸
    const vx = Math.cos(angle) * speed;
    const vy = Math.sin(angle) * speed;
    // 設置箭頭的角度
    arrow.rotation = angle;
    // 將分解後的速度加到箭頭的兩軸位置上
    arrow.x += vx;
    arrow.y += vy;
    // 從新繪製箭頭
    arrow.draw(context);
  }());
};

加速度

【科普】加速度是物理學中的一個物理量,是一個矢量,主要應用於經典物理當中,通常用字母a表示,在國際單位制中的單位爲米每二次方秒。加速度是速度矢量對於時間的變化率,描述速度的方向和大小變化的快慢。

動畫編程中的加速度

計算機動畫中的加速度就是速度的變化量,跟前面的速度同樣是矢量,也能夠分解爲x軸和y軸上的加速度,方法同上。單位能夠是像素每二次方幀,與「力學」有很大聯繫。
加速度可讓運動更加天然,在計算機動畫中模擬真實運動是必要的基礎。
請明確加速度是速度的變化量,也就是加速度的方向與速度相同即加速,方向相反即減速,若是加速度爲零,速度將恆定,物體作勻速直線運動。spring

實例應用

繼續改造前面的例子跟隨鼠標的箭頭爲「往鼠標方向加速的箭頭」。改造量不大,就是把加速度分解後疊加給速度,基本思路:編程

  1. 計算目標點與物體的夾角;
  2. 將加速度一樣分解到x,y軸上;
  3. 分別將每條軸上的加速度與速度相加;
  4. 再分別將每條軸上的速度與物體的位置座標相加。

完整例子:往鼠標方向加速的箭頭
觀察實例,你會發現這個箭頭雖然運動比前面例子天然了很多,但卻永遠都不會停下,這是因爲這裏的加速度不變的,而現實中因爲摩擦力等因素加速度是會被削減的。canvas

/**
 * 往鼠標方向加速的箭頭
 * */
window.onload = function () {
  const canvas = document.getElementById('canvas');
  const context = canvas.getContext('2d');
  const mouse = utils.captureMouse(canvas);
  const arrow = new Arrow();
  // 初始化速度
  let vx = 0;
  let vy = 0;
  // 設定加速度
  const force = 0.02;

  (function drawFrame() {
    window.requestAnimationFrame(drawFrame, canvas);
    context.clearRect(0, 0, canvas.width, canvas.height);

    // 計算鼠標與箭頭的相對距離
    const dx = mouse.x - arrow.x;
    const dy = mouse.y - arrow.y;
    // 求箭頭指向鼠標的夾角
    const angle = Math.atan2(dy, dx);
    // 將加速度分解到x軸和y軸
    const ax = Math.cos(angle) * force;
    const ay = Math.sin(angle) * force;
    // 設置箭頭的角度
    arrow.rotation = angle;
    // 將分解後的加速度加到箭頭的兩軸速度上
    vx += ax;
    vy += ay;
    // 將分解後的速度加到箭頭的兩軸位置上
    arrow.x += vx;
    arrow.y += vy;
    // 從新繪製箭頭
    arrow.draw(context);
  }());
};

比例運動

這裏會介紹兩個較高級的常見技術,緩動和彈動。
所謂比例運動,就是運動程度與目標點距離是成正比,簡單來講就是「距離越遠,運動程度越大」,這裏的運動程度是指但不侷限於速度和加速度的與運動有關的變量。框架

緩動

緩動是指物體的速度與它到目標點的距離成比例,即基於距離的比例速度,這個比例會影響速度的大小。
緩動的運動特質不止一種,你能夠先快後慢,也能夠先慢後快,還能夠先慢後快再慢等,咱們這裏只以最簡單的先快後慢爲例,即距離越大,速度越大,距離縮進到0,速度也爲0函數

仍是改造前面的跟隨鼠標的箭頭,代碼以下,基本思路:

  1. 肯定一個比例係數,這是一個0~1之間的小數;
  2. 肯定目標點,並計算相對距離;
  3. 計算速度,速度=距離×比例係數;
  4. 用當前位置加上速度來計算新的位置;
  5. 重複第2~4步,直到物體到達目標點。

完整例子:緩動到鼠標位置的箭頭

/**
 * 往鼠標方向緩動的箭頭
 * */
window.onload = function () {
  const canvas = document.getElementById('canvas');
  const context = canvas.getContext('2d');
  const mouse = utils.captureMouse(canvas);
  const arrow = new Arrow();
  // 比例係數
  const easing = 0.05;

  (function drawFrame() {
    window.requestAnimationFrame(drawFrame, canvas);
    context.clearRect(0, 0, canvas.width, canvas.height);

    // 計算鼠標與箭頭的相對距離
    const dx = mouse.x - arrow.x;
    const dy = mouse.y - arrow.y;
    // 求箭頭指向鼠標的夾角
    const angle = Math.atan2(dy, dx);
    // 根據距離緩動
    const vx = dx * easing;
    const vy = dy * easing;
    // 設置箭頭的角度
    arrow.rotation = angle;
    // 將分解後的速度加到箭頭的兩軸位置上
    arrow.x += vx;
    arrow.y += vy;
    // 從新繪製箭頭
    arrow.draw(context);
  }());
};

彈動

彈動是指物體的加速度與它到目標點的距離成比例,即基於距離的比例加速度,這個比例會影響加速度的大小。
彈動會使運動天然且有靈性,你會發現物體會衝過目標點,而後開始回彈,往復。這樣就能模擬出彈簧或橡皮筋的效果。
特別注意,距離爲0時加速度也爲0,但速度不必定爲0。

仍是改造前面的往鼠標方向加速的箭頭,代碼以下,你會發現這個跟前面的加速度例子很像,都是不斷的往復運動,其緣由都是加速度和速度很難同時爲0致使的,這裏咱們加了削減係數讓它停下來,基本思路:

  1. 肯定一個比例係數,這是一個0~1之間的小數;
  2. 肯定目標點,並計算相對距離;
  3. 計算速度,加速度=距離×比例係數;
  4. 用當前速度加上加速度;
  5. 用當前位置加上速度來計算新的位置;
  6. 重複第2~5步。

完整例子:往鼠標方向彈動的箭頭

/**
 * 往鼠標方向彈動的箭頭
 * */
window.onload = function () {
  const canvas = document.getElementById('canvas');
  const context = canvas.getContext('2d');
  const mouse = utils.captureMouse(canvas);
  const arrow = new Arrow();
  // 設定彈動係數
  const spring = 0.02;
  // 初始化速度
  let vx = 0;
  let vy = 0;
  // 削減係數
  const friction = 0.95;

  (function drawFrame() {
    window.requestAnimationFrame(drawFrame, canvas);
    context.clearRect(0, 0, canvas.width, canvas.height);

    // 計算鼠標與箭頭的相對距離
    const dx = mouse.x - arrow.x;
    const dy = mouse.y - arrow.y;
    // 求箭頭指向鼠標的夾角
    const angle = Math.atan2(dy, dx);
    // 根據距離彈動
    const ax = dx * spring;
    const ay = dy * spring;
    // 設置箭頭的角度
    arrow.rotation = angle;
    // 將分解後的加速度加到箭頭的兩軸速度上
    vx += ax;
    vy += ay;
    // 削減速度
    vx *= friction;
    vy *= friction;
    // 將分解後的速度加到箭頭的兩軸位置上
    arrow.x += vx;
    arrow.y += vy;
    // 從新繪製箭頭
    arrow.draw(context);
  }());
};
相關文章
相關標籤/搜索