第二篇文章我們完成了第一個作品,我們做出了分散在上下左右,能夠隨著滑鼠移動的四個圓圈。

現在我們希望在第二個作品做優化,讓這四個圓圈,還能繞著滑鼠做圓周運動,就像是行星繞著太陽一樣,那我們該怎麼做呢?

首先我們要先解釋一下 p5.js 中,畫布的 xy 座標系統,這個座標系統的原點 (0,0) 位於畫布的左上角,且 x 軸正向為由左到右,而 y 軸正向為由上到下:

Imgur

當我們要做出圖案隨時間進行運動(圓周運動)的效果,就必須引入 frameCount 這個變數,該變數紀錄了目前 p5.js 執行了幾次 draw() 函數,也就是他繪製了多少幀動畫。

下面是第一個作品的程式,我們試著在裡面加入 frameCount 變數。

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

function draw() { background(100, 100); circle(mouseX+100, mouseY, 20); circle(mouseX-100, mouseY, 20); circle(mouseX, mouseY+100, 20); circle(mouseX, mouseY-100, 20); }

現在我們開啟第二個作品的編輯界面,嘗試加入 frameCount 變數:

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

function draw() { background(100, 100); circle(mouseX+100, mouseY + frameCount, 20); circle(mouseX-100, mouseY + frameCount, 20); circle(mouseX, mouseY+100 + frameCount, 20); circle(mouseX, mouseY-100 + frameCount, 20); }

我在每個圓圈的 y 座標都加上 frameCount,因此除了會跟著滑鼠移動,他們還會因為 y 值的遞增,而逐漸往下移動,離滑鼠越來越遠:

Imgur

那如果我們要使用這個 frameCount 來執行每個圓圈的圓周運動,那要怎麼做呢?

這裡就要稍微引入一下數學的向量概念:

Imgur

上圖中的兩個箭頭分別代表向量 A (x1, y1) 跟向量 B (x2, y2),像這樣的二維向量,我們可以用一組 xy 座標來代表他。

然後這兩個向量他們的長度是一樣的,因此向量 A 和向量 B 這樣看起來就只有一個角度的轉向,然後這個角度就是 θ

重點來了,我們希望找到一個函數,他的輸入為 x1, y1, θ,得到輸出為 x2, y2,這個函數的用意在幹嘛呢?就是我希望輸入某個向量 (x1, y1) 跟某個角度 θ,然後他要將這個向量 (x1, y1) 以逆時針轉 θ 度之後得到的新向量 (x2, y2) 給我們,所以這個函數是用來做向量旋轉的。

假設我們已經有了這個函數叫做 vector_rotate,輸入向量就是圓圈相對於滑鼠的初始位置,角度為 frameCount/30,輸出就是圓圈相對於滑鼠的新位置,現在初始位置固定,那隨著 frameCount 遞增,新位置所轉的位置也遞增,我們的圓圈不就可以繞著滑鼠做圓周運動了嗎?

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

function vector_rotate(x, y, angle) { ... }

function draw() { background(100, 100); // 這是初始位置 let [init_pos_x, init_pos_y] = [100, 0]; // 這是新位置 let [new_pos_x, new_pos_y] = vector_rotate(init_pos_x, init_pos_y, frameCount/30); circle(mouseX+new_pos_x, mouseY + new_pos_y, 20); }

若能夠完成 vector_rotate 的內容,那這段程式呈現出來的動畫會像這樣:

Imgur

如果要實作 vector_rotate,就必須要知道一些高中數學知識,在高中數學會學到一個矩陣叫做旋轉矩陣,就是用來做二維向量的旋轉:

Imgur

我們不需要知道旋轉矩陣的實際細節,我們只需要借用他們的結果就行了,這個 vector_rotate 的內容就是:

function vector_rotate(x, y, angle) {
        return [cos(angle)x-sin(angle)y,sin(angle)x+cos(angle)y];
}

現在我們能夠實現圓周運動了,那我們的第二個作品就是將第一個作品的四個圓圈加上圓周運動:

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

function vector_rotation(x,y,angle) { return [cos(angle)x-sin(angle)y,sin(angle)x+cos(angle)y]; }

function draw() { background(100, 100); let v = PI / 80 * frameCount; let [x1, y1] = vector_rotation(100, 0, v); let [x2, y2] = vector_rotation(-100, 0, v); let [x3, y3] = vector_rotation(0, 100, v); let [x4, y4] = vector_rotation(0, -100, v);

let y = mouseY; let x = mouseX; circle(x+x1, y+y1, 20); circle(x+x2, y+y2, 20); circle(x+x3, y+y3, 20); circle(x+x4, y+y4, 20); }

這是呈現出來的動畫:

Imgur