---
# System prepended metadata

title: 5.p 條件 / 迴圈 與互動 - 建構創作規則(學生版)

---

0
---
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(var i=-5;i<6;i-i+1){
  //ellipse(mouseX+i*r,mouseY,r)
//}

//=========第一個程式碼(2)========
var r_num =13 //產生幾個圓<<奇數值>>
for(var i=1;i<r_num+1;i=i+1){
  ellipse(mouseX+(i-(r_num+1)/2)*r,mouseY,r)
}
}

```


---

for的解說

---

![](https://i.imgur.com/FHbIqHC.png)


---

```javascript=
var r_num=15
for(var k=r_num;k>0;k=k-1){
  fill(map(k,1,r_num,0,255),0,255)
  ellipse(width/2,height/2,k*r)
}



```

---

### 依照mouseX移動產生圓圈放大縮小

![](https://i.imgur.com/Xn18XVR.gif)


---

```javascript=
var r_num=25
//r = mouseX/20
strokeWeight(5)
stroke(122,0,255)
for(var k=r_num;k>0;k=k-1){
  fill(map(k,1,r_num,0,255),0,255)
  stroke(map(k,1,r_num,0,255),0,255)
  ellipse(width/2,height/2,k*r)
}

```


---

### 利用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=

var rect_size = 50
for(var x=0;x<width;x=x+rect_size){
  fill(random(255),random(255),random(255))
rect(x,height/2,rect_size,rect_size/2)
}

```

---

### 會一直變化顏色的方塊，改為固定顏色

