Skip to content

Instantly share code, notes, and snippets.

@misterussell
Created April 11, 2018 19:54
Show Gist options
  • Save misterussell/a64be6a91d34fcf3de8f467f74b1cb1f to your computer and use it in GitHub Desktop.
Save misterussell/a64be6a91d34fcf3de8f467f74b1cb1f to your computer and use it in GitHub Desktop.
4 11 18 Blog Post

Optimizing Conway's Game of Life in JavaScript - Part V

In this post I'll be discussing a distinct feature of the app rather than decision making as a whole.

The goal: to recreate the game board with a static visual representation of the cells and the sum of their lives or deaths.

  • A cell with the greatest value will be a specific colour.
  • Cells will lighten in colour as the values are smaller.
  • A cell that was alive 0 times will be white.
  • A cell's shade will be dynamically generated rather than utilizing an array of precomputed colour values.

Initial Decisions

I am creating a new Grid Component, rather than recycling the component used in the live game. I'm choosing this path rather than refactoring the live grid because the use-cases are quite different. There are no onClick functions on the new grid, array computations and rendering take different values, and the new grid is computing different state based on what was passed in from the parent Stats page not the active game logic.

The data to populate the grid comes through props as a flattened array with cumulative integers that represent that stat I am trying to illustrate.

// image 1

Here's the initial rendering:

// image 2

Based off this array I am choosing to send the value of each index, an alive or dead flag, and some sort of "shade indicator" to the child cell component.

  • The value is mostly for dev purposes and can potentially be used in a toolTip.
  • The alive/dead flag is going to be used for colour selection.
  • The shade indicator is something that needs to be dynamically generated by the parent Grid, as the cells don't have any reference to each other.

Note: I'm inline styling these components due to their dynamic generation. If I can gleam the logic to translate it into CSS I will move the styling off the components. I'm not in love with the idea of mixed styling, but I think styling these smaller components/parts inline doesn't overcomplicate the components. I may choose to keep CSS files for these built and commented out for transparency.

The Logic

Rather than integrate a complicated colour manipulation library I'm using this nice little vanilla converter. It takes a float from -1 to 1 and a hexadecimal colour value as it's parameters and returns a hex colour value such that -1 is the darkest version of that colour and 1 is white.

I have no negative values to worry about so only need to throw in 0-1 values; 0 being the highest value cell and 1 being a cell with no value. Here's how I'm creating a reference object to get the shades of the different cells:

// image 3

This is new syntax so I'm going to break it down.

  1. Define an empty array.
  2. Send the sorted flat array into a new Set to get all of the unique values in the sorted array. I sort from largest to smallest as the largest value needs a shade of Zero; the index of the sorted value represents this.
  3. For each of those values define a key:value pair in a referenceable object.
  4. Rather than try to mathematically compute the decimal values for each of these whole numbers I'm using javascript's flexible nature to build a string which I then coerce into a number. Hoorah. I probably wouldn't do this if these weren't whole numbers.
  5. This object is then set to state to be used when the component mounts.

// image 4

The Initial Product

These steps give us a baseline component that shades each cell depending on its total value:

// image 5

There are a few things to handle here:

  • These variance in the different colours needs to be bumped up so that is more noticeable between similarly valued cells.
  • I'm only accounting for two flags, which isn't very flexible.

Catch up on the rest of the series! Read from the start here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment