The Game of Life with the rule like an environment of nature
The Game of Life of my own rule.
It's a creative coding animation work made with the 'Processing'.
This animation looks like burning and repairing walls.
Bigger cells example.
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!
Processing code example.
Please feel free to use this Processing example code under the terms of the GPL.
To see other works based on my code is my pleasure. And my honor.
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.
/** * 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 <http://www.gnu.org/licenses/> */