Castle Walls.

Made with Processing code examples in this article.
Made with Processing code examples in this article.

Bigger cells example.

Made with Processing code examples in this article.
Made with Processing code examples in this article.


Description.

Creative coding works made with Processing.

I tried to create the Game of Life of my own rule.
I thought that it may be interesting if I could add some random rules like an environment of nature. So I added 2D noise value to have an impact on deciding the cell's life and death.
Climate change, forest fire, drought or blessed rain will seal the cell's fate!

This code does not display any images on the screen but generates image files in frames directory.
You can make an animation movie with these files.

Processing code examples.

Please feel free to use it, if you like it.
To see other works based on my code is my pleasure. And my honor.




/**
 * Castle Walls.
 * an animation with the game of life of my own rule.
 * 
 * @author @deconbatch
 * @version 0.1
 * Processing 3.2.1
 * created : 2019/09/23
 */

void setup() {
  size(720, 720);
  colorMode(HSB, 360.0, 100.0, 100.0, 100.0);
  smooth();
  noStroke();
  noLoop();
}

void draw() {
  int   frmMax   = 24 * 16; // for 24fps x 16s animation
  float cellSize = 4.0;
  
  int canvasW = floor(width / cellSize);
  int canvasH = floor(height / cellSize);
  Cell[][] cells = new Cell[canvasW][canvasH];

  // cells constraction
  for (int x = 0; x < canvasW; x++) {
    for (int y = 0; y < canvasH; y++) {
      cells[x][y] = new Cell();
      cells[x][y].setLife(random(90.0));
    }
  }

  // set neighbor cells
  for (int x = 0; x < canvasW; x++) {
    for (int y = 0; y < canvasH; y++) {
      int mX = getMinus(x, canvasW);
      int mY = getMinus(y, canvasH);
      int pX = getPlus(x, canvasW);
      int pY = getPlus(y, canvasH);
      
      cells[x][y].setNeighbor(new Cell[] {
          // 8 directions
          cells[mX][mY],
          cells[pX][mY],
          cells[mX][pY],
          cells[pX][pY],
          cells[x][mY],
          cells[x][pY],
          cells[mX][y],
          cells[pX][y]
        });
    }
  }

  for (int frmCnt = 0; frmCnt < frmMax; frmCnt++) {
    background(0.0, 0.0, 100.0, 100.0);
    float frmRatio  = map(frmCnt, 0, frmMax, 0.0, 1.0);

    // game of life calculation
    for (int x = 0; x < canvasW; x++) {
      for (int y = 0; y < canvasH; y++) {
        cells[x][y].sumLife();
      }
    }
    
    for (int x = 0; x < canvasW; x++) {
      for (int y = 0; y < canvasH; y++) {
        float envFactor = noise(frmRatio * 2.5, x * 0.05, y * 0.05);
        // game of life calculation
        cells[x][y].liveOrDie(envFactor);
        
        // draw cells
        float eHue = map(envFactor, 0.0, 1.0, 300.0, 360.0 + 300.0) % 360.0;
        float eSat = cells[x][y].getLife() * 40.0;
        float eBri = 100.0 - cells[x][y].getLife();
        float eSiz = cellSize * (100.0 - cells[x][y].getLife() * 0.5) * 0.01;
        fill(eHue, eSat, eBri, 100.0);
        ellipse(x * cellSize, y * cellSize, eSiz, eSiz);
      }
    }

    saveFrame("frames/" + String.format("%04d", frmCnt) + ".png");

  }

  exit();
  
}

/**
 * getMinus
 * calculate the coordinates of the point. take overflow into account.
 * @param  _a      : coordinates of the point, x or y
 * @param  _border : canvas width or height
 */
private int getMinus(int _a, int _border) {
  int ret = _a - 1;
  if (ret < 0) {
    ret = _border - 1;
  }
  return ret;
}

/**
 * getPlus
 * calculate the coordinates of the point. take overflow into account.
 * @param  _a      : coordinates of the point, x or y
 * @param  _border : canvas width or height
 */
private int getPlus(int _a, int _border) {
  int ret = _a + 1;
  if (ret >= _border) {
    ret = 0;
  }
  return ret;
}

/**
 * Cell
 * manage one cell.
 */
private class Cell {

  private float  myLife;
  private float  neighborLives;
  private Cell[] neighbor;

  Cell() {
    myLife = 0.0;
  }

  /**
   * setNeighbor
   * set the neighbor cells.
   * @param  _neighbor : the neighbor cells array
   */
  public void setNeighbor(Cell[] _neighbor) {
    neighbor = new Cell[_neighbor.length];
    for (int i = 0; i < _neighbor.length; i++) {
      neighbor[i] = _neighbor[i];
    }
  }

  /**
   * setLife
   * set the life value of this cell.
   * @param  _life : life value
   */
  public void setLife(float _life) {
    myLife = _life;
  }

  /**
   * getLife
   * get the life value of this cell.
   * @return : life value 0.0 - 100.0
   */
  public float getLife() {
    return constrain(myLife, 0.0, 100.0);
  }

  /**
   * sumLife
   * sum up the life value of neighbor cells.
   */
  public void sumLife() {
    neighborLives = 0.0;
    for (int i = 0; i < neighbor.length; i++) {
      neighborLives += neighbor[i].getLife();
    }
  }

  /**
   * liveOrDie
   * calculate the life value of this cell with deconbatch's game of life rule.
   * @param  _environment : the value that have an impact on calculation
   */
  public void liveOrDie(float _environment) {
    float lifeBorder = 50.0;
    float paramA = map(_environment, 0.0, 1.0, 2.5, 3.5);
    float paramB = map(_environment, 0.0, 1.0, 3.5, 4.5);
    float paramC = map(_environment, 0.0, 1.0, 1.5, 0.5);

    if (myLife < lifeBorder) {
      // I'm dead
      if (neighborLives > lifeBorder * paramA && neighborLives < lifeBorder * paramB) {
        // inject vitality
        myLife += 15.0;
      } else {
        // suck
        myLife -= 15.0;
      }
    } else {
      // I'm alive
      if (neighborLives < lifeBorder * paramC || neighborLives > lifeBorder * paramB) {
        // suck
        myLife -= 20.0;
      }
    }
    myLife = constrain(myLife, 0.0, 100.0);
  }
}


/*
Copyright (C) 2019- deconbatch

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see 
*/




No comments :

Post a Comment