The Joy of the Random Walk

An image result of random walk with vertex() function in Processing.

In this post, we’ll explore the beauty of "Random Walks" in creative coding. While the logic is remarkably simple, the visual results can be surprisingly sophisticated.

What is a Random Walk?

At its core, a random walk is incredibly simple. Here is the basic logic:

x += random(-1.0, 1.0);
y += random(-1.0, 1.0);

The ordinary random walker example.

That’s it! With just these two lines, you can create infinitely complex movement. 😀

Some random walking example
Some random walking example
Some random walking example

 

Movement Variations

Constrained Randomness (Y-axis only)

By restricting randomness to only one axis, you can create organic, wire-like structures.

x += 1.0;
y += random(-1.0, 1.0);

The random walker : Y-axis random only

When applied to radial lines, the effect is even more striking:

Straight radial lines.

The result looks like this:

Random walked radial lines.

Developing the idea further:



 

Perlin Noise

Using Perlin noise results in more fluid, organic motion—reminiscent of natural biological movement or elegant handwriting.

x += map(noise(a, t), 0.0, 1.0, -1.0, 1.0);
y += map(noise(b, t), 0.0, 1.0, -1.0, 1.0);

// a ≠ b : Some value for other noise seed.
// t : time

Random walker with the Perlin noise.

 

Grid-based Movement

By snapping the walker's direction to the X or Y axis and matching the step size to the particle size, you can create a structured, "matrix-like" grid animation.

This example code was written in p5.js.

let direction = random(-1.0, 1.0);
direction = (direction == 0) ? 1.0 : direction / abs(direction);
if (random(1.0) < 0.5) {
  x += direction * pSize;
} else {
  y += direction * pSize;
}

// pSize : Walker size

Random wakler that move on the grid.

 

Creative Stylization

Contrasting Colors

Something as simple as alternating between "ebony and ivory" (black and white) can drastically change the aesthetic. All it takes is adding the fill() function to the code above.

let direction = random(-1.0, 1.0);
direction = (direction == 0) ? 1.0 : direction / abs(direction);
if (random(1.0) < 0.5) {
  x += direction * pSize;
  fill(255);
} else {
  y += direction * pSize;
  fill(0);
}

Painted random walker in ebony and ivory.

This example was implemented in p5.js on OpenProcessing.org. I added a residual image effect using a semi-transparent rectangle.

It will pause on a mouse click.



 

In 3D



 

Draw Lines on the Walker Tail



 

Drawing with vertex()

Here, I used beginShape(TRIANGLES) to render the walker in various colors.

Using beginShape(TRIANGLES) and paint the walker in different colors.

Using beginShape(TRIANGLES) and paint the walker in different colors.

Using beginShape(TRIANGLES) and paint the walker in different colors.

This is the example that draws curve lines using 'curveVertex()' and was implemented in p5.js on OpenProcessing.org. It will pause on a mouse click.



Oh... Poor walker getting lost...


 

Brilliant Works by Others





 







The 'Processing' code examples.

Playing fake board game animation.

Creative coding of random walk creates a fake board game.

 

About this Example

A random walk example made with the 'Processing'. This creative coding creates a fake board game as a result of a random walk.

 

The 'Processing' code example of fake board game animation.

Please feel free to use it under the terms of the GPL.
It is my pleasure and honor to see other works based on my code.

Note: This code generates image files in the "frames" directory instead of displaying them on-screen. You can combine these frames to create a full animation.



/**
 * It's A Game.
 * A random walk animation. Guess which side is superior?
 * 
 * Processing 3.5.3
 * @author @deconbatch
 * @version 0.1
 * created 0.1 2020.02.05
 */

void setup() {
  size(720, 440);
  rectMode(CENTER);
  smooth();
  noLoop();
}

