Op Art with p5
Tags: graphics, javascript
Published: 2020-05-11 14:17:39

---
title: Op Art with p5
published: true
date: 2019-05-05 07:08:00 UTC
tags: Graphics,JavaScript
canonical_url: https://drmsite.blogspot.com/2019/05/op-art-with-p5.html
---

My Dad and I both love [Op art](https://en.wikipedia.org/wiki/Op_art), and he recently forwarded an email from Tumblr with [this link](https://jacobjoaquin.tumblr.com/post/184527746991/opshader-20190429). It piqued my interest as I'm playing with p5 an awful lot at the minute in my spare time as you'll see [from](http://drmsite.blogspot.com/2019/04/p5-invader.html) [previous](http://drmsite.blogspot.com/2019/03/p5-tail.html) [posts](http://drmsite.blogspot.com/2019/03/p5-explosions.html).

So I got to it but clocked that there might be an issue in terms of masking the squares which make up the image. A little judicious playing with [Gimp](https://www.gimp.org/) meant that I knew the graphic would be made up of multiple squares. The squares either started with a black or yellow background and they changed after a delay. To get around the issue of masking, I opted to use [createGraphics()](https://p5js.org/reference/#/p5/createGraphics) and then embed that graphic in the main body of the image using the [image()](https://p5js.org/reference/#/p5/image) function. I ended up making a simple error though, but [Stack Overflow came to my rescue](https://stackoverflow.com/questions/55971705/issues-with-multiple-p5-image), and I'm quite pleased with the [result](https://annoyingmouse.js.org/WireFrameJS/000-MISCELLANEOUS/OPART/).

<iframe style="width: 600px;height: 1000px;transform: scale(0.826);transform-origin: left top;" src="https://annoyingmouse.js.org/WireFrameJS/000-MISCELLANEOUS/OPART/" scrolling="no" frameborder="no" allowtransparency="true" allowfullscreen="true" sandbox="allow-forms allow-pointer-lock allow-popups allow-same-origin allow-scripts allow-modals"></iframe>

The code, which is also [up on GitHub](https://github.com/annoyingmouse/WireFrameJS/tree/master/000-MISCELLANEOUS/OPART) and as a single file on [JSFiddle](https://jsfiddle.net/annoyingmouse/Lbs9v8f4/):

{% jsfiddle https://jsfiddle.net/annoyingmouse/Lbs9v8f4 result %}


```javascript
class Tile {
  constructor(p5, x, y, dimension, row, delay) {
    this.p5 = p5;
    this.x = x;
    this.y = y;
    this.dimension = dimension;
    this.delay = delay;
    this.onFirst = row % 2;
    this.on = p5.color(255, 184, 0);
    this.off = p5.color(26, 17, 16);
    this.diameter = Math.sqrt(Math.pow(dimension, 2) * 2)
    this.pg = p5.createGraphics(dimension, dimension)
    this.pg.noStroke();
  }
  update() {
    if (this.delay === 0) {
      if (this.diameter < 0) {
        this.diameter = Math.sqrt(Math.pow(this.dimension, 2) * 2);
        this.onFirst = !this.onFirst;
        this.delay = 120;
      } else {
        this.diameter -= 1;
      }
    } else {
      this.delay -= 1;
    }
    return this.draw();
  }
  draw() {
    this.pg.fill(this.onFirst ? this.off : this.on);
    this.pg.rect(0, 0, this.dimension, this.dimension);
    this.pg.fill(this.onFirst ? this.on : this.off);
    this.pg.circle(this.dimension / 2, this.dimension / 2, this.diameter);
    return this.pg;
  }
}

new p5(p5 => {
  const rows = 14;
  const columns = 14;
  const dimension = 40;
  const framerate = 20;
  const tiles = [];
  const delay = 30;
  p5.setup = () => {
    p5.createCanvas(columns * dimension, rows * dimension);
    for (let row = 0; row < rows; row++) {
      for (let column = 0; column < columns; column++) {
        tiles.push(new Tile(
          p5,
          column * dimension,
          row * dimension,
          dimension,
          row,
          column % 2 ? ((rows - row) * 5) + 80 : row * 5
        ));
      }
    }
  };
  p5.draw = () => {
    p5.background(200);
    tiles.forEach((tile) => {
      p5.image(tile.update(), tile.x, tile.y);
    });
  };
});
```