# 第五周
---
tags: 程式設計,第三章,學生版,互動藝術程式創作入門,Creative Coding
---
# 4.P 變數與資料 - 賦予可變與連續性(學生版)
## 單元介紹
我們會學到
* 了解「變數」是什麼
* 我們為什麼要使用變數
* 如何使用變數及注意事項
* 進階操作變數使創作更有效率、更有趣
- 什麼是變數?
- 為什麼要用變數
- 開一個櫃子 放會使用到的東西
---
## 程式碼開講
### 產生三個圓

---
```javascript=
ellipse(width/2,height/3,mouseX)
ellipse(width/2,height/2,mouseX)
ellipse(width/2,height*2/3,mouseX)
```
---
### 由滑鼠游標的左右座標控制圓大小
---

---
```javascript=
function draw() {
//background(220);
ellipse(width/2,height/3,mouseX)
ellipse(width/2,height/2,mouseX)
ellipse(width/2,height*2/3,mouseX)
ellipse(width/2,height*3/4,mouseX)
ellipse(width/2,height/4,mouseX)
```
---
### 讓游標越往左移動,中間的圓會亮度越黑
```javascript=
function draw() {
//background(220);
var r_x = mouseX/5
fill(mouseX%256,(184+frameCount)%256,3+mouseY/3)
ellipse(width/2,height/3,r_x)
ellipse(width/2,height/2,r_x)
ellipse(width/2,height*2/3,r_x)
ellipse(width/2,height*3/4,r_x)
ellipse(width/2,height/4,r_x)
}
```

---
### 球移動的程式碼
* 設定一個圓圈,由左向右移動

---
```javascript=
function draw() {
background(220);
var x=25
var y=25
var v_x=1//速率
ellipse(x,y,50)
x=x+v_x
}
```
---
### 讓圓圈上下跳動

---
```javascript=
function draw() {var x=25
var y=25
var v_x=5//速率
background(220);
var x=25
var y=25
var v_x=5//速率
ellipse(x,y,50)
x=x+v_x
y=y+v_y
v_y=v_y+0.2
if(y>height){
v_y=-v_y*0.8
y=height
}
}
```
---
#### 變數(文字)
讓圓圈與文字一起跳動

---
```javascript=
function setup() {
createCanvas(windowWidth, windowHeight);
background(0)
}
function draw() {var x=25
var y=25
var v_x=5//速率
background(220);
var x=25
var y=25
var v_x=5//速率
ellipse(x,y,50)
textSize("淡江大學")
x=x+v_x
y=y+v_y
v_y=v_y+0.2
if(y>height){
v_y=-v_y*0.8
y=height
v_y=-v_y*0.8
}
}
```
---
#### 變數(布林值)
按下滑鼠左鍵,會變顏色

---
```javascript=
function setup() {
createCanvas(windowWidth, windowHeight);
background(0)
}
function draw() {var x=25
var y=25
var v_x=5//速率
background(220);
var x=25
var y=25
var v_x=5//速率
ellipse(x,y,50)
textSize("淡江大學")
x=x+v_x
y=y+v_y
v_y=v_y+0.2
if(y>height){
v_y=-v_y*0.8
y=height
v_y=-v_y*0.8
```
---
### 製作一個磚牆
* 利用方塊製作一個磚牆
* 每塊產生的磚牆可以產生不一樣的顏色(以紅色為準)。

---
```javascript=
```
---
### 不同顏色的磚牆

---
程式碼的修改
RGB三色都用亂數產生
```javascript=
```
---
完整程式碼
```javascript=
```
---
說明map 與lemp
```javascript=
```

---
## 一個利用圓弧產生的時鐘
透過 p5 內建方法拿到當前的時分秒,再用 map() 把時間對應到可以用在 arc() 上面的弧度,是很好用的技巧!

