接下來我選擇4個作品逐步完成上述圖片院喜,在processing上寫亡蓉,并做出一些代碼優(yōu)化。
難度一:
原理很簡單喷舀,追蹤鼠標坐標畫圓就是了砍濒。
void draw1(){
if(mousePressed) {
strokeWeight( 3 );
circle( mouseX, mouseY, size );
}
}
難度二:根據(jù)速度改變圓的大小
定義圓的大小與速度成反比
v += sqrt( Veloc.x*Veloc.x + Veloc.y*Veloc.y ) - v; // ADD
v *= 0.6;
float r = size - v; // ADD
定義畫筆速度同當前幀與上一幀的位置差成正比
Veloc.x += ( mouseX - Pos.x ) * spring;
Veloc.y += ( mouseY - Pos.y ) * spring;
Veloc.x *= friction;
Veloc.y *= friction;
代碼中spring參數(shù)與friction參數(shù)分別模擬了筆刷的慣性與摩擦力,但是效果不怎么理想硫麻,兩個參數(shù)效果的區(qū)別不明顯爸邢,都是值小了畫筆運動慢,值大了畫筆運動快拿愧。杠河。。可能是我太頓感了吧券敌,看不出區(qū)別唾戚。
下圖中上方的筆跡是摩檫力較大的時候,下方筆記是較小的時候待诅,可以看出畫圓的數(shù)量不同
難度三:模擬毛筆刷叹坦,實現(xiàn)連貫
最初看例子的時候玩到這里就一直很好奇要如何讓圓連續(xù)地生成,這么想是因為看到前面畫圓的Demo里卑雁,當鼠標運動慢時募书,多個圓彼此重疊,就很有毛筆筆跡的效果序厉,所以猜測后面的筆跡應當讓圓生成地更連貫锐膜,類似于插值操作,但怎么做呢弛房?
答案是:直接畫線就行了道盏,那么麻煩干什么![/黑臉]
當然文捶,插值還是要做的荷逞,主要的工作是平滑筆刷的大小變化,讓兩幀的筆刷大小有一定數(shù)量的過渡值粹排,代碼如下:
for( int i = 0; i < splitNum; ++i ) { // ADD
oldX = Pos.x;
oldY = Pos.y;
Pos.x += Veloc.x/splitNum; // AMEND: vx -> vx/splitNum
Pos.y += Veloc.y/splitNum; // AMEND: vy -> vy/splitNum
oldR += (r-oldR)/splitNum; // ADD
if(oldR < 1) { oldR = 1; } // AMEND: r -> oldR
strokeWeight( oldR ); // AMEND: r -> oldR
line( Pos.x, Pos.y, oldX, oldY );
} // ADD
但這個畫筆的變化也不是那么平滑种远。。
難度四:模擬筆刷分叉
這個是當時看起來最炫酷的效果顽耳,但了解后坠敷,原理很簡單,只要細心觀察一下分叉部分線的數(shù)量射富,都是三膝迎。。胰耗。限次。
那就很簡單了,將上面畫線的函數(shù)復制兩個柴灯,定義一個位移變量卖漫,令該變量同速度成正比,也就是說當速度小時赠群,位移小羊始,三條線混合在一起,當速度增大查描,位移增大店枣,三條線分離開就有分叉的效果遼
for( int i = 0; i < splitNum; ++i ) { // ADD
oldX = Pos.x;
oldY = Pos.y;
Pos.x += Veloc.x/splitNum; // AMEND: vx -> vx/splitNum
Pos.y += Veloc.y/splitNum; // AMEND: vy -> vy/splitNum
oldR += (r-oldR)/splitNum; // ADD
if(oldR < 1) { oldR = 1; } // AMEND: r -> oldR
strokeWeight( oldR+diff ); // AMEND: r -> oldR
line( Pos.x, Pos.y, oldX, oldY );
strokeWeight( oldR ); // ADD
line( Pos.x+diff*2, Pos.y+diff*2, oldX+diff*2, oldY+diff*2 ); // ADD
line( Pos.x-diff, Pos.y-diff, oldX-diff, oldY-diff );
} // ADD
效果如下:
至此目標達成速警,但還有一些問題:
1.筆刷不夠平滑,三條分叉也太僵硬了點
2.代碼也不夠簡潔
有時間再優(yōu)化吧鸯两。闷旧。。好累钧唐,作業(yè)好多忙灼。。