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