Animation and Wrapping Up

Animation in terms of graphical programming is simply the act of redrawing an object in a different location or position repeatedly to give the illusion of movement. One can use procedural generation techniques to accomplish this as well. In fact, it’s hard not to use procgen when attempting to programmatically animate something. Today, we will animate a ball moving along the y-axis of a canvas – very simple! While it is very simple, we will still be demonstrating the basic concepts of procgen for animation.

Here is the code:

var x, y;

function setup() {
  createCanvas(720, 400);
  // Starts in the middle
  x = width / 2;
  y = height;
}

function draw() {
  background(200);
  
  // Draw a circle
  stroke(50);
  fill(100);
  ellipse(x, y, 24, 24);
  
  // Jiggling randomly on the horizontal axis
  x = x + random(-1, 1);
  // Moving up at a constant speed
  y = y - 1;
  
  // Reset to the bottom
  if (y < 0) {
    y = height;
  }
}

This code creates our canvas and sets us up to draw in it’s center. After colors are declared, our circle is created with a diameter of 24 pixels. Then we make a call to our random function to help create small-scale movement along the x-axis before moving our ball upwards. The movement remains constant along the y-axis. We also include a check to bring our ball to the bottom of our canvas if we go off-screen (which will eventually happen) as to run the animation indefinitely.

The original code with a working example for this post can be found here.

This post marks the end of my series on procedural generation. Many programmers around the world employ this technique to accomplish a wide range of goals from simple data generation to modeling real systems like weather patterns and statistical analytics.

An Introduction to Randomness

This is a very simple topic, but it’s applications are endless. Thus, I thought it warranted a post. Randomness is something that is used everywhere in programming for simple simulations of dice rolls or more complex concepts such as initializing systems with a seed to produce consistent results. This post again uses P5js. Since the code is so simple, let’s just do a quick walk-through.

function setup() {
  createCanvas(710, 400);
  background(255);
  strokeWeight(20);
  frameRate(2);
}

function draw() {
  for (var i = 0; i < width; i++) {
    var r = random(150);
    stroke(r);
    line(i, 0, i, height);
  }
}

This creates a canvas element with a white background and set’s the frame rate to be 2 – meaning it will only call the draw function twice per second. Every time the draw function is called, a new image will be displayed on the canvas so anything more than this would make it too difficult to see the results. The draw function creates a field of bars that go from the top of the canvas to the bottom with each one set to a different shade of gray.

Again, it is a very simple example of randomness, but the applications are endless. Most applications involve some sort of randomness so it is important for the average user to understand that their favorite applications and games are just a pseudo-random number generator determining the final outcome. Suddenly that “magic” seems a lot less impressive.

The code above can be found here with a running example.

Simulating Mathematical Functions

Mathematical (trigonometric) functions such as sine, cosine, tangent, and their derivatives are commonly used in the world of programming. The art of programming is merely applying mathematical concepts to accomplish a goal – procedural generation is no different. In fact, one is more likely to come across these functions when reviewing concepts for procedural systems, especially more advanced ones such as L-systems. This post covers the sine function and how it can be represented via graphical means. To start, it’s important to note what the sine function does.

According to Wikipedia, the sine function:

is a trigonometric function of an angle. More generally, the definition of sine (and other trigonometric functions) can be extended to any real value in terms of the length of a certain line segment in a unit circle.

This might seem like a lengthy or dry explanation, but as long as you think of sine as a wave on a graph that oscillates between -1 and 1 indefinitely, you’ll be able to understand the content of this post. That’s the behavior that we are looking to model. Again, we will be using P5.js to accomplish this.

Here is the code below:

var diameter; 
var angle = 0;

function setup() {
  createCanvas(710, 400);
  diameter = height - 10; // height is 400 as per our call to createCanvas() above
  noStroke();
  fill(255, 204, 0);
}

function draw() {
  background(0);

  var d1 = 10 + (sin(angle) * diameter/2) + diameter/2;
  var d2 = 10 + (sin(angle + PI/2) * diameter/2) + diameter/2;
  var d3 = 10 + (sin(angle + PI) * diameter/2) + diameter/2;
  
  ellipse(0, height/2, d1, d1);
  ellipse(width/2, height/2, d2, d2);
  ellipse(width, height/2, d3, d3);
  
  angle += 0.02;
}

Without getting too technical or math intensive, let’s begin a brief overview of this code.

First we initialize two global variables that will be the base of our logic for the entire program. Then we call our setup()function to create a canvas of 710 pixels wide by 400 pixels tall and declare the color to draw with as a deep yellow. Because P5js calls draw()repeatedly, we don’t need to base any of our logic in a loop, it’s already going to act as though we have a loop. Regardless, we simply say that our background should be black and then we create three variables with a calculated diameter, aptly named d1, d2, and d3. We then use these to draw three circles that will use those diameters in the middle and edges of the of canvas. Finally, we increment our angle variable by a small amount and that will actually produce the oscillating wave effect/behavior that we desire. We increment the angle variable because this is the base of our sine function. The angle that we use will determine the real number that we receive from our sine function call. Because the sine wave only includes all real number values between -1 and 1, we can be sure that whatever our angle is, there is a mapping from the sine function to a usable value. You can read more on this concept here as going too much more in depth with it is beyond the scope of this post.

The original code with a working example can be found here.