---
# System prepended metadata

title: 4.P 變數與資料 - 賦予可變與連續性(學生版)
tags: [第三章, 程式設計, 學生版, 互動藝術程式創作入門, Creative Coding]

---

---
tags: 程式設計,第三章,學生版,互動藝術程式創作入門,Creative Coding
---

# 4.P 變數與資料 - 賦予可變與連續性(學生版)


## 單元介紹
我們會學到

* 了解「變數」是什麼
* 我們為什麼要使用變數
* 如何使用變數及注意事項
* 進階操作變數使創作更有效率、更有趣

- 什麼是變數？
- 為什麼要用變數
- 開一個櫃子 放會使用到的東西


---

## 程式碼開講

### 產生三個圓




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

---


```javascript=
function setup() {
	createCanvas(windowWidth, windowHeight);
	background(100);
}

function draw() {
	ellipse(width/2,height/4, 200,200);
	ellipse(width/2,height/3, 200,200);
	ellipse(width/2,height/2, 200,200);
}


```



---

### 由滑鼠游標的左右座標控制圓大小


---

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


---

```javascript=
function setup() {
	createCanvas(windowWidth, windowHeight);
	background(100);
}

function draw() {
	ellipse(width/2,height/4, mouseX,mouseX);
	ellipse(width/2,height/3, mouseX,mouseX);
	ellipse(width/2,height/2, mouseX,mouseX);
}



```





---

### 讓游標越往左移動，中間的圓會亮度越黑

```javascript=





```

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

---

### 球移動的程式碼

* 設定一個圓圈，由左向右移動
![](https://i.imgur.com/tiApFZI.gif)




---

```javascript=
function setup() {
	createCanvas(windowWidth, windowHeight);
	background(100);
}

function draw() {
	var r=mouseX/2
	
	var R = r*2/3+140//設定紅色
	var G = r/3+100//設定綠色
	var B = r/2+200//設定藍色
	
	fill(R,G,B)
	ellipse(width/2,height/3, r,r);
	ellipse(width/2,height/2,r,r);
	ellipse(width/2,height*2/3, r,r);
}


```



---

### 讓圓圈上下跳動

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

---


```javascript=
function setup() {
	createCanvas(windowWidth, windowHeight);
	background(100);
}
var x =100//x座標
var y =100//y座標
var xx=3	//往右的速度
var yy=3	//往下的速度

function draw() {
	background(100)
	ellipse(x, y, 20, 20);
	x=x+xx
	y=y+yy
	yy=yy+0.2
	if(y>height){
		yy=-yy*0.93
}
}




```







---

#### 變數(文字)

讓圓圈與文字一起跳動

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



---

```javascript=
unction setup() {
	createCanvas(windowWidth, windowHeight);
	background(100);
}
var x =100//x座標
var y =100//y座標
var v_x=3	//往右的速度
var v_y=3	//往下的速度

function draw() {
	background(100)
	ellipse(x, y, 20, 20);
	textSize(100)
	text("123",x+30,y)
	x=x+v_x
	y=y+v_y
	v_y=v_y+0.2
	if(y>height){
		v_y=-v_y*0.93
}
}



```


---
#### 變數(布林值)


按下滑鼠左鍵，會變顏色

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

---


```javascript=



```




---
### 製作一個磚牆

* 利用方塊製作一個磚牆
* 每塊產生的磚牆可以產生不一樣的顏色(以紅色為準)。

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

---


```javascript=
function setup() {
	createCanvas(windowWidth, windowHeight);
	background(100);
}
var x=0
var y=0

function draw() {
	var w = random(50)//會產生一個亂數值,為0~99
	fill(100+random(155),100+random(155),100+random(155))
	rect(x, y, w, 20);//在座標(x,y)畫一個方框
	x=x+w+2
	noStroke()
	if(x>width)
	{
			x=0	
			y=y+20+5
	}
}



```
---

### 不同顏色的磚牆
![](https://i.imgur.com/b57uv03.gif)



---

程式碼的修改
RGB三色都用亂數產生


```javascript=
var colors = "8cb369-f4e285-f4a259-5b8e7d-bc4b51".split("-").map(a=>"#"+a)
function setup() {
	
	createCanvas(windowWidth, windowHeight);
	background(100);
}
var x=0
var y=0


function draw() {

	var w = random(200)//會產生一個亂數值,為0~199
	noStroke()
	
	var clr = colors[frameCount%colors.length]
	fill(clr)
	rect(x, y, w, 20);//在座標(x,y)畫一個方框
	x=x+w+2
	stroke(clr); //線條的顏色
	if(x>width)
	{
			x=0	
			y=y+20+5
	





```

---

完整程式碼

```javascript=



```

---

說明map 與lemp

```javascript=




```

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

---
## 一個利用圓弧產生的時鐘

透過 p5 內建方法拿到當前的時分秒，再用 map() 把時間對應到可以用在 arc() 上面的弧度，是很好用的技巧！
![](https://i.imgur.com/TSpd9Qi.gif)



---


```javascript=
function setup() {
	createCanvas(windowWidth, windowHeight);
	background(100);
}

function draw() {
	background(100)
	var eng=map(mouseX,0,windowWidth,0,PI*2)
	arc(width/2,height/2,200,200,0,eng)
	
}


--------------------------------------------------------



function setup() {
	createCanvas(windowWidth, windowHeight);
	background(100);
}

function draw() {
	background(0)
	var s =second()
	var m =minute()
	var h =hour()
	
	var angelS=map(s,0,60,0,PI*2)
	var angelM=map(m,0,60,0,PI*2)
	var angelH=map(h,0,12,0,PI*2)
	
	fill("#4e5283")
	arc(width/2,height/2,500,500,-PI/2,angelS-(PI/2),PIE)
	fill("#7871aa")
	arc(width/2,height/2,200,200,-PI/2,angelM-(PI/2),PIE)
	fill("#aa9fb1")
	arc(width/2,height/2,150,150,-PI/2,angelH-(PI/2),PIE)
}








```


---

## 課程重點

### 什麼是「變數」 (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)
透過球球當前位置計算下個位置，也讓滑鼠的位置參與互動，點擊的話會讓球的位置逼近滑鼠，最後加上超過畫面底部的話動量反向的設定，讓球有種彈跳的感覺。
![](https://i.imgur.com/DY73OnM.gif)

```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() 增加色塊的寬度與顏色的多樣性。
![](https://i.imgur.com/nhkU8tS.gif)

```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() 上面的弧度，是很好用的技巧！
![](https://i.imgur.com/TSpd9Qi.gif)

```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://i.imgur.com/kPizGrV.png)
    - 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://i.imgur.com/DKoFFke.png)
https://www.openprocessing.org/sketch/883254

![](https://i.imgur.com/GEjkLpw.png)
https://www.openprocessing.org/sketch/883263

稍微修改、調整細節後可以延伸成這樣
![](https://i.imgur.com/XR7F2cj.png)
https://www.openprocessing.org/sketch/884104

- 課後練習？
- 

---