LoginSignup
0
0

More than 1 year has passed since last update.

つぶやきProcessing用に書かれた Processing・p5.js のプログラム(対象2つ)を p5.js で書きかえてみる

Last updated at Posted at 2022-02-20

はじめに

タイトル通りの内容で、「つぶやきProcessing(Twitter の制限文字数内で動くプログラムを書くもの)」のために書かれた「Processing のプログラムと、それとは別の p5.js のプログラム」を、それぞれ p5.js用に書きかえたという話です。
「p5.js を p5.js で書きかえる?」と思われたかもしれませんが、これは「つぶやきProcessing用に短く書ける記法が用いられているものを、短縮版でない記法に展開する」という内容になります。

書きかえには以下の 3つの観点があり、今回の書きかえ対象の 2つのうち、一方は「主に 1 の観点での書きかえをしていて」、「もう1つは、以下の 2・3 の 2つの観点での書きかえ」という形になります。

1) Processing と p5.js とで文法が異なる部分を書きかえる
2) つぶやきProcessing用に短く書ける記法が用いられている部分を展開する
3) その他の書きかえ

なそ、書きかえ版は、普段よく利用している「p5.js Web Editor」を使って動かしています(もちろん、それ以外の環境・方法でも問題ありません)。

ちなみに、出来上がったもの 2つは以下の通りです。
大幅な変更はしてないので、元作品と同じか、ほぼ同じ(一部のパラメータをちょっと書きかえた)なのですがw

書きかえたもの 1つ目(@nicolasbaez さんの作品)

1つ目の話の出力結果などはこちらです。
元のものと同一の動作・見た目になった後、パラメータを少し変えています。

書きかえたもの 2つ目(@sh_sys_ さんの作品)

2つ目の話の出力結果などはこちらです。

書きかえを行った話の詳細

1つ目のほう

元のプログラムは、冒頭のツイート内に書いてあるとおり、以下となります(ハッシュタグは除いています)。

void setup(){size(500,500,P3D);colorMode(HSB,3);}float i,j,r,k,w=250;void draw(){clear();translate(w,w);rotateX(k);rotateY(k/2);for(i=0;i<=3;i+=.02){for(j=0;j<6;j+=.02){r=noise(i,j,k)*w;stroke(i,j,PI);point(r*sin(i)*cos(j),r*sin(i)*sin(j),r*cos(i));}}k+=.01;}

改行を入れると、このような感じでしょうか。

void setup(){
  size(500,500,P3D);
  colorMode(HSB,3);
}
float i,j,r,k,w=250;

void draw(){
  clear();
  translate(w,w);
  rotateX(k);
  rotateY(k/2);
  for(i=0;i<=3;i+=.02){
    for(j=0;j<6;j+=.02){
      r=noise(i,j,k)*w;stroke(i,j,PI);
      point(r*sin(i)*cos(j),r*sin(i)*sin(j),r*cos(i));
    }
  }
  k+=.01;
}

そして、書きかえ後のほうは、以下のとおりです(一部、コメントを残してます)。

let r, k, w;

function setup() {
  createCanvas(500, 500, WEBGL);
  colorMode(HSB, 3);
  w = width / 2;
  k = 0;
}

function draw() {
  background(0); // clear(); をこちらに変更
  // translate(w, w); // 不要っぽい
  rotateX(k);
  rotateY(k / 2);
  // 以下、for分の増分を *5 にしてみた
  for (let i = 0; i <= 3; i += 0.02 * 5) {
    for (let j = 0; j < 6; j += 0.02 * 5) {
      r = noise(i, j, k) * w;
      stroke(i, j, PI);
      point(r * sin(i) * cos(j), r * sin(i) * sin(j), r * cos(i));
      console.log(r * sin(i) * cos(j), r * sin(i) * sin(j), r * cos(i));
    }
  }
  k += 0.01;
}

書きかえ: Processing用の処理を p5.js用に

書きかえをした話の補足を書いていきます。
まずは、「Processing用の処理を p5.js用に書きかえた」という話の部分です。

例えば、「void setup()」や「void draw()」は、「function setup()」・「function draw()」にしています。また、キャンバスの作成のところも「size(500,500,P3D)」という書き方を「createCanvas(500, 500, WEBGL)」に変更します。

その他にも、「float i,j,r,k,w=250」という部分は「let r, k, w」と、setup()内の「w = width / 2」という指定をしています(w の値の決め方の意図も反映させるような書きかえをまじえつつ)。

それと、「clear()」だと背景色のあたりが意図通りにならないため、「background(0)」としていたり、「translate(w, w)」が不要っぽいので外したり、ということもやっています(デフォルトの背景色や 3D を扱うモードの原点の違いがあるっぽい)。

