物理演算を使わず物理っぽい動きー二次関数を使った砂表現ー

初めまして。プログラマの境田です。

ゲームの開発中、いわゆる物理的な表現を実装してくれと依頼されるときがあります。
しかし、コストや時間など、いろいろな都合でしっかり作ることができない場合があります。
そういった時、私は簡単な処理でいかにも物理的な動きをしているように見えるものを作る時があります。
今回は、その一例としまして「立方体の砂の塊を端から徐々に横へ崩れていく」というものを物理演算を使わず作成してみようと思います。

簡単にですが、上の画像がイメージです(茶色いのが砂の塊です)。これを目標に作成します。

手法を検討してみる

ちゃんと作成する場合、一粒一粒の当たりや摩擦、流体力学などを用いて作ると思うのですが、そういった計算方法は使わず、あくまで「それっぽいもの」を作ろうと思います。

そう考えたとき、「砂の塊が曲線状にえぐられながら横へ流れたらそれっぽく見えるのでは」と思い、曲線で真っ先に頭に浮かんだ「二次関数」を用いてそれっぽいものが作れないかと考えました。具体的な方法は

①各砂粒にXY値を覚えさせ、二次関数「y=a(x-(砂粒X数の最大値))^2+(砂粒Y数の最大値)(aは二次関数の傾きで0より大きい値にします)」を作成します。

砂の塊のXYの最大値に最少点が接するような二次関数になります。

茶色い矩形が砂の塊を横から見た図、その上にある曲線が二次関数になります

②作成した二次関数の「砂粒Yの最大値」の部分を毎フレーム「-a*(砂粒Xの最大値)^2」に近づけていきます。

「砂粒Yの最大値」部分が「-a*(砂粒Xの最大値)^2」になりますと、二次関数が砂の塊の真下に行きます。

二次関数を下へ移動させます

③各砂粒をチェックし、自身のX値から作成した二次関数のy値を求め、「自身のY値≧求められたy値」なら崩れるような動きを開始させます。

上記の図の黄色い部分が条件に合致している部分で、そこが崩れることで、曲線状に崩すことができます。
この処理を実際に作ってみてチェックしてみます。

いろいろ雑な部分がありますが、曲線状に崩れているように見えると思います。

拡張してみる

砂粒のY値が同じ場合同時に動いてしまい、不自然に見えてしまいます。
条件に合致し、動ける状態になってもランダムで数フレーム待機するようにし、砂粒の動きをばらけさせてみました。

先ほどのものより自然に見えてきました。
砂の動く方向は二次関数の接線からいい感じのものが作れないか試してみましたが、ほとんど真下に落ちてしまったので、その値を基準にいろいろいじっています。

また、最初は急な曲線状に崩れ、徐々に緩やかな曲線状に崩れればよりそれっぽくなるのではと思いました。
二次関数の場合は、傾きを大きい値から0に近づけていけば急な曲線→緩やかな曲線に変化させることができます。
最初は上下それほど差がなく崩れていきますが、後半は上部分のほうが早く崩れています。
傾きが緩やかになるタイミングで砂粒が一気に崩れてしまい、大量の砂粒が表示されてしまうため、補間に工夫が必要です。
最後に、XY値を使用して曲線状に崩す表現をしましたが、Z値を使用していなかったので、使用してみます。
二次関数を3つ用意し、Z方向に傾きを補間しながら計算してみます。

中心の関数の傾きを緩くし、両サイドの傾きを急にしてみました。
極端に変えすぎたので逆に不自然になってしまいましたが、傾きの値を近いものにすれば、自然に見えると思います。

おわりに

この処理を実行してみますと、砂粒が多すぎて多大な処理負荷が発生してしまい、まだまだ課題が多々ありますが、物理演算を使用せず、それっぽいものが作れたと思います。
プログラムの勉強はもちろん大事ですが、要求されたものをどうすれば作れるかを自力で考えることも必要だと思いますし、なにより自分で考えてプログラムを組むのは楽しいです。
物理演算は難しいですが、工夫次第では物理演算を使わず、それっぽいものも作れるんだということを伝えることができれば幸いです。
本記事を読んでいただき、ありがとうございます。