# September 14-16

## September 14

We reviewed material that’s already discussed in the September 11 notes, including:

• Counting. Generally, computer scientists and computer programs count from zero, so to count 3 things, count 0, 1, 2. To count N things, count 0, 1, … N-1. See Sept. 11 notes on counting and templates for for loops.
• Using declarations in for loops: Write “for (var i = 0; i
• Random squares: see code in Sept. 11 notes.
• Iteration – we made some examples do draw lots of random rectangles to illustrate for loops.
• we talked about clearing the screen. The background() function clears the screen. You can call it in setup(), in draw(), or even inside an if statement depending on what you want to accomplish, and we saw examples of each of these cases.

We went over order of evaluation of sketch.js programs:

1. Compile the program, evaluating all global variable declarations and initializations.
2. Define all the p5.js library functions and variables such as random() and PI.
3. Call setup().
4. Call draw() repeatedly.

The point here is that random() and PI and other p5.js functions are not available for global variable initializations. Rather than writing “var myVar = random(10);” at the top of your program, write “var myVar;” at the top, and in setup (where random() will be defined), write “myVar = random(10);”.

We looked at rotations. A good tutorial is this one, although it is for Java/Processing rather than JavaScript. The principles are the same. See your textbook too: Chapter 6.

## September 16

We started with a review of rotation: Make a square rotate in the center of the screen. The tutorial mentioned above is very nice (this one, although it is for Java/Processing rather than JavaScript). Here’s the example we did in class:

### Rotation/Translate Example

``````var gAngle = 0;

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

function draw() {
background(150, 200, 150);
push();
translate(width / 2, height / 2);
rectMode(CENTER);
rect(0, 0, 50, 50);
pop();
gAngle = gAngle + 1;
}
``````

This example is slightly changed from class:

• The canvas size is smaller — how do you control the canvas size?
• Why is the box still in the middle of the canvas even though the canvas size changed?
• The `angle` variable was changed to `gAngle`.

### Global Variables Names

In future examples, I will be using the notation “`gSomething`” to mean global variables. The reason is that p5js defines a lot of global variables such as `top`, `width`, `height`, and `scrollX` — it’s just dangerous to pick a name for your own variable and hope there will not be a conflict. the “`gSomething`” notation (in the case, `gAngle`) safely generates non-p5js names and helpfully reminds the reader that the variables are global. You can use any naming scheme you want, but avoid simple names like top to stay out of trouble.

### Iteration Examples

Next, we reviewed some iteration examples. Let’s draw 10 boxes:
sketch

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

function draw() {
background(150, 200, 150);
var x = 50;
for (var i = 0; i < 10; i = i + 1) {
rect(x, 50, 10, 10);
x = x + 20;
}
}
``````

Notice in this example that we completely separate the task of counting (10) boxes (with loop variable `i`) and deciding where to draw them (with local variable `x`).

Do we really need the extra variable `x` to compute location? I don’t think so! Try this:

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

function draw() {
background(150, 200, 150);
for (var i = 0; i < 10; i = i + 1) {
rect(i * 20 + 50, 50, 10, 10);
}
}
``````

Here, we’ve used a little math (multiply to scale up to 20-pixel spacing, add to shift boxes by 50 pixels) to translate the counting variable `i` into a screen coordinate (formerly the `x` variable). Fun fact: Some programming languages like C have “optimizers” that actually convert the first program example into the second automatically to make them run faster. (Or in the old days, when multiplication hardware did not exist, “*” was really slow, so optimizers could convert the second form to the first, eliminating the multiplication!)

But do we really need to do the math to convert i from counting numbers to pixels? Why not just work with pixels directly? Here’s how that solution looks:

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

function draw() {
background(150, 200, 150);
for (var i = 50; i < 250; i = i + 20) {
rect(i, 50, 10, 10);
}
}
``````

Notice here that we have to be very careful about the condition in the `for` loop. Quick, look at “`for (var i = 50; i " and tell me how many boxes will this code draw. But it's still a good example of the flexibility of ``for` loops.

### Nested For Loops

Next, we look at nested loops. Remember that whatever is inside the `for` loop brackets is repeated, even another loop that draws an entire row. Here, the “outer” or first loop draws rows, and the “inner” or second embedded loop draws each box within the row.

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

function draw() {
background(150, 200, 150);
for (var row = 0; row < 5; row = row + 1) {
// BEGIN ROW
for (var i = 0; i < 10; i = i + 1) {
rect(i * 20 + 50, row * 30 + 25, 10, 10);
}
// END ROW
}
}
``````

Notice that each `rect` location depends on what `row` it is in and on the value of `i`, which can be understood as the column number. What makes `row` a row and `i` a column? Try switching parameters in rect, i.e. write `rect(row * 30 + 25, i * 20 + 50, 10, 10)`.

Here’s another way to approach the problem. Rather than changing the code to draw rows at different coordinates, let’s leave the row code the way it was, and instead use `translate()` to shift each row further down the screen.

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

function draw() {
background(150, 200, 150);
for (var row = 0; row < 5; row = row + 1) {
push();
translate(0, row * 30);
// BEGIN ROW
for (var i = 0; i < 10; i = i + 1) {
rect(i * 20 + 50, 25, 10, 10);
}
// END ROW
pop();
}
}
``````

Notice here that the 2nd parameter to `rect` (the Y coordinate) is always the same (25), but the actual location on the canvas changes for each row due to the `translate()` call.

## Sine = Sin, Cosine = Cos, Radius, and Angle

Next, we talked about expressing locations in terms of angles and radius rather than X and Y.

### Introducing Sin and Cos

Cos and Sin functions tell you X and Y coordinates of a point on a circle of radius 1. The input parameter for Cos and Sin is the angle: How far to rotate around the circle. The output is where you land in terms of X (cos) and Y (sin):

Here’s a graph showing how the functions `sin()` and `cos()` translate angle (here represented by the x coordinate) into a value shown as displacement in the Y axis.

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

function draw() {
background(150, 200, 150);
for (var x = 0; x < width; x = x + 1) {
stroke(0);
point(x, 60 - 50 * sin(radians(x)));
stroke(255, 255, 0);
point(x, 60 - 50 * cos(radians(x)));
}
}
``````

### Rotating

Perhaps more interestingly, we can now write a program that creates circular motion by translating radius and angle into X and Y. You should understand how the following program works and why the circle moves in a circle. How would you make it go faster? How would you make the circle bigger? How would you make circle orbit bigger? What happens if the radius is zero?

``````function setup() {
createCanvas(200, 200);
frameRate(30);
}

var gAngle = 45;

function draw() {
var centerx = width / 2;
var centery = height / 2;
// line(centerx, centery, centerx + x, centery - y);
background(150, 200, 150);
line(centerx, centery, centerx + x, centery - y);
noStroke();
ellipseMode(CENTER);
ellipse(centerx + x, centery - y, 10, 10);
gAngle = gAngle + 2;
}
``````

### Spiral

Finally, change the previous example as follows:

• Start the radius at 1, but increase the radius for each frame.
• Move the `background()` call to `setup()` so it does not erase every frame.
• Remove the `line`, just draw the circle.
• For this web page version, call `background` and reset `radius` after a bunch of `draw`
calls.
``````function setup() {
createCanvas(200, 200);
frameRate(30);
background(150, 200, 150);
}

var gAngle = 45;
var gFrameCount = 0;

function draw() {
var centerx = width / 2;
var centery = height / 2;
// line(centerx, centery, centerx + x, centery - y);
noStroke();
ellipseMode(CENTER);
ellipse(centerx + x, centery - y, 10, 10);
gAngle = gAngle + 2;
gFrameCount = gFrameCount + 1;
if (gFrameCount > 1000) {
gFrameCount = 0;