JavaScript+Canvasで自由落下、放物運動の物理シミュレーションを作る

自由落下運動のシミュレート

ボールに見立てた円図形をJavaScriptで書いてみる。最初は上下だけの自由落下運動。手に握った野球の球を放し、地面に落とすイメージ。

まず、簡単なHTMLファイルを用意。

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset=UTF-8">
<title>自由落下運動と放物運動のシミュレート</title>
</head>
<body>
<canvas id="canvas"></canvas>

<script type="text/javascript" src="./main.js"></script>
</body>
</html>

次に、ボールのスクリプト部分が以下。

class Main {
	constructor() {
		this._canvas;
		this._context;
		this._timer;

		// ①各パラメータ
		this._v = 0.0;	// 初速度
		this._y = 15;	// ボールの中心
		this._a = 9.8;	// 重力(加速度)
		this._t = 0.2;	// 時間
		this._e = -0.8;	// 反発係数

		this._init();
	}

	_init() {
		this._canvas = document.getElementById("canvas");
		this._canvas.width = 200;
		this._canvas.height = 500;
		this._context = this._canvas.getContext("2d");

		// ②タイマーを開始し、_darw()を20ミリ秒間隔で呼び出し
		this._timer = setInterval(this._draw.bind(this), 20);
	}

	_draw() {
		// ③速度と位置を更新
		this._v = this._v + this._a + this._t;
		this._y = this._y + this._v * this._t + 0.5 * this._a * this._t * this._t;

		// ④地面との衝突処理
		if (this._y > this._canvas.height - 15) {
			this._y = this._canvas.height - 15;
			this._v = this._v * this._e;
		}

		// ⑤キャンバスを白紙に戻す
		this._context.fillStyle = "rgba(255, 255, 255, 0.2)";
		this._context.rect(0, 0, 200, 500);
		this._context.fill();

		// ⑥ボールの描画処理
		this._context.beginPath();
		this._context.fillStyle = "#000000";
		this._context.arc(100, this._y, 15, 0, 360 * Math.PI / 180);
		this._context.fill();
	}
}

let run = new Main();

①、必要となる物理のパラメータ。反発係数はボールが地面に衝突した時のバウンドの力。

②、setInterval()で画面更新を担当する_draw()を、20ミリ秒で呼び出すよう設定。

③、落下による時間経過と共に変化するボールの速度、位置を計算している。加速と位置を計算する式は以下。

vやyの0は運動を観察し始めた時という意味。

④、ボールがキャンバスの最下部に到達したら、速度に反発係数をかけバウンドさせる。

⑤、ボールを再描画する直前にキャンバスを白紙に戻す。そうしないと以前描画したボールが残るため。アルファ値を0.2に設定してボールの軌跡が見えるようにした。

⑥、計算したy座標を元に、arc()で円を描画。

放物運動をシミュレート

次に、自由落下運動にx軸方向の動きを加えた放物運動をシミュレートしてみる。HTMLファイルは同じものを使用。

class Main {
	constructor() {
		this._canvas;
		this._context;
		this._timer;

		// ①各パラメータ
		this._vx, this._vy;	// 初速度
		this._x, this._y;	// ボールの中心
		this._a = 9.8;		// 重力(加速度)
		this._t = 0.2;		// 時間
		this._e = -0.8;		// 反発係数

		this._init();
	}

	_init() {
		this._canvas = document.getElementById("canvas");
		this._canvas.width = 600;
		this._canvas.height = 400;
		this._context = this._canvas.getContext("2d");

		// ②ボールの初速度の設定
		this._vx = 3;
		this._vy = -100;

		// ③ボールの初期位置の設定
		this._x = 0;
		this._y = this._canvas.height;

		// 最初のボールを描画
		//this._context.arc(this._x, this._y, 10, 0, 360 * Math.PI / 180);

		this._timer = setInterval(this._draw.bind(this), 20);
	}

	_draw() {
		// ④x方向の等速度運動
		this._x = this._x + this._vx;
		this._vy = this._vy + this._a * this._t;
		this._y = this._y + this._vy * this._t + 0.5 * this._a * this._t * this._t;

		if (this._y > this._canvas.height - 15) {
			this._y = this._canvas.height - 15;
			this._vy = this._vy * this._e;
		}

		this._context.fillStyle = "rgba(255, 255, 255, 0.2)";
		this._context.rect(0, 0, 600, 400);
		this._context.fill();

		this._context.beginPath();
		this._context.fillStyle = "#000000";
		this._context.arc(this._x, this._y, 15, 0, 360 * Math.PI / 180);
		this._context.fill();
	}
}

let run = new Main();

①、放物運動は横移動もあるため、速度をvを_vx、_vyの2つにする。

②、x、y軸方向の初速度を設定。_vx値が大きいほど右へ、_vy値が大きいほど上へ上がる。

③、キャンバスの左下隅にボールを配置。

④、自由落下運動ではy軸方向だけ計算したが、今回はx軸方向も計算する。ボールが横に動く運動は一定の速度にしている。こういった動きを等速度運動という。時間tにおけるx軸方向のボール位置は以下の式で求められる。

今回、x軸方向は等速度運動のため、_vxに時間は掛けていない。

コメント

タイトルとURLをコピーしました