各位好久不見,著實過了好一陣子沒有更新processing的介紹了.
沒辦法,我只要一找到機會可以打懶可是從來都不客氣的,
所以最近都很心安理得的告訴自己因為要弄迪化街的東西,
沒有做processing介紹也是情非得已啦.
不過好景不常,昨天上課就被道德勸說是不是該繼續processing的研究了?
套用我爸的名句"伸頭是一刀,縮頭也是一刀",不如就乖乖繼續吧. :)
------------------------------------------------------------------------------------------------------------------
除了後來才補講的noise之外,
我們的課本進度已經來到如何以void來做2D的GIF動畫了.
http://tesignstudio.blogspot.com/2011/07/blog-post_917.html
而那一篇能含蓋的內容我覺得一該從p173-200應該看一看都會懂,
所以我就不多說了,不過還是自己做過一遍比較穩當囉.
唯一額外需要講的我覺得是p201-205的小單元, Recursion
Recursion顧名思義就是遞迴,循環.
因此我們可以簡單推測如果在使用這方法時,
沒有告訴電腦什麼時候停(一個終點)的話,那它就會一直算到電腦燒起來為止.
以下就先來一盤小菜讓大家簡單了解,p201的22-07.
void setup(){
size(200,200);
background(255);
smooth();
noLoop();
}
int a = 10; //a對應的是x
int b = 18; //b對應的是num
void draw(){
frameRate(10);
drawLines(a,b);
//saveFrame("p201-##.jpg");
}
void drawLines(int x, int num){
strokeWeight(x/30);
line(x,20,x,180);
if(num > 0){
drawLines(x+10,num-1);
}
}
最重要的部分就是
if(num > 0){
drawLines(x+10,num-1);
}
我們可以看到在drawLines這集合裡又跑了drawLines,
這意味著drawLines會先把自己內裡的drawLines都跑完,
之後才會再丟給上面的void draw去畫出來.(很饒舌我知道.)
所以到底它是怎麼跑的呢?
首先我們知道b = num = 18,
因此一開始跑就會符合if(num > 0)
因為每畫一次就會drawLines(x+10,num-1);
到減第18次時num都還會大於1,
同時還要加最原本的那條,所以線會依序畫19條,
至於x方面因為drawLines(x+10,num-1);因而為呈現為
line( x , 20 , x , 180 );
第00代 10 10
第01代 20 20
第02代 30 30
第03代 40 40
. .
. .
. .
第17代 180 180
第18代 190 190
所以我們知道recursion其實是在還未丟入void draw的集合內進行其內部的自行運算.
再來進階一點的是p203的22-10,以下
void setup(){
size(200,200);
background(255);
noStroke();
smooth();
noLoop();
}
int xx = 100;
int r = 85;
int n = 4;
void draw(){
drawCircles(xx,r,n);
//saveFrame("p203-##.jpg");
}
void drawCircles(int x, int radius, int num){
float tt = 200 * num/4;
fill(tt);
ellipse(x,100,radius*2,radius*2);
if(num > 1){
num -= 1;
drawCircles(x - radius/2, radius/2, num);
drawCircles(x + radius/2, radius/2, num);
}
}
在這部分最重要的是
if(num > 1){
num -= 1;
drawCircles(x - radius/2, radius/2, num);
drawCircles(x + radius/2, radius/2, num);
}
除了num的處理跟上面一個案例一樣之外,
我們可以看到在畫完第一個中心為(100,100)的大圓之後,
隨著recursion每次會畫兩個圓,其直徑為之前圓的一半,
同時其兩個圓的圓心會一往左一往右順x軸偏移,
移動大小為之前圓直徑的1/4.
所以最後我們可以看到因為總共算了4次,
除了原本大圓之外還分裂了3次,所以可以看到
1 + 2 + 4 + 8 = 15個大小不一的圓.
所以最後的終極魔王就是p204的22-11,
它不但用if的recursion,同時還在if中加了for,以下.
void setup(){
size(200,200);
background(255);
noStroke();
smooth();
}
int x = 100;
int y = 100;
int r = 50;
int n = 5;
void draw(){
frameRate(10);
drawCircle(x,y,r,n);
//if(frameCount < 200){
// saveFrame("p204-###.jpg");
//}
}
void drawCircle(float x, float y, int radius, int num){
float value = 126 * num / 6;
fill(value,153);
ellipse(x,y,radius*2,radius*2);
if(num > 1){
num = num - 1; // num的多少決定會算幾次
int branches = int (random(2,6)); //這更可怕,branch的多少決定它之後衍生的數量
for(int i = 0; i < branches; i += 1){
float a = random(0,TWO_PI);
float newx = x + cos(a) * 6 * num; //每次新的圓心x點會偏移
float newy = y + sin(a) * 6 * num; //每次新的圓心y點會偏移
drawCircle(newx,newy,radius/2,num);
}
}
}
如果還看不懂,嘗試把int n改小,而int branches也改成不要random,
同時在setup裡加上noLoop,好好看一張圖是怎麼運算的,可以幫助你理解.
所以只要稍做調整,我們也可以很輕易的做出類似潑油漆的畫作.
void setup(){
size(200,200);
background(255);
noStroke();
smooth();
}
int x = 100;
int y = 100;
int r = 50;
int n = 8;
int c = 0;
void draw(){
frameRate(100);
c += 1;
if(c>2){
background(255);
c = 0;
}
drawCircle(x,y,r,n);
//if(frameCount < 200){
// saveFrame("p204-2-###.jpg");
//}
}
void drawCircle(float x, float y, int radius, int num){
float value = 126 * num / 6;
fill(value,random(255),random(255),50);
ellipse(x,y,radius*2,radius*2);
if(num > 1){
num = num - 1;
int branches = int (random(2,6));
for(int i = 0; i < branches; i += 1){
float a = random(0,TWO_PI);
float newx = x + cos(a) * 6 * num;
float newy = y + sin(a) * 6 * num;
drawCircle(newx,newy,radius/2,num);
}
}
}
Try it. :)
沒有留言:
張貼留言