細かいところで「for(i=0。。。」というところを「for (let i = 0。。。」としていたりもします。

主には、このような書きかえをしました。
あとは、動作させるだけなら不要な書きかえですが、「for文の中の i+=.02 を i += 0.02 * 5 と変える」パラメータの変更をしたくらいです(後で変更しやすいように、乗算の形で書いています)。

2つ目のほう

元のプログラムは、冒頭のツイート内に書いてあるとおり、以下となります。

v=0
p=[]
draw=_=>{
v||createCanvas(w=640,w)+noFill(colorMode(HSB,9))
B=blendMode
R=random
B(BLEND)
background(0,.2)
B(ADD)
if(v++%30==0)p.push([R(9),R(w),R(w),0])
p .map(([c,x,y,r])=>stroke(c,9,9,5)+circle(x,y,r))
p=p.filter(q=>q[3]++<w/2)
}

そして、書きかえ後のほうは、以下のとおりです。

let cxyrArray = [];

function setup() {
  createCanvas(600, 550);
  noFill();
  colorMode(HSB, 9);
}

function draw() {
  blendMode(BLEND);
  background(0, 0.2);
  blendMode(ADD);

  if (frameCount % 30 == 0) {    
    cxyrArray.push({
      "c": random(9),
      "x": random(width),
      "y": random(width),
      "r": 0,
    });
  }

  for (const val of cxyrArray) { // map を for...of に
    stroke(val.c, 9, 9, 5);
    circle(val.x, val.y, val.r);
    val.r++;
  }

  cxyrArray = cxyrArray.filter(
    (elem) => elem.r < width / 2);
}

書きかえ: 主に「つぶやきProcessing用に短く書ける記法」を展開する話

ここから、短縮記法などの部分を展開するような書きかえの補足を書いていきます。

まず、「setup()」を省略できるように書かれていたのを、「1回だけ実行する処理は、setup()内に書く」という形に書き直しました。
v||createCanvas(w=640,w)+noFill(colorMode(HSB,9)) の部分の || より後ろを展開したような形です。

また、文字数制限を気にしないならば、「v」というカウントアップしていく部分を「frameCount」にしてしまえば意図が分かりやすくなりそうです。

それと、「B=blendMode」や「R=random」と短縮のための処理は、書く処理が必要な部分で「blendMode」・「random」を用いるようにしました。

余談ですが、上記のような書きかえをしていると、つぶやきProcessing用のノウハウが見られて、勉強になります。

さて、続きで以下の部分の話です。

if(v++%30==0)p.push([R(9),R(w),R(w),0])
p .map(([c,x,y,r])=>stroke(c,9,9,5)+circle(x,y,r))
p=p.filter(q=>q[3]++<w/2)

ここは、何となくそうしたかったという変更も含め、以下のようにしています。
以下の処理に関連して、プログラムの最初で「let cxyrArray = []」という空の配列を初期値にして、というものも書いています。

  if (frameCount % 30 == 0) {    
    cxyrArray.push({
      "c": random(9),
      "x": random(width),
      "y": random(width),
      "r": 0,
    });
  }

  for (const val of cxyrArray) { // map を for...of に
    stroke(val.c, 9, 9, 5);
    circle(val.x, val.y, val.r);
    val.r++;
  }

  cxyrArray = cxyrArray.filter((elem) => elem.r < width / 2);

「何となくそうしたかった」という部分は、push により [c,x,y,r] の 4つの値をランダムに作っては追加する、という部分のところです。
これを、「配列の 0番目から 4番目の値」という形でなく、オブジェクトの「key で設定したい内容を示す文字を、value でその値を指定する」という形にしました。
もちろん、これをやらなくても OK です。

あと、map でやっている処理は「for...of」を使う形にしていたりもします。
オブジェクトの配列となっている中身を 1つずつ取り出し、その取り出したオブジェクトの中の必要な値を key の文字で指定して使っています(val.c や val.x など)。

これで、書きかえ後のプログラムができあがりました。

おわりに

今回、つぶやきProcessing用に書かれた Processing・p5.js のプログラムを、p5.js で書きかえてみました。
書きかえの中で、特に「つぶやきProcessing用に短く書ける記法」を展開す部分は、短く書くためのノウハウの勉強になる部分なので、またこれからもたまにやっていければと思います。

ちなみに、以前も以下のように、今回やったようなのと似たことを試して記事にしていたりしました。

●#つぶやきProcessing で気になった作品を p5.js Web Editor で動かしてみる 【その2】 - Qiita
 https://qiita.com/youtoy/items/ac2f953d9a0ced3b881a
●#つぶやきProcessing で気になった作品を p5.js Web Editor で動かそうとしてみる【 #GWアドベントカレンダー 2021/5/2 】 - Qiita
 https://qiita.com/youtoy/items/0806ba53db59261da3f8

余談

今回の記事の 1つ目に出てきていたものは、その後に、少しだけ追加実装をしました。
なお、今回の記事のメイン部分に含めると、トピック的に少しだけ発散するように思ったので、余談としてここに書いています。

やったことは、「mouseX・mouseY(マウスカーソルの位置座標を取得するもの)を使って、一部の表示に関わるパラメータを動的に変化させる」というものでした。

この追加実装をしたものも、ソースコードをのせておこうと思います。

let r, k, w;
let dist = 1.0,
  weight = 5;

function setup() {
  createCanvas(500, 500, WEBGL);
  colorMode(HSB, 3);
  w = 0.7 * width;
  k = 0;
}

function draw() {
  background(0);
  rotateX(k);
  rotateY(k / 2);
  const temp = 3;
  for (let i = 0; i <= 3; i += 0.02 * temp) {
    for (let j = 0; j < 6; j += 0.02 * temp) {
      r = noise(i, j, k) * w;
      stroke(i, j, PI);
      dist = map(width - mouseX, 0, width, 0.3, 1);
      weight = map(height - mouseY, 0, height, 12, 2);
      strokeWeight(weight);
      const x = dist * r * sin(i) * cos(j),
        y = dist * r * sin(i) * sin(j),
        z = dist * r * cos(i);
      point(x, y, z);
    }
  }
  k += 0.01;
}

【追記】 コメントをいただきました

メンションつけてツイートしてたところに、コメントをいただきました。
「OMG」と「Gracias」と断片的な単語は意味が分かるのですが(選択必修科目の第二外国語で、スペイン語を選択していた過去より)、他の部分は分からないので DeepL で訳してみました。

「自分が何かのきっかけになると、とても気持ちがいいものです!!!」というような内容を書いていただいたようです。
そうえいば、英語圏の方から英語のコメントをいただくことはあったものの、スペイン語でのコメントツイートをいただいたのは初めてかも?

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0