1. 程式人生 > >1.4 開始第一幅“碼繪”——活用變數和常量,實現滑鼠互動

1.4 開始第一幅“碼繪”——活用變數和常量,實現滑鼠互動

引言——如何在程式中改變繪製內容

回顧之前畫懵逼臉的程式碼,可以看出,每個語句中都是直接用數值精確指定橢圓/直線/色彩:



  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
// 函式setup() : 準備階段function setup() { // 建立畫布,寬度640畫素,高度480畫素 // 畫布的座標系統為,左上角座標為(0,0), // x方向水平向右,y方向垂直向下,單位畫素 createCanvas(640,480);}// 函式draw():作畫階段function draw() { fill(255);// 填充白色 // 1 畫臉 ellipse(320,240,200,200);// 圓圈 // 2 左眼 ellipse(280,240,50,50);// 另一個圓圈 // 3 右眼 ellipse(360,240,50,50); // 4 嘴巴 ellipse(320,300,80,40); fill(0);// 填充黑色 // 5 左眼珠 ellipse(280,240,20,20); // 6 右眼珠 ellipse(360,240,20,20); // 7 頭髮:從左到右畫一排豎線 line(260,180,260,100); line(280,180,280,100); line(300,180,300,100); line(320,180,320,100); line(340,180,340,100); line(360,180,360,100); line(380,180,380,100);}

例如,畫臉的語句“ellipse(320,240,200,200);”中,橢圓的中心點位置(320,240)和長(200)寬(200)都是用精確的數值來指定的。如果我們希望它的位置為滑鼠的實時位置,這種方式就不行了。但通過簡單改造程式碼即可做到,即吧這句改為“ellipse(mouseX,mouseY,200,200);”,整段程式碼如下:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
38 39
// 函式setup() : 準備階段function setup() { // 建立畫布,寬度640畫素,高度480畫素 // 畫布的座標系統為,左上角座標為(0,0), // x方向水平向右,y方向垂直向下,單位畫素 createCanvas(640,480);}// 函式draw():作畫階段function draw() { fill(255);// 填充白色 // 1 畫臉 ellipse(mouseX,mouseY,200,200);// 只有這一句改動了 // 2 左眼 ellipse(280,240,50,50);// 另一個圓圈 // 3 右眼 ellipse(360,240,50,50); // 4 嘴巴 ellipse(320,300
,80,40); fill(0);// 填充黑色 // 5 左眼珠 ellipse(280,240,20,20); // 6 右眼珠 ellipse(360,240,20,20); // 7 頭髮:從左到右畫一排豎線 line(260,180,260,100); line(280,180,280,100); line(300,180,300,100); line(320,180,320,100); line(340,180,340,100); line(360,180,360,100); line(380,180,380,100);}

執行效果如下:


p5.js程式框架執行機制

實際執行發現,卡通人物的臉部會始終隨著滑鼠位置移動,移動的軌跡也會記錄在畫布上。

為了理解上述現象,必須要解答兩個問題:

問題1 draw()這個函式是如何呼叫的?

問題2 mouseX和mouseY是啥玩意?

draw()函式呼叫方式

我們先來探討一下第一個問題。從之前的教程1.1節已經瞭解,setup()和draw()兩個函式定義了畫畫的兩個主要步驟,準備和作畫。然而,根據之前對於“函式”的討論,我們的程式碼中其實只是這兩個函式的“函式定義",而非“函式呼叫”。也就是說,這段程式碼中只是詳細說明了setup()和draw()兩個”行為/方法/招數/功能”的具體執行過程,但卻並沒有表達出在何時何地“施放”它們倆。那麼我們的程式怎麼就自動施放了它們呢?其實這就是p5.js幫我們做好的事情。p5.js既提供一大堆寫好的“函式/招數/功能/方法/行為“,同時也定義了一個”框架“(framework),也就是規定了程式的執行的方式如下:


可見,setup()只會在程式開始時執行一次,而draw()函式會反覆執行直到”中止“。而我們在sketch.js這個檔案中寫的程式其實只是整個程式的一部分,setup()和draw()的實際呼叫是由這個”框架“來實現的。