---
```javascript=
```
---
## 課程重點
### 什麼是「變數」 (variable)?
「變數」是程式語言中非常重要的概念。你可以想像它其實像一個抽屜,可將某些資料儲存起來。只要呼叫這個抽屜的名字就可以取用存在其中的資料。 在 JavaScript 中,變數宣告的語法為:
---
```javascript=
var r = 100 // 概念像是把 100 這個「數字」儲存在叫做 r 的這個抽屜中
var txt = '你好' // 也可以存「字串」在裡面
```
取用變數的方法:呼叫它的名字!
```javascript=
print(r) // 透過 print() 把 r 的內容印出來。結果會是 100
print(txt) // 會印出「'你好'」
```
- NOTE : 在程式語言中,‘=’ 代表「賦予數值」,‘==’ 才是數學中的「等於」!
---
### 為什麼要用變數,變數哪裡好用?
* 減少重複的數值,程式碼管理起來更方便 例如畫多個相同半徑的球時,可以快速同時改變他們的半徑。
---
```javascript=
var r = 50
ellipse(width/2, height/3, 50)
ellipse(width/2, height/2, 50) // 這兩個圓半徑重複了
ellipse(width/2, height/3, r, r)
ellipse(width/2, height/2, r, r) // 這樣更好管理!
```
---
* 暫存之後可能會用到的資料 利用變數的特性,先將經過運算的資料儲存起來,等到要用時再呼叫。 例如下面的寫法就會比上面乾淨明瞭:
---
```javascript=
// 不使用變數的寫法
//.....某些程式碼
fill(r/2 + 40, mouseX/2 +40, mouseY/2 +40 + mouseX/5) // 要用到顏色了,來直接運算!但這樣看起來很醜...
// 使用變數的寫法
var brightnessR = r/2 + 40
var brightnessG = mouseX/2 + 40
var brightnessB = mouseY/2 + 40 + mouseX/5 // 這些算好後先準備起來
//.....某些程式碼
fill(brightnessR, brightnessG, brightnessB) // 要用到顏色囉,這樣好看多了!
```
---
* 做較複雜運算時能夠解構、梳理並進一步清晰邏輯 我們可以直接拿變數再做進一步處理並存起。這能讓變數間的邏輯關係更清晰,而且你也不用在意原先的變數是怎麼來的。
---
```javascript=
var halfWidth = width/2 // 要一半視窗寬度,直接拿 width
```
來用!你也不用在意 p5 到底是怎麼去抓到視窗寬度
再以上面顏色的例子來說,若我沒有取用原先做好的變數來運算:
```javascript=
var darkR = (r/2 + 40)/2
var darkG = (mouseX/2 + 40)/2
var darkB = (mouseY/2 + 40 + mouseX/5)/2
fill(darkR, darkG, darkB)
```
跟這個相比:
```javascript=
var darkR = brightnessR/2
var darkG = brightnessG/2
var darkB = brightnessB/2 // 反正我要更暗的,直接拿原先的 brightness 除以 2 就好了
fill(darkR, darkG, darkB)
```
---
後者一眼就知道 dark 是拿原先的 brightness 來砍半。因此透過如此撰寫,
---
* 保留先前的狀態,並藉此形成連續的狀態變化 這是變數運算特性的應用。我們可以把某些狀態,例如位置、大小、顏色等狀態先設定為變數,然後以先前的值運算並放回原先變數中來複寫舊內容,藉此來實現動態且連續地改變變數內容。 例如把球的位置設定為 x, y 兩個變數,我們透過以上技巧就可以畫出球移動的效果:
---
```javascript=
// 球會往畫面右下方移動
var x = 50, y = 50
function draw(){
ellipse(x, y, 50) // 會取到更新的 x 及 y 位置資訊,並藉此畫出圓
x = x+5 // 每次都拿原先的 x 來加 5,並塞回原先的 x
y += 5 // 等同於 y = y+5,只是簡略寫法
}
```
---
* 賦予數值與資料意義 對於電腦來說這些變數其實也只是一堆數字。所以變數的命名除了可以讓我們呼叫之外,最主要是為了讓人類自己可以看得懂,並且透過這些名字建立邏輯關係以方便我們操作跟編寫
```javascript=
var ballPositionX = 200 // 指「球的 x 位置」
var ballSize = 15 // 指「球的大小」
var rectFillColor = 'red' // 指「矩形的填充色」
```
## 變數可以裝哪些東西(資料型態)?
### 基礎的資料型態:
* <font color="red">數字</font>: 0,1,2,-1,-2,0.1,0.2 … 各種可以被用來計算的數字
* <font color="red">字串</font>:'yellow', 'pig', '範例好難'… 可以簡單的想像成是被包覆起來的一段文字
* <font color="red">boolean</font>:即所謂「布林變數」,是用來判斷邏輯正確與否的。只會有true/false兩個值,也就是「是」或「不是」。
例如把 p5 的 <font color="red">mouseIsPressed</font> 打印出來,就只會看到 true 或是 false,分別代表有按下去 / 沒按下去。我們在使用 if() 判斷式的時候也會使用到 boolean 的概念呦!
## 變數的命名方式與習慣
* 要言之有意:例如<font color="red">滑鼠的位置命名</font>為 mousePos 會比 asdfgqwert 來的清楚明白,協助以後的自己與同事更好地了解程式碼。
* 駝峰式命名 (Camel case):若變數的名字是由多個單字構成,規則是頭一個單字的字首小寫,其他單字字首大寫,例如 var camelCase = '駝峰式命名規則'。
* 避免使用到語法 / 套件的保留字:JavaScript 內建的 function, window, alert ,或是 p5 的 width, height, mouseX, mouseY 之類的都要避免,以免造成程式錯誤。命名前可以參考ㄧ下 p5 的文件 或是 JavaScript 的保留字。
## 範例練習
```javascript=
function setup() {
createCanvas(windowWidth, windowHeight);
background(0);
stroke(0)
strokeWeight(2)
x=0
y=height/2
// strokeWeight(0.1)
}
// var number = 1
var x = 0
var y = 0
var r = 30
var vy = 0
var sec = 0
function draw() {
// background(0,5)
// print(number)
//---------
px=x
py=y
x=x+2
y=y+vy
vy=vy+0.5
if (y>height){
vy=-vy
}
//---------
x+=random(-5,5)
y+=random(-5,5)
// if (second()!=sec){
// sec=second()
// x=random(width)
// y=random(height)
// r=random(50)
// }
fill(map(y,0,height,0,255),map(x,0,width,0,255) ,50)
ellipse(x,y,r,r)
// stroke(255)
r+=random(-5,5)
line(x,y,px,py)
if (mouseIsPressed){
x = lerp(x,mouseX,0.1)
y = lerp(y,mouseY,0.1)
}
// line(0,0,px,py)
// line(0,0,x,y)
// // fill(255)
// text(sec,x+random(-50,50),y)
// let ll = dist(mouseX,mouseY,pmouseX,pmouseY)
// stroke(255,map(ll,0,100,0,255,true)*2)
// line(pmouseX,pmouseY,mouseX,mouseY)
// strokeWeight(1)
// // stroke(0)
// line(x,y,mouseX,mouseY)
// line(x,y,pmouseX,pmouseY)
// ellipse(mouseX, mouseY, 20, 20);
}
```
---
### [彈跳球球](https://openprocessing.org/sketch/883254)
透過球球當前位置計算下個位置,也讓滑鼠的位置參與互動,點擊的話會讓球的位置逼近滑鼠,最後加上超過畫面底部的話動量反向的設定,讓球有種彈跳的感覺。

