Meanderings

So the title is a play on the idea of a ‘random walker’…inspired, I know.

Random walkers are fairly ubiquitous in the world of creative coding, but as a quick google image search will reveal (click here if you can’t be bothered to type yourself…), even such a simple little procedure can produce some stunning results. (There’s a handful of examples to be found on TheCodeLessTravelled twitter & instagram accounts as well).

So this article will serve as a launchpad in to this random world, we’ll code a simple but happy little walker & then see what we can do with him in future posts. So, here we go (code is JavaScript & uses a fair amount of es6-y stuff…but the concepts are extractable & transferrable…I’ve written the example in codepen, but if you want to do yourselves elsewhere you’ll need to set up some sort of compiling)

A random walker, at it’s core, is just an object that makes a random choice & then moves according to that choice. First off, we’re working in the canvas, so lets get things setup with a basic square, grey canvas element:

*** html ***

<!DOCTYPE html>
   <html>
      <head>
         <title>Random Walker</title>
      </head>

      <body>
         <canvas id='canvas' width=500 height=500></canvas>
         <!-- if you're compiling stuff, the src attribute of
              the script tag below should point to your output file
              I've just thrown in a placeholder example filename -->
          src='./js/script.js'>
      </body>
   </html>

*** javascript ***
   
   const canvas = document.getElementById('canvas');
   const c = canvas.getContext('2d');

   // draw background 
   c.fillStyle = '#d3d3d3';
   c.fillRect(0, 0, canvas.width, canvas.height);

Nothing too exciting here, the html is basic boilerplate stuff & one canvas element. In the javascript we get ahold of the DOM element and store it in a ‘canvas’ variable, get the context & draw a grey rectangle to cover the whole thing. Let’s meet our walker…imagine, if you will, the following code appended to the above:

   // create Walker class
   class Walker {
      constructor(x, y) {
         this.x = x;
         this.y = y;
      }
 
      show() {
         c.beginPath();
         c.arc(this.x, this.y, 12, 0, Math.PI * 2);
         c.fillStyle = '#222';
         c.fill();
      }
   }

   // create new walker and render to canvas
   const walker = new Walker(canvas.width * .5, canvas.height * .5);
   walker.show();

So we set up a class that takes an x & y upon instantiation, & has a method that draws a circle at that particular x & y. I’ve rendered our walker in the middle of the canvas, but feel free to start yours from wherever takes your fancy (remembering that by default 0, 0 is the top-left-most pixel of the canvas).

Now, these objects were made for walking…so we need a mechanism for our walker to make a more or less random choice. There are probably a whole bunch of ways of doing this, but what I’ll show below is fairly standard. Also, we’ll need to setup a loop of sorts, some kind of oft-reoccurring function call to give the illusion of our walker animating its way around the canvas. Again, there are options here, all with their own special merits & concerns; I’ll use setInterval…don’t judge me.

   /* setup the animation,
      a function that we give the walker we want to animate */
   function animate(w) {
      // make random choice, Math.random returns number between 0 - 1
      // all possible directions are set with equal probability
      // x & y of the passed in walker (w) are altered depending on choice
      let choice = Math.random();
      if (choice < .25) w.x += 1;
      else if (choice < .5) w.y += 1;
      else if (choice < .75) w.x -= 1;
      else if (choice < 1) w.y -= 1;

      // redraw background to clear all previous circles
      c.fillStyle = '#d3d3d3';
      c.fillRect(0, 0, canvas.width, canvas.height);

      // draw walker at updated location
      w.show();
   }

So we have a function that randomly moves the x, y co-ordinates of our walker. All of this, incidentally, is configurable to your heart’s content. The x & y don’t have to be incremented by 1, & they don’t have to all have an equal probability…tinker away. The final stage is that this function needs calling over & over, & quickly so…

   setInterval(() => {
      // call our animate function, passing in our walker object
      animate(walker);
   }, 100)

The ‘100’ at the end is a value in milliseconds of how often this function should be called. You could think of this, therefore, as 10 times per second. Feel free to mess with this value as well.

So all things being good & equal, you should now have a little circle bobbing inanely around a grey box…but this is just the beginning…next time will look at how we can start to make something a bit more visually appealing with our little meandering friend. (See my full code in operation here).

 

Cheers

One thought on “Meanderings

Leave a comment