ニュートンの運動方程式は物体の動きを理解するための基本的な原理で、これをProcessingで実装することで、物理に基づくリアルなアニメーションやシミュレーションを作成できます。この記事ではニュートンの運動方程式を利用して、運動のシミュレーションを実装する方法を解説します。
※ニュートンの運動方程式に関する物理学的に詳しい解説は物理学の教科書などを参考にしてください。
目次
ニュートンの運動方程式のコード
ニュートンの運動方程式
ニュートンの第二法則に基づく運動方程式は以下のように表されます。
F=ma
ここで、Fは力、mは質量、aは加速度です。この方程式に基づいて、Processingで物体の運動をシミュレートします。
Processingにおける実装
以下のステップでニュートンの運動方程式を基にしたシミュレーションを実装します。
- 変数の設定
- 質量
m
- 位置
position
- 速度
velocity
- 加速度
acceleration
- 質量
- 力の計算と運動の更新
- 力のベクトルを用いて加速度を計算
- 加速度を用いて速度を更新
- 速度を用いて位置を更新
コード例
以下は、上記の原理に基づくProcessingのコード例です。
画面下方向(Processingではyの正の方向)に重力が働いて円が落下していくシミュレーションを作ってみます。
float m = 10.0; // 円の質量
PVector position = new PVector(400, 0); // 円の初期位置
PVector velocity = new PVector(0, 0); // 円の初期速度
PVector acceleration = new PVector(0, 0); // 円の初期加速度
void setup() {
size(800, 600);
}
void draw() {
background(255);
// 力を計算(この例では重力のみ)
PVector force = new PVector(0, 1); // F = maにおけるFを(0, 1)と下向きに一定の力が働いているように定義
// 力から加速度を計算
acceleration = PVector.div(force, m); // F=maを変形して、a=F/mとし、aを求めた
// 速度と位置を更新
velocity.add(acceleration); //加速度を速度に加えて速度を更新
position.add(velocity); //位置に速度を加えて、位置を更新
// 地面に到達したら反射
if (position.y > height) {
position.y = height; // 位置を修正
velocity.y *= -0.9; // 反射と同時にエネルギー損失
}
// オブジェクトの描画
ellipse(position.x, position.y, 20, 20);
}
※実行すると円が重量に引かれて落下し、画面下端でバウンドします
このコードは、質量m
の物体が重力の影響を受けて落下し、地面に到達した際に反射するシミュレーションを表現しています。これは基本的な例ですが、これを基に様々な力や物体を加えて、より複雑なシミュレーションを作成できます。
多数のオブジェクトにニュートンの運動方程式を実装する方法
先ほどのコード例では1つの円の動きをシミュレートしましたが、複数(例えば100個のボール)の物体の動きをシミュレートしようとした場合にはクラスとクラスの配列(またはArrayList)を用いることでシンプルに記述することができます。具体例で解説します。
またニュートンの運動方程式が適用できるクラスを作っておくことで、今後ニュートンの運動方程式に従って動かしたいクラスの元となるクラスが実装できたことになります。
Step.1 Moverクラスを作る
円の代わりに、Moverというクラスを定義します。Moverクラスは先ほどの円を描画するときに用意したものと同様の変数(属性)と処理(位置や速度の更新などのメソッド)を持つものになります。
class Mover {
PVector position; //位置ベクトル
PVector velocity; //速度ベクトル
PVector acceleration; //加速度ベクトル
float m; // 質量
Mover(float x, float y, float mass) {
position = new PVector(x, y);
velocity = new PVector(random(-5, 5), 0);
acceleration = new PVector(0, 0);
m = mass;
}
void applyForce(PVector force) {
PVector a = PVector.div(force, m); // 力から加速度を計算: a = F/m
acceleration.add(a); // 加速度に力の影響を加える
}
void update() { // 情報の更新を1つの関数にまとめる
velocity.add(acceleration); // 速度を加速度で更新
position.add(velocity); // 位置を速度で更新
acceleration.mult(0); // 加速度をリセット
bounce(); //画面の端だった場合の処理をまとめた関数
}
void display() {
fill(127);
stroke(0);
ellipse(position.x, position.y, m*2, m*2); // 質量に基づいて大きさを設定
}
void bounce() {
// 地面に到達したら反射
if (position.y > height) {
position.y = height; // 位置を修正
velocity.y *= -0.9; // 反射と同時にエネルギー損失
}
// 画面両端に到達したら反射
if (position.x > width) {
position.x = width;
velocity.x *= -0.9;
}
if (position.x < 0) {
position.x = 0;
velocity.x *= -0.9;
}
}
}
Step.2 Moverクラスからオブジェクトを作成し、ニュートンの運動方程式に従ってアニメーションを作る
次にMoverクラスから多数のオブジェクトを作成し、ニュートンの運動方程式を適応してアニメーションを作っていきます。ここではArrayListを利用します。※ArrayListと配列の違いについては、ざっくりいうと配列はサイズ変更が不可ですが、ArrayListはサイズ変更が可能です。すなわち、後から要素を追加したり、削除したい場合はArrayListを用いるのが適しています。今回の例の場合は配列でも結果に差はありません。)
ArrayList<Mover> movers;
void setup() {
size(800, 600);
movers = new ArrayList<Mover>();
for(int i = 0; i < 10; i++) {
movers.add(new Mover(random(width), random(height), random(5, 20))); // ランダムな位置と質量でオブジェクトを作成
}
}
void draw() {
background(255);
for(Mover mover : movers) {
PVector gravity = new PVector(0, 0.1 * mover.m); // 重力
mover.applyForce(gravity); // 各オブジェクトに重力を適用
// 任意の追加の力もここで適用できます。
mover.update(); // オブジェクトの状態を更新
mover.display(); // オブジェクトを描画
}
}
力の決め方
ニュートンの運動方程式では初期条件(初期位置や初期速度)と力が決まると、その後の物体の運動をシミュレートできます。この時の力はどのようにして決めればいいのでしょうか?
パターン1 : 自分で勝手に決める
Processingでシミュレーションを作る目的次第ですが、自分で何か物が動くようなアニメーションを作りたい場合などは、物体にどのような力が働くのかを自分で定義して構いません。そのため、現実世界ではあり得ないくらい重力の強い世界を作ったり、場所によって方向の異なる力を定義したり自由に設定することができます。
パターン2 : 物理法則で勝手に決める
現実世界のシミュレーションや自然っぽいアニメーションを作りたい場合は、物理学の教科書に載っている公式をコード化して組み込むことができます。正確な数値計算をするのではなく、あくまで自然っぽいアニメーションを作ることが目的の場合は公式の定数などは適当に簡単な数字で置き換えることができます。
※今後様々な事例で物理現象のシミュレーションも紹介する予定です。
演習
課題1: 基本的な力の適用
1つの物体に対して、重力のみを適用し、物体が垂直に落下するアニメーションを作成してください。
課題2: 重力と抵抗
空気抵抗と重力の両方が作用する環境での物体の落下をシミュレートしてください。
課題3: フックの法則
フックの法則(F=−kx)を用いて、バネに取り付けられた物体の振動をシミュレートしてください。
課題4: 投射運動
物体を斜め上方向に投げる投射運動をシミュレートし、物体の軌跡を描画してください。
課題5: 複数の力の適用
1つの物体に対して、複数の異なる方向と大きさの力を同時に適用し、結果としてどのような動きになるか観察してください。
課題6: 多数の物体
複数の物体に重力を適用し、それぞれが独立して動くアニメーションを作成してください。
課題7: 衝突と反射
物体が壁にぶつかった際に、適切に反射するようにしてください。反射の際のエネルギー損失も考慮してみてください。
課題8: マウスアトラクション
マウスの位置に引き寄せられる力を物体に適用し、物体がマウスカーソルに向かって動くアニメーションを作成してください。
課題9: オブジェクト間の引力
2つの物体が互いに引き合う引力をシミュレートしてください。ニュートンの万有引力の法則(F=G⋅m1⋅m2/r2)を利用できます。
課題10: ロケットの打ち上げ
ロケットの打ち上げをシミュレートし、重力とロケットの推進力の影響を観察してください。ロケットの燃料が尽きたら、推進力が0になるようにしてください。