一天一點Processing|10另類繪畫1——圈圈圓圓圈圈
本次教程使用的圖片來自於攝影師Mae Mu,他有許多美食相關的攝影,歡迎大家訪問它的主頁哦~~
這次我們嘗試一種另類的繪畫方式,雖然十分簡單,但是效果很好哦。學完就可以盡情地重繪自己喜歡的照片啦,各位加油~~~
在寫程式碼之前,我們可以梳理一下總體步驟(和把大象關進冰箱一樣,只有三步哦~):
匯入自己喜歡的影象
畫素點取色
畫圓
主體
我們先可以將主體碼出來,除了setup()函式與draw()函式,我們還需要一個Ball物件,來建立小球,還可以用一個makeBalls()功能來建立一個圓的集合。
ArrayList
//
初始化函式
void setup(){
}
//
週期回撥函式
void draw(){
makeBalls(); //建立小球集合
}
//建立小球集合
void makeBalls(){
ballCollection。add(new Ball()); //建立球體,將小球放入集合之中
}
//建立球體
class Ball{
}
匯入影象
首先我們要準備一張自己喜歡的圖片(還是做不到無中生有的~~)。
PImage img; //初始化
影象變數
void setup(){
size(500, 650); //建立畫布
img = loadImage(“tomato。jpg”); //匯入圖片,“”輸入影象的名稱
imageMode(CENTER); //將圖片定位調整為中心點
img。resize(width, height); //圖片大小調整為畫布大小
image(img, width/2, height/2); //將圖片繪製在畫布上
}
點選除錯按鈕,我們就能夠看到畫布中影象的存在啦~~
在此時可能會報錯,說影象不存在,不要慌,我們有兩種方式解決這個問題:
直接將圖片放入資料夾中,圖片名稱需要和程式碼中一致
或者透過 速寫本 - 新增檔案
畫素點取色
我們透過color型別的顏色變數col提取顏色,注意get()之中的變數型別是int;
color col = img。get((int)position。x, (int)position。y);
小球三部曲1 · 編寫小球物件
雖然畫圓是一個很簡單的步驟,但在編寫程式碼時我們需要分為兩個步驟。一是設定一個物件,方便透過控制變數繪製小球;二是透過輸入
變數值
繪製小球。我們首先設定小球的類。
我們先寫好主要框架。
class Ball{ //自定義宣告物件
//公共變數
//自定義屬性
Ball() {
}
//自定義功能
}
我們可以思考一下這個物件的變數有哪些?我們來繪製每個小球的時候需要考慮的因素是什麼呢?
我們可以來回顧一下我們畫圈的步驟,從原圖片中提取一個點,提取點的顏色,然後畫一個相同顏色的圓。因此,影響小球繪製的三個屬性就很明確了:位置點的座標,想要繪製的小球半徑,小球的顏色。其中需要注意的是位置點座標用向量類來儲存。
class Ball { //自定義宣告物件
//公共變數
PVector position;
float radius;
color c;
//自定義屬性
Ball(PVector _position, float _radius, color _c){
position = _position;
radius = _radius;
c = _c;
}
//自定義功能
}
上面我們完成了小球的屬性輸入了,接下來,我們要利用這個類做什麼呢??
當然是希望能夠繪製小球啦!
此時就可以在自定義功能中加入繪製功能display(),當然,將函式設定成什麼名字隨便啦,按照你的喜好就好。
void display() {
noStroke(); //繪製的圖形沒有邊線
fill(c); //用顏色c填充
ellipse(position。x, position。y, radius*2, radius*2); //畫圓
}
小球三部曲2
·
集合
我們希望每一幀都有多個小球產生,此時就需要編寫makeBalls()這個功能,讓一次性產生多個小球,利用
迴圈
多次輸入不同屬性的小球,並將它們儲存起來,在同一幀中進行繪製。
void makeBalls() {
for (int i=0; i < num; i++) {
PVector position = new PVector(random(width), random(height)); //產生隨機位置
float radius = random(5,10); //隨機確定小球大小
color col = img。get((int)position。x, (int)position。y); //提取畫素顏色
ballCollection。add(new Ball(position, radius, col)); //將球放入集合之中
}
}
在這個功能中,提取隨機位置,確定小球半徑,以及提取畫素顏色,透過ballCollection這個集合將小球都收集起來。
小球三部曲3
·
繪製
最終在draw()函式中我們可以繪製小球啦
void draw(){
makeBalls(); //建立小球集合
//繪製圓圈,迴圈提取球進行顯示
for (Ball draw : ballCollection) { //迴圈提取ballCollection中的每個元素,依次賦值給draw
draw。display();
}
}
問題篇
至此繪製的工作就基本完成啦。但是在這個過程中我們會發現小球會重複繪製,繪製的速度也過於快了,不好控制最終的成果。如何來解決這些問題呢??
1.幀數過快?
frameRate(1); //在setup()函式中加入frameRate(),透過內部數字對幀數進行控制,數字越大越快
2.小球重複繪製?
將程式碼
ballCollection。add(new Ball(position, radius, col));
改為
if (col != 0) { //判定當前座標點還沒有繪製圓,顏色不為黑,則可以進行繪製
ballCollection。add(new Ball(position, radius, col));
}
3.小球大小相似,沒有層次感?
可以透過每次繪製減小圓的半徑這種方式,先繪製
大圓
在用小圓進行補充,會讓整幅畫更有層次。將radius設定為
全域性變數
,在draw()中每迴圈一次增加就減少一點。
最終附上所有程式碼供大家學習哦~~
主程式
ArrayList
PImage img; //初始化圓
int num
= 200;
float radius = 20; //
初始半徑
int count = 0; //繪製次數
//初始化函式
void setup() {
size(500, 650); //建立畫布
background(0); //黑色
img = loadImage(“tomato。jpg”); //匯入圖片
imageMode(CENTER); //將圖片定位調整為中心點
img。resize(width, height); //圖片大小調整為畫布大小
image(img, width/2, height/2); //將圖片放置在畫布上
frameRate(4);
}
//週期回撥函式
void draw() {
if (count <10) { //當計數為10停止
makeBalls(); //建立小球集合
//繪製
圓圈
,迴圈提取球進行顯示
for (Ball draw : ballCollection) {
draw。display();
}
radius *= 0。8;
num *= 1。2;
count ++; //增加計數
}
}
void makeBalls() {
for (int i=0; i < num; i++) {
PVector position = new PVector(
random(width
), random(height)); //產生
隨機位置
//float radius = random(5,10);
color col = img。get((int)position。x, (int)position。y); //提取畫素顏色
if (col != 0) { //判定當前座標點沒有繪製圓
ballCollection。add(new Ball(position, radius, col));
}//將球放入集合之中
}
}
Ball物件
class Ball{ //自定義宣告物件
//公共變數
PVector position;
float radius;
color c;
//自定義屬性
Ball(PVector _position, float _radius, color _c) {
position = _position;
radius = _radius;
c = _c;
}
//自定義功能
void display() {
noStroke(); //繪製的圖形沒有邊線
fill(c); //用顏色c填充
ellipse(position。x, position。y, radius*2, radius*2); //畫圓
}
}