BioErrorLog Tech Blog

試行錯誤の記録

Generative Art #6 - Processing作品

おはよう。@bioerrorlogです。

ProcessingによるGenerative Art作品
6作目を記録します。

自作品まとめはこちら: www.bioerrorlog.work

Output

f:id:BioErrorLog:20191216083138p:plain f:id:BioErrorLog:20191216083206p:plain f:id:BioErrorLog:20191216083232p:plain f:id:BioErrorLog:20191216083258p:plain

フル解像度/その他出力パターンはこちら:
Generative_6 - BioErrorLog - pixiv


Material

使用言語: Processing 3.5.3

Processingというプログラミング言語に聞き覚えがない、という方は是非こちらをご参考ください:
www.bioerrorlog.work


Source Code

GitHubはこちら

Cell[][] _cellArray;
int _cellSize = 1; // Cellの大きさ(pixel)
int _numX, _numY; // ディスプレイのCell格子


void setup() { 
  size(1920, 1080);
  _numX = floor(width/_cellSize);
  _numY = floor(height/_cellSize);
  restart();
} 


void restart() {
  // _cellArrayに画面分のCellを入れる
  _cellArray = new Cell[_numX][_numY];    
  for (int x = 0; x<_numX; x++) {
    for (int y = 0; y<_numY; y++) {    
      Cell newCell = new Cell(x, y);  
      _cellArray[x][y] = newCell;      
    }               
  }                 

  
  for (int x = 0; x < _numX; x++) {
    for (int y = 0; y < _numY; y++) {  
      
      int above = y-1;        
      int below = y+1;        
      int left = x-1;         
      int right = x+1;            
      
      // 画面端の処理
      if (above < 0) { above = _numY-1; }    
      if (below == _numY) { below = 0; } 
      if (left < 0) { left = _numX-1; }  
      if (right == _numX) { right = 0; } 

     _cellArray[x][y].addNeighbour(_cellArray[left][above]);    
     _cellArray[x][y].addNeighbour(_cellArray[left][y]);        
     _cellArray[x][y].addNeighbour(_cellArray[left][below]);    
     _cellArray[x][y].addNeighbour(_cellArray[x][below]);   
     _cellArray[x][y].addNeighbour(_cellArray[right][below]);   
     _cellArray[x][y].addNeighbour(_cellArray[right][y]);   
     _cellArray[x][y].addNeighbour(_cellArray[right][above]);   
     _cellArray[x][y].addNeighbour(_cellArray[x][above]);       
    }
  }
}


void draw() {
  background(200);
                    
  for (int x = 0; x < _numX; x++) {
    for (int y = 0; y < _numY; y++) {
     _cellArray[x][y].calcNextState();
    }
  }
                        
  translate(_cellSize/2, _cellSize/2);     
                        
  for (int x = 0; x < _numX; x++) {
    for (int y = 0; y < _numY; y++) {
     _cellArray[x][y].drawMe();
    }
  }
}


void keyPressed(){
    /*
    ENTERキー押下: 画像を保存する
    BACKSPACEキー押下: setup()を呼ぶ
    */
    
    if (keyCode == ENTER){
        saveFrame("generative_5_####.png");
    }
    if (keyCode == BACKSPACE){
        setup();
    }
}


class Cell {
  float x, y;
  float state;         
  float nextState;  
  float lastState = 0; 
  Cell[] neighbours;
  
  Cell(float ex, float why) {
    x = ex * _cellSize;
    y = why * _cellSize;
    
    // Cellの初期状態を定義
    // 画面の真ん中のCellは255, それ以外は2
    if(ex == width/2 && why == height/2){
      nextState = 255;
    }else{
      nextState = 2;
    }

    state = nextState;
    neighbours = new Cell[0];
  }
  
  void addNeighbour(Cell cell) {
    neighbours = (Cell[])append(neighbours, cell); 
  }
  
  void calcNextState() {
    /*
    1. もし隣接するセルの状態の平均が255であれば状態は0に
    2. もし隣接するセルの状態の平均が0であるなら状態は255に
    3. そうでなければ、新しい状態=現在の状態+隣接セルの状態の平均ー前の状態の値
    4. もし新しい状態が255を超えたら255にし、
    5. もし新しい状態が0以下ならそれを0にする
    */
                
    float total = 0;              
    for (int i=0; i < neighbours.length; i++) { 
       total += neighbours[i].state;        
    }                   
    float average = int(total/8);
                
    if (average == 255) { // 1.
      nextState = 0;
    } else if (average == 0) {
      nextState = 255; // 2.
    } else {
      nextState = state + average;
      if (lastState > 0) { nextState -= lastState; } // 3.
      if (nextState > 255) { nextState = 255; } // 4.
      else if (nextState < 0) { nextState = 0; } // 5.
    }
 
    lastState = state;  
  }
  
  void drawMe() {
    state = nextState;
    noStroke();
    fill(state);    
    rect(x, y, _cellSize, _cellSize);
  }
}

Discussion

マット・ピアソン「ジェネラティブ・アート―Processingによる実践ガイド」7章で紹介される、セルオートマトンのケーススタディを改変して作成。

画面中央のピクセルから徐々にセルオートマトンを波及させていきます。

今回のセルオートマトンの規則は次の通り(「ジェネラティブ・アート―Processingによる実践ガイド」より引用)。

  • もし隣接するセルの状態の平均が255であれば状態は0に
  • もし隣接するセルの状態の平均が0であるなら状態は255に
  • そうでなければ、新しい状態=現在の状態+隣接セルの状態の平均ー前の状態の値
  • もし新しい状態が255を超えたら255にし、もし新しい状態が0以下ならそれを0にする


脳の染色画像のような、あるいは悪い夢を見ているときのような、不思議で不気味なパターンが面白いところです。


See also

www.bioerrorlog.work

www.bioerrorlog.work

www.bioerrorlog.work

Reference