《每週一點canvas動畫》——速度與加速度(2)

在上一節中咱們介紹了速度的基本概念,包括沿座標軸的速度,和更普適的任意方向的速度,在文章的最後咱們作了一個鼠標跟隨的示例,以及經過改變物體的rotation屬性作了一個關於速度的擴展。經過上一節的學習你會發現咱們的物體能夠沿着任意方向運動,可是這還遠遠不夠,由於咱們的物體都是在作勻速運動
既然有勻速運動,固然就有變速運動嘍!這一節咱們介紹本章的另外一個重要內容加速度。本節將分爲下面幾個部分:canvas

  • 加速度基本概念bash

  • 沿座標軸的加速度編輯器

  • 加速度的合成與分解函數

  • 重力加速度工具

  • 太空船(運用實例)學習

  • 本章總結動畫

1.加速度基本概念

以防有的同窗把物理知識都還給老師了!在這我先廢話的介紹下加速度是什麼,好吧!就一句話,加速度是描述物體速度變化快慢的物理量。咱們知道速度是表徵物體運動快慢的物理量,這裏加速度是來表徵速度的變化的。用物理上的時間/速度圖來表示就是這個樣子:this

圖片描述

從圖中咱們能夠看到,勻速運動的速度是一直保持不變的,而變速運動的速速是隨着時間變化的。如圖所示,這裏展現了一個勻加速運動,在Δt的時間內,速度增長了Δv,那麼加速度用公式就能夠表示爲 a= Δv / Δt。ok!噁心的物理公式就此打住吧!下面咱們來看看在代碼中是如何實現的吧。spa

2.沿座標軸的加速度

在這裏,咱們先介紹沿着座標軸的的加速度,具體代碼以下:prototype

<canvas id="canvas" width="500" height="500" style="background:#000;">
       your browser not support canvas
   </canvas>
   <script src="../js/ball.js"></script> //引入工具函數文件
   <script src="../js/utils.js"></script> //引入球類
   <script>
       window.onload = function(){
           var canvas = document.****getElementById("canvas");
           var context = canvas.getContext("2d");
           
           var ball = new Ball(20);
           ball.x = canvas.width/6;
           ball.y = canvas.height/6;
           
           var vx = 0, ax = 0.1; //定義初始速度vx, 定義加速度a
           (function drawFrame(){
               window.requestAnimationFrame(drawFrame, canvas);
               context.clearRect(0,0,canvas.width,canvas.height);
               
               vx += ax; //速度每一幀都加上加速度的值
               ball.x += vx;
               ball.draw(context);
           }());
       }
    </script>

在上面的代碼中咱們首先,定義了速度和加速度,而後在動畫循環中讓速度每一幀都加上加速度,這樣每一幀速度的值都在增長,球的位置相對來講每一幀就會增長的愈來愈多,反映到動畫中就是運動的愈來愈塊。這裏我要感謝熱心的網友給我推薦的GIF製做工具,讓本文再也不是乾巴巴的文字與圖片。廢話很少說,上圖:

勻速運動
圖片描述

加速運動
圖片描述

爲了效果更加突出,這裏放上了勻速運動的圖片,與加速運動的圖片作了一個對比。在示例代碼中小球的運動方向沿着X軸,固然你也能夠沿着Y軸,或者二者同時。當你同時在X軸和Y軸定義了加速度,你會發現和任意方向的速度同樣,小球會沿着二者合速度的方向移動,這就引出了咱們的下一部分--任意方向的加速度。

3.加速度的合成與分解

有了前一節關於速度的合成與分解的鋪墊,這裏就變得很簡單了,加速度一樣能夠像速度那樣合成分解。這裏咱們假設要讓小球沿着30度的方向作加速度爲0.05的加速運動,具體代碼以下:

window.onload = function(){
           var canvas = document.getElementById("canvas");
           var context = canvas.getContext("2d");
           
           var ball = new Ball(20);
           ball.x = 0;
           ball.y = 0;
           
           var vx = 0, vy = 0, //初始速度爲0
               ax = 0, ay = 0, //分加速度爲0
               angle = 30, //運動方向
               aTotal = 0.05; // 定義加速度的大小
           
           (function drawFrame(){
               window.requestAnimationFrame(drawFrame, canvas);
               context.clearRect(0,0,canvas.width,canvas.height);
               
               //加速度分解
               ax = Math.cos(30 * Math.PI/180)*aTotal;
               ay = Math.sin(30 * Math.PI/180)*aTotal;
               
               vx += ax;
               vy += ay;
         
               ball.x += vx;
               ball.y += vy;
               ball.draw(context);
           }());
       }

具體效果以下圖所示:

圖片描述

與任意方向速度的概念同樣,咱們設定加速度的大小,以及物體運動的方向。而後再動畫循環中,將加速度分解到水平和垂直兩個方向,而後讓水平速度和垂直速度在每一幀都加上相對應的加速度值,咱們就能夠獲得一個沿任意方向加速(減速)運行的小球。

4.重力加速度

在這一部分咱們介紹加速度中比較特別的一個 —— 重力加速度。重力加速度實際上是由兩個物體間的引力造成的,到後面咱們專門會有一個章節來介紹萬有引力,而且將它運用於咱們的動畫之中。

對於這個特殊的加速度,我相信你對它應該不會感到陌生,由於在中學的課本中G這個符號不知道出現了多少次。咱們須要知道的是,在地球上,任何一個物體從空中下落到地面,它都有一個豎直向下的加速度。

ok!代碼時間,咱們的題目是:小球從空中自由降落至地面,而後彈起,循環往復,直到它最終速度爲零停留在地面。好吧!此次咱們先看看模擬出來的效果:

圖片描述

具體代碼以下:

window.onload = function(){
           var canvas = document.getElementById('canvas');
           var context = canvas.getContext('2d');
           
           var ball = new Ball(20, "red");
               ball.x = canvas.width/2
               ball.y = canvas.height/2 - 200;
               
           var vy = 0,  //初始速度
                gravity = 0.2, //定義重力加速度
                bounce = -0.8; //定義反彈係數
                
           //碰撞檢測
           function checkGround(ball){
               if(ball.y + ball.radius > canvas.height){
                   ball.y = canvas.height - ball.radius;
                   vy *= bounce; //速度反向而且減少
               }
           }

           (function drawFramw(){
              window.requestAnimationFrame(drawFramw, canvas);
              context.clearRect(0, 0, canvas.width, canvas.height);
              
              vy += gravity;
              ball.y += vy;
              
              //碰撞檢測
              checkGround(ball);
              ball.draw(context);
           }());
   }

在這段代碼中,除了本章介紹的內容,還包括部分下一章會介紹的內容,可是以大家的聰明才智我相信這徹底是小菜一碟,對吧!咱們在初始化階段定義了在Y軸方向的初始速度vy, 還有重力加速度gravity, 以及一個反彈係數bounce。這裏面咱們作了一個簡單的碰撞檢測,當小球下落到地面(也就是canvas畫布的底部),它的位置爲 canvas.height - ball.radius,而且此時速度反彈,方向向上。而後再循環動畫中調用碰撞檢測函數,這樣就出現了落地反彈的效果,至於爲何會最後停留在地面上,那是由於bounce是個小數,每碰撞一次vy 都會減少。好了,這只是一個簡單的動畫,我就不費嘴皮子了。

5.太空船

在這個實例中咱們要達到的效果是:經過鍵盤上的方向鍵控制太空船朝着不一樣的方向運動。在這裏咱們須要新建一個spaceShip.js類文件,值得注意的是加上該文件你的js文件夾中應該包含了如下四個文件:

  • utils.js

  • arrow.js

  • ball.js

  • ship.js

