---
tags: 程式設計,第四章,學生版,互動藝術程式創作入門,Creative Coding
---
# 5.p 條件 / 迴圈 與互動 - 建構創作規則(學生版)
---
## 單元介紹
### 目標
* 了解程式中達成重複的「for 迴圈」概念與常見的應用方式
* 了解如何在重複中套用規則與創造變化
* 嘗試不同的重複概念應用與變化
* 結合變數、使用者操作創作重複的作品
* 使用變數做出場景管理
---

---
```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)
}
```
---
可多一些圓圈(七個圓)

---
```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的解說
---

---
```javascript=
```
---
### 依照mouseX移動產生圓圈放大縮小

---
```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大小
---

---
```javascript=
```
---
### 利用fill(random(255),random(255),random(255))改變顏色,畫一排長高為50方框

---
```javascript=
```
---
### 會一直變化顏色的方塊,改為固定顏色

把程式碼放在setup() 內
---
```javascript=
```
---
## 畫一面方框

---
```javascript=
```
---
### 把方框長寬變小,比for間距來得小。

---
改變雙迴圈內的指令
背景設定為黑色會比較好看(background(0); )
```javascript=
```
---
### 利用一個count變數,每次除以4取餘數如果為1,才顯示方框。

---
```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,才顯示方框。

---
```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)
}
}
```
---

---
完整程式碼
```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)}
}
}
}
}
```
---

---
### 加上方框的線條顏色與線條寬度
```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(){}

---
```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)
}
```
---

---
### 用一個for指令來做每隔5畫一個圓,一次共畫十個圓
```javascript=
```
---
### 為了讓第一個圓最大,慢慢變小往上堆
利用r*=0.9,讓半徑越來越小

---
```javascript=
```
---
### 高度都為10,可以設定為5到15圈的高度
```javascript=
var count = int(random(5,15))
```
---
完整程式碼
```javascript=
```
---
### 產生有大有小的圓柱體

---
```javascript=
```
---
## 滑鼠移動變動

---
改了"滑鼠按下"變成"滑鼠移動"
每個圓圈相距利用亂數設定-50到50,xy軸距離都有改變
```javascript=
```
---
讓滑鼠移動越快,擴大的圈會越大

---
* pmouseX,pmouseY為前一個滑鼠座標
* 利用dist(pmouseX,pmouseY,mouseX,mouseY)取得距離值
* 利用sqrt取開根號值,避免值太大
* 然後乘以一個數字
---
```javascript=
```
---
### 按一下mouse就可以改變一個筆刷
由小點,按一下滑鼠後,變成方框,再按一下滑鼠後,變成圓,再按一下又回到小點,以此類推....

---
* 設定一個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() 把讓重疊的圓行邊框出現漸層,再控制滑鼠的位置,改變圓形的大小。

```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 取餘數(%),符合特定條件才繪製,就會創造出有規律的排列感覺。最後再對顏色與內部色塊做點隨機變化,就完成多樣的網格畫面了!

```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://openprocessing.org/sketch/889996) 筆刷的部分加入了前一禎圖片的滑鼠位置(pmouseX, pmouseY),與當前的滑鼠位置做距離計算(dist),藉由 dist 的大小來決定噴濺的距離。另外加上點擊滑鼠之後可以改變繪圖狀態,切換噴灑、圓形、方形的繪製結果。

## 內容回顧
### 常見的重複使用手法
* 改變物件大小、方向、時間、頻率
* 重複粒子、文字、符號、紋理、以及動作等
* 善用重複可以讓畫面看起來有整體感
### 可以利用的創作小技巧
* 用 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://www.epochtimes.com/b5/17/10/2/n9693014.htm
https://www.pinterest.com/search/pins/?q=generative&rs=typed&term_meta[]=generative%7Ctyped


https://www.openprocessing.org/sketch/859999

https://www.openprocessing.org/sketch/881611

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://www.openprocessing.org/sketch/889991
- 使用迴圈與陣列繪製連續圖形
- for(初始條件;結束條件;每次變化)
- for(var i=0;i<10;i++)
- https://www.openprocessing.org/sketch/889973


https://www.instagram.com/the_real_theory/
- 滑鼠位置的抓取和點擊
- function mousePressed
- function mouseReleased
- function keyPressed
- function keyTyped()
- pmouseX / pmouseY / mouseX / mouseY

https://www.openprocessing.org/sketch/570597

https://www.openprocessing.org/sketch/889995
- 數學計算
- dist
- floor / ceil
- min / max
- abs
- sqrt
- scene / mode 場景管理
- 狀態機

https://www.openprocessing.org/sketch/889996
- 補充工具
- Translate https://www.openprocessing.org/sketch/888896
- 範例延伸 - 迴圈之山

https://www.openprocessing.org/sketch/890072
---
5.p 條件 / 迴圈 與互動 - 建構創作規則(學生版).md
目前顯示的是「5.p 條件 / 迴圈 與互動 - 建構創作規則(學生版).md」。