![見出し画像](https://assets.st-note.com/production/uploads/images/72286470/rectangle_large_type_2_dc7d81a9c5079492704acbd38dad1bce.png?width=1200)
ジェネラティブアート作成時の頭のなか #AltEdu2022 15 日目
#AltEdu2022 も気がつけば後半戦(?)となった。ここまでは何とか遅れずについていけているので、残りもこの調子で頑張ってみたく思う。
さて、本日のお題は「『懐かしさ』を感じるコード」とのこと。これもなかなか厳しい。ちなみに「懐かしい」で Google 画像検索をすると、レトロなおもちゃや家電などが表示されるが、「懐かしさ」(「懐かし『さ』」)で検索すると夕日の風景などが表示されるようになる。「懐かしい」と「懐かしさ」には差異があるということであり、これもなかかなに興味深い。
自分は何に懐かしさを感じるのだろう。そんなことも考えつつ、でも作品にするのであれば、できるだけ多くの人が懐かしさを感じるものが良いのだろう、とも思う。そんなことを考えていると、画像検索で表示されたように、夕日の景色が良いのではないかと考えがまとまった。
青空と雲は私の興味を惹く主題であるが、夕焼け空もまた興味を惹かれる主題の一つでもある。実際、過去にはこんな作品も制作している。
空をちょっと夕焼け気味にー、と思ったらあっと言う間に文字数超過し、つぶやきProcessing できませんでした。
— Koji Saito (@KojiSaito) May 13, 2020
表現&コードゴルフ共に難しい。
本作品のソースコードは、Web で公開予定です(こちらでも URL をツィートする予定です)。
お題:ロマンティック#dailycodingchallenge https://t.co/LbKWo9Xl2d pic.twitter.com/FG9JgHQ56A
今回は先日作成した空のコード(下記参照)を利用して、夕焼け空を作ってみようと思う。
#つぶやきProcessing#AltEdu2022
— Koji Saito (@KojiSaito) February 11, 2022
size(550,280);noStroke()
background(80,170,230)
K=150
R=random
for i in range(K*K):x=i%K;y=99-i/K;t=noise(x*.01,y*.02);t=pow(t,8)*8;fill(220,t*200);circle(x*4,y*3,9)
noFill();stroke(-1);x=0
for i in range(50):x+=R(20)+9;square(x,R(190)+50,R(7)+5) pic.twitter.com/OJiJUrlxTr
まず、空と雲の部分だけを取り出し、背景を夕日のように変更する:
size(550,280);noStroke()
background(200,50,60)
K=150
for i in range(K*K):
x=i%K
y=99-i/K
t=noise(x*.01,y*.02)
t=pow(t,8)*8
fill(220,t*200);circle(x*4,y*3,9)
![](https://assets.st-note.com/img/1644911718373-MuWQcbpwF3.png?width=1200)
単に赤い空になっただけである。まるでエヴァンゲリオンのセカンドインパクトである。
やはり空はグラデーションでないと夕焼けのようにはならない…気がする。というわけで、色を変えつつ水平線を描画することにより、夕焼け空のグラデーションを表現してみる。指向錯誤しつつ、パラメータを調整しつつ、ついでに雲の色も調整する。
size(550,280);noStroke()
for y in range(280):
stroke(y+10,y*y*.003,50-y*.5)
line(0,y,550,y)
noStroke()
K=150
for i in range(K*K):
x=i%K
y=99-i/K
t=noise(x*.01,y*.02)
t=pow(t,8)*8
fill(250,180,170,t*255+y*.01);circle(x*4,y*3,9)
![](https://assets.st-note.com/img/1644911997768-QI8y3YMZup.png?width=1200)
かなり良い感じになってきた。
絵としてはもう少し横長の方が良い気がするので(空に広がる夕焼けだし)、画像サイズを 600x280 にする(50 ピクセル増やす)。また、沈みゆく太陽もあった方が良いので、描画位置を試行錯誤をしつつ、それも描画する。単に描画しただけだと、単なる円になってしまうので、ブラーフィルタを少々適用しておく:
size(600,280);noStroke()
for y in range(280):
stroke(y+10,y*y*.003,50-y*.5)
line(0,y,600,y)
noStroke()
fill(240,255,99);circle(80,270,90)
filter(BLUR,2)
K=150
for i in range(K*K):
x=i%K
y=99-i/K
t=noise(x*.01,y*.02)
t=pow(t,8)*8
fill(250,180,170,t*255+y*.01);circle(x*4,y*3,9)
![](https://assets.st-note.com/img/1644912351797-3TSlNEQpjU.png?width=1200)
なかなか良い感じである。
この絵は冬の夕暮れを想定しており、私の記憶の中にある冬の夕暮れには、建物などのシルエットが存在している。町並みのシルエットを描くのは難しいので、ノイズ関数を使って山のシルエットを描いてみる。シルエットの色は単に黒ではなく、試行錯誤の末、暗い灰色とした。
size(600,280);noStroke()
for y in range(280):
stroke(y+10,y*y*.003,50-y*.5)
line(0,y,600,y)
noStroke()
fill(240,255,99);circle(80,270,90)
filter(BLUR,2)
K=150
for i in range(K*K):
x=i%K
y=99-i/K
t=noise(x*.01,y*.02)
t=pow(t,8)*8
fill(250,180,170,t*255+y*.01);circle(x*4,y*3,9)
stroke(40)
for i in range(600):
line(i,300-noise(i*.0045)*99,i,280)
filter(BLUR,1.2)
![](https://assets.st-note.com/img/1644912570981-8VeaoHAJo6.png?width=1200)
なかなか良い感じであるが、冬の雲はもう少し細長く、横長な印象がある(あくまでも私の主観であるが)。上記の画像の雲は、なんだか晩秋の雲を連想させる。というわけで、noise 関数に与える x と y の係数を調整する。より大きく変動すると、変化が激しくなるため雲は薄くなる。なので y の係数は x の係数よりも大きくする。x の係数の方も雲の広がり具合をみつつ、試行錯誤しながら調整する:
size(600,280);noStroke()
for y in range(280):
stroke(y+10,y*y*.003,50-y*.5)
line(0,y,600,y)
noStroke()
fill(240,255,99);circle(80,270,90)
filter(BLUR,2)
K=150
for i in range(K*K):
x=i%K
y=99-i/K
t=noise(x*.015,y*.07)
t=pow(t,8)*8
fill(250,180,170,t*255+y*.01);circle(x*4,y*3,9)
stroke(40)
for i in range(600):
line(i,300-noise(i*.0045)*99,i,280)
filter(BLUR,1.2)
![](https://assets.st-note.com/img/1644912794312-GifTnWkeHo.png?width=1200)
まだまだ改善できそうであるが、なんとか冬の夕暮れになったのではないかと思う。本日はこれを #つぶやきProcessing 化していこうと思う。
複数の場所で使用されている関数を1文字の変数に代入して使うことと、for ループの range を range(K*K) ですべて置き換える。というのも、空のグラデーションも山の稜線も十分に大きな値であれば、それらは画面の外に描画されるだけであり、静止画の場合は特に問題は発生しない(画像生成時間が長くなるが、一瞬待つ程度である)。このように変更したコードであっても、まだ文字数が多い:
C=circle
F=filter
S=stroke
K=150
L=range(K*K)
size(600,280);noStroke()
for y in L:S(y+10,y*y*.003,50-y*.5);line(0,y,600,y)
noStroke()
fill(240,255,99);C(80,270,90);F(BLUR,2)
for i in L:
x=i%K;y=99-i/K
t=noise(x*.015,y*.07)
t=pow(t,8)*8
fill(250,180,170,t*255+y*.01);C(x*4,y*3,9)
S(40)
for i in L:line(i,300-noise(i*.0045)*99,i,280)
F(BLUR,1.2)
よく見ると変数 t は 1 箇所でしか使用されていないので、使用箇所に展開する。
C=circle
F=filter
S=stroke
K=150
L=range(K*K)
size(600,280);noStroke()
for y in L:S(y+10,y*y*.003,50-y*.5);line(0,y,600,y)
noStroke()
fill(240,255,99);C(80,270,90);F(BLUR,2)
for i in L:
x=i%K;y=99-i/K
fill(250,180,170,pow(noise(x*.015,y*.07),8)*2040+y*.01);C(x*4,y*3,9)
S(40)
for i in L:line(i,300-noise(i*.0045)*99,i,280)
F(BLUR,1.2)
まだ 88 文字も多い。
仕方がないので、山の稜線の描画はあきらめよう。また、よく見ると最初の noStroke は不要である(すぐその後で、空のグラデーション表現のため stroke 関数を呼び出しているので)。
C=circle
F=filter
S=stroke
K=150
L=range(K*K)
size(600,280)
for y in L:S(y+10,y*y*.003,50-y*.5);line(0,y,600,y)
noStroke()
fill(240,255,99);C(80,270,90);F(BLUR,2)
for i in L:
x=i%K;y=99-i/K
fill(250,180,170,pow(noise(x*.015,y*.07),8)*2040+y*.01);C(x*4,y*3,9)
![](https://assets.st-note.com/img/1644914380929-sbSJZHAy3N.png?width=1200)
まだあと 11 文字減らさないといけない。
さて、どうしたものか。空のグラデーション描画での色指定で用いている式、y+10 は y+9 で近似できることに気がつく。いや、そもそも y (つまり y+0)でも絵にはあまり変化がない。なので、y+10 ではなく、単に y とする。y*.5 も y/2 で良い。y*y*.003 も 0.003≒1/300 なので、y*y/300 に変更する。
雲の描画部分にある noise 関数のところであるが、0.015≒1/66 であるので、x*.015 は x/66.0 で近似(実際のコードは x/66.)。2040 は 2000=2e3 で近似。そして noStroke を stroke(0,0) つまり S(0,0) で代理。
このような努力により、#つぶやきProcessing することができました。
#つぶやきProcessing#AltEdu2022
— Koji Saito (@KojiSaito) February 15, 2022
C=circle
F=filter
S=stroke
K=150
L=range(K*K)
size(600,280)
for y in L:S(y,y*y/300,50-y/2);line(0,y,600,y)
S(0,0)
fill(240,255,99);C(80,270,90);F(BLUR,2)
for i in L:x=i%K;y=99-i/K;fill(250,180,170,pow(noise(x/66.,y*.07),8)*2e3+y*.01);C(x*4,y*3,9) pic.twitter.com/GbH671EKH6
やれやれ。今日は #つぶやきProcessing の技法について、お伝えできたのでは?と思う。参考になれば幸いである。