Conway's Game Of Life

In this example below you will see how to do a Conway's Game Of Life with some HTML / CSS and Javascript

Thumbnail
This awesome code was written by centropy, you can see more from this user in the personal repository.
You can find the original code on Codepen.io
Copyright centropy ©

Technologies

  • HTML
  • CSS
  • JavaScript
<!DOCTYPE html>
<html lang="en" >

<head>
  <meta charset="UTF-8">
  <title>Conway's Game Of Life</title>
      <link href="https://fonts.googleapis.com/css?family=Nunito" rel="stylesheet">    
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">

  
  <link rel='stylesheet prefetch' href='https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css'>

      <link rel="stylesheet" href="css/style.css">

  
</head>

<body>

  <div id='root'></div>
  <script src='https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/react/15.6.1/react-dom.min.js'></script>

  

    <script  src="js/index.js"></script>




</body>

</html>

/*Downloaded from https://www.codeseek.co/centropy/conwayandaposs-game-of-life-eExvbJ */
body {
  margin: 0;
  padding: 0;
  font-family: sans-serif;
  background:#253151;
  color:#fff;
  font-family: 'Nunito', sans-serif;
  overflow:hidden;
}

input[type="button"] {
  border: 1px solid #666
}

input[type="button"]:focus {
  outline: none;
}

/* https://codepen.io/mburnette/pen/LxNxNg */

input[type=checkbox]{
	height: 0;
	width: 0;
  visibility: hidden;
  
}

label {
  cursor: pointer;
  text-indent: 25px;
  width: 150px;
  height: 25px;
  background: #666;
  display: block;
  border-radius: 3px;
  position: relative;
  float: right;
  transition: background 1s;  
}

label:after {
  content: '\f00d';
  position: absolute;
  font-family: FontAwesome;
  top: 3px;
  left: -16px;
  width: 16px;
  height: 16px;
/*   background: #fff; */
  border-radius: 1px;
  -webkit-transition: 0.5s;
  -o-transition: 0.5s;
  transition: 0.5s;
}
input:checked + label {
  background: #E97F02;
}

input:checked + label:after {
  content: '\f00c';
	left: calc(100% - 27px);
	transform: translateX(-100%);
}

label:hover {
  box-shadow: 1px 1px 1px 1px rgba(20,20,20,0.5);
}
label:active:after {
  content: '\f05b';
/* 	width: 0; */
}

/*Downloaded from https://www.codeseek.co/centropy/conwayandaposs-game-of-life-eExvbJ */
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

function _toConsumableArray(arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) { arr2[i] = arr[i]; } return arr2; } else { return Array.from(arr); } }

function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }

function _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError("this hasn't been initialised - super() hasn't been called"); } return call && (typeof call === "object" || typeof call === "function") ? call : self; }

function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }

var App = function (_React$Component) {
  _inherits(App, _React$Component);

  function App() {
    _classCallCheck(this, App);

    return _possibleConstructorReturn(this, (App.__proto__ || Object.getPrototypeOf(App)).apply(this, arguments));
  }

  _createClass(App, [{
    key: 'render',
    value: function render() {
      return React.createElement(Game, { grid: 12 });
    }
  }]);

  return App;
}(React.Component);

var getNColor = function getNColor(index) {
  return 'hsl(' + (index > 360 ? 0 : index * 2) + ',90%,60%)';
};
var colors = {
  background: '#253151',
  live: '#BD1550',
  live2ndGen: '#840D47',
  livetext: '#F9F4F1',
  deadtext: '#253151',
  dead: '#fff',
  pattern: 'rgba(233,127,2,0.5)',
  button: '#ffeeed',
  hoverButton: '#fff',
  disabledButton: 'rgb(48, 63, 148)',
  menuBg: '#253151',
  bottomBg: '#253151',
  categories: ['#BD1550', '#E97F02', '#8A9B0F', '#F8CA00']
  // some patterns from http://www.radicaleye.com/lifepage/picgloss/picgloss.html
};var patts = {
  ships: {
    ship: '00000000000110001101100111100001100',
    glider: '00000111000010001000',
    gliders: '00000110011000110011'
  },
  periodic: {
    toad: '000001110001110000000',
    blink: '0000000000111',
    beacon: '11000100000001000110',
    caterer: '000000100011110001000010001000000001000001000000000110',
    clock: '00010011000001100100'
  },
  other: {
    flower: '00000000111000010010000110000000000',
    acorn: '000000000001000000000010000011001110000000000000000000',
    'die hard': '000000000000000100110000000010001110000000000000000000',
    pentomino: '0011001100001000',
    bunnies: '000000000010000010000100010000100101001010000000000000'
  },
  static: {
    'carrier': '11000100100011000000',
    block: '0000001100011000',
    boat: '00000011000101000100',
    ship: '00000011000101000110',
    tub: '00000001000101000100',
    barge: '01000101000101000100',
    hive: '00000000011000010010000110000000000',
    loaf: '00000000011000010010000101000001000',
    hollow: '01100100101001001100'
  }
};

