Search code examples
javascriptp5.jsgame-developmentconways-game-of-life

Conway's game of life prefers bottom-left of screen


I'm creating Conway's Game of Life, but I've run into an issue: The pixels seem to prefer "moving" towards the bottom-left side of the screen. I'm not sure what's causing this. I've tried debugging this but to no avail.

link to editor: https://editor.p5js.org/KoderM/sketches/T-Vr35vZy

I'm going off of The Coding Train's game of life: https://editor.p5js.org/codingtrain/sketches/UtSMCB1zv

Sketch.js:

let conwaysGameOfLife;

function setup() {
  createCanvas(1000, 615);
  conwaysGameOfLife = new gameOfLife(0, 0, 500, 500, 5);
}

function draw() {
  background("white");
  conwaysGameOfLife.update();
}

function create2DArray(amount, amount2, fillUp) {
  let result = [];
  let filled = fillUp;

  for (let a = 0; a < amount; a++) {
    result.push([]);

    for (let i = 0; i < amount2; i++) {
      if (fillUp == "random") {
        filled = floor(random(2));
      }

      result[a].push(filled);
    }
  }

  return result;
}

class gameOfLife {
  constructor(x, y, width, height, size) {
    this.x = x;
    this.y = y;
    this.width = width;
    this.height = height;
    this.size = size;
    this.randomList = [];

    this.currentState = create2DArray(
      ceil(width / this.size),
      ceil(height / this.size),
      "random"
    );

    this.blank = create2DArray(
      ceil(width / this.size),
      ceil(height / this.size)
    );

    this.next = create2DArray(
      ceil(width / this.size),
      ceil(height / this.size)
    );
  }

  update() {
    let surrounding;
    let state;
    let result = 0;

    for (let i in this.currentState) {
      for (let j in this.currentState[i]) {
        surrounding = this.getSurrounding(i, j);

        if (surrounding < 2) {
          result = 0;
        }

        if (surrounding == 3) {
          result = 1;
        }

        if (surrounding == 2 && this.currentState[i][j] == 1) {
          result = 1;
        }

        if (surrounding > 3) {
          result = 0;
        }

        this.next[i][j] = result;
      }
    }

    for (let i in this.currentState) {
      for (let j in this.currentState[i]) {
        if (this.currentState[i][j] == 1) {
          fill("blue");

          noStroke();

          square(i * this.size, j * this.size, this.size);
        }
      }
    }

    this.currentState = this.next;

    this.next = this.blank;
  }

  getSurrounding(col, row) {
    let result = 0;
    if (this.getCurrentState(Number(col) - 1, Number(row) - 1)) {
      result++;
    }
    if (this.getCurrentState(Number(col) - 1, Number(row) + 1)) {
      result++;
    }
    if (this.getCurrentState(Number(col) - 1, Number(row) - 1)) {
      result++;
    }
    if (this.getCurrentState(Number(col) + 0, Number(row) - 1)) {
      result++;
    }
    if (this.getCurrentState(Number(col) + 0, Number(row) + 1)) {
      result++;
    }
    if (this.getCurrentState(Number(col) + 1, Number(row) - 1)) {
      result++;
    }
    if (this.getCurrentState(Number(col) + 1, Number(row) + 0)) {
      result++;
    }
    if (this.getCurrentState(Number(col) + 1, Number(row) + 1)) {
      result++;
    }

    return result;
  }

  getCurrentState(col, row) {
    if (col < 0 || row < 0) {
      return false;
    }

    if (
      col > ceil(this.width / this.size) - 1 ||
      row > ceil(this.height / this.size) - 1
    ) {
      return false;
    }

    const result = this.currentState[col][row];

    if (!result || result == 0) {
      return false;
    }

    if (result == 1) return true;
  }
}

function keyPressed() {
  if (keyCode == ENTER) {
    conwaysGameOfLife.currentState = create2DArray(
      ceil(conwaysGameOfLife.width / conwaysGameOfLife.size),
      ceil(conwaysGameOfLife.height / conwaysGameOfLife.size),
      "random"
    );
  }
}


Solution

  • The first call of update() sets this.next = this.blank, making both point to the same array. The second call of update() sets this.currentState = this.next, after which all three point to the same array.

    Since counting and updating happen on the same array, the counting of neighbors in getSurrounding() is wrongly influenced by the updates this.next[i][j] = result you make in the same loop.