理解了這個框架,就能理解在上述程式中,為何懵逼臉隨著滑鼠移動反覆繪製——draw()函式反覆執行,每次執行中,滑鼠位置不同,所以每次畫臉的位置也就不同了。

 mouseX和mouseY是什麼?——變數

下面再討論第二個問題,即mouseX和mouseY是啥?

我們開啟官網的reference頁面(https://p5js.org/reference/),搜尋“mouse”,可以看到這哥倆的參考頁面連結:


開啟其中一個,可以檢視其解釋:


其含義就是,“變數” mouseX始終包含當前滑鼠的橫座標數值。

也就是說,mouseX是一個在程式執行過程中數值會發生變化的傢伙,其數值是隨著滑鼠的橫向移動而變化的。像這樣的在程式執行過程中數值可以改變的量就稱為變數(variable)。同理,mouseY也是一個變數,並且其數值隨著滑鼠的縱向移動而變化。相對的,我們之前那種直接指定的數值就叫做常量(constant),例如”ellipse(mouseX,mouseY,200,200);”中,第三四個引數就是用常量200來指定的。

現在,我們已經可以完整理解為何會發生上述現象。然而,光是臉部跟隨著滑鼠移動,效果很詭異,若能讓整個臉部都跟隨滑鼠移動,那才算達到我們的效果。為了實現這個目的,我們還需要進一步改造上述程式,並且要用到“表示式”進行一些簡單的四則運算,先看程式碼:

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
// 函式setup() : 準備階段function setup() { // 建立畫布,寬度640畫素,高度480畫素 // 畫布的座標系統為,左上角座標為(0,0), // x方向水平向右,y方向垂直向下,單位畫素 createCanvas(640,480);}// 函式draw():作畫階段function draw() { fill(255);// 填充白色 // 1 畫臉 ellipse(mouseX,mouseY,200,200);// 圓圈 // 2 左眼 ellipse(mouseX-40,mouseY,50,50);// 另一個圓圈 // 3 右眼 ellipse(mouseX+40,mouseY,50,50); // 4 嘴巴 ellipse(mouseX,mouseY+60,80,40); fill(0);// 填充黑色 // 5 左眼珠 ellipse(mouseX-40,mouseY,20,20); // 6 右眼珠 ellipse(mouseX+40,mouseY,20,20); // 7 頭髮:從左到右畫一排豎線 line(mouseX-60,mouseY-60,mouseX-60,mouseY-140); line(mouseX-40,mouseY-60,mouseX-40,mouseY-140); line(mouseX-20,mouseY-60,mouseX-20,mouseY-140); line(mouseX ,mouseY-60,mouseX ,mouseY-140); line(mouseX+20,mouseY-60,mouseX+20,mouseY-140); line(mouseX+40,mouseY-60,mouseX+40,mouseY-140); line(mouseX+60,mouseY-60,mouseX+60,mouseY-140);}
其執行結果顯示如下:


從執行結果可見,整個臉部都會跟隨滑鼠移動了。

從程式碼可見,原先與繪製位置有關的數值都改為與變數mouseX和mouseY有關的量,例如語句”ellipse(mouseX-40,mouseY,50,50);”中,指定橢圓中心位置為(mouseX-40,mouseY),其中"mouseX-40"就是一個“表示式”,其含義是計算出mouseX減小40得出數值,所以這個語句可以解釋為“在滑鼠當前位置偏左40畫素的位置畫一個長寬都是50的橢圓。” 再如語句“line(mouseX+20,mouseY-60,mouseX+20,mouseY-140);”,含義就是畫一個連線(mouseX+20,mouseY-60)和(mouseX+20,mouseY-140)兩個點的線段,第一個點的位置(mouseX+20,mouseY-60)即滑鼠位置偏右20畫素/偏上60畫素,第二個點的位置(mouseX+20,mouseY-140)即滑鼠當前位置偏右20畫素/偏上140畫素。

關於”表示式”,我們在後續章節在專門講解,這裡可以簡單理解為對用運算子對一系列變數和常量進行計算並得出結果的操作,它可以看作是程式的最基本元件。

相關資源