iT邦幫忙

2024 iThome 鐵人賽

DAY 12
0
Modern Web

p5.js 的環形藝術系列 第 12

[Day 12] p5.js 基礎教學(六) –– random 函數

  • 分享至 

  • xImage
  •  

現在我們來學如何使用隨機函數,最後幫我們作品的每個 circle 隨機填上不一樣的顏色。

random() 語法解說

random()

如果我們只接使用無參數版本的 random() 函數,那這個參數會回傳 0 ~ 1 之間的隨機數(但不包含 1),以下執行一個簡單的取隨機數範例:

function setup() {
    createCanvas(500, 500);
    colorMode(HSB, 500);
	
    translate(width/2, height/2);
	
    textSize(50);
    text(random(), -250, 0); // 把隨機數結果寫在畫布上

    noLoop(); // 停止 draw() 渲染
}

每次執行都會重新指派一個 0 ~ 1 之間的隨機數。

random(max)

若傳入一個參數,則函數能回傳 0 ~ max(不包含 max)之間的隨機數。

random(min, max)

若傳入一個參數,則函數能回傳 min ~ max(不包含 max)之間的隨機數。

幫每個 circle 隨機分配顏色

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

function draw() {
    background(100, 10);
    translate(width/2, height/2);

    var outer_orbit_speed = -frameCount/60/6 * 2 * PI;
    var inner_orbit_speed = frameCount/60/3 * 2 * PI;
    var inner_orbit_num = 5;
    var circle_num = 5;

    for (var i = 0; i < inner_orbit_num; i++) {
        push();

        rotate(outer_orbit_speed);
        translate(200 * cos(i / inner_orbit_num * 2 * PI), 200 * sin(i / inner_orbit_num * 2 * PI));
        rotate(-outer_orbit_speed);
		
        rotate(inner_orbit_speed);
        for (var j = 0; j < circle_num; j++) {
            colorMode(HSB, 100);
            // stroke(sin(frameCount/60/4)*50+50, 100, 80);
		    stroke(random(0,100), 100, 80);
            circle(100 * cos(j / circle_num * 2 * PI), 100 * sin(j / circle_num * 2 * PI), 20);
            colorMode(RGB);
        }
		
        pop();
    }
}

Imgur

我們把原本的 stroke(sin(frameCount/60/4)*50+50, 100, 80); 改成 stroke(random(0,100), 100, 80);,所以從原本的顏色漸變,變成每個 circle 經過每一幀就會隨機變換一個顏色。

但這樣看起來亂糟糟的,如果我們希望的是讓每個 circle 都隨機分配不一樣的顏色,但這顏色經過分配後就不會再隨時間進行改變,我們該怎麼做?

var inner_orbit_num = 5;
var circle_num = 5;
var random_color_list = [];

function setup() {
    createCanvas(windowWidth, windowHeight);
    background(100);
	
    for (var i = 0; i < inner_orbit_num; i++) {
        for (var j = 0; j < circle_num; j++) {
            random_color_list.push(random(0, 100));
        }
    }
}

function draw() {
    background(100, 10);
    translate(width/2, height/2);
	
    var outer_orbit_speed = -frameCount/60/6 * 2 * PI;
    var inner_orbit_speed = frameCount/60/3 * 2 * PI;

    for (var i = 0; i < inner_orbit_num; i++) {
        push();

        rotate(outer_orbit_speed);
        translate(200 * cos(i / inner_orbit_num * 2 * PI), 200 * sin(i / inner_orbit_num * 2 * PI));
        rotate(-outer_orbit_speed);
		
        rotate(inner_orbit_speed);
        for (var j = 0; j < circle_num; j++) {
            colorMode(HSB, 100);
            stroke(random_color_list[i * circle_num + j], 100, 80);
            circle(100 * cos(j / circle_num * 2 * PI), 100 * sin(j / circle_num * 2 * PI), 20);
            colorMode(RGB);
        }
		
        pop();
    }
}

Imgur

我們可以在 setup() 的時候,先用雙重迴圈指派所有顏色到 random_color_list(一共有 inner_orbit_num * circle_num 個顏色),然後我們再用 random_color_list[i * circle_num + j] 將顏色指派到對應的 circle。

randomSeed() 語法解說

依照我們剛剛完成的作品,每次作品在運行的時候,都會重新隨機指派顏色到每一個 circle,但如果現在我們的需求,是希望每次都能復現原先的隨機分配結果,就需要用到 randomSeed() 函數。

randomSeed(seed)

