Processingで再帰の勉強
人生で初めて、再帰ってものを使ってみました。上のやつがソレです。
今まで趣味でやってたゲーム開発では、再帰関数を使用する場面はなかったのですが
processingでジェネラティブアートを創作するには、知ってないとまずいヤツです。
端的に説明すると、関数の中に同じ関数を生成するというもので
一度その関数を呼び出すと延々と同じ関数が実行されるという、危険な代物です。
実使用の際は、関数の繰り返し回数を制限し、無限ループには陥らないよう注意が必要です。
今まで馴染みのない考えだったので、
参考書読みつつもなかなかうまくいかず、
夜更かしして睡眠不足に。
それでも不思議なことに、
一晩もソースコードとにらめっこしていると
だんだんと概念が体の芯に染み込んできて
ソースコードが頭でビジュアル化されていく感覚になり
上手く再帰を扱えるようになりました。
再帰は指数関数的に処理が増えていくので
パラメーター変更すると、processingの表示がしばしば表示されなくなりました。
原因がソースコードなのかPCの非力さなのかがわからず、 時間を浪費しました。
ソースは以下。
final int startBranchNum = 3; Branch[] branch = new Branch[startBranchNum]; void setup() { size(1600, 1200); background(255); smooth(); noStroke(); frameRate(10); for (int i=0; i<startBranchNum; i++) { branch[i] = new Branch(0, width/2, 300, 90, true); } } void draw() { for (int i=0; i<startBranchNum; i++) { branch[i].updateMe(); } } class Branch { final float branchLength; final float maxAngleRange = 180; final float colBase = 100; final float colRandom = 155; final int maxCounter = 100; final float branchAlpha = 20; final float branchWidth = 10; final int childNum = 2; float startX; float startY; float stopX; float stopY; float branchAngle; color branchColor = color(random(colRandom)+colBase, random(colRandom)+colBase, random(colRandom)+colBase, branchAlpha); int myGeneration; int stopGeneration = 7; int maxCnt = 20; int cnt = 0; boolean goBranch; Branch[] children = new Branch[0]; Branch(int myGen, float motherStopX, float motherStopY, float motherAngle, boolean go) { branchLength = 150/(myGen+1) + 70; goBranch = go; startX = motherStopX; startY = motherStopY; myGeneration = myGen; branchAngle = random(maxAngleRange); float angle = branchAngle%maxAngleRange - maxAngleRange/2 + motherAngle;//Go to Lower stopX = startX + cos(radians(angle))*branchLength; stopY = startY + sin(radians(angle))*branchLength; if (myGeneration < stopGeneration) { children = new Branch[childNum]; for (int i = 0; i < childNum; i++) { children[i] = new Branch(myGeneration+1, stopX, stopY, angle, false); } } } void updateMe() { if (goBranch == true && cnt<maxCnt) { stroke(branchColor); strokeWeight(branchWidth); float posX; float posY; posX = (stopX - startX)*cnt/maxCnt + startX; posY = (stopY - startY)*cnt/maxCnt + startY; line(startX, startY, posX, posY); cnt++; } if (myGeneration < stopGeneration) { for (int i = 0; i < childNum; i++) { if (cnt == maxCnt) { children[i].goBranch = true; } children[i].updateMe(); println("children's StopX is "+ children[i].stopX); println("children's StartX is "+ children[i].startX); } } } }