--- tags: 程式設計,第四章,學生版,互動藝術程式創作入門,Creative Coding --- # 5.p 條件 / 迴圈 與互動 - 建構創作規則(學生版) --- ## 單元介紹 ### 目標 * 了解程式中達成重複的「for 迴圈」概念與常見的應用方式 * 了解如何在重複中套用規則與創造變化 * 嘗試不同的重複概念應用與變化 * 結合變數、使用者操作創作重複的作品 * 使用變數做出場景管理 --- ![](https://i.imgur.com/Bh9843h.gif) --- ```javascript= function setup() { createCanvas(windowWidth, windowHeight); background(255); } var r =100 function draw() { ellipse(mouseX-100,mouseY,r,r) ellipse(mouseX,mouseY,r,r) ellipse(mouseX+100,mouseY,r,r) } ``` --- 可多一些圓圈(七個圓) ![](https://i.imgur.com/if0q9oE.gif) --- ```javascript= function setup() { createCanvas(windowWidth, windowHeight); background(255); } var r =100 function draw() { ellipse(mouseX-300,mouseY,r,r) ellipse(mouseX-200,mouseY,r,r) ellipse(mouseX-100,mouseY,r,r) ellipse(mouseX,mouseY,r,r) ellipse(mouseX+100,mouseY,r,r) ellipse(mouseX+200,mouseY,r,r) ellipse(mouseX+300,mouseY,r,r) } ``` --- 改寫以上程式碼(七個圓) ```javascript= ``` --- for的解說 --- ![](https://i.imgur.com/FHbIqHC.png) --- ```javascript= ``` --- ### 依照mouseX移動產生圓圈放大縮小 ![](https://i.imgur.com/Xn18XVR.gif) --- ```javascript= function setup() { createCanvas(windowWidth, windowHeight); background(255); } var r=40 function draw() { background(255); for(var i=0;i<10;i=i+1){ fill(map(i,0,9,0,255),0,255) // map(i,0,9,0,200),255) ellipse(width/2, height/2, r*(10-i)+map(mouseX,0,width,0,600)); } } ``` --- ### 利用map指令,把滑鼠的X軸數值改用為 ```javascript= ellipse(width/2,height/2,width-i*25-map(mouseX,0,width,0,20)) //用這樣的方式最好 ``` --- * 把fill顏色改為noFill * 把線條寬度改為strokeWeight(5) * 線條顏色改stroke(map(i,0,10,0,255),0,255) * 把迴圈改為50大小 --- ![](https://i.imgur.com/uEidIQm.gif) --- ```javascript= ``` --- ### 利用fill(random(255),random(255),random(255))改變顏色,畫一排長高為50方框 ![](https://i.imgur.com/sNfgqRa.gif) --- ```javascript= ``` --- ### 會一直變化顏色的方塊,改為固定顏色 ![](https://i.imgur.com/fcCrQhu.gif) 把程式碼放在setup() 內 --- ```javascript= ``` --- ## 畫一面方框 ![](https://i.imgur.com/3rfi70i.gif) --- ```javascript= ``` --- ### 把方框長寬變小,比for間距來得小。 ![](https://i.imgur.com/e3qekfF.gif) --- 改變雙迴圈內的指令 背景設定為黑色會比較好看(background(0); ) ```javascript= ``` --- ### 利用一個count變數,每次除以4取餘數如果為1,才顯示方框。 ![](https://i.imgur.com/szndlQf.gif) --- ```javascript= function setup() { createCanvas(windowWidth, windowHeight); background(0); var count=0; for(var x=0;x<width;x+=50){ for(var y=0;y<height;y+=50){ count=count+1 if(count%4==1) { fill(random(200,255),random(255),random(255)) rect(x,y,40) } } } } function draw() { } ``` --- ### 利用一個count變數,每次除以4取餘數如果小於3,才顯示方框。 ![](https://i.imgur.com/eLpUsyp.gif) --- ```javascript= ``` --- ### 新增兩個圓圈在方塊中(一個比方框小的大圓全黑,另外一個更小的小圓,顏色為亂數產生) 利用random()取得0到1間的數據,來機率性的產生 ```javascript= if (random()<0.5){ fill(0) ellipse(x+20,y+20,20) if (random()<0.5){ fill(random(200,255),random(255),random(255)) ellipse(x+20,y+20,10) } } ``` --- ![](https://i.imgur.com/fosUBaH.gif) --- 完整程式碼 ```javascript= function setup() { createCanvas(windowWidth, windowHeight); background(0); var count=0; for(var x=0;x<width;x+=50){ for(var y=0;y<height;y+=50){ count=count+1 if(count%4==3) { fill(random(255),random(255),random(255)) rect(x,y,40) if(random()<0.5){ fill(0) ellipse(x+20,y+20,20)} if(random()<0.5){ fill(255) ellipse(x+20,y+20,10)} } } } } ``` --- ![](https://i.imgur.com/kfkNqnz.gif) --- ### 加上方框的線條顏色與線條寬度 ```javascript= stroke(random(200,255),random(255),random(255)) strokeWeight(3) ``` --- 完整程式碼 ```javascript= function setup() { createCanvas(windowWidth, windowHeight); background(0); var count=0; for(var x=0;x<width;x+=50){ for(var y=0;y<height;y+=50){ count=count+1 if(count%4==3) { fill(random(255),random(255),random(255)) rect(x,y,40) if(random()<0.5){ fill(0) ellipse(x+20,y+20,20)} if(random()<0.5){ fill(255) ellipse(x+20,y+20,10)} } } } } ``` --- ### 透過滑鼠按下後,產生一個亂數顏色的圓 產生一個函數function mousePressed(){} ![](https://i.imgur.com/ac08QLL.gif) --- ```javascript= function setup() { createCanvas(windowWidth, windowHeight); background(100); } function draw() { //ellipse(mouseX, mouseY, 20, 20); } function mousePressed(){ var r=random(20,50); fill(random(255),random(200,255),random(100,200)) ellipse(mouseX,mouseY,r) } ``` --- ![](https://i.imgur.com/GIOjUWl.gif) --- ### 用一個for指令來做每隔5畫一個圓,一次共畫十個圓 ```javascript= ``` --- ### 為了讓第一個圓最大,慢慢變小往上堆 利用r*=0.9,讓半徑越來越小 ![](https://i.imgur.com/RWLxmEy.gif) --- ```javascript= ``` --- ### 高度都為10,可以設定為5到15圈的高度 ```javascript= var count = int(random(5,15)) ``` --- 完整程式碼 ```javascript= ``` --- ### 產生有大有小的圓柱體 ![](https://i.imgur.com/1Aaf4Lb.gif) --- ```javascript= ``` --- ## 滑鼠移動變動 ![](https://i.imgur.com/xjuB89J.gif) --- 改了"滑鼠按下"變成"滑鼠移動" 每個圓圈相距利用亂數設定-50到50,xy軸距離都有改變 ```javascript= ``` --- 讓滑鼠移動越快,擴大的圈會越大 ![](https://i.imgur.com/Jcdaxz2.gif) --- * pmouseX,pmouseY為前一個滑鼠座標 * 利用dist(pmouseX,pmouseY,mouseX,mouseY)取得距離值 * 利用sqrt取開根號值,避免值太大 * 然後乘以一個數字 --- ```javascript= ``` --- ### 按一下mouse就可以改變一個筆刷 由小點,按一下滑鼠後,變成方框,再按一下滑鼠後,變成圓,再按一下又回到小點,以此類推.... ![](https://i.imgur.com/1Py9pZK.gif) --- * 設定一個mode變數 --- ```javascript= ``` --- ### 課程重點 #### 程式中的重複 - for 迴圈 ```javascript= // for 的基本語法結構 for(計數變數的起始狀態; 結束條件; 每次結束後變數如何變化) { 概念相同,需要重複執行的事情 } ``` 所以如果我們要水平間隔每 100px 畫一個圓,共三次的話 下面兩種寫法的結果會是一樣的: 寫法一:手動複製貼上=人工迴圈 ```javascript= ellipse(0,100,30,30) ellipse(100,100,30,30) // 相較於上面,右移動了 100 px ellipse(200,100,30,30) // 相較於上面,又右移動了 100 px ``` 寫法二:使用程式語言的 for 迴圈 ```javascript= for(var i=0; i<3 ; i++){ ellipse(100*i, 100, 30, 30) // 計數變數 i 只要小於 3 時都會做這件事,直到不滿足條件則停下並跳出該程式區塊 } ``` 進階技巧:多層 for 迴圈 一層的 for 迴圈中還可以再包另一層,如此可以做更複雜的重複~ ```javascript= for(var i=0; i<2; i++){ for(var j=0; j<2; j++){ // 在每一個 i 中,都會這層迴圈完再跳往下一個 i ellipse(50*i, 50*j, 40) // 分別於 (50*i, 0) 和 (50*i, 50) 畫圓,畫完之後再往下一個 i 繼續重複 } } ``` --- ## 範例練習 * [創造線框感的圓](https://openprocessing.org/sketch/889973):使用多個圓形重複堆疊起來,使用了 map() 把讓重疊的圓行邊框出現漸層,再控制滑鼠的位置,改變圓形的大小。 ![](https://i.imgur.com/xxI2qHd.gif) ```javascript= function setup() { createCanvas(windowWidth, windowHeight); background(100); } function draw() { background(0) let r = 100 for(var i=0;i<50;i++){ print(i) noFill() strokeWeight(5) stroke(map(i,0,10,0,255),0,255) ellipse(width/2,height/2,800-i*25-i*map(mouseX,0,width,0,20) ) } // ellipse(mouseX-200, mouseY, r, r); // ellipse(mouseX-100, mouseY, r, r); // ellipse(mouseX, mouseY, r, r); // ellipse(mouseX+100, mouseY, r, r); // ellipse(mouseX+200, mouseY, r, r); } ``` * [重複且規律排列的網格系統](https://openprocessing.org/sketch/889991) 自己定義一些會影響畫面隨機性的變數,例如讓 count 從 0 開始數,每執行完一次 for 迴圈就 +1,而在迴圈內如果對 count 取餘數(%),符合特定條件才繪製,就會創造出有規律的排列感覺。最後再對顏色與內部色塊做點隨機變化,就完成多樣的網格畫面了! ![](https://i.imgur.com/K58WBuz.png) ```javascript= function setup() { createCanvas(windowWidth, windowHeight); background(0); noStroke() var count=0 for(var x=0;x<width;x+=50){ for(var y=0;y<height;y+=50){ count+=1 fill(random(200,255),random(255),random(255)) stroke(random(200,255),random(255),random(255)) strokeWeight(3) if (count%5<4){ rect(x,y,40,40,5) if (random()<0.5){ fill(0) noStroke() ellipse(x+20,y+20,20) if (random()<0.5){ fill(random(200,255),random(255),random(255)) ellipse(x+20,y+20,10) } } } } } } function draw() { // ellipse(mouseX, mouseY, 20, 20); } ``` * [山脈筆刷](https://openprocessing.org/sketch/889995) 將一群大小有隨機與特定比例變化的圈圈堆疊起來,看起來就像是一座座的山⛰ ![](https://i.imgur.com/1Aaf4Lb.gif) * [狀態變換的筆刷](https://openprocessing.org/sketch/889996) 筆刷的部分加入了前一禎圖片的滑鼠位置(pmouseX, pmouseY),與當前的滑鼠位置做距離計算(dist),藉由 dist 的大小來決定噴濺的距離。另外加上點擊滑鼠之後可以改變繪圖狀態,切換噴灑、圓形、方形的繪製結果。 ![](https://i.imgur.com/sUHsJDX.gif) ## 內容回顧 ### 常見的重複使用手法 * 改變物件大小、方向、時間、頻率 * 重複粒子、文字、符號、紋理、以及動作等 * 善用重複可以讓畫面看起來有整體感 ### 可以利用的創作小技巧 * 用 random() 時限制某個顏色的範圍,可讓畫面的色相更一致但又具有不同變化,如:color(random(200,255), 150 , 250) * 利用變數,如宣告一個 count,讓程式能夠根據方塊的編號製造規律變化,甚至再進一步利用 % 取餘數、frameCount 等創造更豐富圖形 * 加入隨機的繪圖要素,例如: ```javascript= if(random()<0.5){ ellipse() // 一半的機率會畫出圓 } ``` * 偵測滑鼠移動速度,來製造類似噴濺的效果。例如使用 dist 來取得 (pmouseX, pmouseY) 與 (mouseX, mouseY) 的距離,隨著移動距離的遠近來決定筆刷粒子的分散程度。 * 可以利用sqrt 收斂一下計算出來的數值,以免粒子們太過分散 * 也可以再乘以某個數字,以更細緻的控制散度 * 善用變數及 if/else 條件判斷來設定不同的場景狀態,以產生不同的繪圖行為。比方可以切換筆刷的型態、畫筆 & 橡皮擦之類的操作,例如: ```javascript= var mode = 1 // 設定 mode 這個狀態計數變數。我們預計定在 1~3 之間切換 // 這邊設定狀態對應的繪圖方式 if(mode ){ rect(mouseX, mouseY, 100,100) // 如果是 1 的話,就畫方形 }else if(mode == 2){ ellipse(mouseX, mouseY, 100,100) // 如果是 2 的話,就畫圓形 }else{ point(mouseX, mouseY) // 其餘狀況就畫點。在這個例子裡面是指 mode 為 3 時 } // 這邊設定如何改變狀態計數。讓狀態在一定的區間內跳動 function mousePressed(){ mode++ // 每當點擊滑鼠,狀態計數就加 1 if (mode>3){ mode=1 // 如果狀態超過 3 就切換回 1 } } ``` ## 新的 p5 語法(能力解鎖!) ### 抓取使用者的操作行為 * mousePressed():當滑鼠點擊的時要執行的動作 * mouseMoved():當滑鼠移動的時候要執行的動作 * keyPressed() * keyTyped() * mouseReleased():相對於 mousePressed(),是負責偵測使用者放開點擊的動作 ### 畫布操作 * rotate():旋轉當前的畫布。 * scale():縮放當前的畫布。 * translate():平移當前的畫布。 ### 數值運算 * dist():取得兩點間的距離。給兩點的 x 與 y 位置,回傳相對的距離長度。 * floor() / ceil() * min() / max() * abs() * sqrt():取某值的平方根 * pmouseX / pmouseY:是變數,存著前一禎時的滑鼠位置。 ### 圖形繪製補充 * 矩形的圓角設定:rect() 的第 5~8 個之後的參數(們)。 ## 課後問題 ### 課後作業 圖騰、花磚、樹葉、花園、波浪甚至是人群,有什麼是具備重複概念的場景呢?使用用程式把他們呈現出來吧! ## 延伸閱讀 ### function 的概念 function() 跟 property的差別?(函式 vs 變數) --- - 核心概念 - 如何重複動作? - 如何再重複中創造不同與套用規則? - 有哪些不一樣的重複方式 - 重複與條件或變數的結合 - 如何讓作品有更多不同形式的互動 - 如何管理利用變數管理場景 - 案例 ![](https://i.imgur.com/i6WVwG4.jpg) https://www.epochtimes.com/b5/17/10/2/n9693014.htm https://www.pinterest.com/search/pins/?q=generative&rs=typed&term_meta[]=generative%7Ctyped ![](https://i.imgur.com/nIBFsOB.jpg) ![](https://i.imgur.com/CkyOmcu.jpg) https://www.openprocessing.org/sketch/859999 ![](https://i.imgur.com/o2Ipa6c.png) https://www.openprocessing.org/sketch/881611 ![](https://i.imgur.com/mpSl0yN.jpg) https://www.openprocessing.org/sketch/880483 https://www.pinterest.com/search/pins/?q=Textile%20patterns&rs=autocomplete_bubble&b_id=BCJbOvr0wqY_AAAAAAAAAACQHHazYOT-gVVCYQtg6OJsLuFSjCxjANcln4VGNHtmbYlrSUxqlP98U-8JV6OjwXQc0t7nsnvwEVjxitaI2E_M&source_id=Z0g5Lb1l - 重複動作 - 迴圈 - 重複 - 帶參數的重複 - 條件 - 創作心法 - 韻律與規則 - 粒子 - 層次 - 隔線系統 - 對比性與獨特 - 細節 - 條件執行 - if / else if / else - && || ![](https://i.imgur.com/K58WBuz.png) https://www.openprocessing.org/sketch/889991 - 使用迴圈與陣列繪製連續圖形 - for(初始條件;結束條件;每次變化) - for(var i=0;i<10;i++) - https://www.openprocessing.org/sketch/889973 ![](https://i.imgur.com/7M4gtJU.png) ![](https://i.imgur.com/WPqVHa6.jpg) https://www.instagram.com/the_real_theory/ - 滑鼠位置的抓取和點擊 - function mousePressed - function mouseReleased - function keyPressed - function keyTyped() - pmouseX / pmouseY / mouseX / mouseY ![](https://i.imgur.com/LqikGIR.png) https://www.openprocessing.org/sketch/570597 ![](https://i.imgur.com/G0M3TJs.png) https://www.openprocessing.org/sketch/889995 - 數學計算 - dist - floor / ceil - min / max - abs - sqrt - scene / mode 場景管理 - 狀態機 ![](https://i.imgur.com/lipja4V.png) https://www.openprocessing.org/sketch/889996 - 補充工具 - Translate https://www.openprocessing.org/sketch/888896 - 範例延伸 - 迴圈之山 ![](https://i.imgur.com/mlsYVFM.jpg) https://www.openprocessing.org/sketch/890072 --- 5.p 條件 / 迴圈 與互動 - 建構創作規則(學生版).md 目前顯示的是「5.p 條件 / 迴圈 與互動 - 建構創作規則(學生版).md」。