September 11

Pre-class video

We watched a bit of Jaap Blonk’s live performance of Kurt Schwitters’ sound poem “Ursonate” (1932), augmented by real-time (live) computational typography by Golan Levin. Performance at STUK kunstencentrum, Leuven, January 2007.

Academic Integrity

We watched Prof. David Kosbie’s Automated Plagiarism Detection Tool, developed for CMU Course 15-110/112 and used in 15-104.

As the semester goes on, we understand that the onslaught of homework assignments and projects cause a great deal of stress. However, under no circumstances does this mean that it’s okay to cheat. Autolab has automatic plagiarism detection, and all of your code will be looked over by an instructor or a TA. Cheating is a serious offense of academic integrity, so don’t do it. Instead, seek help from an instructor or TA when you need it.

min, max, constrain

In this program, we have taken our simple program that moves an ellipse to the mouse position and used min() and max() in order to cap off the movement of the ellipse. Here’s an example using the min function to limit how high x can be, i.e. how far to the right we can drag the circle.

min example

function setup() {
    createCanvas(200, 200);
    frameRate(10);
}

function draw() {
    background(200);
    rect(50, 50, 100, 100); // just for reference
    fill(0); // black
    var x = min(mouseX, 150); // upper limit of x is 150
    ellipse(x, mouseY, 30, 30);
    print(mouseX.toString() + " " + mouseY.toString());
}

Here, we add code using max to assert a lower bound on the x coordinate, i.e. we limit how far left we can drag the ball:

min and max example

function setup() {
    createCanvas(200, 200);
    frameRate(10);
}

function draw() {
    background(200);
    rect(50, 50, 100, 100); // just for reference
    fill(0); // black
    var x = min(mouseX, 150); // upper limit of x is 150
    // note that in the next line, we take x as an "input" to max
    // and assign the "output" back into to variable x:
    x = max(x, 50); // lower limit is 50
    // Note that if we had written max(mouseX, 50), we would be
    // ignoring the result of the min() operation performed above.
    ellipse(x, mouseY, 30, 30);
    print(mouseX.toString() + " " + mouseY.toString());
}

As you can see from the program, min(x,y) returns the minimum of x and y, while max(x,y) returns the maximum.

Finally, we replace min and max with constrain, a handy function that limits a value between lower and upper bounds. In this example, we constrained the Y motion as well as the X motion. Notice the two different styles. For the X axis, we make a variable x, compute a value in terms of mouseX, and then pass x as a parameter to ellipse. For the Y axis, we take advantage of the fact that function calls can be nested. We pass the result of the constrain function directly as the Y parameter to ellipse.

constrain example

function setup() {
    createCanvas(200, 200);
    frameRate(10);
}

function draw() {
    background(200);
    rect(50, 50, 100, 100); // just for reference
    fill(0); // black
    var x = constrain(mouseX, 50, 150);
    ellipse(x, constrain(mouseY, 50, 150), 30, 30);
    print(mouseX.toString() + " " + mouseY.toString());
}

Using print

We may not have talked about this much but print statements are an essential tool for debugging your code. You can print any message or value that you want to the browser console in order to make sure the values you are generating are correct or checking where in your code that an error might appear.

Just a reminder, this is how you see your console in the browser:
1) Right click and select ‘Inspect Element’
2) Navigate to the ‘Console’ tab

In the min() and max() example, we have a print statement at the bottom to display the values of the ellipse position. We use the expression, print("Hello, world!"), to print the message “Hello, world!” to the console. If you want to print numbers or other values, you can use print(some_Number.toString()). And finally, if you want to mix-and-match string messages and values, you can use the ‘+’ operator for string concatenation:

The Eyes Have It

In this example, we want the pupils to follow the mouseX position. But, we don’t want the pupils to move outside of the white ellipses. So we can use the function constrain(variable, val1, val2) in order to constrain a variable between values val1 and val2. In this case, we constrain each pupil movement between -40 and 40 pixels from the white ellipse’s center.

You should understand how mouseX is shifted (by addition, subtraction) and scaled (buy multiplication, division) to convert from raw coordinates to useful parameter values. There are many ways to do this, and this is generally called “mapping.” In fact the map function is one built-in implementation of a particular form of mapping.

sketch

function setup() {
    createCanvas(400, 100);
    frameRate(10);
}

function draw() {
    background(200);
    var x = 100, y = 50;
    ellipse(x, y, 100, 50);
    ellipse(x + 150, y, 100, 50);
    fill(0);
    // get the raw input from the mouse, range is roughly
    //    0 to 400:
    var offset = mouseX - 200;
    // after subtracting, the range is -200 to 200
    offset = offset / 10; // new range is -20 to 20
    // limit range to -40 to 40, 
    //    effective new range is still -20 to 20 unless
    //    the mouse goes way off the screen:
    offset = constrain(offset, -40, 40);
    // add the offset to make eyeballs move:
    ellipse(offset + x, y, 40, 40);
    ellipse(offset + x + 150, y, 40, 40);
}

A note about random() and frameRate()
In lecture we applied a random y position to the left eyeball. However, because the default frame rate of the program is 60 frames per second, the animation happens so quickly that it looks spastic. We can use the frameRate(some_number) function in setup() in order to change the frame rate of the animation to some_number. Movies and games usually use a frame rate of 24 or 30 because those are more natural to human vision.

Conditional Execution and the if Statment

