C CS 2 | Programming for Interactive Digital Arts | Fall 2023
Programming for Interactive Digital Arts
CS 2, Fall 2023

1. Introduction

What's this course about?

Let's look at the title -- what's your perspective on these phrases?

  • Digital arts
  • Programming (using p5.js)
  • Interactive

See the following examples from the p5.js Showcase:

The goal of this course is to teach you the fundamental techniques underlying works like these, and give you the chance to develop your own interactive works using the JAVASCRIPT with p5.js. To get there, we will cover topics such as how to represent and manipulate two-dimensional shapes, color, and images; how to represent and respond to input from mouse, keyboard, webcam, and the network; and how to represent and simulate the movements and interactions of physical objects. See the course schedule.

Administrative stuff

See course homepage and canvas site.

  • Who, what, where
  • Philosophy
  • Homework, quizzes
  • Honor code
  • Disabilities

Getting started

Walk through SA 1.

Get acquainted with the p5.js Editor, by playing with provided sketches; e.g., Visual | Data Visualization | Games | Advanced:

An example

The following steps build up an interactive sketch. Don't worry about the details here -- we'll do that over the next week(s). Just take it in holistically, to get a feel for what it's like to work with P5.Js. In general, a good way to learn is to copy examples into the p5.js editor yourself, and modify and play around with them, simply copy and paste from this page into the p5.js editor.

  1. We'll start with what's perhaps the simplest possible sketch -- an ellipse, here at position (50,50) and of size 25x25:
    // An ellipse with center at (50,50) and size of 25x25
    function draw()
    {
       ellipse(50,50,25,25);
    }
    
    screenshot
  2. That's not interactive, but by having the P5.Js draw() function plot an ellipse at the current mouse position each frame, we have perhaps the simplest possible interactive sketch, a drawing program:
    // What to do every frame
    function draw()
    {
      // An ellipse with center at (mouseX,mouseY) and size of 25x25
      ellipse(mouseX,mouseY,25,25);
    }
    
    screenshot
  3. Now let's make it so that we only draw when the mouse is pressed:
    // What to do every frame
    function draw()
    {
      // Only when the mouse button is held down...
      if (mouseIsPressed) {
        // An ellipse with center at (mouseX,mouseY) and size of 25x25
        ellipse(mouseX,mouseY,25,25);
      }
    }
    
    screenshot
  4. Let's customize the set-up and add in a splash of color to let our mouse draw "strings of soap bubbles":
    // Initialization
    function setup()
    {
      createCanvas(500,500);          // Make the window bigger
      smooth();               // Make the edges smoother (anti-aliased)
      background(0,0,0);      // Black background
      strokeWeight(2);        // Thicken the lines drawn 
    }
    
    // What to do every frame
    function draw()
    {
      if (mouseIsPressed) {
        // Choose random red, green, and blue components of the fill and stroke color.
        // also make it a bit transparent
        fill(random(200,255),random(200,255),random(200,255),100);
        stroke(random(128,255),random(128,255),random(128,255),100);
        // pick a random radius and save it away
        var radius = random(50);
        // draw the ellipse
        ellipse(mouseX,mouseY,radius,radius);
        // draw a line connecting this position to the last one
        line(mouseX,mouseY,pmouseX,pmouseY);
      }
    }
    
    screenshot
  5. Let us makes our strings behave like a brush, where the color will fade away after a while. To do this, we have to remember things (in this case when we clicked the mouse).
    // let us remember the last time we clicked the mouse
    var strength = 0;
    
    // Initialization
    function setup()
    {
      createCanvas(500,500);          // Make the window bigger
      smooth();               // Make the edges smoother (anti-aliased)
      background(0,0,0);      // Black background
      strokeWeight(2);        // Thicken the lines drawn 
    }
    
    // What to do every frame
    function draw()
    {
      if (mouseIsPressed) {
        // set the strength to high
        strength = 1;
        // Choose random red, green, and blue components of the fill and stroke color
        // also make it a bit transparent
        fill(random(200,255),random(200,255),random(200,255),100);
        stroke(random(128,255),random(128,255),random(128,255),100);
        // pick a random radius and save it away
        var radius = random(50);
        // draw the ellipse
        ellipse(mouseX,mouseY,radius,radius);
        // draw a line connecting this position to the last one
        line(mouseX,mouseY,pmouseX,pmouseY);
      } else { 
        // continue a fading stroke whe the mouse is released, until the strength fades completely
        if(strength > 0.05) {
          // Choose random red, green, and blue components of the fill and stroke color
          // also make it a bit transparent
          fill(random(200,255),random(200,255),random(200,255),100*strength);
          stroke(random(128,255),random(128,255),random(128,255),100*strength);
          // pick a random radius and save it away
          var radius = random(50);
          // draw the ellipse
          ellipse(mouseX,mouseY,radius,radius);
          // draw a line connecting this position to the last one
          line(mouseX,mouseY,pmouseX,pmouseY);
          // decrease the strength
          strength = strength * 0.95;
        }
      }
    }
    
    screenshot
  6. To make this a bit more interactive and give power to the computer to draw with us. We will base the idea on an example by Sharp Hall on the Processing exhibition.
    The computer will either continue our strokes or start his own if we do not paint for a while. At random, he will also add some softer bubbles around.
    // Based on a sketch by Sharp Hall, http://stereotheism.org/071106/
    
    // Stuff that needs to be remembered from one frame to the next
    var x, y;            // The end of the line
    var dx, dy;          // The length of the line
    var strength=0;      // Computer-drawn lines decay and fade away
    var lastLineFrame=0;   // When did the last computer-drawn line start?
    
    // Initialization
    function setup()
    {
      createCanvas(500,500);          // Make the window bigger
      smooth();               // Make the edges smoother (anti-aliased)
      background(0,0,0);      // Black background
      strokeWeight(2);        // Thicken the lines drawn 
    }
    
    // What to do every frame
    function draw()
    {
      if (mouseIsPressed) {
        // set the strength to high
        strength = 1;
        // Choose random red, green, and blue components of the fill and stroke color
        // also make it a bit transparent
        fill(random(200,255),random(200,255),random(200,255),100);
        stroke(random(128,255),random(128,255),random(128,255),100);
        // pick a random radius and save it away
        var radius = random(50);
        // draw the ellipse
        ellipse(mouseX,mouseY,radius,radius);
        // draw a line connecting this position to the last one
        line(mouseX,mouseY,pmouseX,pmouseY);
        // Remember this stroke
        x = mouseX; y = mouseY;
        dx = mouseX-pmouseX; dy = mouseY-pmouseY;
        lastLineFrame = frameCount;
      }
      else {
        if (frameCount - lastLineFrame > 150) {
          // Start a new random computer-drawn line
          x = random(width);
          y = random(height);
          dx = random(-20,20);
          dy = random(-20,20);
          strength = 1.0;
          lastLineFrame = frameCount;
        }
        if (strength > 0.05) {
          // Continue a decaying line kind of along the same direction
          var x2 = x, y2 = y;
          x = x+random(dx);
          y = y+random(dy);
          // Random color and weight like before; note that opacity is a function of strength
          fill(random(200,255),random(200,255),random(200,255),100*strength);
          stroke(random(128,255),random(128,255),random(128,255),100*strength);
          // pick a random radius and save it away
          var radius = random(50);
          // draw the ellipse
          ellipse(x,y,radius,radius);
          // draw a line connecting this position to the last one
          line(x,y,x2,y2);
          // decrease the strength
          strength = strength * 0.95;
        }
      }
      
      // Every 30-th frame, draw a random ellipse
      if (frameCount % 45 == 0) {
        // Choose darker random colors
        fill(random(30,100),random(30,100),random(30,100),100);
        stroke(random(30,120),random(30,120),random(30,120),100);
         // pick a random radius and save it away
        var radius = random(100,200);
        // draw the ellipse at random position
        ellipse(random(width),random(height),radius,radius);
      }
    }
    
    screenshot