
ジェネラティブアート作成時の頭のなか #AltEdu2022 3 日目
#AltEdu 2022 3 日目のお題は「住んでいる国や地域の文化的な風習をモチーフに…(中略)…例えば節分」とのこと。
コーディングチャレンジ #AltEdu2022 に多数ご参加いただき,ありがとうございます!2/3のお題は「住んでいる国や地域の文化的な風習をモチーフにコードを書いてみてください。例えば:節分」です.その他,恵方や旧正月などをモチーフに自由に想像を膨らませてコードで書いてみてください〜!🙌
— Processing Community Japan (@PCD_Tokyo) February 2, 2022
せっかくなので、例示されているように節分に関する作品を作ってみようと思う。節分と言えば豆まき。なので、パーティクルで豆まき的なアニメーションを…などと考えていたのだが、面白そうな絵が浮かばない。
さてどうしようか…と考えていると、節分と言えば鬼なので、鬼のお面でも作ってみようかと、ふと思いつく。お面と言えば NFT で話題の高尾先生の GenerativeMasks が有名である:
My first NFT art project "generativemasks" was launched today. The project uses p5.js to generate mask graphics from 10000 unique shapes and patterns.https://t.co/lKPv8zEBmu
— TAKAWO Shunsuke (@takawo) August 17, 2021
これをそのまま真似するわけにもいかない。とはいえ、実は私も 1 年以上前に、お面にも見えるような作品を作っていたりする。
#つぶやきProcessing
— Koji Saito (@KojiSaito) October 14, 2020
G=range
L=G(8)
def D(x,y,t,q):
for i in L:
if t&q:rect(x+i*4,y,4,4)
q/=2
R=lambda n:int(random(n))
P=[0x81,0x42,0x24,0x18]
size(500,500)
clear()
for t in G(100):
x=t%10;y=t/10
for i in L:D(x*50+8,y*50+i*4+8,P[R(4)]|P[R(4)],128)#dailycodingchallenge pic.twitter.com/3Qqg41qh64
この時は敵キャラに見えるドット絵ジェネレータであった訳だが、これに色を付けたり、別の色でアクセントを付けたりするとお面の様にもみえないことも無い(ちなみに、この方法で作成した作品は昨年度職場で出している冊子に掲載済みだったりする。#つぶやきProcessing をやっていると「何か(作品)出して」と言われても困ることはない)。上に示したコードを少し修正するだけで、効果を試せるのでざっと書いてみる:
G=range
L=G(8)
def D(x,y,t,q):
for i in L:
if t&q:rect(x+i*4,y,4,4)
q/=2
R=lambda n:int(random(n))
P=[0x81,0x42,0x24,0x18]
size(500,500)
clear()
colorMode(HSB,8)
for t in G(100):
x=t%10;y=t/10
fill(random(8),8,8)
for i in L:D(x*50+8,y*50+i*4+8,P[R(4)]|P[R(4)],128)
fill(random(8),8,8)
D(x*50+8,y*50+int(random(8))*4+8,P[R(4)]|P[R(4)],128)

なかなか面白い…と自分では思っているのだが、どうだろうか。全く余談であるが、ジェネラティブアート作りに限らず、作品を作る人は、ある程度の自画自賛能力は必要なんだと思う。その方が、作品つくりを楽しむことができると思う。
…話をもとに戻そう。つまり、ある線を対称に図形を描き、ベースの図形が描けたら ー これを顔の部分とみたて、後は目に相当する部分を線対称で描画すればよさそうだ。
ちなみに、バラエティに富むお面についての思いつきは、秋田県の男鹿半島にある なまはげ館の展示に影響を受けている(と思う)。それほど広くない地域で作られている伝統的なお面であるにも関わらず、こんなにも多くの種類があるのか!と驚いたことを今でも覚えている。
と、それはさておき、コードに起こしてみる。ランダムな三角形を線対称でいくつか描いて様子をみることとする:
size(500,500)
background(-1)
fill(255,0,0)
noStroke()
for i in range(30):
l=[ random(400) for t in range(6)]
triangle(*l)
l[0]=500-l[0]
l[2]=500-l[2]
l[4]=500-l[4]
triangle(*l)

なかなか良い感じではあるが、ちょっと描画位置が上すぎる。というわけで、リスト l の偶数要素が y 座標指定なので、偶数の時だけ +100 などして様子をみる:
size(500,500)
background(-1)
fill(255,0,0)
noStroke()
for i in range(30):
l=[ random(400)+t%2*50 for t in range(6)]
triangle(*l)
l[0]=500-l[0]
l[2]=500-l[2]
l[4]=500-l[4]
triangle(*l)

うん。なかなか良い感じになってきた。後は目を描けばなんとかなりそうだ。 #つぶやきProcessing 化することも考慮し、左右対称の図形を描く部分を関数 D として括りだしておく:
def D(w):
l=[ random(w)+t%2*50 for t in range(6)]
triangle(*l)
l[0]=500-l[0]
l[2]=500-l[2]
l[4]=500-l[4]
triangle(*l)
size(500,500)
background(-1)
fill(255,0,0)
noStroke()
for i in range(30):D(400)
fill(0)
D(200)

あとは #つぶやきProcessing として tweet するための文字数削減作業に入る。今回はあまり複雑なコードではないので、インデントの文字数を 1 文字に変更したら、特に修正する必要もなく #つぶやきProcessing と #AltEdu2022 タグ込みで 280 文字に収まってしまった。
こういう場合は、もう少し表現を豊かにしてみたくなる。triangle を T に、range を L にして(R は random 用にとっておく)、さらに文字数を圧縮する。そして、顔部分の三角形の描画の際には色を変えてより複雑な表現にしてみる:
T=triangle
L=range
R=random
def D(w):
l=[R(w)+t%2*50 for t in L(6)]
T(*l)
l[0]=500-l[0]
l[2]=500-l[2]
l[4]=500-l[4]
T(*l)
size(500,500)
background(-1)
colorMode(HSB,8)
noStroke()
for i in L(20):fill(0,8,R(4)+4);D(400)
fill(0)
D(200)

いい感じである。しかし、こうなってくると地の色である白色が気になってくる。こんなに眩しい白色である必要も無いようにも思える。であれば、いっそのことデフォルトの灰色にしてみたらどうか ー という考えが浮かんでくる。そうすれば background 関数の呼び出しも消去でき、#つぶやきProcessing 的にも嬉しい。さっそく、background 関数を削除して実行してみる:

なかなか落ち着いた感じになってきた。そうすると、色相も少し変化させたくなる。というわけで、色相を 0 固定ではなく、random(1) として若干変化させてみる:
T=triangle
L=range
R=random
def D(w):
l=[R(w)+t%2*50 for t in L(6)]
T(*l)
l[0]=500-l[0]
l[2]=500-l[2]
l[4]=500-l[4]
T(*l)
size(500,500)
colorMode(HSB,8)
noStroke()
for i in L(20):fill(R(1),8,R(4)+4);D(400)
fill(0)
D(200)

ちょっと赤鬼の雰囲気からは遠ざかってしまったが、これはこれで趣がある。
もうすこし赤系に寄せるため、色相の変動範囲を 0〜0.8 とし、目の位置ももう少し中央よりにするため、最後の関数 D の呼び出しパラメータを少し増やす。
T=triangle
L=range
R=random
def D(w):
l=[R(w)+t%2*50 for t in L(6)]
T(*l)
l[0]=500-l[0]
l[2]=500-l[2]
l[4]=500-l[4]
T(*l)
size(500,500)
colorMode(HSB,8)
noStroke()
for i in L(20):fill(R(.8),8,R(4)+4);D(400)
fill(0)
D(220)

なかなか良い感じの鬼の面ができたのではないだろうか(自画自賛)。まだまだ文字数削減できる ー つまり、もっとコードを詰め込むこともできるが、#AltEdu2022 3 日目はこの辺りで終わりにしようと思う。
#つぶやきProcessing #AltEdu2022 day 3
— Koji Saito (@KojiSaito) February 3, 2022
T=triangle
L=range
R=random
def D(w):
l=[R(w)+t%2*50 for t in L(6)]
T(*l)
l[0]=500-l[0]
l[2]=500-l[2]
l[4]=500-l[4]
T(*l)
size(500,500)
colorMode(HSB,8)
noStroke()
for i in L(20):fill(R(.8),8,R(4)+4);D(400)
fill(0)
D(220)#python pic.twitter.com/lq24mEiZ1t
それでは皆さん、良いジェネラティブアートライフを(ハンターチャンネル風)。