Processing.pyでアート #2 de Jong Attractor
せっかくpythonモードなので、なにかpythonっぽいことがしたい!
そんなわけでde Jongアトラクタです。
de Jong Attractor
x, y = sin(a*y) - cos(b*x), sin(c*x) - cos(d*y)
de Jongアトラクタは、上記の漸化式にしたがって点を打つことで描けるパターンです。詳しくはFALさんやdeconbatchさんが書いているので、そちらをどうぞ!
ジェネレータ
で、この「漸化式をもとに次々に点を生成する」って部分が、pythonモードだとジェネレータを使ってこんなふうに書けるのです。
def deJongAttractor(a, b, c, d):
x, y = random(1), random(1)
while True:
x, y = sin(a*y) - cos(b*x), sin(c*x) - cos(d*y)
yield x, y
return のかわりに yield で値を返すことで、呼び出されるたびに次々に値を返すジェネレータができるのです。カッコイイ!もとい、便利!
ただ、このジェネレータは無限に点を生み出し続けるので、呼び出し側で回数を決めて呼び出す必要があります。
だったらforループでいいじゃないか、という気もしますが、ジェネレータはひとつのオブジェクトなので、グローバル変数にして何度も使えるのが強み。Processingのdraw()関数で各フレーム1万点描画して、次のフレームでは前のフレームの続きから描画、みたいなことができます。
Processing.pyでde Jong Attractor
あとは多分、以下の実際のコードを見てもらうのが早いかもです。
乱数生成の部分に手を入れたので、deJongAttractor()の実装は上の例とはちょっと違います。
def setup():
size(360, 360)
colorMode(HSB, 360, 100, 100, 100)
blendMode(ADD)
pixelDensity(displayDensity()) # retinaディスプレイ対応
reset()
def reset():
background(0)
# グローバル変数を作る時はglobalで宣言する必要あり
global attractor, dot_color
attractor = deJongAttractor()
dot_color = color(random(360), 100, 100, 10)
def draw():
# 背景色を半透明にして重ねることで、昔の点を薄くしていく
noStroke()
fill(0, 20)
rect(0, 0, width, height)
# 点の描画
translate(width/2, height/2)
stroke(dot_color)
strokeWeight(1./displayDensity())
for i, (x, y) in enumerate(attractor):
point(x*width/4, y*height/4)
if i == 5e4:
break
print frameCount
def deJongAttractor():
# 乱数の取り方をこうするとレアキャラの排出率が上がる気がする
from random import choice
a, b, c, d, x, y = [choice([random(-2, -1), random(1, 2)]) for _ in range(6)]
while True:
# 複数変数への同時代入便利...!
x, y = sin(a*y) - cos(b*x), sin(c*x) - cos(d*y)
yield x, y
# ガチャを引き直したり、お気に入りの結果を保存したりする
def keyPressed():
if key == 'r': reset()
if key == 's': saveFrame("####.png")
keyPressed()関数を使って、"r"を押すたびに違うアトラクタを生成するので、"r"連打でde Jongアトラクタガチャを引くことができます。
このガチャはなんと無料なので、レアキャラ(面白いパターン)が出るまで何度でもトライできますよ!
この記事が気に入ったらサポートをしてみませんか?