![見出し画像](https://assets.st-note.com/production/uploads/images/73322098/rectangle_large_type_2_7c7aa53db8b2cb4c3369f7f8fe08f233.png?width=1200)
20 行のプログラムで水面のアニメーションを作る
見た目を気にしなければ、20 行も必要なく 280 文字でインタラクティブな水面シミュレーターは記述できる。
#tinycode
— Koji Saito (@KojiSaito) November 27, 2020
R=range(51)
P=O=[0]*52
def setup():size(450,255);stroke(-1)
def draw():
global O,P;clear();q=[0]*52
if pmouseX!=mouseX:t=mouseX/10;P[t]=125-mouseY
for i in R:q[i]=(1.99)*P[i]-.99*O[i]+.4*(P[(i+50)%51]+P[(i+1)%51]-2*P[i]);line(i*9,99-P[i],(i+1)*9,99-P[i+1])
O=P;P=q pic.twitter.com/Daysepk9YN
このプログラムでは配列 P に水面の高さを入れると、あとは自動的にシミュレーションを行い、水面の高さを計算してくれる。これはそこそこ真面目な水面シミュレータであり、nVIDIA が出しているホワイトペーパーの方法を実装したものである。
以前解説記事も書いた気がするので、検索してもらえると出てくるかもしれない。
今回は上から何か落ちてきて、それが水面に当たり波が起きる様子をプログラムで実装してみた。X が落ちてくる物体(四角形)の横方向の位置であり、Y が縦方向の位置である。変数 V が落下速度であり、この V は一定速度で増加しつづけるため、透過速度運動となっている。
P=O=[0]*52
def setup():size(450,255);noStroke();fill(10,120,200)
X=Y=256
V=1
def draw():
global O,P,X,Y,V;background(-1);q=[0]*52
if Y>255:
X=int(random(52));Y=0;V=2
square(X*9,Y,10)
Y+=V
V+=.2
if Y>99-P[X]:
P[X]+=randomGaussian()*2
for i in range(51):
q[i]=(1.99)*P[i]-.99*O[i]+.4*(P[(i+50)%51]+P[(i+1)%51]-2*P[i]);
u,v=99-P[i],99-P[i+1]
s=i*9
t=s+9
quad(s,u,t,v,t,255,s,255)
O=P;P=q
中央付近にある、P[X]+=randomGaussian()*2 にて、水面の位置を変化させている。水面が高くなれば、その部分の水の量が増えることになる。逆の場合は減ることを意味する。そのため、これは水量を変化させることに他ならないが、randomGaussian は平均 0 の正規分布に従う乱数を発生させるため、長い時間でみると統計的には全体の水量は変化しない。でも、短期的には偏りが出るため、水位が上がったり下がったりする。
これを防ぐには、増えた水量を記録しておき、水量の増減を調整するのが良いと思うが、今回のプログラムには入れていない。
たった 20 行のプログラムではあるが、水面のシミュレーションができることを今回は示してみた。実際の動画は以下の tweet を見てもらえれば、と思う。
水面シミュレータでなんか新作できないかと、ちょっと遊んでみたけど、とても つぶやきProcessing 化はできそうにない。Processing の 20 行のコードで、ここまでできるんだけどね。 pic.twitter.com/pplkWNkJZC
— Koji Saito (@KojiSaito) March 1, 2022