var Game = function (_React$Component2) {
  _inherits(Game, _React$Component2);

  function Game(props) {
    _classCallCheck(this, Game);

    var _this2 = _possibleConstructorReturn(this, (Game.__proto__ || Object.getPrototypeOf(Game)).call(this, props));

    _this2.state = {
      started: false,
      moveEditor: false,
      testing: false,
      frameRate: 24,
      generation: 0,
      gridSize: props.grid,
      gap: 0.1,
      viral: false,
      activeMenu: true,
      ballSquare: false,
      clearGrid: false,
      rainbow: true
    };
    _this2.handleStart = _this2.handleStart.bind(_this2);
    _this2.handleMouse = _this2.handleMouse.bind(_this2);
    _this2.changeCell = _this2.changeCell.bind(_this2);
    _this2.changeGridSize = _this2.changeGridSize.bind(_this2);
    _this2.setTestMode = _this2.setTestMode.bind(_this2);
    _this2.changeFrameRate = _this2.changeFrameRate.bind(_this2);
    _this2.makePattern = _this2.makePattern.bind(_this2);
    _this2.drawPattern = _this2.drawPattern.bind(_this2);
    _this2.finishPattern = _this2.finishPattern.bind(_this2);
    _this2.showGridLines = _this2.showGridLines.bind(_this2);
    _this2.makeViral = _this2.makeViral.bind(_this2);
    _this2.ballsOrSquares = _this2.ballsOrSquares.bind(_this2);
    _this2.clearGrid = _this2.clearGrid.bind(_this2);
    _this2.rainbow = _this2.rainbow.bind(_this2);
    return _this2;
  }

  _createClass(Game, [{
    key: 'rainbow',
    value: function rainbow() {
      this.setState({ rainbow: !this.state.rainbow });
    }
  }, {
    key: 'clearGrid',
    value: function clearGrid() {
      this.livePattern = null;
      this.patternCheck = [];
      this.setState({
        clearGrid: !this.state.clearGrid,
        generation: 0
      });
    }
  }, {
    key: 'activeMenu',
    value: function activeMenu(props) {
      this.setState({
        activeMenu: props
      });
    }
  }, {
    key: 'ballsOrSquares',
    value: function ballsOrSquares() {
      this.resetCanvas();
      this.setState({ ballSquare: !this.state.ballSquare });
    }
  }, {
    key: 'resetCanvas',
    value: function resetCanvas() {
      var ctx = this.refs.canvas.getContext('2d');
      ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
    }
  }, {
    key: 'showGridLines',
    value: function showGridLines() {
      this.setState({
        gap: this.state.gap === 0.1 ? 1 : 0.1
      });
    }
  }, {
    key: 'makeViral',
    value: function makeViral() {
      this.setState({
        viral: !this.state.viral
      });
    }
  }, {
    key: 'increaseGen',
    value: function increaseGen() {
      var tests = this.state.testing && this.state.gridSize >= 15 ? this.state.testing : false;
      this.setState({
        generation: this.state.generation + 1,
        testing: tests
      });
    }
  }, {
    key: 'changeFrameRate',
    value: function changeFrameRate(event) {
      var frameRate = event.target.value === '-' ? this.state.frameRate - 1 : this.state.frameRate + 1;
      this.setState({
        frameRate: frameRate < 1 ? 1 : frameRate > 60 ? 60 : frameRate
      });
    }
  }, {
    key: 'setTestMode',
    value: function setTestMode(event) {
      this.setState({
        testing: event.target.checked
      });
    }
  }, {
    key: 'changeGridSize',
    value: function changeGridSize(event) {
      var canvas = this.refs.canvas;
      var plusMinus = event.target.value;
      var ctx = canvas.getContext('2d');
      ctx.clearRect(0, 0, canvas.width, canvas.height);
      var gridSize = plusMinus === '-' ? this.state.gridSize - 1 : this.state.gridSize + 1;
      if (gridSize < 5) {
        gridSize = 5;
      }
      this.setState({
        gridSize: gridSize,
        generation: 0,
        testing: gridSize < 20 ? false : this.state.testing
      });
    }
  }, {
    key: 'handleStart',
    value: function handleStart(event) {
      this.patternCheck = [];
      if (event.target.checked) {
        this.runChecker();
      }
      this.setState({
        started: !this.state.started
      });
    }
  }, {
    key: 'handleMouse',
    value: function handleMouse() {
      var canvas = this.refs.canvas;
      if (!this.state.moveEditor) {
        canvas.removeEventListener('mousemove', this.drawPattern);
        canvas.removeEventListener('click', this.finishPattern);
        canvas.removeEventListener('click', this.changeCell);
        canvas.addEventListener('mousemove', this.changeCell);
        this.livePattern = [];
        this.patternCheck = [];
      } else {
        canvas.addEventListener('click', this.changeCell);
        canvas.removeEventListener('mousemove', this.changeCell);
      }
      this.setState({
        moveEditor: !this.state.moveEditor
      });
    }
  }, {
    key: 'componentDidMount',
    value: function componentDidMount() {
      this.addMenuClicker();
      this.makeCanvas();
      this.setState({
        started: true
      });
      this.runChecker();
    }
  }, {
    key: 'addMenuClicker',
    value: function addMenuClicker() {
      var _this3 = this;

      var menuHeight = document.getElementById('menu').scrollHeight;
      window.addEventListener('mousemove', function (event) {
        if (event.clientY < menuHeight - 30 || !_this3.state.started) {
          _this3.activeMenu(true);
        } else {
          _this3.activeMenu(false);
        }
      });
    }
  }, {
    key: 'changeSingleCell',
    value: function changeSingleCell(y, x) {
      var grid = this.state.grid;
      grid[y][x] = !grid[y][x];
      this.replaceGrid(grid);
    }
  }, {
    key: 'changeCell',
    value: function changeCell(event) {
      event.preventDefault();
      var y = Math.abs(Math.floor(event.offsetY / this.state.gridSize));
      var x = Math.abs(Math.floor(event.offsetX / this.state.gridSize));
      var hovered = [y, x];
      if (!this.hovering) {
        this.hovering = [y, x];
        this.changeSingleCell(y, x);
      } else if (this.hovering[0] !== hovered[0] || this.hovering[1] !== hovered[1]) {
        this.hovering = [y, x];
        this.changeSingleCell(y, x);
      }
    }
  }, {
    key: 'makeCanvas',
    value: function makeCanvas() {
      var canvas = this.refs.canvas;
      canvas.removeEventListener('click', this.changeCell);
      canvas.addEventListener('click', this.changeCell);
      var grid = this.state.gridSize;
      var width = Math.floor(window.innerWidth / grid) * grid - grid;
      var height = Math.floor((window.innerHeight - 100) / grid) * grid - grid;
      canvas.width = width;
      canvas.height = height;
      canvas.style.marginLeft = (window.innerWidth - width) / 2 + 'px';
      canvas.style.marginTop = 50 + 'px';
      canvas.style.background = colors.background;
      var newCanvas = this.getCells(canvas);
      this.setGrid(newCanvas);
    }
  }, {
    key: 'setGrid',
    value: function setGrid(props) {
      this.setState({
        grid: props.grid,
        rows: this.refs.canvas.width / this.state.gridSize,
        cols: this.refs.canvas.height / this.state.gridSize
      });
    }
  }, {
    key: 'replaceGrid',
    value: function replaceGrid(props) {
      this.setState({
        grid: props
      });
    }
  }, {
    key: 'drawGrid',
    value: function drawGrid(grid) {
      var size = this.state.gridSize;
      var gap = this.state.gap;
      var canvas = this.refs.canvas;
      var ctx = canvas.getContext('2d');
      if (!gap) {
        canvas.style.background = colors.dead;
      }
      for (var y in grid) {
        for (var x in grid[y]) {
          if (grid[y][x]) {
            if (grid[y][x] === 2) {
              ctx.fillStyle = colors.live2ndGen;
            } else if (grid[y][x] > 2) {
              ctx.fillStyle = this.state.rainbow ? getNColor(grid[y][x]) : colors.live2ndGen;
            } else {
              ctx.fillStyle = colors.live;
            }
          } else {
            ctx.fillStyle = colors.dead;
          }
          if (this.patternCheck && this.patternCheck[y] && this.patternCheck[y][x]) {
            ctx.fillStyle = colors.pattern;
          }
          if (!gap) {
            if (!this.state.ballSquare) {
              ctx.fillRect(x * size + 1, y * size + 1, size - gap - 2, size - gap - 2);
            } else {
              ctx.beginPath();
              ctx.arc(x * size + size / 2 + 0.5, y * size + size / 2 + 0.5, size / 2 - 1, 0, 2 * Math.PI, true);
              ctx.fill();
            }
          } else {
            if (!this.state.ballSquare) {
              ctx.fillRect(x * size + 0.5, y * size + 0.5, size - gap - 1, size - gap - 1);
            } else {
              ctx.beginPath();
              ctx.arc(x * size + size / 2 + 0.5, y * size + size / 2 + 0.5, size / 2 - 1, 0, 2 * Math.PI, true);
              ctx.fill();
            }
          }
          if (this.state.testing) {
            if (!this.state.gap) {
              this.showGridLines();
            }
            var count = this.getLiveNeighbours([y, x]);
            var ld = grid[y][x] ? 'Live' : 'Dead';
            var gen = !grid[y][x] ? 0 : grid[y][x] === true ? 1 : grid[y][x] > 99 ? '9^' : grid[y][x];
            var fSize = size < 44 ? size / 4 : size / 5;
            var showtext = size < 29 ? +x + ',' + y : 'x:' + x + ' y:' + y;
            ctx.font = fSize + 'px \'Nunito\', sans-serif';
            ctx.fillStyle = ld === 'Live' ? colors.livetext : colors.deadtext;
            ctx.fillText(showtext, x * size + 3, y * size + fSize, size - 2);
            if (size > 44) {
              ctx.fillText(ld, x * size + 3, y * size + fSize * 2, size - 2);
              ctx.fillText('nei: ' + count, x * size + 3, y * size + fSize * 3, size - 2);
              ctx.fillText('gen: ' + gen, x * size + 3, y * size + fSize * 4, size - 2);
            } else {
              ctx.font = fSize * 1.5 + 'px \'Nunito\', sans-serif';
              ctx.fillStyle = ld === 'Live' ? colors.livetext : colors.deadtext;
              ctx.fillRect(x * size + fSize * 2, y * size + fSize * 2, fSize * 1.5, fSize * 1.5);
              ctx.fillRect(x * size + 2, y * size + fSize * 2, fSize * 1.5, fSize * 1.5);
              ctx.fillStyle = ld === 'Live' ? colors.deadtext : colors.livetext;
              ctx.fillText(count, x * size + 3, y * size + fSize * 3 + 2, size - 2);
              ctx.font = fSize + 'px \'Nunito\', sans-serif';
              ctx.fillText(gen, x * size + fSize * 2 + 1, y * size + fSize * 3 + 2, size - 2);
            }
          }
        }
      }
    }
  }, {
    key: 'getCells',
    value: function getCells() {
      var canvas = this.refs.canvas;
      var wh = this.state.gridSize;
      var rows = canvas.width / wh;
      var cols = canvas.height / wh;
      var grid = [];
      for (var y = 0; y < cols; y++) {
        grid[y] = [];
        for (var x = 0; x < rows; x++) {
          if (this.state.started || this.livePattern) {
            if (this.state.grid[y] && this.state.grid[y][x] !== undefined) {
              grid[y][x] = this.state.grid[y][x];
            } else if (!this.state.clearGrid) {
              grid[y][x] = Math.round(Math.random() * 20) > 12 ? true : false;
            } else {
              grid[y][x] = false;
            }
          } else if (!this.state.clearGrid) {
            grid[y][x] = Math.round(Math.random() * 20) > 12 ? true : false;
          } else {
            grid[y][x] = false;
          }
        }
      }
      return { grid: grid, rows: rows, cols: cols };
    }
  }, {
    key: 'componentDidUpdate',
    value: function componentDidUpdate(prevProps, prevState) {
      var rules = prevState.gridSize !== this.state.gridSize || prevState.gap !== this.state.gap || prevState.clearGrid !== this.state.clearGrid;
      if (rules) {
        this.makeCanvas();
      }
      this.drawGrid(this.state.grid);
    }
  }, {
    key: 'runChecker',
    value: function runChecker() {
      var _this4 = this;

      // https://stackoverflow.com/questions/19764018/controlling-fps-with-requestanimationframe
      var now = void 0,
          elapsed = void 0;
      var fpsInterval = 1000 / this.state.frameRate;
      var then = Date.now();
      var animate = function animate() {
        var animater = requestAnimationFrame(animate, fpsInterval);
        now = Date.now();
        elapsed = now - then;
        if (elapsed > fpsInterval) {
          if (!_this4.state.started) {
            cancelAnimationFrame(animater);
          }
          then = now - elapsed % fpsInterval;
          _this4.checkGrid();
          _this4.increaseGen();
        }
      };
      animate();
    }
  }, {
    key: 'checkGrid',
    value: function checkGrid() {
      var grid = this.state.grid;
      var nGrid = Object.assign([], [].concat(_toConsumableArray(grid)));
      for (var y = 0; y < grid.length; y++) {
        if (this.state.viral) {
          nGrid[y] = grid[y];
        } else {
          nGrid[y] = Object.assign([], [].concat(_toConsumableArray(grid[y])));
        }
        for (var x = 0; x < grid[y].length; x++) {
          var count = this.getLiveNeighbours([y, x]);
          if ((count === 3 || count === 2) && grid[y][x]) {
            nGrid[y][x] += 1;
          }
          if (count === 3 && !grid[y][x]) {
            nGrid[y][x] = 1;
          }
          if (grid[y][x] && (count < 2 || count > 3)) {
            nGrid[y][x] = false;
          }
        }
      }
      this.replaceGrid(nGrid);
    }
  }, {
    key: 'getLiveNeighbours',
    value: function getLiveNeighbours(cell) {
      var rows = this.state.rows;
      var cols = this.state.cols;
      var grid = this.state.grid;
      var neighbourCount = 0;
      var nX = void 0,
          nY = void 0;
      var cel0 = parseInt(cell[0], 10);
      var cel1 = parseInt(cell[1], 10);
      for (var y = cel0 - 1; y <= cel0 + 1; y++) {
        for (var x = cel1 - 1; x <= cel1 + 1; x++) {
          if (y !== cel0 || x !== cel1) {
            nY = y < 0 ? cols - 1 : y >= cols ? 0 : y;
            nX = x < 0 ? rows - 1 : x >= rows ? 0 : x;
            if (grid[nY][nX]) {
              neighbourCount++;
            }
          }
        }
      }
      return neighbourCount;
    }
  }, {
    key: 'makePattern',
    value: function makePattern(event) {
      this.pattern = event.target.pattern;
      var canvas = this.refs.canvas;
      canvas.addEventListener('mousemove', this.drawPattern);
      canvas.addEventListener('click', this.finishPattern);
    }
  }, {
    key: 'finishPattern',
    value: function finishPattern() {
      var _this5 = this;

      var canvas = this.refs.canvas;
      var ctx = canvas.getContext('2d');
      this.resetCanvas();
      this.livePattern.forEach(function (cell) {
        _this5.changeSingleCell.apply(_this5, _toConsumableArray(cell));
      });
      this.setState({ generation: 0 });
    }
  }, {
    key: 'drawPattern',
    value: function drawPattern(event) {
      if (this.state.moveEditor) {
        this.handleMouse();
      }
      var canvas = this.refs.canvas;
      canvas.removeEventListener('click', this.changeCell);
      var size = this.state.gridSize;
      var pattern = this.pattern.split('');
      var wh = Math.sqrt(pattern.length);
      var center = Math.round(wh / 2);
      var ctx = canvas.getContext('2d');
      var rows = this.state.rows;
      var cols = this.state.cols;
      var y = Math.abs(Math.floor(event.offsetY / size));
      var x = Math.abs(Math.floor(event.offsetX / size));
      var startY = y >= center ? y - center : cols - center + y;
      var startX = x >= center ? x - center : rows - center + x;
      var endX = x + center < rows ? x + center : x - rows + center;
      var endY = y + center < cols ? y + center : y - cols + center;
      var count = 0;
      var livePattern = [];
      var patternCheck = [];
      for (var ypos = startY; ypos <= endY; ypos++) {
        patternCheck[ypos] = [];
        for (var xpos = startX; xpos <= endX; xpos++) {
          if (parseInt(pattern[count], 10) === 1) {
            livePattern.push([ypos, xpos]);
            patternCheck[ypos][xpos] = true;
          }
          count++;
        }
      }
      this.patternCheck = patternCheck;
      this.livePattern = livePattern;
    }
  }, {
    key: 'render',
    value: function render() {
      var _this6 = this;

      var menuHeight = document.getElementById('menu');
      var menuStyle = {
        position: 'absolute',
        top: this.state.activeMenu ? 0 : !menuHeight ? 30 : -menuHeight.scrollHeight + 30,
        left: 0,
        paddingLeft: '10px',
        paddingTop: '10px',
        paddingBottom: '30px',
        background: colors.menuBg,
        fontSize: '16px',
        transition: 'top ease-in-out 0.4s',
        width: '100%'
      };
      var boxStyle = {
        float: 'right',
        paddingRight: '20px'
      };
      var gridValue = { fontWeight: 'bold', fontSize: '22px' };
      return React.createElement(
        'div',
        null,
        React.createElement(
          'div',
          { id: 'menu', style: menuStyle },
          React.createElement(
            'div',
            { style: { float: 'left' } },
            React.createElement(Toggle, {
              v: this.state.started,
              c: this.handleStart,
              l: this.state.started ? 'stop' : 'start' }),
            React.createElement(Toggle, {
              v: this.state.moveEditor,
              c: this.handleMouse,
              l: this.state.moveEditor ? 'move editor' : 'click editor' }),
            React.createElement(Toggle, {
              v: this.state.ballSquare,
              c: this.ballsOrSquares,
              l: this.state.ballSquare ? 'round' : 'square' }),
            React.createElement(Toggle, {
              v: this.state.rainbow,
              c: this.rainbow,
              l: this.state.rainbow ? 'rainbow' : 'not rainbow' }),
            React.createElement(Toggle, {
              v: this.state.viral,
              c: this.makeViral,
              l: this.state.viral ? 'standard rules' : 'viral rules' }),
            React.createElement(Toggle, {
              v: this.state.gap === 1 ? true : false,
              c: this.showGridLines,
              l: this.state.gap === 1 ? 'hide grid' : 'show grid' }),
            this.state.gridSize >= 20 ? React.createElement(Toggle, {
              v: this.state.testing,
              c: this.setTestMode,
              l: this.state.testing ? 'normal view' : 'test view' }) : null,
            !this.state.started ? React.createElement(Toggle, {
              v: this.state.clearGrid ? true : false,
              c: this.clearGrid,
              l: this.state.clearGrid ? 'randomize' : 'clear cells' }) : null
          ),
          React.createElement(
            'div',
            { style: boxStyle },
            'Grid Size:',
            React.createElement(Button, {
              v: '+',
              c: this.changeGridSize,
              color: '#BD1550' }),
            React.createElement(
              'span',
              {
                style: gridValue },
              this.state.gridSize
            ),
            ' \xA0',
            React.createElement(Button, {
              v: '-',
              c: this.changeGridSize,
              color: '#BD1550' }),
            'Speed:',
            React.createElement(Button, {
              v: '+',
              c: this.changeFrameRate,
              s: this.state.started,
              color: '#BD1550' }),
            React.createElement(
              'span',
              {
                style: gridValue },
              this.state.frameRate
            ),
            ' fps \xA0',
            React.createElement(Button, {
              v: '-',
              c: this.changeFrameRate,
              s: this.state.started,
              color: '#BD1550' }),
            React.createElement(
              'div',
              { style: {
                  position: 'absolute',
                  bottom: '3px',
                  left: '10px',
                  color: this.state.activeMenu ? colors.menuBg : 'white',
                  transition: 'color 0.5s'
                } },
              'Menu | ',
              React.createElement(
                'span',
                { style: { color: 'white' } },
                'Generation: ',
                this.state.generation,
                '  '
              )
            )
          )
        ),
        React.createElement(
          'div',
          { style: {
              position: 'absolute',
              bottom: '0',
              float: 'left',
              background: colors.bottomBg,
              padding: '5px 0',
              transition: 'height 0.5s',
              textAlign: 'center'
            } },
          Object.keys(patts).map(function (category, id) {
            var section = patts[category];
            return React.createElement(
              'span',
              null,
              _this6.state.started ? '' : category,
              Object.keys(section).map(function (key, index) {
                return React.createElement(Button, {
                  key: index,
                  v: key,
                  pattern: section[key],
                  c: _this6.makePattern,
                  font: _this6.state.started,
                  b: true,
                  color: colors.categories[id]
                });
              })
            );
          })
        ),
        React.createElement('canvas', { ref: 'canvas' })
      );
    }
  }]);

  return Game;
}(React.Component);