```javascript=
function setup() {
createCanvas(windowWidth, windowHeight);
background(0);
stroke(0)
strokeWeight(2)
x=0
y=height/2
// strokeWeight(0.1)
}
// var number = 1
var x = 0
var y = 0
var r = 30
var vy = 0
var sec = 0
function draw() {
// background(0,5)
// print(number)
//---------
px=x
py=y
x=x+2
y=y+vy
vy=vy+0.5
if (y>height){
vy=-vy
}
//---------
x+=random(-5,5)
y+=random(-5,5)
// if (second()!=sec){
// sec=second()
// x=random(width)
// y=random(height)
// r=random(50)
// }
fill(map(y,0,height,0,255),map(x,0,width,0,255) ,50)
ellipse(x,y,r,r)
// stroke(255)
r+=random(-5,5)
line(x,y,px,py)
if (mouseIsPressed){
x = lerp(x,mouseX,0.1)
y = lerp(y,mouseY,0.1)
}
// line(0,0,px,py)
// line(0,0,x,y)
// // fill(255)
// text(sec,x+random(-50,50),y)
// let ll = dist(mouseX,mouseY,pmouseX,pmouseY)
// stroke(255,map(ll,0,100,0,255,true)*2)
// line(pmouseX,pmouseY,mouseX,mouseY)
// strokeWeight(1)
// // stroke(0)
// line(x,y,mouseX,mouseY)
// line(x,y,pmouseX,pmouseY)
// ellipse(mouseX, mouseY, 20, 20);
}
```
---
### [彩色磚牆](https://openprocessing.org/sketch/883263)
使用使用變數判斷目前 x 的位置,如果超出寬度的話就換行,另外使用 random() 增加色塊的寬度與顏色的多樣性。

```javascript=
var x,y
function setup() {
createCanvas(windowWidth, windowHeight);
background(0);
x=20
y=20
}
function draw() {
let ww = random(100)
fill(random(255),random(50)+150,random(50)+100)
noStroke()
rect(x,y,ww,12)
x+=ww+5
if (x>width/2){
x=0
y+=20
}
// ellipse(mouseX, mouseY, 20, 20);
}
```
---
### 模擬時鐘
透過 p5 內建方法拿到當前的時分秒,再用 map() 把時間對應到可以用在 arc() 上面的弧度,是很好用的技巧!

