常用指令
上課一直會用到的 p5.js 小段程式:存圖、重來、全螢幕、粒子模板、麥克風測試,複製就能貼進 OpenProcessing。
起手模板
粒子起手模板:Hahow Week 3-0 Particle Template
講師的粒子模板(OpenProcessing 上直接 Fork):Particle 的 update() 寫規則、draw() 寫長相;開頭三行 OPC 是拉桿、顏色、色盤,邊跑邊調。這份多補了四條常用規則(重力、noise 力場、追滑鼠、分裂),先註解掉,一次打開一條。之後有粒子的示範都從這裡開始。
最快:到 OpenProcessing 打開 https://openprocessing.org/@cheyuwu/3033176 按 Fork(OPC 函式庫已經開好)。自己貼進空白草圖的話,要到草圖設定的 Libraries 打開 OP Configurator 3000,不然會報 OPC is not defined。先跑起來,拉拉桿;再到 update() 打開一條規則、改數字看它變成什麼;想換長相就改 draw()。
OPC 拉桿:把數字變成邊跑邊調的控制項
OpenProcessing 的函式庫 OP Configurator 3000(OPC):把 let radius = 10 換成 OPC.slider(...),畫面旁邊就多一根拉桿,不用改程式、不用重跑就能試數字。拉桿、開關、顏色、下拉選單都有。
在 OpenProcessing 的草圖設定打開 Libraries 的 OP Configurator 3000(沒打開會報 OPC is not defined)。把想試的數字從 let 改成 OPC.slider,畫面旁邊出現拉桿就可以邊跑邊調;調到喜歡的數字記下來。分享時網址加 ?sketch_radius=30 可以換預設值。
自然的演算法
海龜繪圖:照字串畫線
一個 turtle(cmds, len, angle) 函式,讀一串指令照著走:F 前進畫線、+ 和 - 轉向、[ 記住位置、] 回到位置,改字串就改圖形。
只把最底下的 turtle() 整個複製進自己的 sketch,在 draw() 裡先 translate() 到出發點,再呼叫 turtle(字串, 步長, 角度);字串裡的 [ ] 一定要成對。
L-System:規則換字長出一棵樹
一個 grow(axiom, rules, n) 函式,把起始字串照規則改寫 n 代(F 換成 F[+F]F[-F]F)再交給畫字串函式,字串越長樹越茂密,點一下多長一代。
把 grow() 和 drawString() 複製進自己的 sketch,在 setup() 用 grow(起始字, 規則, 代數) 算好字串,draw() 裡 translate() 到出發點再 drawString();改 RULES 就是改樹的長相。
遞迴樹:branch 自己呼叫自己
一個 branch(len, depth, angle) 函式,畫一段樹枝再往左右各長兩根短一點的,depth 減到 0 就停;範例從畫面底部長一棵,滑鼠左右移動改分枝角度。
複製 branch() 進自己的 sketch,在 draw() 裡先 translate() 到樹根,再呼叫 branch(長度, 層數, 角度);層數每加 1,枝條數量翻倍,電腦跑不動就調小。
Noise 年輪:接得起來的不規則圈
一個 noiseRing(x, y, r, amp, k, z) 函式,用 noise 讓圓的半徑忽大忽小,起點跟終點接得起來;範例疊 30 圈變年輪,按 R 換一棵樹。
複製 noiseRing() 進自己的 sketch,先 noFill() 再呼叫;想畫年輪就用迴圈,每圈的 r 加大、z 加一點;k 越大越碎,amp 越大起伏越誇張。
Boid 三條規則:分離、對齊、聚合
一個 flock(me, others, radius) 函式,回傳分離、對齊、聚合三條規則合成的力;粒子模板的 p/v 或 Boid 的 pos/vel 都認得,在粒子模板的 update() 加一行就變鳥群,範例用最小的 class 跑 60 隻。
把最底下的 flock() 複製進自己的 sketch;粒子模板(Hahow Week 3-0)在 update() 的規則區加一行 this.a = flock(this, particles, 60); 就變鳥群,不用另外寫 class。
存檔與輸出
按 S 存 JPG(檔名帶日期時間)
按一下 S 就把畫面存成 JPG,檔名像 sketch-2026-09-29-1905-12.jpg,存再多張也不會互相蓋掉,還會照時間排好。
把 keyPressed、pad、timestamp 三段貼到自己的 sketch 最下面;已經有 keyPressed 就把 if 那段併進去。在 OpenProcessing 要先點一下畫布,按鍵才會送進作品。
按 S 存 PNG(透明背景)
draw() 裡用 clear() 取代 background(),存成 PNG 背景就是透明的,可以直接疊到海報、簡報或影片上。
把自己 draw() 第一行的 background() 換成 clear(),再貼上 keyPressed、pad、timestamp。只是要存 PNG、不需要透明的話,background() 留著、把 jpg 改成 png 就好。
存高解析度圖(pixelDensity)
pixelDensity(2) 讓 600×600 的畫布存出 1200×1200 的圖;要印刷就調到 3、4,存出來的尺寸=寬高 × 密度。
在自己的 setup() 裡、createCanvas 的下一行加上 pixelDensity(2)。動態作品密度太高會變慢:平常用 1,要存圖前再改成 3 或 4。
按 G 存 3 秒 GIF(saveGif)
saveGif() 把動畫一格一格重畫、錄成 GIF;p5.js 1.5 以上與 2.x 都有,存好之前畫面會停一下是正常的。
把 keyPressed 裡的 if、pad、timestamp 貼進自己的 sketch。saveGif 會把 frameCount 從 0 重新算起(1.x、2.x 都是),用 frameCount 做的動畫錄出來最準。
按 V 錄 5 秒影片(WebM)
用瀏覽器內建的 MediaRecorder 把畫布錄成影片,不用裝函式庫;檔案比 GIF 小很多,錄影時畫面照常跑、滑鼠互動也會錄進去。
把 SECONDS、recorder 兩行放在最上面,keyPressed 裡的 if、startRecording、pad、timestamp 貼到下面。要上 IG 可以再用剪輯軟體把 WebM 轉成 MP4。
鍵盤滑鼠
按 R 換一組隨機
把 random 的種子存在變數裡,按 R 抽一個新種子、重畫一次;同一個種子永遠畫出同一張。
動態作品把 noLoop() 和 redraw() 拿掉,只留 randomSeed(seed) 在 draw() 第一行:每一格抽到同一組隨機,畫面就不會閃。有用 noise() 的話再加一行 noiseSeed(seed)。
按空白鍵暫停/繼續
noLoop() 讓 draw() 停下、loop() 讓它繼續,isLooping() 知道現在是哪一種;想截某一格或停下來慢慢看時最好用。
把 keyPressed 裡的 if 貼進自己的 sketch。暫停時再按 S(配上存圖那段),存到的就是停住的這一格。
按 C 清空畫布(筆刷作品)
不畫 background() 的筆刷作品會一直疊上去;按 C 用同一個底色蓋掉整張,就是清空重來。
把 keyPressed 裡的 if 貼進自己的筆刷作品,background() 的顏色改成跟 setup() 裡一樣。
取座標小工具:點一下印出 vertex
在畫布上點一下,console 就印出一行 vertex(x, y);;點出形狀的頂點,整串貼回 beginShape() 和 endShape(CLOSE) 之間,就是自己的形狀。
整段貼進一個新的 sketch 當工具用:點出想要的形狀頂點,從 console 複製那幾行 vertex 貼回自己作品的 beginShape() 與 endShape(CLOSE) 之間;按 C 清掉重點。
MIDI 一行接上:鍵盤、螢幕上的控制器、手機都能彈
在草圖最上面貼一行 Open Audio Visual,就能用 MIDI 鍵盤(MiniLab 3、LPD8)演奏作品:knob1~knob8 像 mouseX 一樣直接讀,notePressed() 像 keyPressed() 一樣按了就叫。沒有鍵盤就按畫面角落的 🎹 用螢幕上的控制器,或 📱 用手機。草圖裡有 OPC.slider(像 3-0 粒子模板)的話,旋鈕會照順序自動接上那些拉桿。
把第一行貼在自己草圖的最上面,之後 knob1~knob8、fader1~fader4、pad1~pad8、notePressed(note, velocity)、noteIsDown(60) 都能用。草圖裡已經有 OPC.slider 的話(像 3-0 粒子模板),旋鈕 1 會接第一根拉桿、旋鈕 2 接第二根,不用改程式。
畫布與視窗
按 F 全螢幕+畫布跟著視窗
fullscreen() 切換全螢幕;視窗大小一變 p5 會呼叫 windowResized(),在裡面 resizeCanvas() 畫布就永遠填滿視窗。
把 createCanvas 改成 windowWidth、windowHeight,再貼上 keyPressed 和 windowResized;按 Esc 也能離開全螢幕。沒畫 background() 的筆刷作品,換尺寸時畫過的東西會被清掉。
時間與隨機
用時間當參數:秒數與 sin 呼吸
millis() ÷ 1000 就是開始到現在幾秒,丟進 sin() 再用 map() 換算成大小和亮度,圓就會像呼吸一樣一脹一縮。
在自己 draw() 的開頭加 const t = millis() / 1000;,想要會動的數值就寫成 sin(t * TWO_PI / 週期秒數),再用 map() 換算到要的範圍。
在畫面上印出日期時間
year()、month()、day()、hour()、minute()、second() 拿到現在的時間,用跟存檔檔名同一個 pad() 補零,印成時鐘。
貼上 pad、timestamp 兩個函式,在 draw() 裡用 text() 印出來;已經貼過存檔那段就不用再貼一次。
存檔名帶種子:喜歡的那張找得回來
按 R 換一組隨機、按 S 存 PNG,檔名記下種子;之後把 seed 設回那個數字,就能畫回同一張、再存一次高解析度。
draw() 第一行放 randomSeed(seed) 和 noiseSeed(seed),存檔名加上 seed。找到喜歡的就把 seed 固定成檔名裡的數字,再配合 pixelDensity 存一張大圖。
顏色
色票陣列+random(palette)
先挑好幾個顏色放進陣列,random(palette) 每次抽一個;整張作品只用這幾色,配色馬上就統一。
把 palette 那一行放在最上面,原本寫 fill(random(255), …) 的地方改成 fill(random(palette))。配色可以到 coolors.co 挑好,把色碼整串貼進陣列。
HSB 彩虹:色相跟著時間轉
colorMode(HSB) 之後第一個數字是色相,0 到 360 繞一圈就是彩虹;飽和度、亮度分開調,比 RGB 直覺。
在 setup() 裡加 colorMode(HSB, 360, 100, 100, 1);之後所有 fill、stroke、background 的數字都照 HSB 解讀,原本的 RGB 顏色要跟著改。
除錯
左上角顯示 fps 與 frameCount
作品卡不卡看數字最準:frameRate() 是現在每秒幾格、frameCount 是第幾格,畫在 draw() 最後才會蓋在作品上面。
把 drawDebug() 貼進自己的 sketch,在 draw() 最後一行呼叫它;作品完成、要展示時把那一行刪掉就好。
滑鼠十字線+座標
跟著滑鼠畫一條直線、一條橫線,旁邊寫出 (mouseX, mouseY);想知道某個點的座標,移過去看一眼就知道。
把 drawCrosshair() 貼進自己的 sketch,在 draw() 最後一行呼叫它;對好位置、把數字抄進程式之後,刪掉那一行。
每秒在 console 印一次變數
print() 放在 draw() 裡一秒會洗掉 60 行;用 frameCount % 60 === 0 只在每 60 格印一次,看得清楚數值怎麼變。
把 if (frameCount % 60 === 0) { print(…); } 放進自己的 draw(),括號裡換成想看的變數;OpenProcessing 的 console 在畫布下方。
麥克風測試
點一下畫面開始,畫一條跟著聲音跳的音量條;沒聲音時畫面上直接寫三個檢查點(瀏覽器權限、系統麥克風、OpenProcessing 要點進作品頁放大看,或改用 p5 網頁編輯器)。第 4 堂開播前先點開來測一次。
貼進 OpenProcessing 或 p5 網頁編輯器,點一下畫面開始;看到條跟著聲音跳就 OK。條不跳時,畫面上的三個檢查點照著查。這支只測瀏覽器拿不拿得到麥克風,第 4 堂的示範是同一個權限。
到 Hahow 報名。價格與優惠以 Hahow 頁面為準。