Living Grid - matricies in p5.js

product | source code | interactive coding menu | home

I focused more on technical coding and learning more about javascript than interactivity with this week's assignment. It's an adjustable grid of squares that grow and shrink slowly. The + and - keys increase and decrease the number of squares in the window. The size of the squares will adapt to changes in window size so that (most) of the screen is always filled. It accomplishes the following:

  • Clearly demonstrates nested "for" loops.
  • Uses scale and translate functions effectively.
  • Attempts to use more object oriented programming (I didn't do it right, so I used a more familiar work-around).
  • Adjusts animation speed according to refresh rate (makes the animation more consistent between different systems)
  • Demonstrates using matricies to make a change over time.
  • Have the sketch react to the window size, and be able to change the number of squares on the screen.

Process:

  • First I made sure I could get a square to scale correctly (relative the center of the square) and then place it wherever I wanted in the window using translate functions. This involved figuring out how push() and pop() work exactly and some trial and error.
  • Then I tried to make the square an object that I could easily duplicate and manipulate. I found out javascript doesn't really have Structure functions like C and C++. and I didn't think making a class was worth the trouble. I searched around and experimented with making my own structure-making function, but every time I tried to implement something akin to a structure p5 would stall and crash. I ended up cutting my losses and just making four different arrays, each containing the same number of elements as there are squares. This arrays held the x and y location, the current scale, and the scale rate of each square.
  • To scale the squares over time, I first used a linear rate of change, changing "direction" once the scale reached a max or minimum boundary. This was successful, but I decided to make the animation more smooth with a trig function. Now the "scale rate" is simply a continually-growing value plugged into a sine function. This makes the size oscillate between two scales.
  • As it turns out, making the animation smoother ended up making it choppier due to computation time. The other day I was looking into solutions for latency issues bewteen client and server updates in multiplayer games, so I wanted to see if I could apply the same function into this project. Basically it expects to do enough updates a second to match the maximum frame rate (60 in this case). If it does not meet the quota of updates, it updates a number of times corresponding to how far behind it lagged. This is done by multiplying the the rate at which the scale (the value plugged into the sine function) updates by how many times it should have updated if it were running at 60 fps. This didn't really fix the smoothness of the animation, but now it should animate at the same rate on any machine.
  • Throughout programming this project, I made sure every dimensional or size value was set by variables, so that I could go back and make the everything changeable and adaptable. For instance, the number of squares drawn to the screen is dictated by a single "num" value that is user controlled. The longest window dimension is divided by this number to determine the maximum size of each square. Then the shortest window dimension is divided by the maximum size to determine how many squares will fit on that dimension of the screen ("otherNum"). These two vaariables, num and otherNum, are multiplied together to get the total number of squares. This tells how many elements need to be initialized in the four arrays for the squares' data. When initialized, each square gets a random starting scale and two nested "for" loops assign an x and y value corresponding to where they need to be drawn on the window. All of these variables are updated when either the user changes the values of "num" or the window size has changed.
  • The drawing of the squares occurs in a single "for" loop, iterating for the total number of squares. Each iteration fetches the data from the four arrays corresponding to the current square being plotted. Each square is located at the origin with the same size (maxSize calculated during intitialization as explained previously), so the size and position of each drawn square comes from the matricies.
  • The colors are all a shade of blue-green, with the blue and green green and blue values increased by the row or collumn number of the grid, respectively
  • To give a little space between each square, I simply gave each square a stroke color that matched the background color. The stroke width is always 1/16th of the of maxSize of the squares, so the stroke weight is always proportional to the size of the squares.