```javascript=
function setup() {
createCanvas(windowWidth, windowHeight);
background(100);
}
var ang =0
function draw() {
background(0)
// var ang = map(mouseX,0,width,0,PI*2,true)
var s = second();
var m = minute()
var h = hour()
var angleS = map(s,0,60,0,PI*2)
var angleM = map(m,0,60,0,PI*2)
var angleH = map(h,0,12,0,PI*2)
fill('red')
arc(width/2, height/2, 200, 200, 0, angleS, PIE);
fill('yellow')
arc(width/2, height/2, 100, 100, 0, angleM, PIE);
fill('white')
arc(width/2, height/2, 50, 50, 0, angleH, PIE);
}
```
---
---
## 內容回顧
### 變數入門
* 變數的宣告語法: var 變數的名稱 = 變數的內容
* 變數可以裝什麼? 最基本的資料型態有 數字、字串與 boolean 值等等
* 變數的命名方式與習慣:駝峰式命名
### p5 好用的函式與方法
#### 數值操作:
* map():將某個區間的數值對映到另ㄧ個區間
* lerp():在兩個值之間依特定比例取值(線性插值)
* random():隨機取值
#### 形狀:
* arc():繪製扇形
#### 時間:
* hour():取得當前時
* minute():取得當前分
* second():取得當前秒
#### 其他
* 賦值運算符(assignment operator):把原先變數 x 的值經過某個運算另一個值 y 之後,賦值給 x。如 x+=1 的計算結果會等同於 x = x+1,等號前可以放入任意的運算,例如 x *= 2 的計算結果會等同於 x = x*2。
* CSS 色彩名稱:可以直接填入 fill() 函式的顏色字串值,例如 'yellow', 'red', 'cornflowerblue' 之類。可以點這邊看可以用的顏色。
#### 數值的運算與處理:
* %:讀作 mod,用來取餘數。例如 16%3 => 1
* abs():取絕對值。例如 abs(-4) => 4
* floor():取「地板」,即為「無條件捨去」。例如floor(1.4) => 1
* ceil():取「天花板」,即為「無條件進位」。例如ceil(1.4) => 2
* +,-,*,/ :分別為加減乘除
## 五、課後問題
### 變數是什麼?我們為什麼要使用變數?
除了提到的三種類型(數字、字串、boolean),JavaScript 這個程式語言還有哪些資料型態呢?
## 六、作業方向
創造你的時間表達方式:除了時鐘之外,還有哪些元素與型態可以作為表達時間的方式呢?水的流動、星辰的轉動或是張眼閉眼都可以是時間走動的象徵,活用 p5 的時間函數與 map() 應對,呈現ㄧ個屬於你的時間表達吧!
---
---
---
創作概念
連結 軌跡 狀態
- 觀摩
- 
- https://www.openprocessing.org/sketch/763615
- https://www.pinterest.com/pin/125608277095922192/
- https://www.pinterest.com/search/pins/?q=generative%20art&rs=typed&term_meta[]=generative%7Ctyped&term_meta[]=art%7Ctyped
- 物理模擬 - 粒子
- 變數
- 減少重複
- 暫存手邊需要的資料
- 做複雜的運算時解構概念
- 留下上一刻的狀態
- 賦予數值與資料意義
- 類型
- 數字
- 字串
- true/false
- p5.js的系統變數 滑鼠、鍵盤
- mouseX / mouseY / pmouseX / pmouseY
- mouseIsPressed
- keyPressed
- mousePressed
- LEFT_ARROW
- RIGHT_ARROW
- UP_ARROW
- DOWN_ARROW
- SPACE
- https://p5js.org/reference/#/p5/keyCode
- 數字的操作
- % 取得餘數
- abs
- floor
- +-*/
- 變數命名的規則
- Camel Size
- 轉換數值的範圍應用
- map / constrain
- lerp 逼近
- min / max
- 繪製圖形進階 PIZZA
- arc
- curve
- 亂數的應用
- random(最小,最大)
- random(陣列)
- 時間
* day()
* hour()
* minute()
* millis()
* month()
* second()
* year()
- 繪製時間表達的函數
- 範例:球球物理

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

https://www.openprocessing.org/sketch/883263
稍微修改、調整細節後可以延伸成這樣

https://www.openprocessing.org/sketch/884104
- 課後練習?
-
---