![](https://i.imgur.com/fcCrQhu.gif)

把程式碼放在setup() 內

---

```javascript=

function setup() {
  createCanvas(windowWidth,windowHeight);
var rect_size = 50
for(var x=0;x<width;x=x+rect_size){
fill(random(255),random(255),random(255))
rect(x,height/2,rect_size,rect_size/2)
}
}
var r = 50

```
---

## 畫一面方框

![](https://i.imgur.com/3rfi70i.gif)



---



```javascript=

var rect_size = 50
function setup() {
  createCanvas(windowWidth,windowHeight);
  for(var y=0;y<height;y=y+rect_size){
    fill(random(255),random(255),random(255))  
//var rect_size = 50
for(var x=0;x<width;x=x+rect_size){
//fill(random(255),random(255),random(255))
rect(x,y,rect_size)
}
}
}

```

---

### 把方框長寬變小，比for間距來得小。

![](https://i.imgur.com/e3qekfF.gif)



---

改變雙迴圈內的指令
背景設定為黑色會比較好看(background(0); )

```javascript=

var rect_size = 50
function setup() {
  createCanvas(windowWidth,windowHeight);
  background(100)
  for(var y=0;y<height;y=y+rect_size){
    fill(random(255),random(255),random(255))  
//var rect_size = 50
for(var x=0;x<width;x=x+rect_size){
//fill(random(200,255),random(255),random(255))
rect(x,y,rect_size-10)
}
}
}
```


---

### 利用一個count變數，每次除以4取餘數如果為1，才顯示方框。

![](https://i.imgur.com/szndlQf.gif)


---


```javascript=

var rect_size = 50
var count = 0
function setup() {
  createCanvas(windowWidth,windowHeight);
  background(100)
  for(var y=0;y<height;y=y+rect_size){
  //fill(random(255),random(200,255),random(255))  
//var rect_size = 50
for(var x=0;x<width;x=x+rect_size){
  count = count+1
  if(count%4 ==1){
fill(random(255),random(200,255),random(255))
strokeWeight(3)
stroke(random(255),random(200,255),random(255))
rect(x,y,rect_size-6,rect_size-6,5)
}
}
}
}

```



---

### 利用一個count變數，每次除以4取餘數如果小於3，才顯示方框。

![](https://i.imgur.com/eLpUsyp.gif)


---

```javascript=
var rect_size = 50
var count = 0
function setup() {
  createCanvas(windowWidth,windowHeight);
  background(100)
  for(var y=0;y<height;y=y+rect_size){
  //fill(random(255),random(200,255),random(255))  
//var rect_size = 50
for(var x=0;x<width;x=x+rect_size){
  count = count+1
  if(count%4 <3){
fill(random(255),random(200,255),random(255))
strokeWeight(3)
stroke(random(255),random(200,255),random(255))
rect(x,y,rect_size-6,rect_size-6,5)
}
}
}
}


```

---

### 新增兩個圓圈在方塊中(一個比方框小的大圓全黑，另外一個更小的小圓，顏色為亂數產生)
利用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=
var rect_size = 50
var count = 0
function setup() {
  createCanvas(windowWidth,windowHeight);
  background(100)
  for(var y=0;y<height;y=y+rect_size){
  //fill(random(255),random(200,255),random(255))  
//var rect_size = 50
for(var x=0;x<width;x=x+rect_size){
  count = count+1
  if(count%4 <3){
fill(random(255),random(200,255),random(255))
strokeWeight(3)
stroke(random(255),random(200,255),random(255))
rect(x,y,rect_size-6,rect_size-6,5)
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/kfkNqnz.gif)


---

### 加上方框的線條顏色與線條寬度

```javascript=
    stroke(random(200,255),random(255),random(255))    
    strokeWeight(3) 
```

---

完整程式碼

```javascript=
var rect_size = 50
var count = 0
function setup() {
  createCanvas(windowWidth,windowHeight);
  background(100)
  for(var y=0;y<height;y=y+rect_size){
  //fill(random(255),random(200,255),random(255))  
//var rect_size = 50
for(var x=0;x<width;x=x+rect_size){
  count = count+1
  if(count%4 <3){
fill(random(255),random(200,255),random(255))
strokeWeight(3)
stroke(random(255),random(200,255),random(255))
rect(x,y,rect_size-6,rect_size-6,5)
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) //小圓
}
}
}
}
}
}
var r = 50
function draw() {
  //background(220);
  //=======第0個程式碼==========
  //ellipse(mouseX-5*r,mouseY,r)
  //ellipse(mouseX-4*r,mouseY,r)
  //ellipse(mouseX-3*r,mouseY,r)
  //ellipse(mouseX-2*r,mouseY,r)
  //ellipse(mouseX-1*r,mouseY,r) //左邊
  //ellipse(mouseX+0*r,mouseY,r)
  //ellipse(mouseX+1*r,mouseY,r) //右邊
  //ellipse(mouseX+2*r,mouseY,r)
  //ellipse(mouseX+3*r,mouseY,r)
  //ellipse(mouseX+4*r,mouseY,r)
  //ellipse(mouseX+5*r,mouseY,r)
  //=======第一個程式碼==========

//for(var i=-5;i<6;i-i+1){
//ellipse(mouseX+i*r,mouseY,r)
//}

//=========第一個程式碼(2)========
//var r_num =13 //產生幾個圓<<奇數值>>
//for(var i=1;i<r_num+1;i=i+1){
//ellipse(mouseX+(i-(r_num+1)/2)*r,mouseY,r)
//}
//=======第二個程式碼=============
//ellipse(width/2,height/2,1*r)
//ellipse(width/2,height/2,2*r)
//ellipse(width/2,height/2,3*r)
//ellipse(width/2,height/2,4*r)
//ellipse(width/2,height/2,5*r)
//ellipse(width/2,height/2,6*r)
//for(var j=1;j<7;j=j+1){
// ellipse(width/2,height/2,j*r)
//}
//+++++++++++++++++++++++++++++++++
//ellipse(width/2,height/2,6*r)
//ellipse(width/2,height/2,5*r)
//ellipse(width/2,height/2,4*r)
//ellipse(width/2,height/2,3*r)
//ellipse(width/2,height/2,2*r)
//ellipse(width/2,height/2,1*r)
//+++++++++++++++++++++++++++++++++
//var r_num=25
//r = mouseX/20
//strokeWeight(5)
//stroke(122,0,255)
//for(var k=r_num;k>0;k=k-1){
//fill(map(k,1,r_num,0,255),0,255)
// stroke(map(k,1,r_num,0,255),0,255)
// ellipse(width/2,height/2,k*r)
//}
//=============第三個程式碼==========
//var rect_size = 50
//for(var x=0;x<width;x=x+rect_size){
//fill(random(255),random(255),random(255))
//rect(x,height/2,rect_size,rect_size/2)
//}
}



```

---

### 透過滑鼠按下後，產生一個亂數顏色的圓
產生一個函數function mousePressed(){}

![](https://i.imgur.com/ac08QLL.gif)


---


```javascript=


```



---


![](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


---