void draw() {
  int frmMax = 5 * 30; // 5fps x 30s animation
  int pLen   = floor(width * 0.04);
  int pSize  = floor(width * 0.012);
  ArrayList<path> paths = new ArrayList<Path>();

  int pX = 0;
  int pY = 0;
  int pC = 0;
  for(int frmCnt = 0; frmCnt < frmMax; frmCnt++) {
    float direction = random(-1.0, 1.0);
  direction = direction == 0 ? 1.0 : direction / abs(direction);
  if (random(1.0) < 0.5) {
   pX += direction * pLen;
   pC = 255;
  } else {
   pY += direction * pLen;
   pC = 0;
  }
  if (abs(pX) > width * 0.5) {
   pX -= direction * pLen;
  }
  if (abs(pY) > height * 0.5) {
   pY -= direction * pLen;
  }
    paths.add(new Path(pX, pY, pC));
  }  

  translate(width * 0.5, height * 0.5);
  for(int frmCnt = 0; frmCnt < frmMax; frmCnt++) {
    background(240.0);
    strokeWeight(1.0);
    stroke(0);

    beginShape(TRIANGLES);
    for(int i = 0; i < frmCnt; i++) {
      Path p = paths.get(i);
      fill(p.colour);
      vertex(p.x, p.y);
      ellipse(p.x, p.y, pSize, pSize);
    }
    endShape();

    casing();
    saveFrame("frames/" + String.format("%04d", frmCnt) + ".png");
 }
    
  exit();

}

/**
 * casing : draw fancy casing
 */
private void casing() {
  fill(0.0, 0.0);
  strokeWeight(20.0);
  stroke(20.0);
  rect(0.0, 0.0, width, height);
  strokeWeight(15.0);
  stroke(240.0);
  rect(0.0, 0.0, width, height);
}

/**
 * Path : hold random walk path
 */
private class Path {
  public int x, y;
  public int colour;

  Path(int _x, int _y, int _c) {
    x = _x;
    y = _y;
    colour = _c;
  }
}

/*
Copyright (C) 2020- deconbatch

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>
*/


 
 

Walking on the grid animation.

It's a random walk example that walks on the triangular grid.

 

About this creative coding example.

It's a creative coding work of random walk made with the 'Processing'. It walks on the triangular, quadrangular and hexagonal grid.

To render the walker's tail, I implemented a "shift" technique using an ArrayList. This allows the tail to follow the head dynamically as it moves.

Structure of walkers.
  walkers(tails01(Walker0101, Walker0102..), tails02(Walker0201, Walker0202..)..)

Structure of tails.
            ← tail                     head →
  tails01(Walker0101, Walker0102, .., Walker01nn)
          ↓ shift
  tails01(Walker0102, Walker0103, .., Walker01nn + 1)

 







The 'Processing' code example of walking on the grid.

Please feel free to use it under the terms of the GPL.
To see other works based on my code is my pleasure. And my honor.

Note: This code generates image files in the "frames" directory instead of displaying them on-screen. You can combine these frames to create a full animation.


/**
 * Saturday In The Park.
 * A random walk on the grid.
 * 
 * Processing 3.5.3
 * @author @deconbatch
 * @version 0.1
 * created 0.1 2020.02.15
 */

void setup() {
  size(720, 480);
  colorMode(HSB, 360, 100, 100, 100);
  rectMode(CENTER);
  smooth();
  noLoop();
}

