Meanderings #2

If you haven’t read part one, here it is: Meanderings

All the code hereafter is going to build on what we went through it the aforementioned part one. We’ll have a look here at some very tentative steps towards visualisations of our walker, but, firstly, let’s just get control of our little walker a bit more by changing a few lines:

// setup animation
function animate(w) {
   let choice = Math.random();
   if (choice < .25) w.x += 5;
   else if (choice < .5) w.y += 5;
   else if (choice < .75) w.x -= 5;
   else if (choice < 1) w.y -= 5;
 
   c.fillStyle = '#d3d3d3';
   c.fillRect(0, 0, canvas.width, canvas.height);
   w.show();
}

So all that’s changed here is the increment value at the end of each bit of logic, so we’re now moving by 5 pixels instead of just 1 & the movement is a bit more obvious. You could even store this in a variable somewhere if you want to save the hassle of writing it four times. Let’s also slow our little guy down a bit; in the setInterval, we’re currently calling our animation function every 10 milliseconds, let’s plump for 500 instead, or 2 times a second…

setInterval(() => {
   animate(walker);
}, 500);

Ok, so that’s all a bit calmer…now, if we’re going to start visualising his path, we need to give our walker some way of keeping track of where he’s been. Let’s add his history as an array on the class:

class Walker {
   constructor(x, y) {
      this.x = x;
      this.y = y;
      this.history = [];
   }
...the rest of the walker code stays the same...except that I've
shrunk the radius in the c.arc(... to 8, instead of 12, & the fill
colour to 'rgba(255, 255, 255, .4), all just so we can see the
history a little better in a moment.

It’s also important to get the rendering order correct, I’ve moved the 2 lines that draw the background up to the top of the animate function, just to make sure it overwrites everything.

So now, we need to go through the following steps:

  • with each animation loop, push the current position of the walker into it’s history array (stored as an object with x & y properties)
  • OPTIONAL – check the length of the array & limit it to a particular value (I’ve started at 50…but this is arbitrary)
  • loop through every object in the history array & draw a circle at that x & y

Here’s the new code, all within the animate() function:

function animate(w) {
   // draw background
   c.fillStyle = '#d3d3d3';
   c.fillRect(0, 0, canvas.width, canvas.height);
   // push walker's position into history array
   w.history.push({ x: w.x, y: w.y });
   /* optional check for limiting length of history, remove the first
   (oldest) array item */
   if (w.history.length > 50) w.history.shift();
   // loop through the history array & draw a circle at each location
   for (let i = 0; i < w.history.length; i++) {
      c.beginPath();
      c.arc(w.history[i].x, w.history[i].y, 6, 0, Math.PI * 2);
      c.fillStyle = 'rgba(200, 0, 100, .4)';
      c.fill();
   }
   // then all the same walker code from before...
   let choice = Math.random();
   if (choice < .25) w.x += 5;
   else if (choice < .5) w.y += 5;
   else if (choice < .75) w.x -= 5;
   else if (choice < 1) w.y -= 5;

   w.show();
}

So we’re now getting a visual representation of the path our little dude has chosen to walk. From here, your creativity & artistic talents can kick in. There’s a whole bunch of variables/values to play with & all sorts of ways you could show the history. I’ll give a couple of basic suggestions for you to use as a launch pad next time. One of other consideration (which we’ll also address in the next article) is how to stop our walker from getting lost. At the moment, there’s nothing to prevent him from walking off the canvas & never returning!

But for now, walk on…here’s the pen

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

Recursive functions…

Have you ever done that thing where you stand in front of a mirror & hold up a mirror…so you’re looking at a reflection of yourself in a reflection of yourself in a reflection of yourself…or when you take a photo of someone taking a photo of you taking a photo of them taking a photo of you…? Recursive functions mess with my head in a very similar way. But let’s take a tumble down the rabbit hole.

A recursive function is, predictably, a function that recurs…that is to say that it calls itself from within itself. For example, imagine a function drawLine() {}…(guess what it does). Well what if, having drawn my line, I then, at the bottom of the function, call drawLine()..? So drawing a line causes the drawing of a line, which causes the drawing of line…and what does this mean..?

We have a really long line

But, crucially, these sort of patterns can yield some spectacularly complex & beautiful looking results (they can also yield some spectacularly infinite loops that will crash your browser, so it’s worth putting some sort of incrementing counter in the function & capping how many times it can be called). Future articles will give more detail, perhaps even unpacking some of the code that has produced the following images, but for now, enjoy the elegant beauty of these fairly simple examples of recursion & start exploring the world of generative art…

Chainable methods…

So I’ve set about building a library of sorts…it may amount to nothing, but it’s turning into a seriously useful learning experience for me if nothing else.

Anyhoo, I wanted to be able to chain various methods together, à la jQuery or d3, code that looks like: something().dothis().makeoneofthese().change()… ad infinitum (feel free to steal those method names by the way…)

So here’s what I was hoping for…(es6-y code to follow):

*** Thing.js ***
// define a class
export default class Thing {
   example() {
      console.log('example method')
   }

   chainable() {
      console.log('I called another method!')
   }
}

*** thingFunc.js ***
import Thing from './Thing';
export default function thing() {
   return new Thing()
}

*** main.js ***
// this file included in index.html
import thingFunc from './thingFunc';

thingFunc().example().chainable();

The problem with this code is that it’s entirely meaningless and trivial…but the relevant problem is that it returns an error, specifically something like: “e… .chainable() is not a function”; which confused me at first, because it is. But here’s the thing to consider: what are you calling the methods on?

Calling thingFunc() returns a Thing, so .example() is called on that Thing…but .example() gives us nothing back; and nothing.anything() isn’t going to work. The solution, therefore, is a simple one…all your class methods must ‘return this’; so all subsequent methods have something to call on… here’s the modified code and not an error in sight:

*** Thing.js ***
// define a class
export default class Thing {
   example() {
      console.log('example method');
      return this;
   }

   chainable() {
      console.log('I called another method!');
      return this;
   }
}

*** thingFunc.js ***
import Thing from './Thing';
export default function thing() {
   return new Thing()
}

*** main.js ***
// this file included in index.html
import thingFunc from './thingFunc';

thingFunc().example().chainable();

Chain away my friends

Welcome

I’m a self taught developer…I think. It’s a mirky definition; I have been taught by blogs & tutorial videos & forums & documentations & no small amount of trial & error. But in so far as my learning has been in solitude & entirely self-motivated, self-directed, self-determined…I am self taught.

This has been a journey that has, for the most part, invigorated & empowered & inspired…and has, at times, frustrated & bullied & taunted me.

Some topics I have found to be well covered, a wealth of resources readily at my fingers. The numerous, for example, ‘learn React’ courses that vie for our attention on YouTube. Other problems, however, have been less forthcoming with their solution, the answer tucked away, unannounced in the midst of some strangers 3-hour live-coding live-stream; or a subordinate clause sneaking by in a blog post; or one stackoverflow question that leads to another to another to another…

Some of these problems I have solved; some continue to elude. My hope is that the articles herein, where I provide a solution, will dare to be educational; and those that I can’t figure out, perhaps we can tackle together?

Furthermore, over this time, the artist & pattern-lover in me has found an affinity with creative code, generative art & all things recursive, so much of what follows may well end up being on that or similar topic(s).