在前一篇文章中,我們透過逐一設定每顆氣球的大小、高度,成功繪製了天外奇蹟的電影海報,但如果今天要畫二十顆、甚至是上百顆氣球呢?如果一樣需要一顆一顆地設定給和值,那應該會做到天荒地老。日文中有一句俗語「猫の手も借りたい(ねこのてもかりたい)」,意思就是「非常忙錄,連貓的手都想借來幫忙」。今天我們就要借助貓的手──變數,來製作更加複雜的生成式藝術。
「變數」是程式語言中非常重要的概念。你可以想像它其實像一個抽屜,可將某些資料儲存起來。只要呼叫這個抽屜的名字就可以取用存在其中的資料。
在 JavaScript 中,變數宣告的語法為:
var r = 100 // 概念像是把 100 這個「數字」儲存在叫做 r 的這個抽屜中 var txt = '你好' // 也可以存「字串」在裡面
取用變數的方法:呼叫它的名字!
print(r) // 透過 print() 把 r 的內容印出來。結果會是 100 print(txt) // 會印出「'你好'」
透過「儲存櫃」這個概念,變數可以幫我們做到這些事:
- 減少重複的動作 程式碼管理起來更方便,例如畫多個相同半徑的球時,可以快速同時改變他們的半徑。
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) // 這樣更好管理!
- 暫存手邊需要的資料 利用變數的特性,先將經過運算的資料儲存起來,等到要用時再呼叫。
var brightnessR = r/2 + 40 var brightnessG = mouseX/2 + 40 var brightnessB = mouseY/2 + 40 + mouseX/5 // 這些算好後先準備起來 .....某些程式碼 fill(brightnessR, brightnessG, brightnessB) // 要用到顏色囉,這樣好看多了!
- 做較複雜運算時能夠解構、梳理並進一步清晰邏輯 我們可以直接拿變數再做進一步處理並存起,這能讓變數間的邏輯關係更清晰,而且你也不用在意原先的變數是怎麼來的。
var halfWidth = width/2 // 要一半視窗寬度,直接拿 width 來用! var darkR = brightnessR/2 var darkG = brightnessG/2 var darkB = brightnessB/2 // 反正我要更暗的,直接拿原先的 brightness 除以 2 就好了 fill(darkR, darkG, darkB)
- 保留先前的狀態,並藉此形成連續的狀態變化 這裡或許有些抽象,需要用到動畫影格(frame)的概念。應用變數的運算特性,我們可以把某些狀態,例如位置、大小、顏色等狀態先設定為變數,然後以先前的值運算並放回原先變數中來複寫舊內容,藉此來實現動態且連續地改變變數內容。
// 球會往畫面右下方移動 var x = 50, y = 50 function draw(){ ellipse(x, y, 50) // 會取到更新的 x 及 y 位置資訊,並藉此畫出圓 x = x+5 // 每次都拿原先的 x 來加 5,並塞回原先的 x y += 5 // 等同於 y = y+5,只是簡略寫法 }
介紹完變數的基礎概念,就讓我們進入範例練習吧!今天的靈感來源是川野 源(Hiroshi Kawano)的作品──Design 3-1. Data 4, 5, 6, 6, 6,哲學系出身的川野先生可以說是生成式藝術的先驅之一,早在1964年時便開始藉由電腦程式進行藝術創作,風格以色彩繽紛、交錯排列的方塊為主。
如果不知道從何下手,可以利用Google Arts等藝術相關的搜尋引擎,從藝術家們的作品之中找尋靈感唷。
首先準備幾個會用到的變數,相當於桌子裡面空的抽屜,待會我們會把工具逐一放到抽屜裡面。這邊要注意的是變數的命名有一定的準則:
- 可讀性 :好的命名必須名符其實,讓人一看就懂。在大型的專案中,常常有機會需要維護別人的code或vice versa,如果打開code看到一連串aaa、bbb、ccc的變數命名,也許你從茶水間回來椅子上面就多了幾個圖釘(喂)。
- 駝峰式:每種語言的方式不一,有些採用首字母小寫駝峰式、有些則是首字母大寫駝峰式。沒有硬性的規定,但坊間通常會有不成文的默契。(p5.js使用的是首字母小寫駝峰式)
- 避開保留字:指程式語言保留下來的英文單字,作為語法的關鍵字(Keyword)不能當變數名稱,如先前所使用的square()、background()等已被p5.js作為函式庫內語法使用的英文單字。
根據川野先生的作品,我們可以大致推測需要的變數會有顏色、尺寸、還有在不同方塊之中當前使用的顏色與變換的顏色。
//Inspired by the work of Hiroshi Kawano var colors; var size; var probChangeColor; var currentColor;
接下來準備800*800px的畫布,使用語法noLoop()避免一直重複執行,設定方塊中的尺寸和改變顏色的基準值,由於方塊都是純色塊,所以使用noStorke()取消外框線。
接下來針對會使用到的顏色給予RGB值,不知道RGB是什麼的請看前篇的色票介紹。把色票放到名叫colors
的陣列(array)裡面,陣列是一種資料的集合,也是一種比較複雜的物件 (object),我們剛剛針對不同的顏色名稱給予了相對的RGB值,所以只要在陣列裡面填入顏色名稱,程式就會自動理解名稱背後所代表的意義,這就是變數儲存櫃的特性。
因為我們希望作畫時隨機選取顏色,所以命名一個新的function叫randomColor()
,他有點像大樂透抽號碼時的球池,在這個球池中我們會有號碼,所以運用語法array.length()
回傳該陣列實體中包含的元素個數,再透過random()
隨機產生0~6區間的數字,用floor()
將數字轉成最接近該值的整數。因為陣列有順序的概念,所以抽出來的整數字代表陣列中的第幾個,再將值return。
準備開始繪製主要的元素──彩色方塊
function createComposition() { for (var y = 0; y < height; y += size) { for (var x = 0; x < width; x += size) { if (random(1) < probChangeColor) { currentColor = randomColor(); } fill(currentColor); square(x, y, size); } } }
加個邊框感覺更像畫作,命名一個function為addBorder()
調整框線的粗度、顏色和畫線方向。
接下來加入一些跟使用者的互動,只要每次按下空白鍵space,就會自動產生新的pattern。
這樣就完成啦~成品請往這邊走 👉🏻 https://openprocessing.org/sketch/1108202
語法統整大補帖
圖形相關語法:ellipse()、circle()、rect()
填色相關語法: fill()、background()
線條相關語法: line()、stroke()、noStroke()、strokeWeight()
文字相關語法: text()、textAlign()
想學習更多程式創作嗎?那你必不可以錯過哲宇老師的【互動藝術程式創作入門】課程,快跟著其他一千多名同學開始發揮你無限的創意吧!
作者:Ju編 Jeudi Kuo