Maxwell Gate 1.20 リリース 同じ長さの尾を描く方法

 前回のブログで、パーティクル同じ尾の長さにする方法というのを簡単にお話しました。
 今回、もう少し詳しくお話してみようと思います。


 尾に見えるのは、本体に近いと大きく、遠いと小さくなっている多数のパーティクルです。
 これらのパーティクルが本体の花が動いた軌跡を追いかけて動くと、尾に見える訳です。


 このパーティクルの位置を決める方法ですが、1.20より前は、本体の毎フレームの位置を記憶し、各パーティクルを3/60秒前の位置、6/60秒前の位置、というように置いていく方式でした。
 この方法だと、本体のスピードが上がると、尾がだんだん伸びていってしまい、ある程度以上のスピードにパーティクル同士が離れて、尾に見えなくなってしまいます。


 そこで尾の長さを一定にする方式を考えました。
 本体の毎フレームの位置を保存するのは同じです。
 取り出す際の方式を変えたのでした。


 話を簡単にするために、パーティクルを本体に近い方からp1、p2、p3の3つとします。
 例えばスピードが1の時は、p1は10/60秒前に保存したデータ、p2は20/60秒前に保存したデータ、p3は30/60秒前に保存したデータから座標を取ってきます。
 スピードが2の時は、1の2倍になっているのですから、おなじようにデータを取ってくると距離は2倍になってしまいます。
 スピードが2倍なら、時間の方を半分にすると、同じ長さになります。


 距離=スピード×時間


 となるので、スピード2の時は、p1は5/60秒前に保存したデータ、p2は10/60秒前に保存したデータ、p3は15/60秒前に保存したデータ、という事になります。


 データを取り出す間隔 = 1/スピード

 とすると、上手く行くようです。
 この「データを取り出す間隔」という変数(プロパティ)は、スピードを変更する時に、一緒に変更するように、スピードのセッタに組み込んじゃうと、管理が楽ですね。


 でも、このままだと、データの密度と兼ね合いが悪いスピードの時、尾がガクガクになります。
 例えば、スピード3の場合、p1は本来3.3/60秒前のデータが良いんですが、データはフレーム単位なので、切り捨てて3/60秒前、p2は、6/60、p3は10/60となってしまいます。p3だけ少数部が積み重なって、少し遠くに行ってしまったのです。


 これを避ける方法として、線形補完で本来存在しない少数部のデータを作り出してしまいます。
 p1の3.333なら、3/60秒前のデータと4/60秒前のデータの差分に3.333の少数部を乗じて、3/60秒前のデータに足す、という手法で作る訳です。


 これで綺麗につながった尾になりました。
 この本体の毎フレームの位置を記録したり、少数分付きでデータを取り出すものをクラスにまとめると、本体の方からは、毎回データを通知して記憶してもらい、今から4.5秒前の位置をちょうだい、とお願いするとそれを返してくれる便利なオブジェクトが出来上がります。
 こんなオブジェクトを作って、管理しています。
 n/60秒前というのを普通の配列で行うと、ちょっと面倒なので、リングバッファという方法で行いました。
 リングバッファは、詳しく説明しているサイトが多数ありますから、興味のある方は調べてみると良いと思います。