# 11. The Matrix - Enter into the Matrix

Do you ever wake up in the morning and think, 'I should make the digital rain effect from the Matrix franchise? Well, I did, and so here we go. For those of you who don't know, the Matrix franchise had a well-known effect called the 'Digital Rain'. This effect features random sets of characters falling across a black terminal. Sort of like in [this video](https://youtu.be/ZIjfK4MGrGI?list=RDZIjfK4MGrGI). Let's see how to make an animation like this on Processing...

First step, of course, would be to find the correct font, obviously 😐. I checked several options, but the one that stood out for me was the font called `Matrix Code NFI Font` by *Norfok Incredible Font Design*. You can find it at [www.fontspace.com](https://www.fontspace.com/matrix-code-nfi-font-f11467).

![](https://cdn.hashnode.com/uploads/covers/61a2243af0cb2e37690c63e1/5006f6f8-324f-4b09-bf32-bbc824bb3e21.png align="center")

I downloaded the font and converted it to be used in Processing. This is pretty straightforward. Just download the font, and you will get a zipped archive.

1.  Extract the archive, and you will see a font file called `MatrixCodeNfi-YPPj.otf` inside.
    
2.  Double-click and install this font to the system.
    
3.  Create a folder titled `data` in the root folder of our sketch.
    
4.  Open the Processing application.
    
5.  Go to *Tools* -> *Create Font...*.
    
6.  Scroll through the list of fonts and select the font we just installed. (`MatrixCodeNFI`)
    
7.  Change the filename to `font.vlw`.
    
8.  Click on *OK*.
    
9.  A file called `font.vlw` will be created in the `data` directory. If it's created somewhere else, copy it to the `data` directory.
    

Now that the fonts are ready, we will move on to the actual sketch. First, we'll start with some settings. Here, we will set up the canvas size, load the font, prepare the sizes and counts and create a copy of the charset.

```java
void settings() {
  size(1800, 1000);
  font = loadFont("font.vlw");

  column_size = width/COLUMN_COUNT;
  row_size = column_size;
  row_count = ceil((height * 1.0) / row_size);
  text_size = column_size - (TEXT_OFFSET * 2);

  System.arraycopy(CHARACTER_SET, 0, characters, 0, CHARACTER_SET.length);
}
```

The column size is calculated with the width and number of columns we have defined to be included. I've also approximated the row size to be the column size. The number of rows is defined by the height and the size of the row that we're defined. Here, we take the ceiling to allow for an extra row below instead of keeping an empty row. This creates a seamless visual that spans the whole window.

I've also defined the `CHARACTER_SET` that will be used for text streaks. The set is as below.

```java
char[] CHARACTER_SET = {
  '!',      '"',      '#',      '$',      '%',      '&',      '\'',
  '(',      ')',      '*',      '+',      ',',      '-',      '.',      '/',
  '0',      '1',      '2',      '3',      '4',      '5',      '6',      '7',
  '8',      '9',      ':',      ';',      '<',      '=',      '>',      '?',
  'A',      'B',      'C',      'D',      'E',      'F',      'G',
  'H',      'I',      'J',      'K',      'L',      'M',      'N',      'O',
  'P',      'Q',      'R',      'S',      'T',      'U',      'V',      'W',
  'X',      'Y',      'Z',      '[',      '\\',     ']',      '^',      '_',
  'a',      'b',      'c',      'd',      'e',      'f',      'g',
  'h',      'i',      'j',      'k',      'l',      'm',      'n',      'o',
  'p',      'q',      'r',      's',      't',      'u',      'v',      'w',
  'x',      'y',      'z',      '{',      '|',      '}',      '~'
};
```

This is copied to a temporary buffer called `characters`. The reason is that we intend to inject *glitches* into the streaks, which will be apparent later. This makes sure the original list stays intact without worrying about losing characters. Of course, you can modify the original character set according to your requirements and font.

Next, we will move into the setup.

```java
void setup() {
  background(BACKGROUND);
  frameRate(FRAMERATE);
  textFont(font);

  for (int i = 0; i < (int)random(0, COLUMN_COUNT); i++) {
    buffer.add(new Streak((int)random(0, COLUMN_COUNT), (int)random(0, row_count)));
  }

  textSize(MESSAGE_SIZE);
  fill(STATIC);
  textAlign(CENTER);
  text(message, width/2, MESSAGE_Y);

  delay(MESSAGE_DELAY);
}
```

We set the background colour, set the frame rate, and set the text font. The hallmark feature of the digital rain animation is the streaks of characters that fall from the top of the screen. To define the behaviour of such a *streak*, we will define a class called a `Streak`. We will see how this works later. A critical feature is to have a buffer of such streaks to allow them to appear and disappear on the screen. To do this, we have a `buffer` variable that will hold the streaks that are visible on the screen at any given time. At the start, we will add a random number of *streaks* to the buffer at random x and y positions.

This is followed by the text size, defining a static font, aligning to the centre, and printing an initial message defined in `message` variable. This is followed by a delay. The message is as follows:

```java
String message = "PRESS THE SPACE KEY TO EXIT THE MATRIX\nCLICK ANYWHERE TO GENERATE A GLITCH";
```

Before moving into the draw function, we will look at the `Streak` class. The structure is as follows:

```java
public class Streak {
  private int x, y;
  private int cursor = (int)random(0, characters.length/2);
  private int lives = STREAK_LIVES;
  private int state = 0;
  private int floor = cursor;
  private int ceiling = (int)random(cursor + 1, characters.length);

  public Streak(int x, int y) {
    this.x = x; this.y = y;
  }

  public void draw();

  public boolean dead();

  private void draw_char(int j, color colour);
}
```

There are a few private variables defining the characteristics of the *streak*. The x, y coordinates, cursor position at the start, number of lives remaining, current state, floor and ceiling: which define the subset of characters from the main character set that are utilised in this streak.

I believe x and y are self-explanatory. Also, floor and ceiling. A streak has two main states: alive and dead. The alive state is when the streak is visible on the screen. Dead is when it disappears from the screen.

An alive streak will be in two main states: active and passive. The streak starts its life with the `cursor` at the first character of the sub-characters buffer. The `lives` will be at maximum and `state` will be 0. (alive) If you check the animation, a streak starts with nothing. Then one after the other, characters from the buffer appear one after the other until the end of its buffer is reached. The `cursor` is the last character displayed by the streak. Once it reaches the end of its buffer, the `cursor` is gone.

To emulate this, for each time the `draw()` function is called, we increase the `cursor`. When the end of the buffer is reached, we keep the `cursor` in place, but start decreasing the `lives`. This leaves the streak visible on the screen until the `lives` reach zero, at which point we change the `state` to 1. (dead) While the `cursor` is not at the `ceiling`, we draw the *cursor* or the last character currently visible on the buffer as white. The characters we print are from the `floor` to the `cursor` only. The rest of the visible characters are left as green. When the `ceiling` is reached, we display all characters as green. When dead, we do not print the characters.

You can see this behaviour in the following code snippet:

```java
  public void draw() {
    if (this.state == 0) {
      if (this.cursor >= this.ceiling) {
        draw_char(this.cursor - 1, STATIC);
        this.lives--;

        if (this.lives <= 0) {
          this.state = 1;
        }
      } else {
        draw_char(this.cursor, CURSOR);
        this.cursor++;
      }

      for (int j = this.floor; j < this.cursor - 1; j++) {
        draw_char(j, STATIC);
      }
    }
  }
```

The `dead()` function is simply there to return whether the streak is dead or alive.

```java
  public boolean dead() {
    return (this.state == 1);
  }
```

The `draw_char()` function draws the characters to the screen according to the logic we discussed under `draw()`.

```java
  private void draw_char(int j, color colour) {
    textSize(text_size);
    fill(colour);
    textAlign(CENTER);

    if (this.y + j >= row_count) {
      text(characters[j], (this.x * column_size) + (column_size / 2), (this.y + 1 + j - this.floor - row_count) * row_size);
    } else {
      text(characters[j], (this.x * column_size) + (column_size / 2), (this.y + 1 + j - this.floor) * row_size);
    }
  }
```

Now that we understand how the *streaks* work, we will move into one of the most critical functions of the code. The `glitch()` function.

```java
void glitch() {
  for (int i = 0; i < character_glitch.length; i++) {
    if (character_glitch[i]) {
      characters[i] = CHARACTER_SET[(int)random(0, CHARACTER_SET.length)];
    }
  }

  if ((int)random(0, GLITCH_ENTROPY) == 4) {
    int pos = (int)random(0, character_glitch.length);
    character_glitch[pos] = !character_glitch[pos];
  }
}
```

The purpose of this function is to introduce *glitches* into the streaks. Remember we discussed that we need a separate copy of the original charset. This is why. We have a separate array which defines if each char in the charset is glitched.

```java
char[] characters = new char[CHARACTER_SET.length];
boolean[] character_glitch = new boolean[characters.length];
```

What we do in the `glitch()` function is, we first go through each char of the `characters`. We check if the corresponding `character_glitch` is enabled or not. If a glitch is enabled, we *glitch* that specific character. IE, we pick a random character from the `CHARACTER_SET` and replace this character with that.

Next, we randomly pick some characters from the `character_glitch` and flip their state: stable or glitched. This is what creates the iconic **glitching** effect of the streaks.

Since each streak in the buffer is tied to the `characters`, when a glitch is introduced, this is visible across all streaks.

Next, we will move on to the `draw()` function. This is pretty straightforward.

```java
void draw() {
  fill(BACKGROUND >> 16 & 0xFF, BACKGROUND >> 8 & 0xFF, BACKGROUND & 0xFF, FADE);
  rect(0, 0, width, height);

  if ((random(0, 10) < STREAK_ENTROPY) && (matrix)) {
    buffer.add(new Streak((int)random(0, COLUMN_COUNT), (int)random(0, row_count)));
  }

  for (int i = 0; i < buffer.size(); i++) {
    Streak streak = buffer.get(i);

    if (streak.dead()) {
      buffer.remove(i);
      i--;
    } else {
      streak.draw();
    }
  }

  glitch();
  
  drawTopic();
}
```

We first fill the screen with black accompanied by an alpha value. This allows the dead streaks to fade away smoothly. We also make sure to add some new streaks to the buffer to replenish any that have gone dead. Then for each streak, we remove it from the buffer if it's dead, and `draw()` it if it's alive. Then we introduce the `glitch()`.

We also draw the topic using the `drawTopic()` function.

```java
void drawTopic() {
  String topic_str = "";
  for (int i = 0; i < topic.length; i++) {
    topic_str += characters[topic[i]];
  }

  fill(0, 0, 0, TOPIC_FADE);
  rect(0, (TOPIC_Y / 2) + 5, width, TOPIC_SIZE);

  textSize(TOPIC_SIZE);
  fill(STATIC);
  textAlign(CENTER);
  text(topic_str, width/2, TOPIC_Y);
}
```

Notice how the topic is described by the position of each character of the text **THE\_MATRIX**.

```java
int[] topic = {50, 38, 35, 61, 43, 31, 50, 48, 39, 54};
```

When displaying, the text is reconstructed using the `characters`. This introduces the glitching effect to the topic too.

That is pretty much the guts of this demo. We also have two supporting functions.

```java
void keyPressed() {
  if (key == PAUSE_KEY) {
    matrix = !matrix;
  }
}
```

Here, when the space bar is pressed, the matrix effect is paused; essentially stops spawning new streaks in the buffer. And vice versa if pressed again.

```java
void mouseClicked() {
  int x = (mouseX * COLUMN_COUNT) / width;
  int y = (mouseY * row_count) / height;

  fill(STATIC);
  rect(x * column_size, y * row_size, column_size, row_size, 5);

  buffer.add(new Streak(x, y));
}
```

Also, when the mouse is clicked on the screen, using the x and y coordinates of the cursor, a new streak is created in that specific location.

![Matrix animation](https://cdn.hashnode.com/uploads/covers/61a2243af0cb2e37690c63e1/0971b9d0-b1e2-4b4c-9f3c-b940898688f0.gif align="center")

Combined, this simple code creates an amazing and sophisticated visual effect created for the movie screen. You can tweak some of the parameters to see how that affects the animation.

External Links:

*   GitHub Repository with the Processing Code: [Github Repository](https://github.com/asankaSovis/Matrix)
    
*   Wikipedia article on Digital Rain: [Digital Rain](https://en.wikipedia.org/wiki/Digital_rain)
    
*   Reference animation: [YouTube](https://youtu.be/ZIjfK4MGrGI?list=RDZIjfK4MGrGI)
