Processing 網格紋理製作(棋盤格)

EYE發表於2020-09-25

寫在前面的話

很久沒有寫博文了。最近在整理Processing有關文件,看到之前做的一些例子,想著分享在網際網路上,當然和以前一樣,目前也僅為了給初學者有個學習參考,筆者能力有限。廢話不多說,幹就完事了。
來做個紋理怎麼樣?基本紋理很多樣式,我們慢慢嘗試去實現,今天搞一個網格紋理,準確的說是棋盤格,就像下圖所示:

Processing 網格紋理製作(棋盤格)

開始

首先寫好Processing該有的樣子,定義settings(),setup(),draw()等函式:

void settings(){
   size(800,800);
}
void setup() {
   
}

void draw() {
   
}

這個settings()我會單獨去做講解,這裡簡單說一下:它是早於setup()初始化的處理函式,有點像Unity指令碼系統中Start()Awake()的關係,但是邏輯層面是不一樣的。很多PApplet類中的函式在這裡是不能被呼叫的,除了size()smooth()兩個函式。而且,一旦寫了settings(),就必須得把上述兩個函式寫在settings()裡頭!大家以後都可以養成習慣這麼去填寫,因為Processing系統這麼設定,有它的道理,不過如果是純碎學習,那不碼這個settings()也無妨。還有個值得說的,因為只是要做個圖,其實draw()沒必要寫上。

小試牛刀

我們先試一試畫一個矩形框,如下:

noStroke();
fill(255);
rect(150,150,100,100);

這樣會在畫布上出現一個白色矩形框,ok,接下來要做的是把這個事情給過程化(程式導向),寫個函式封裝其過程:

void drawRect(int c, int x, int y, int w, int h) {
  noStroke();
  fill(c);
  rect(x, y, w, h);
}

drawRect()可以被傳入五個引數,分別代表其顏色、座標資訊x,y、矩形長寬大小。為什麼能這麼去封裝它,這要求思考問題本身。細細觀察棋盤格的特點,黑白方塊相隔,如果抽象出它的屬性,那麼就不難想得到有諸如上述的引數,我們把它稱之為屬性(當然這個說法其實是不嚴謹的,因為現在我們的程式設計思路僅僅是程式導向,在OOP物件導向中這個特點會更加明顯)[哦對,有讀者感興趣的話也能找找有關函數語言程式設計的資料,絕對會讓你開拓眼界,在思考問題的方式上會有不一樣的感受哦,參考https://www.zhihu.com/question/28292740?sort=created]。

再接再厲

有了這個函式就可以在外頭傳進引數來繪製想要的結果,那問題來了,如何傳進去?首先是顏色,顏色好辦,

int c = color(200,20,20);  //這裡可以將color型別看成是int 型別,其實在計算機裡顏色這概念也就是一個數值而已

這樣就結束了。然後是位置,如果你之前學過或者感受過迴圈結構(程式設計是要多多感受的,你說程式設計有沒有套路,其實很多時候是可以憑經驗辦事的),那麼就不難想到兩個for迴圈遍歷來繪製佈滿整個畫布的圖形的例子,那在這裡,同樣是做這樣的處理(這就是所謂的演算法):

for (int x = 0; x  < width; x += increW)
  {
    for (int y = 0; y < height; y += increH)
    {
      int c = color(255);
      drawRect(c, x, y, increW, increH);
    }
  }

而對於矩形大小,我們做一假設,設想要在畫布上繪製10*10個方塊陣列,那麼每個方塊的大小,即位置偏移增量increWincreH(increment表示增量,一般我們會使用常用的英文縮寫定義變數名)就可以這麼計算得出:

  increW = width / WCOUNT;   //   WCOUNT、HCOUNT代表數量10、10  你可以寫成 increW=width/WCOUNT;這樣,沒問題!
  increH = height / HCOUNT;  //   但是養成良好的程式設計習慣和修養,加上些空格,你自己也覺得便於閱讀,還haokanmeiguan

在for語句的第三個表示式中寫明x自加increW,y自加increH,得到的結果便是每次傳入drawRect()函式中的位置有了相應偏移,大小也有了定義,即每次位移的數值。如果你按照這一步驟敲碼執行,你會得到全白的畫布,為什麼呢?很簡單,事實上Processing已經幫你繪製了這麼多方塊,只是顏色統一,位置統一,完美無瑕得散步在畫布上了,沒有任何縫隙。而要想實現間隔黑白效果,是不是還得加上黑色方塊呢。是的,就得是要繪製這樣的rect:

noStroke();
fill(0);
rect(150,150,100,100);

但是,如何把它整合在for迴圈體裡呢?這就又要談到簡單的演算法技巧,我們可以引入一個開關變數來處理間隔繪製不同顏色的流程,對於"開關變數"這一說法,讀者請參考https://blog.csdn.net/fddxsyf123/article/details/62848357這一篇之前寫的。在這裡你腦力應是如下的邏輯:

if(k == 0)
{
   fill(255);
   rect(150,150,100,100);
}
if(k == 1)
{
   fill(0);
   rect(150,150,100,100);
}

結成正果

我們進一步把它簡化,看成是奇數和偶數差別,這樣只要定義一個int值,每次繪畫完畢,相當於狀態要改變了,就得切換,這個值自加一個值或者自減就可以達成了。有機整合進迴圈體,可以這樣表示:

int k = 0;   // k代表狀態,具體數值代表什麼意思得看上下文
int c = 0;
for (int x = 0; x  < width; x += increW)
{
  for (int y = 0; y < height; y += increH)
  {
    if(k % 2 == 0)  //注意這個判斷條件是關鍵的,判斷是否被2整除,如果真,則是偶數,反之奇數,這就達成了兩種狀態互切效果
      c = color(255);
    else 
      c = color(0);
    drawRect(c, x, y, increW, increH);
    k++;   //一個狀態完畢,切換
  }
  k++;   //現在是一列一列遍歷繪製,因此沒換一列也得切換狀態,形成棋盤網格效果
}

好了基本圖形已經展現出來了~~~ 完整程式碼如下:

int increW;
int increH;
int WCOUNT = 10;
int HCOUNT = 10;

void drawRect(int c, int x, int y, int w, int h) {
  noStroke();
  fill(c);
  rect(x, y, w, h);
}

void settings() {
  size(800, 800);
}
void setup() {
  increW = width/WCOUNT;
  increH = height/HCOUNT;
  int k = 0;
  int c = 0;
  for (int x = 0; x  < width; x += increW)
  {
    for (int y = 0; y < height; y += increH)
    {
      if (k % 2 == 0)
        c = color(255);
      else 
      c = color(0);
      drawRect(c, x, y, increW, increH);
      k++;
    }
    k++;
  }
}

void draw() {
}

呈現的效果

Processing 網格紋理製作(棋盤格)

寫在最後的話

好久沒寫了,是該多分享多交流,我會同步更新於CSDN上,請多多支援鼓勵,有問題留言,感謝。

相關文章