趣味としてのクリエイティブ・コーディング:009:もう面倒な計算しなくていいの
コードをきれいに整理したので、変更するのがやりやすくなりました。
どんどん変更して大暴れしちゃいましょう!
本シリーズの趣旨は初回をご覧ください。
思いつくままいろんなパターン
前回のソースコードはこれでした。
これを元に遊んでみましょう。
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.js"></script>
</head>
<body>
<script>
// Creative Commons CC0
// sc008 趣味としてのクリエイティブ・コーディング:008:パズルはお好き?
function setup() {
createCanvas(400, 400);
colorMode(HSB, 360, 100, 100, 100);
blendMode(SCREEN);
noStroke();
noLoop();
}
function draw() {
background(0, 0, 0, 100);
translate(40.0, height / 2.0);
prevWaveNo = 1;
for (waveNo = 1; waveNo <= 3; waveNo += 1) {
for (lineNo = -2; lineNo < 5; lineNo += 0.5) {
for (radians = 0; radians < TWO_PI; radians += 0.01) {
eHue = lineNo * 60;
eSat = 100 - radians * 5;
eBri = radians * waveNo * waveNo * 3;
eX = radians * 25 * (prevWaveNo + waveNo - 1);
eY = -sin(radians) * radians * lineNo * waveNo * waveNo * 2.0;
eR = lineNo;
fill(
eHue,
eSat,
eBri,
100
);
ellipse(
eX,
eY,
eR,
eR
);
}
}
prevWaveNo = waveNo;
}
}
</script>
</body>
</html>
まずは、このコードを動かして描かれる結果はこう。
波形をひとつ追加してみましょうか。
それには?
for (waveNo = 1; waveNo <= 4; waveNo += 1) {
こうですね。
線の本数も増やしてみましょうか。
方法はいくつかありますが、線と線の間隔を狭めてみましょう。
それには?
for (lineNo = -2; lineNo < 5; lineNo += 0.1) {
例えばこうですね。
もっと狭めると?
for (lineNo = -2; lineNo < 5; lineNo += 0.05) {
ちょっとやり過ぎかな?
じゃあ、線を構成する円と円の間隔を広げてみましょう。
それには?
for (radians = 0; radians < TWO_PI; radians += 0.2) {
例えばこう。
お!なんかまた面白い絵になりました!
よし、次は色を変えてみましょう。今は線毎に色を変えていますね。
eHue = lineNo * 60;
これ、 lineNo が -2 のときとか、 eHue = -2 * 60 = -120 とマイナスの色というあり得ないことになってました。
これはバグなのですが、マイナスの色だと赤扱いになるみたいで、その色が気に入ってそのままにしてたんです。
詳しくはシリーズ第6話参照ください。
バグのある状態で十分楽しんだので、そろそろこのバグを無くしておきましょう。
例えば、lineNo が -2 から 5 にかけて色を 0 から 360 まで変化させるというのはどうでしょう?
(色が 0 から 360 というのも第6話参照してね)
それには?
lineNo が -2, 5
↓
eHue を 0 , 360
このパズルを解けばいいですね。
-2 が 0 になるようにするには 2を足せばいいから
-2 + 2, 5 + 2
↓
0 , 360
0 には何を掛けても 0 だし、7 に何かを掛けて 360 になるようにすればいいから、これが、
0, 7
↓
0 , 360
こんな感じ?
0 * 360 / 7, 7 * 360 / 7
↓
0 , 360
これをコードにすると、
(lineNo + 2) * 360 / 7
こうじゃないですかね?
やってみましょう。
線と円の間隔はもとに戻して、
for (lineNo = -2; lineNo < 5; lineNo += 0.5) {
for (radians = 0; radians < TWO_PI; radians += 0.01) {
eHue = (lineNo + 2) * 360 / 7;
う〜ん、よくわかんないけど、なんか出来てるっぽい!
これでバグ無くなりましたね!
(色についてはね…)
計算めんどいよ…
さて、めでたく lineNo の -2, 5 を色の 0, 360 に変換することができました。
…でも、計算式考えるの面倒くさかったですね。
これを 0, 360 じゃなくて 360, 0 にしたかったら?
う〜、考えたくない!
こういう プログラム上面倒くさいとか、しんどいと感じた場合、大抵のことにはいい方法が用意されています 。
今回の場合に使えるのは、「map()」です!
これ超便利!
例えばさっきの例だと、
eHue = map(lineNo, -2, 5, 0, 360);
と書くだけで OK! 面倒な計算を肩代わりしてくれるんです!
書き方は、
map(これが, ここから, ここまでを, ここから, ここまでに変換)
です。
正にやりたかった計算ですね!
さっきの「0, 360 じゃなくて 360, 0 にしたかったら?」は、
eHue = map(lineNo, -2, 5, 360, 0);
とするだけなんです! 簡単で感嘆!
map() について紹介した別記事もあるので、よかったらどうぞ。
プログラマはしんどいのが大嫌い
プログラマはめんどくさがりです。怠惰ともいいます。
面倒くさくてしんどいことはしたくないので、それを回避することを真面目に一所懸命に考えます。
おかげで、大抵のことにはしんどくない方法が用意されてるわけです。
怠惰な先人に感謝です。
ここでも出てくるプログラミングのキモ!
じゃあ今度は、色を左から右に行くにつれて変化するようにしてみましょう。
左から右は x 軸ですから、eX の値が例えば 0 から 400 までに、色が 0 から 360 になるように、map() を使って書くと、
eHue = map(eX, 0, 400, 0, 360);
こうですね。
あれ?
…動かない。
はい! 単に eHue の式を変えるだけでは動きません。
そうです。 eX はこの時点ではまだ計算されてないんですね。
eHue = map(eX, 0, 400, 0, 360);
eSat = 100 - radians * 5;
eBri = radians * waveNo * waveNo * 3;
eX = radians * 25 * (prevWaveNo + waveNo - 1);
eX が計算されるより前に eHue の map() で eX を使おうとしたのがマズいです。
前回やった変数のセットと使う場所の関係ですね。
解決するには、eX の計算の後に eHue の式を持ってくればいいわけです。
eHue だけ持っていけば解決なんですが、eSat と eBri も fill() の中で使う eHue の仲間ですから、コードのわかり易さのために一緒に移動しましょう。
eX = radians * 25 * (prevWaveNo + waveNo - 1);
eY = -sin(radians) * radians * lineNo * waveNo * waveNo * 2.0;
eR = lineNo;
eHue = map(eX, 0, 400, 0, 360);
eSat = 100 - radians * 5;
eBri = radians * waveNo * waveNo * 3;
グッド、グッド! OK ですね!
いろいろな技伝授!
0 の赤から始まって、黄色、緑、水色、青、紫と変わってまた 360 の赤に戻るとなってます。
この図の角度 0度から 360度 にかけて一周してるかたちですね。
じゃあ、これを二周、三周させることはできないでしょうか?
三周なら 3倍?
eHue = map(eX, 0, 400, 0, 360 * 3);
あら、違うみたい…
0 から 360 まで行って、361 になったらまた 1 から始まるといいんですが、これって…
そう! 360 で割り算した余りですね。
これは % で表すことが出来て、 % 360 とすると、360 で割った余りを計算してくれます。
なので、さっきの三周させたかったものは、
eHue = map(eX, 0, 400, 0, 360 * 3) % 360;
これで、
こう!
うわー、派手!
面白いからここに y 軸も追加して、y 軸は大体 -200 から 200 の間の変化なのでこうしてみましょう。
eHue = (map(eX, 0, 400, 0, 360 * 3) + map(eY, -200, 200, 0, 360 * 3)) % 360;
結果がどうなるか考える前に動かしちゃえ!
ほう!斜めになるのね。
x 軸側を一周にすると?
eHue = (map(eX, 0, 400, 0, 360 * 1) + map(eY, -200, 200, 0, 360 * 3)) % 360;
ああ、そうか!斜めが緩やかになるのか。
こっちのほうが好きかも。
じゃあ、極端に y 軸側を 10周とかしてみたら?
eHue = (map(eX, 0, 400, 0, 360 * 1) + map(eY, -200, 200, 0, 360 * 10)) % 360;
わあ!気持ち悪い!ダメだこりゃー。楽しー!
…いや、でもこれで線を増やしてみたら…
for (lineNo = -2; lineNo < 5; lineNo += 0.1) {
これはこれで…
いや、やっぱり気持ち悪いや。
最後にこうしてみましょう。
eHue = (map(eX, 0, 400, 0, 360 * 1) + map(abs(eY), 0, 200, 0, 360 * 1)) % 360;
なんか良い感じじゃありません?
abs() というのが出てきましたが、これは絶対値を計算してくれるものです。
-200 は 200 になるんで、範囲は 0 から 200 として、y 軸を対称に上下が同じ結果になるわけです。
lineNo がマイナスのときに色がマイナスになってしまうバグ、実はもうひとつバグがあって、
eR = lineNo;
ここで、円の大きさもマイナスになってました。
これを解決するには?
そう!
eR = abs(lineNo);
こうですね!天才!
はい、今回はここまでです。
今回は
map() 計算を楽にしてくれる
% 割り算の余りを出してくれる
abs() 絶対値を出してくれる
こんなに沢山覚えました!
遊び道具がまた増えましたね!
今回の最後の例のコードを掲載しておきます。新しい遊び道具を使ってまた遊んでみてください。
<html>
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/p5.js/0.7.2/p5.js"></script>
</head>
<body>
<script>
// Creative Commons CC0
// sc009 趣味としてのクリエイティブ・コーディング:009:もう面倒な計算しなくていいの
function setup() {
createCanvas(400, 400);
colorMode(HSB, 360, 100, 100, 100);
blendMode(SCREEN);
noStroke();
noLoop();
}
function draw() {
background(0, 0, 0, 100);
translate(40.0, height / 2.0);
prevWaveNo = 1;
for (waveNo = 1; waveNo <= 4; waveNo += 1) {
for (lineNo = -2; lineNo < 5; lineNo += 0.5) {
for (radians = 0; radians < TWO_PI; radians += 0.01) {
eX = radians * 25 * (prevWaveNo + waveNo - 1);
eY = -sin(radians) * radians * lineNo * waveNo * waveNo * 2.0;
eR = abs(lineNo);
eHue = (map(eX, 0, 400, 0, 360) + map(abs(eY), 0, 200, 0, 360)) % 360;
eSat = 100 - radians * 5;
eBri = radians * waveNo * waveNo * 3;
fill(
eHue,
eSat,
eBri,
100
);
ellipse(
eX,
eY,
eR,
eR
);
}
}
prevWaveNo = waveNo;
}
}
</script>
</body>
</html>
この記事が面白かったらサポートしていただけませんか? ぜんざい好きな私に、ぜんざいをお腹いっぱい食べさせてほしい。あなたのことを想いながら食べるから、ぜんざいサポートお願いね 💕