ship.js文件的代碼以下:

spaceShip.js文件

    function SpaceShip(){
      this.x = 0;
      this.y = 0;
      this.width = 25;
      this.height = 25;
      this.rotation = 0;
      this.showFlame = false;
    }

    SpaceShip.prototype.draw = function(context){
        context.save();
        context.beginPath();
        context.translate(this.x, this.y);
        context.rotate(this.rotation);
        context.strokeStyle = "#ffffff";
        context.moveTo(10, 0);
        context.lineTo(-10, 10);
        context.lineTo(-5, 0);
        context.lineTo(-10, -10);
        context.lineTo(10, 0);
        context.closePath();
        context.stroke();
        if(this.showFlame == true){
            context.save()
            context.beginPath();
            context.strokeStyle = "#f69";
            context.moveTo(-7.5, -5);
            context.lineTo(-15, 0);
            context.lineTo(-7.5, 5);
            context.stroke();
            context.restore();
        }
        context.restore();
    }

效果圖以下:

圖片描述

具體代碼以下:

<canvas id="canvas" width="1000" height="500" style="background:#000;">
       your browser not support canvas
   </canvas>
   <script src="../js/utils.js"></script>
   <script src="../js/spaceship.js"></script>
    <script>
      window.onload = function(){
          var canvas = document.getElementById('canvas'),
              context = canvas.getContext('2d');

          var spaceShip = new SpaceShip();
              spaceShip.x = canvas.width/2;
              spaceShip.y = canvas.height/2;
          
         //初始化
          var vr = 0,
              vx = 0,
              vy = 0,
              ax = 0,
              ay = 0,
              angle = 0,
              thrust = 0;
              
          //經過方向鍵控制各變量的值
          window.addEventListener('keydown',function(event){
              switch (event.keyCode){
                  case 37:    //left
                      vr = -3;
                      vx = 0;
                      vy = 0;
                      break;
                  case 39:  //right
                      vr = 3;
                      vx = 0;
                      vy = 0;
                      break;
                  case 38: //up
                      spaceShip.showFlame = true;
                      thrust = 0.05;
                      break;
                  case 40:
                      ax = 0;
                      ay = 0;
                      vx = 0;
                      vy = 0;
                      break;
              }
          }, false);

          window.addEventListener('keyup', function(event){
               vr = 0;
               thrust = 0;
               spaceShip.showFlame = false;
          }, false);

          (function drawFrame(){
              window.requestAnimationFrame(drawFrame, canvas);
              context.clearRect(0, 0, canvas.width, canvas.height);
              
              //角度
              spaceShip.rotation += vr *Math.PI/180;
              
              angle = spaceShip.rotation;
              ax = Math.cos(angle)*thrust;
              ay = Math.sin(angle)*thrust;
              
              vx += ax;
              vy += ay;
          
              spaceShip.x += vx;
              spaceShip.y += vy;
              
              spaceShip.draw(context);

          }());
      }

好了,看看是否是挺炫的,如今只要經過鍵盤上的方向鍵你就能控制飛船朝任意的一個方向移動。把代碼放到你的編輯器中親手體驗一把吧。雖然咱們的太空船隻是一個簡單的多邊形,可是它能噴火啊!哈哈!

6.總結

本章中要公式總結:

//任意方向速度
vx = speed * Math.cos(angle);
vy = speed * Math.sin(angle);

//任意方向加速度
ax = force * Math.cos(angle);
ay = force * Math.xin(angle);

//改變速度
vx += ax;
vx += ay;

//改變位置
object.x += vx;
object.y += vy;

好吧!到這裏速度與加速度一章就告一段落了,咱們講解了基本的速度與加速度概念,而且結合前面的三角函數實現了不少不一樣的效果。簡單的示例,是否可以勾起你無限的創造力呢?敬請期待下一章——邊界與摩擦力

相關文章
相關標籤/搜索