var Toggle = function (_React$Component3) {
  _inherits(Toggle, _React$Component3);

  function Toggle() {
    _classCallCheck(this, Toggle);

    return _possibleConstructorReturn(this, (Toggle.__proto__ || Object.getPrototypeOf(Toggle)).apply(this, arguments));
  }

  _createClass(Toggle, [{
    key: 'render',
    value: function render() {
      var style = {
        float: 'left',
        padding: '3px'
      };
      var label = this.props.v ? 'edit on move' : 'edit on click :';
      return React.createElement(
        'span',
        { style: style },
        React.createElement('input', { type: 'checkbox', id: this.props.l,
          checked: this.props.v,
          onChange: this.props.c }),
        React.createElement(
          'label',
          { htmlFor: this.props.l },
          this.props.l === 'mouse' ? label : this.props.l
        ),
        '  \xA0'
      );
    }
  }]);

  return Toggle;
}(React.Component);

var Button = function (_React$Component4) {
  _inherits(Button, _React$Component4);

  function Button(props) {
    _classCallCheck(this, Button);

    var _this8 = _possibleConstructorReturn(this, (Button.__proto__ || Object.getPrototypeOf(Button)).call(this, props));

    _this8.state = {
      color: props.s ? colors.disabledButton : colors.button,
      background: props.color ? props.color : '#ccc'
    };
    return _this8;
  }

  _createClass(Button, [{
    key: 'render',
    value: function render() {
      var _this9 = this;

      var bgColor = !this.props.s ? this.props.color : 'none';
      var style = {
        padding: '3px 10px',
        margin: this.props.font ? '0px' : '3px',
        marginLeft: this.props.font ? '0px' : '5px',
        marginRight: '0px',
        width: this.props.font ? '50px' : 'auto',
        fontSize: this.props.font ? '1em' : '1.5em',
        borderRadius: '0px',
        border: 'none',
        background: this.state.color === colors.hoverButton ? colors.disabledButton : bgColor,
        color: this.props.s ? colors.disabledButton : this.state.color,
        transition: 'all 0.5s'
      };
      return React.createElement('input', {
        style: style,
        type: 'button',
        pattern: this.props.pattern ? this.props.pattern : null,
        disabled: this.props.s,
        value: this.props.v,
        onClick: this.props.c,
        onMouseOver: function onMouseOver() {
          _this9.setState({ color: colors.hoverButton });
        },
        onMouseOut: function onMouseOut() {
          _this9.setState({ color: colors.button });
        } });
    }
  }]);

  return Button;
}(React.Component);

ReactDOM.render(React.createElement(App, null), document.getElementById('root'));
if (typeof Object.assign != 'function') {
  // Must be writable: true, enumerable: false, configurable: true
  Object.defineProperty(Object, "assign", {
    value: function assign(target, varArgs) {
      // .length of function is 2
      'use strict';

      if (target == null) {
        // TypeError if undefined or null
        throw new TypeError('Cannot convert undefined or null to object');
      }
      var to = Object(target);
      for (var index = 1; index < arguments.length; index++) {
        var nextSource = arguments[index];
        if (nextSource != null) {
          // Skip over if undefined or null
          for (var nextKey in nextSource) {
            // Avoid bugs when hasOwnProperty is shadowed
            if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
              to[nextKey] = nextSource[nextKey];
            }
          }
        }
      }
      return to;
    },
    writable: true,
    configurable: true
  });
}

Comments