randomSeed() 接收一個整數參數 seed,該參數指定一個隨機種子數值,只要該數值固定,往後重新執行 scripit 裡面的 random() 函數都會重現原本的隨機數值:

function setup() {
  createCanvas(500, 500);
  colorMode(HSB, 500);
	
	translate(width/2, height/2);
	
	randomSeed(100);
	
	textSize(50);
	text(random(), -250, -200);
	text(random(), -250, -150);
	text(random(), -250, -100);
	text(random(), -250, -50);
	text(random(), -250, 0);
	text(random(), -250, 50);
	text(random(), -250, 100);
	text(random(), -250, 150);
	text(random(), -250, 200);

	noLoop(); // 停止 draw() 渲染
}

Imgur

只要指定一個固定的隨機種子,每次執行該 script 都會生成一樣的隨機數列。

var inner_orbit_num = 5;
var circle_num = 5;
var random_color_list = [];

function setup() {
    createCanvas(windowWidth, windowHeight);
    background(100);
    
    randomSeed(20); // 固定一個隨機種子數值
	
    for (var i = 0; i < inner_orbit_num; i++) {
        for (var j = 0; j < circle_num; j++) {
            random_color_list.push(random(0, 100));
        }
    }
}

function draw() {
    background(100, 10);
    translate(width/2, height/2);
	
    var outer_orbit_speed = -frameCount/60/6 * 2 * PI;
    var inner_orbit_speed = frameCount/60/3 * 2 * PI;

    for (var i = 0; i < inner_orbit_num; i++) {
        push();

        rotate(outer_orbit_speed);
        translate(200 * cos(i / inner_orbit_num * 2 * PI), 200 * sin(i / inner_orbit_num * 2 * PI));
        rotate(-outer_orbit_speed);
		
        rotate(inner_orbit_speed);
        for (var j = 0; j < circle_num; j++) {
            colorMode(HSB, 100);
            stroke(random_color_list[i * circle_num + j], 100, 80);
            circle(100 * cos(j / circle_num * 2 * PI), 100 * sin(j / circle_num * 2 * PI), 20);
            colorMode(RGB);
        }
		
        pop();
    }
}

Imgur

只要指定一個隨機種子,我們分配給 circle 的隨機顏色就會是固定的,不會因為重新執行 script 就改變顏色。

帶領作品邁向無人之境

如果這些顏色變化看起來太無聊,沒關係!我們把作品的參數調整一下,馬上將這個作品帶向無人之境。

var inner_orbit_num = 80; // 把小公轉軸數量加到 80
var circle_num = 30; // 把每個小公轉軸的 circle 數量加到 30
var random_color_list = [];

function setup() {
    createCanvas(windowWidth, windowHeight);
    background(100);
    
    randomSeed(20); // 固定一個隨機種子數值
	
    for (var i = 0; i < inner_orbit_num; i++) {
        for (var j = 0; j < circle_num; j++) {
            random_color_list.push(random(0, 100));
        }
    }
}

function draw() {
    background(100, 10);
    translate(width/2, height/2);
	
    var outer_orbit_speed = -frameCount/60/6 * 0.5 * PI; // 將大公轉速率調慢 4 倍
    var inner_orbit_speed = frameCount/60/3 * 0.5 * PI; // 將小公轉速率調慢 4 倍

    for (var i = 0; i < inner_orbit_num; i++) {
        push();

        rotate(outer_orbit_speed);
        translate(200 * cos(i / inner_orbit_num * 2 * PI), 200 * sin(i / inner_orbit_num * 2 * PI));
        rotate(-outer_orbit_speed);
		
        rotate(inner_orbit_speed);
        for (var j = 0; j < circle_num; j++) {
            colorMode(HSB, 100);
            stroke(random_color_list[i * circle_num + j], 15, 50); // 調整飽和度跟亮度
            circle(100 * cos(j / circle_num * 2 * PI), 100 * sin(j / circle_num * 2 * PI), 5); // 把 circle 直徑調整為 5
            colorMode(RGB);
        }
		
        pop();
    }
}

Imgur

作品網址:
https://openprocessing.org/sketch/2316255

非常奇妙,調整了一些參數就讓作品變得魔幻起來了,無數個 circle 以一種神秘的秩序互相連動,並且隨機配色的軌跡讓作品隱隱散發各種光芒。

大家也來試試自己調整參數,這些意想不到的變化讓人感嘆 p5.js 的世界真的很美!


上一篇
[Day 11] p5.js 基礎教學(五) –– p5.js 的顏色系統
下一篇
[Day 13] p5.js 基礎教學(七) –– 繪製不規則形狀
系列文
p5.js 的環形藝術30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言