こんにちは。
今回は「p5.jsを始めてみる」という題でやっていきます。
p5.jsの存在は知っていましたが、processingのブラウザ版だと捉えていた自分は、オフラインでコードを書きたいという欲があるので触っていませんでした。
ですが、twitterを始めてからしばらく経ち、「つぶやきProcessing」というものの存在を知りました。
「つぶやきProcessing」は、twitterで投稿できる文字数(140字)内でコードを書くことを指すようです。
言語はprocessingでも良いのでしょうが、p5.jsのものが多いので、この企画(?)をより楽しみたいということでp5.jsにも手を出してみようと思います。
そして、自分もつぶやきProcessingでツイートしてみたい!
(「7行テトリス」みたいで面白いですよね。)
今はこのブログではカテゴリーを「processing」にして書いていますが、記事が増えることがあればカテゴリー分けしようと思います。
(違う言語みたいなものなので初めから分けた方が良いのかもしれませんが…)
追記(2022/03/23)
一応分けておくことにしました。
以上
p5.jsを始める
「p5.js」と検索して公式サイトに飛び、「Start creating with the p5 Editor!」をクリックすればエディターが開きます。
インストールなどが必要ないところが始めやすくて良いです。
プログラムをつくってみる
壁で反射する丸をつくってみます。
let x, y; let pos, vel; let v, d; function setup(){ createCanvas(300,300); //画面の大きさ pos = createVector(width/2, height/2); //位置ベクトル vel = p5.Vector.random2D(); //速度ベクトル v = 5; //速さ vel.mult(v); //速度ベクトルの大きさを指定 d = 50; //丸の大きさ } function draw(){ background(255); //背景色 ellipse(pos.x, pos.y, d, d); //丸を描く pos.add(vel); //位置ベクトルに速度ベクトルを足していく //画面外に出たら跳ね返す if(pos.x < 0 || width < pos.x){ vel.x *= -1; } if(pos.y < 0 || height < pos.y){ vel.y *= -1; } }
(JavaScriptでシンタックスハイライトを適用してみましたが、やはりうまくはいかないようですね…)
processingとだいたい同じですが、関数名など一部違うところがあるようです。
また、変数はだいたい「let」で宣言すれば動いてくれそうです。
(ちなみに「let 変数名;」の部分は省略可能でした。)
つぶやきProcessingのコードを読む
それでは、「つぶやきProcessing」でツイートされているコードを読んでみようと思います。
この記事を書くきっかけとなった、「Almina」さんのコード。
draw=_=>{createCanvas(w=600,w),background(220),noLoop(),C=cos,S=sin,b(w/2,562,w/2,w,-PI/2,14);}b=(x,y,p,q,a,n,d)=>{line(x,y,p,q);if(n>0){D=38;let A=d==0?(random()>.5?-.2:.3):0;b(x+C(z=a+A)*D,y+S(z)*D,x,y,z,n-1,0),d==0?b(x+C(z=a-A)*D,y+S(z)*D,x,y,z,n-1):0;}} #つぶやきProcessing pic.twitter.com/f0KLAvWiH8
— Almina (@Code4_11) 2022年3月7日
これまで書いてきたコードとは全く違う形になっていて、もはや「解読」の域なのですが、いかに短くするかの技術が詰まっていそうです。
1行で書かれているので、なんとなく行を変えて見やすくしてみます。
draw=_=>{ createCanvas(w=600,w), background(220), noLoop(), C=cos, S=sin, b(w/2,562,w/2,w,-PI/2,14); }; b=(x,y,p,q,a,n,d)=>{ line(x,y,p,q); if(n>0){ D=38; let A=d==0?(random()>.5?-.2:.3):0; b(x+C(z=a+A)*D,y+S(z)*D,x,y,z,n-1,0), d==0?b(x+C(z=a-A)*D,y+S(z)*D,x,y,z,n-1):0; } }
解読してみると、
「アロー関数」を使った関数の短縮
関数名 = 引数 => { 処理 }の形
(drawについては引数が無いため「_」で表記。無かったとしても「a」など適当な引数を指定しておくことも可。「()」でも可能だが、文字数的に「_」や「a」。)頻出する文字の短縮
C=cos、S=sinなど「三項演算子」を使ったif文の短縮
条件式 ? trueのときの処理 : falseのときの処理の形小数の短縮
「0.5」を「.5」と書くなど
といった技術がありました。
完璧に理解できたわけではありませんが、短縮の技のいくつかを知ることができました。
(こういうものを「ショートハンド」というらしい。)
その他、たくさんの手法があるようです。
つぶやきProcessing用にコードを書く
では実際につぶやきProcessing用のコードを書いてみます。
まずは先程書いた、反射する丸のプログラムをつぶやけるようにしてみます。
「#つぶやきProcessing」まで入れて140文字以内に収めなければならないので、実際は140文字よりも短いコードにしなければなりません。
(twitter的にはアルファベットは2文字で1文字分としているようなので、コード自体は270文字くらいまでいけそうです。)
そのままではあふれてしまったので、先程学んだショートハンドを使って短くしてみました。
x=y=0; vx=3;vy=5; d=50; draw=_=>{ createCanvas(w=300,w); ellipse(x,y,d,d); x+=vx;y+=vy; vx*=(x<0||width<x)?-1:1; vy*=(y<0||height<y)?-1:1; } //#つぶやきProcessing
実際につぶやくときは、実行結果も添えなければなりませんが、動画はいろいろと面倒だったのでやめることにしました。
(そのうちprocessingのときのようにGIFを保存できるようなものをつくりたい。)
ということで、以前つくった「ウラムの螺旋」をつぶやけるようにしてみました。
t=d=p=1;c=0;x=y=(w=300)/2;draw=_=>{createCanvas(w,w);noLoop();for(n=1;n<w*w;n++){p=n==1?0:1;for(i=2;i<=sqrt(n);i++)if(n%i==0)p=0;p&&rect(x,y,1,1);n==t+d&&(t=n,c++,d+=c%2==0?1:0);x+=c%4==0?2:(c%4==2&&-2);y+=c%4==3?2:(c%4==1&&-2);}save("image.png")} //#つぶやきProcessing
(行間まで詰めてやっと収まる程度ですが、なんとかつぶやけるようになりました。)
for(i=2;i<=sqrt(n);i++)if(n%i==0)p=0;
この部分ももう少し短くできれば良かったのですが、うまくいかず。
一応あふれなかったので、初つぶやきProcessingはこれにて完成としたいと思います。
実際につぶやいてみました。
t=d=p=1;c=0;x=y=(w=300)/2;draw=_=>{createCanvas(w,w);noLoop();for(n=1;n<w*w;n++){p=n==1?0:1;for(i=2;i<=sqrt(n);i++)if(n%i==0)p=0;p&&rect(x,y,1,1);n==t+d&&(t=n,c++,d+=c%2==0?1:0);x+=c%4==0?2:(c%4==2&&-2);y+=c%4==3?2:(c%4==1&&-2);}save("image.png")}
— taq (@taq2777) 2022年3月11日
//#つぶやきProcessing pic.twitter.com/Cr2FLxvFkZ
追記(2022/03/11)
背景色を指定していなかったので、白く見えている部分が透過する設定になっていました…
画像の保存は諦めて、背景色を白にする処理を追加しました。
t=d=p=1;c=0;x=y=(w=300)/2;draw=_=>{createCanvas(w,w);background(255);noLoop();for(n=1;n<w*w;n++){p=n==1?0:1;for(i=2;i<=sqrt(n);i++)if(n%i==0)p=0;p&&rect(x,y,1,1);n==t+d&&(t=n,c++,d+=c%2==0?1:0);x+=c%4==0?2:(c%4==2&&-2);y+=c%4==3?2:(c%4==1&&-2);}} //#つぶやきProcessing
以上
まとめ
以上で、p5.jsを触ってみるとともに、「つぶやきProcessing」を始めてみました。
短縮するために試行錯誤するのが想像以上に楽しかったので、今後もやってみることがあるかもしれません。