リモート開発メインのソフトウェア開発企業のエンジニアブログです

Flutter の物理シミュレーションを理解する ‐ ② GravitySimulation

このシリーズでは、Flutter の各種物理シミュレーションについて解説しています。

第2回となるこの記事では、重力をシミュレートする GravitySimulation について解説します。

Playground

細かい解説をする前に、まずはどんなものか触ってみましょう。前回同様 DartPad で Playground を作りました。

https://dartpad.dev/?id=871ead87084059ddcc4bfe5bc26ebc32

再生ボタンを押すと、ボックスが重力で落下するかのように移動するのが確認できると思います。

パラメータを変えてみましょう。“Acceleration” を変えると、シミュレーション対象に常にかかり続ける加速度を変えることができます。負の値にすると移動の向きも逆になりますね。

“Distance” はざっくり言えばシミュレーション開始時の位置です。-0.5 あたりにしてみます。

開始位置が変わりましたね。-1 にしてみましょうか。

……あれ? 動きませんね。なぜでしょうか。

一旦置いてくことにして、次は “End Distance” をみてみます。これはざっくり言えばシミュレーション終了時の位置です。負の値にすることはできません。……なぜでしょうか? それも一旦置いておいて、とりあえず 0.5 にしてみます。

途中で止まりましたね。

最後に、“Velocity” を変えるとシミュレーション開始時の速度が変わります。符号の向きによって叩きつけるような挙動か、投げ上げるような挙動になります。

これで一通りパラメータを確認できました。ここで、ちょっと引っかかった部分について解説します。

“Distance” と “End Distance”

“Distance” と “End Distance” についてはもしかすると直感に反する挙動だったかもしれません。ここが GravitySimulation の若干特殊な部分なのですが、これらのパラメータは厳密には位置ではなく、「原点からの距離」を表しています

“Distance” は言い換えると「開始時点で原点から既にどれくらい移動しているか」を表し、“End Distance” は「原点からどれくらいの量 (絶対値) を移動したら完了とするか」を表すパラメータなのです。

前の例で “Distance” が -1 で “End Distance” が 1 の時、一切移動しないという挙動がみられましたが、これは開始時点で -1 をすでに移動した扱いになっており、完了の基準である移動量 1 を開始時点で満たしてしまっているので、動かなかったというわけです。“End Distance” が負の値を受け付けないのも、これが正負は関係しない移動量を表すものであることを踏まえると、理解できるかと思います。

例をもう一つ挙げてみます。以下の動画では、“Distance” を 0.9、“End Distance” を 1 にしています。“Velocity” が -5 の時は原点からの位置が -1 まで行かないので、上昇した後下降し、0.9 を通り越して 1 で停止します。“Velocity” を -6 にすると上昇が -1 まで達するので、そこで移動量が 1 となり、シミュレーションが停止します。

最初は面食らうかもしれませんが、掘り下げてみると一貫したロジックのもとで動いていることが分かりますね (ただこのロジックにすると何が嬉しいのかは分かっていません……) 。

Moba Pro

コンストラクタ

改めて、GravitySimulation のコンストラクタをおさらいしておきましょう。定義は以下のようになっています。

GravitySimulation(
  double acceleration,
  double distance,
  double endDistance,
  double velocity,
)

これに加えて assert(endDistance >= 0) とアサーションが付いており、endDistance に負の値を渡すとデバッグ環境では実行時エラーになります。

accelerationvelocityの単位は、任意の長さの単位 L と時間単位 T をもって、それぞれ L/T²L/T になります。distanceendDistance は、原点からの距離を L を単位として表したものです。単位時間は AnimationController を用いる場合秒になります。任意の長さの単位については、第1回の記事を参照ください。

参考: 位置と速度の計算式

初期位置を $x_0$ 、初速度を $v_0$ 、加速度を $a$ としたとき、時間 $t$ における位置 $x(t)$ は以下の式で表されます。

$$
x(t) = x_0 + v_0 t + \frac{1}{2} at^2
$$

また、同様に時間 $t$ における速度 $v(t)$ は以下の式です。

$$
v(t) = v_0 + at
$$

どちらも教科書通りの等加速度運動の式ですね。

まとめ

Flutter の GravitySimulation の性質と使い方を解説しました。gravity と銘打たれていますが、重力に関係なく等加速度運動をシミュレーションするものと捉えた方がより正確でしょうか。存在だけでも覚えておけば、リッチなアニメーションの構築に役立てられるかもしれません。

次回は SpringSimulation を解説する予定です。

← 前の投稿

AWS CDK の個人的に良かったプラクティス

次の投稿 →

生成 AI に質問しまくってシステムを作ってみた

コメントを残す