We looked at the (relatively) simple problem of “lighting up” a square if the mouse moves over it. The first example just tests one condition: Is the mouse to the right of the left edge of the square?

sketch

function setup() {
    createCanvas(200, 200);
    frameRate(10);
}

function draw() {
    background(200);
    var left = 50, top = 50;
    // if the mouse is to the right (greater than)
    // the left edge of the square...
    if (mouseX > left) {
        fill(255, 0, 0);  // make the square RED
    }        
    rect(left, top, 100, 100);
}

Next, we use the “and” operation && to check all 4 boundaries of the square. Now the square turns red only when the mouse is inside the square. Note that everything inside the braces {...} is performed only if the condition expression is true. We also added an “else” clause which provides commands to perform if the condition expression is false. In this case, the fill color is yellow if the mouse is not inside the square.

sketch

function setup() {
    createCanvas(200, 200);
    frameRate(10);
}

function draw() {
    background(200);
    var left = 50, top = 50, right = 150, bottom = 150;
    if ((mouseX > left) && (mouseX < right) &&
        (mouseY > top) && (mouseY < bottom)) {
        fill(255, 0, 0);  // make the square RED
    } else {
        fill(255, 255, 0);
    }
    rect(left, top, right - left, bottom - top);
}

Simple Iteration

We looked at a different example in class, but this one by Dan Shiffman is quite nice. After this example, I’ll give a formula for the most simple case of iterating something N times, for some value N.

sketch

// Learning Processing
// Daniel Shiffman
// http://www.learningprocessing.com
// Example 6-1: Many lines

function setup() {
    createCanvas(480, 270);
    background(255);
    // Legs
    stroke(0);
    line(50,60,50,80);
    line(60,60,60,80);
    line(70,60,70,80);
    line(80,60,80,80);
    line(90,60,90,80);
    line(100,60,100,80);
    line(110,60,110,80);
    line(120,60,120,80);
    line(130,60,130,80);
    line(140,60,140,80);
    line(150,60,150,80);
}

sketch

// Learning Processing
// Daniel Shiffman
// http://www.learningprocessing.com
// Example 6-2: Many lines with variables

function setup() {
    createCanvas(480, 270);
    background(255);
    // Legs
    stroke(0);
    var y = 80; // Vertical location of each line
    var x = 50; // Initial horizontal location for first line
    var spacing = 10; // How far apart is each line
    var len = 20; // Length of each line
    // Draw the first leg.
    line(x, y, x, y + len);
    // Add spacing so the next leg appears 10 pixels to the right.
    x = x + spacing;
    // Continue this process for each leg, repeating it over and over.
    line(x, y, x, y + len);
    x = x + spacing;
    line(x, y, x, y + len);
    x = x + spacing;
    line(x, y, x, y + len);
    x = x + spacing;
    line(x, y, x, y + len);
    x = x + spacing;
    line(x, y, x, y + len);
    x = x + spacing;
    line(x, y, x, y + len);
    x = x + spacing;
    line(x, y, x, y + len);
    x = x + spacing;
    line(x, y, x, y + len);
    x = x + spacing;
    line(x, y, x, y + len);
    x = x + spacing;
    line(x, y, x, y + len);
}

sketch

// Learning Processing
// Daniel Shiffman
// http://www.learningprocessing.com
// Example 6-6: Legs with a for loop

function setup() {
    createCanvas(480, 270);
    background(255);

    var y = 80; // Vertical location of each line
    var spacing = 10; // How far apart is each line
    var len = 20; // Length of each line

    // Translation of the legs while loop to a for loop.
    for (var x = 50; x <= 150; x += spacing) {
        line(x, y, x, y + len);
    }
}

To write a for loop:

  1. Pick a variable name (let’s say VARNAME)
  2. Pick a STARTINGVALUE
  3. Pick an INCREMENT
  4. Pick a LIMIT that is one greater than the last value of VARNAME
  5. Decide WHAT_TO_DO with each value of VARNAME
  6. Fill in the template:

for (var VARNAME = STARTINGVALUE; VARNAME < LIMIT; VARNAME += INCREMENT) {
    WHAT_TO_DO;
}

The most common case is i = 0, 1, 2, 3, …, n-1:

for (var i = 0; i < n; i += 1) {
    WHAT_TO_DO;
}

Note that i takes on n different values. Because we start numbering at 0, the last value of i is n-1, not n. Make sure you understand this! It’s confusing at first, but if you always start counting at 0, and if the limit is always n, the number of times you want the loop to run, and if you always write i < n (never write i <= n even though Dan Shiffman did it) then you’ll be programming like a pro.

Example of N Iterations

Here’s an example: Draw 5000 random rectangles. This will change every time you reload the page.

sketch

function setup() {
    createCanvas(200, 200);
    background(200);
    for (var i = 0; i < 5000; i++) {
        fill(random(200), random(200), random(200));
        rect(random(400), random(400), random(50), random(50));
    }
    noLoop(); // turn off looping
}

function draw() {
}

Using var in for Loops

I was sloppy in class, writing for (i = ...) rather then for (var i = ...). The difference is that if you write “var,” you are declaring the loop variable to be a local variable. You can get the same effect by writing var i; for (i = ...). If you do not write var, you might be declaring or reusing a global variable, which might have unintended side effects. You will usually get away with it, but you can’t afford to live so dangerously because the problems will be very subtle and mysterious. Declaring the loop variable with “var” is equivalent to declaring the variable (but not initializing it) at the beginning of the function.