【scratch】で物理演算エンジンをつくろう!45度で投げれば本当に最も遠くに飛ぶのか?をシミュレーション




皆様、こんにちは!プロクラスの山足です。

小中学生は夏休みの真っ最中、夏の宿題は順調に進んでいますでしょうか。自由課題に困っているかもしれません!?

今回は、scratchで簡単な「物理エンジン」をつくって、シミュレーションをしてみたいと思います!もしよかったら参考にしてみてください!

今回のお題は、ソフトボール投げや砲丸投げなどの時、よく話題になる「投射角度45度で投げれば本当に最も遠くまで飛ぶのか?」です。

まずは簡単な物理の法則から確認して、scratchにその法則に従ってプログラムを動かしてもらうようにいたしましょう!

物理エンジンとは?

物理エンジンとは、現実の世界で何か科学的な現象をコンピュータ上で再現する際に使われるソフトウェアの事を指します。

例えば、今回のソフトボール投げシミュレーションも、現実の世界で実験をするのには、常に同じ力で、決められた角度にボール投げを再現するのは簡単ではありませんよね。そのほかにも、衝突実験や危険な場面など再現が現実的に難しい場合にも、コンピュータを利用して安全に、かつ、短時間で何度もシミュレーションが可能になるため、物理エンジンが活躍する場合があります。

物理エンジンは、基本的に古典物理学という、18世紀末あたりまでに確立された、数々の法則にしたがい、計算が組み込まれておりますので、今回の再現も、古典物理学の法則に従ってプログラムを組んでいきたいと思います!

ボール投げに必要な物理的法則について

ボール投げに必要な物理の知識を考えてみましょう。

必要な要素は、ボールを投げるときの「速さ」、ボールが段々落ちてくる「重力」が基本となり、さらにはボールが地面と接触した際の「摩擦」や、より再現を詳しくするためには「空気抵抗」や、環境(風や気圧)、ボールの材質や…となってきます。

今回は更にはの部分は省略して、特に簡単な部分だけで再現するようにしてみます。

「速さ」の法則

速さは、皆様ご存じの「速さ=距離÷時間」などの計算の事です。

つまり、速さを再現するには「距離(道のり、長さ)」や「時間」が必要になってきます。

これは、scratchでは、「x,yの座標」「処理時間(fps)」が関連してくることとなります。
※fps【フレーム毎秒 / frames per second】とは、動画のなめらかさを表す単位の一つで、画像や画面を1秒間に何回書き換えているかを表したもの。

次に、速さには2つの考え方があり「平均の速さ」「瞬間の速さ」があります。

「平均の速さ」は算数のテキストでもよく出るような、A地点からB地点までの凡その経過時間や速度感を表すときに使われる考え方になります。例えば、「京都から東京までは新幹線でだいたい2時間30分ですよね」、の会話は「平均の速さ」的な考えとなります。

「瞬間の速さ」は、その時々の速さ、例えば車のスピードメーターが表すものがこれに当たります。例えば、京都から東京までの新幹線でも、その時々では「速さ」が違いますよね。「瞬間の速さ」を考える場合は、平均の速さにはない、その時々の速さを変える要因「加速度」という概念が必要になります。車や新幹線でいう「アクセル」の部分になります。

その「加速度」によって、時間が経過すると「速さ」が変わる、と考えます。
車がアクセルを踏む大きさにより速度を変える、と同じ考え方です。

加速による「加速後の速さ(v)」は、「加速前の速さ(v0)」に「加速度(a)」の強さに、それを加えた「時間(t)」を掛けあわせて、

となります。

ボールに加わる力

次に、ボールを投げた時に、ボールの速さが変わっていく要因となる「力」についての考え方です。

ボールを投げた時、どのような動きになるかというと、投げた瞬間は前方上の方向に飛んでいくと思いますが、だんだんと上昇する動きが無くなっていき、最高点に達した後、今度は下降しはじめ、地面に衝突することになりますよね。

なぜこうなるのか、というと、もちろん「重力」が働くためです。

ボールを投げた後、仮に空気抵抗やその他の力が加わらないと仮定すると、ボールには実質重力のみが作用することになります。

この重力によって、地面に向かって垂直方向にボールが「加速する」といった考え方になります。

ボールの速さをx、y軸方向に分解する

ボールは地面の水平面から考えると、斜め上向きに飛んでいくわけですが、その動き方をとらえるときに、地面と水平方向(x方向)、地面と垂直方向(y方向)に分けると、実はある法則的な運動をしていると見えてきます。