void draw() {
  int frmMax  = 24 * 3; // 24fps * 3s animation with each pattern
  int corners = 3;      // initial pattern = 3 corners shape
  
  translate(width * 0.5, height * 0.5);

  for (int pattern = 0; pattern < 3; pattern++) {

    corners += pattern; // 3, 4, 6
    int   walkerMax = 21 - pattern * 4;
    int   tailMax   = corners * 3; // walker's tail
    float sideLen   = 8.0 - pattern * 2.0;

    ArrayList walkers = new ArrayList();
    for (int i = 0; i < walkerMax; i++) {
      float wX = sideLen * corners * i - (sideLen * corners * walkerMax) * 0.5;
      float wY = 0.0;
      float wC = (50.0 * i) % 360.0;
      float wD = TWO_PI / corners;
      int   wR = floor(random(corners));
      ArrayList<Walker> tails = new ArrayList<Walker>();
      for (int j = 0; j < tailMax; j++) {
        tails.add(new Walker(wX, wY, wC, wD, wR));
      }
      walkers.add(tails);
    }

    for(int frmCnt = 0; frmCnt < frmMax; frmCnt++) {
      background(0.0, 0.0, 100.0, 100.0);
      strokeWeight(5.0);
      noFill();

      for (int i = 0; i < walkers.size(); i++) {
        float wX = 0.0;
        float wY = 0.0;
        float wC = 0.0;
        float wD = 0.0;
        int   wR = 0;
        
        ArrayList<Walker> tails = (ArrayList)walkers.get(i);
        for (Walker walker : tails) {
          wX = walker.x;
          wY = walker.y;
          wC = walker.colour;
          wD = walker.radianDiv;
          wR = walker.rotateCnt;

          stroke(wC, 40.0, 80.0, 100.0);
          beginShape();
          vertex(wX, wY);
          for (int j = 0; j < corners; j++) {
            // it makes a straight line between corners
            wX += sideLen * cos(wR * wD);
            wY += sideLen * sin(wR * wD);
            vertex(wX, wY);
          }
          endShape();
        }
        
        if (abs(wX) < width * 0.35 && abs(wY) < height * 0.35) {
          if (random(1.0) < 0.5) {
            --wR; // not turn
          } else {
            if (random(1.0) < 0.1) {
              wD *= -1.0; // turn
            }
          }
        }
        
        ++wR;
        wR %= corners;
        // tail shift
        tails.add(new Walker(wX, wY, wC, wD, wR));
        tails.remove(0);
      }

      casing();

      // for stop motion of first pattern
      if (frmCnt == 0) {
        for (int i = 0; i < 18; i++) {
          saveFrame("frames/" + String.format("%02d", corners) + ".00." + String.format("%04d", i) + ".png");
        }
      }

      saveFrame("frames/" + String.format("%02d", corners) + ".01." + String.format("%04d", frmCnt) + ".png");
    }
  }
  exit();

}

/**
 * casing : draw fancy casing
 */
private void casing() {
  fill(0.0, 0.0, 0.0, 0.0);
  strokeWeight(20.0);
  stroke(0.0, 0.0, 0.0, 100.0);
  rect(0.0, 0.0, width, height);
  strokeWeight(15.0);
  stroke(0.0, 0.0, 100.0, 100.0);
  rect(0.0, 0.0, width, height);
}

/**
 * Walker : hold random walker attributes
 */
private class Walker {
  public float x, y;
  public float colour;
  public float radianDiv;
  public int   rotateCnt;

  Walker(float _x, float _y, float _c, float _d, int _r) {
    x = _x;
    y = _y;
    colour = _c;
    radianDiv = _d;
    rotateCnt = _r;
  }
}

/*
Copyright (C) 2020- deconbatch

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>
*/
  



 

Next Post Previous Post
4 Comments
  • Unknown
    Unknown Tuesday, October 27, 2020

    Really great article. Nice examples. I am sort of new to the processing system - we rebuilt something like it in ZIM at https://zimjs.com so I look forward to doing more relative drawing. I made some walking code without realizing that it was called walking ;-).

    • deconbatch
      deconbatch Saturday, February 06, 2021

      Thank you for your interest! I love your Zim cat. 🐱

  • dax
    dax Friday, February 07, 2025

    Hi great article - in your example "This is the Random Walk" it always moves to 2 o'clock but you have -1,1 as the x and y ranges ??

    • deconbatch
      deconbatch Friday, February 07, 2025

      Thank you for reading.
      You can think 'It's just one example of examples'. It may go left side, up and down after this.

      I realized this example is not the best. So I added some other examples.
      I appreciate your comment. Thank you! 😉✨

Add Comment
comment url