はしくれエンジニアもどきのメモ

情報・Web系技術の勉強メモ・備忘録です。

Canvas で自由落下運動、水平投射運動、斜方投射運動アニメーション

Canvas で自由落下運動、水平投射運動、斜方投射運動アニメーション

Canvas で、 自由落下運動、水平投射運動、斜方投射運動アニメーションを作ったのでメモ。

サンプル

cartman0.github.io

共通の関数

Canvasのid名(canvas_id)、canvasの設定(canvas_config)、運動関数(motionFunc)、運動関数の設定(motion_config)、Canvasの領域をはみ出した際の処理(outside_process)を入力して、Canvas上に描画する。

Canvasのid名(canvas_id)、canvasの設定(canvas_config)、運動関 ...

自由落下運動

motionFunc を入力する運動関数は、自由落下運動なので以下になります。

{\displaystyle y = -\frac{1}{2}gt^{2} }

Canvasの領域をはみ出した際の処理(outside_process)として、 t = 0 に戻している。

自由落下運動のサンプルコード

        
(function(){
  var freeFallAnime = function(canvas_id, canvas_config, motion_config, outside_process){
    motionAnime(canvas_id, canvas_config, freeFall, motion_config, outside_process );

    function freeFall (motion_config){
      var ball_pos = {
        x: motion_config.ball_config.ball_pos0.x,
        y: motion_config.ball_config.ball_pos0.y
      };
      ball_pos.y = motion_config.ball_config.ball_pos0.y - 0.5 * motion_config.g * motion_config.t * motion_config.t;
      return ball_pos;
    }
  }

  freeFallAnime('canvas-free',
    {
      globalAlpha: 0.1,
      fillStyle: 'black'
    },
    {
      ball_config: {
        fillStyle: 'white',
        globalAlpha: 1,
        r: 2,
        ball_pos0: // 初期位置
        {
          x: 150,
          y: canvas.height
        },
        ball_pos:
        {
          x: 0,
          y: 0
        }
      },
      g: 9.8, //重力加速度ss
      interval_s: 0.05, //50 msごとに描画
      t0: 0, //初期時間
      t: 0
    },
    function(canvas, motion_config){
      //ボールが着地したら時間をリセット
      if (motion_config.ball_config.ball_pos.y < 0){
        motion_config.t = 0;
      }
    });
})();
        
      

水平投射運動

自由落下運動に加えて初速度v_{0}が追加されています。 水平投射運動の運動関数は以下です。

{\displaystyle x = v_{0}t \\ y = - \frac{1}{2}gt^{2} }

outside_process では、 x方向にはみ出した場合、 ball_config.ball_pos.x %= canvas.width; で反対側から描画するようにしている。 y方向にはみ出した場合は、自由落下と同じように、 t = 0; として水平投射運動を繰り返す。

水平投射運動のサンプルコード

       

(function(){
  var horizontalProjectionAnime = function(canvas_id, canvas_config, motion_config, outside_process){
    motionAnime(canvas_id, canvas_config, horizontalProjection, motion_config, outside_process);

    function horizontalProjection(motion_config) {
      var ball_pos = {
        x: 0,
        y: 0
      };
      ball_pos.x = motion_config.ball_config.ball_pos0.x + motion_config.v0 * motion_config.t;
      ball_pos.y = motion_config.ball_config.ball_pos0.y - 0.5 * motion_config.g * motion_config.t * motion_config.t;
      return ball_pos;
    }
  };

  horizontalProjectionAnime('canvas-horizon',
    {
      globalAlpha: 0.1,
      fillStyle: 'black'
    },
    {
      ball_config: {
        fillStyle: 'white',
        globalAlpha: 1,
        r: 2,
        ball_pos0: // 初期位置
        {
          x: 0,
          y: 150
        },
        ball_pos:
        {
          x: 0,
          y: 0
        }
      },
      v0: 70,
      g: 9.8, //重力加速度
      interval_s: 0.05, //50 msごとに描画
      t0: 0, //初期時間
      t: 0
    },
    function(canvas, motion_config){
      //ボールが着地したら時間をリセット
      if (motion_config.ball_config.ball_pos.y < 0){
        motion_config.t = 0;
      }
      //ボールが右にはみ出したら左からでてくる
      if (canvas.width < motion_config.ball_config.ball_pos.x){
        motion_config.ball_config.ball_pos.x %= canvas.width;
      }
  });
})();
        
      

斜方投射運動

水平投射運動に加え、角度パラメータが追加されています。 運動関数は以下です。

{\displaystyle x = v_{0}\cos{\theta} \cdot t \\ y = v_{0}\sin{\theta} \cdot t - \frac{1}{2}gt^{2} }

outside_process では、x方向がはみ出した場合、上記の水平投射運動と同じで、反対側から描画する。 y方向がはみ出した場合は、


t = 0;
motion_config.ball_config.ball_pos0.x = motion_config.ball_config.ball_pos.x     

で、時間を初期化し、ボールの初期位置を更新し、
バウンドしているように見せている。

斜方投射運動のサンプルコード

        

(function() {
  var obliqueProjectionAnime = function(canvas_id, canvas_config, motion_config, outside_process){
    motionAnime(canvas_id, canvas_config, obliqueProjection, motion_config, outside_process);

    function obliqueProjection(motion_config) {
      var ball_pos = {
        x: 0,
        y: 0
      };
      ball_pos.x = motion_config.ball_config.ball_pos0.x + motion_config.v0 * Math.cos( motion_config.deg * Math.PI / 180) * motion_config.t;

      ball_pos.y = motion_config.ball_config.ball_pos0.y + motion_config.v0 * Math.sin( motion_config.deg * Math.PI / 180) * motion_config.t - 0.5 * motion_config.g * motion_config.t * motion_config.t;

      return ball_pos;
    }
  };
  obliqueProjectionAnime('canvas',
    {
      globalAlpha: 0.1,
      fillStyle: 'black'
    },
    {
      ball_config: {
        fillStyle: 'white',
        globalAlpha: 1,
        r: 2,
        ball_pos0: // 初期位置
        {
          x: 0,
          y: 0
        },
        ball_pos:
        {
          x: 0,
          y: 0
        }
      },
      v0: 70,
      g: 9.8, //重力加速度
      deg: 40, //打ち出し角度
      interval_s: 0.05, //50 msごとに描画
      t0: 0, //初期時間
      t: 0
    },
    function(canvas, motion_config){
      //ボールが右にはみ出したら左からでてくる
      if (canvas.width < motion_config.ball_config.ball_pos.x)
      {
        motion_config.ball_config.ball_pos.x %= canvas.width;
      }
      // if (canvas.width < motion_config.ball_config.ball_pos0.x)
      // {
      //   motion_config.ball_config.ball_pos0.x -= canvas.width;
      // }

      //ボールが着地したらバウンド
      if (motion_config.ball_config.ball_pos.y < 0) {
        motion_config.t = 0;
        motion_config.ball_config.ball_pos0.x = motion_config.ball_config.ball_pos.x;
      }
    });
  })();