先程の「ボールに加わる力」では、重力(地面と垂直方向に働く)のみが作用することになりますので、それ以外に加わる力は存在しないとします。

そうすると、ボールが飛ぶ地面と水平方向(x方向)には加速させる力が存在しない為、常に一定速度で動く事となります(等速運動)。

つまり、時間と関係なく、

となります。(const = 一定)
※三角関数は今回省略しますが、まだ学習してない方は、角度によって速さをx、y軸方向に分解できるもの、ととらえてください。

それに対し、ボールが飛ぶ地面と垂直方向(y方向)には重力が加わるため、速さが常に変化することとなります。

どのように変化するかは、先程の「瞬間の速さ」より、加速度 a ⇒ 重力 g となり、「加速後のy方向の速さvy」は、

となります。

以上が、ボール投げに必要な法則となります。

シミュレーションに必要な要素

まず、シミュレーションに必要な要素を定めていきます。

計算に必要な要素は、ボールを投げた時の「①初速度」「②角度」、「③1処理辺りの時間」、「④重力加速度」となります。

①初速度 v0

初速度は好きに決められますが、今回は、秒速5メートル、

とします。

②投げる角度 θ

投げる角度は、変数で好きに切り替えられるようにします。

変数「投げる角度」を作って、表示のしかたを「スライダー」にすると、好きに変えられるようになります。

③1処理の時間 t

今回は、scratchを使ってシミュレーションしますので、まずは1回の処理が何秒かかるのかを簡単に計測してみましょう。

タイマーを使って計測してみたところ、だいたい0.032秒でしたが、おおよそ32fps(1秒間に32回処理)していることがわかりました。

④重力加速度 g

重力による加速度は、地球上で行うものとして、代表的な数値を利用します。

また、scratchではy軸方向は上向きに+(プラス)なりますので、地面向きは反対(-)となり、

となります。

scratchにシミュレーションを組み立てよう

それでは、ここまで準備してきたことをscratchに取り込みましょう。

まずは、ボールと地面を準備しましょう。

今回、1ピクセルを1cmと考えます。それぞれの値をmからcm(×100)に変換し、計算がわかりやすいように変数を用意して、初期設定を加えます。

初速度をx、y軸方向に三角関数を利用して分解します。

y方向の速度は時間ごとに変化するので、瞬間の速度として用意します。

あとは、適度な高さの人を準備して、ボールの初期位置を定めれば準備完了です。!

x方向の速さは初速度から変わりませんので、x座標は「x方向の初速度 × 1処理の時間 t」ずつ進むようにします。(距離=速さ×時間)

y方向は速さが変わりますので、1処理毎に速さを変える計算をしなければなりません(瞬間の速さ)。

その速さによって、y座標は「 y方向の瞬間の速さ × 1処理の時間」ずつ進むようにします。

今回は、摩擦等を考えないので、地面につくまで計算を進めるものとしましょう。これをscratchでプログラミングすると、

となります。

以上でシミュレーションが完成しました!

あとは、ボールのx座標を見える様にすれば、飛距離を確認することができますので、簡単な物理エンジンを作成することができました!

実際、scratchでは地面に潜り込む直前までを計算させるには、もう少しプログラム処理の工夫が必要にはなりますが、投射角度45°付近が最も飛距離が長くなることが、シミュレーションでも証明することができました!

さいごに

例えば、地面に触れた時にはねるようにするとか、風の影響を追加するなどすると、より現実的なシミュレーションができるかもしれません。

物理エンジンは、このように物理の法則に則って、プログラムに計算させることで簡単に作成することができるのです。

特に中学校から物理の計算は学んでいくことになりますが、高校生で三角関数やベクトル、微分積分等を数学で学ぶことでより詳細なシミュレーションを作っていくことが可能になります。

このように、学校で学ぶ物理や数学の知識は、現社会のあらゆるところで、さまざまな現象をシミュレーションすることによって、皆様の安全や、危険予測、製品の作成や開発を行い、くらしの豊かさを実現しているのです。

皆様も、学校で良く学び、ぜひ良い社会づくりが出来る人材になってください!

それではまた次回まで、さようなら…

プロクラスにはスクラッチ講座やUnity講座があります!

よりレベルアップを図りたい皆様に、プロクラスにはプロのプログラマーが教える講座がさまざま用意されています!

興味がある方はぜひご確認ください!

大人が学べるスクラッチ講座もあります!

先生方や保護者の方が学べるスクラッチ講座やUnity講座もありますので、短期間でプログラミングを習得されたい方はぜひご活用ください!