Week 4 - Loops and Functions

Today’s Schedule

  • local vs global variables
  • custom functions
  • loops
  • map and constrain
  • build pong
  • simple functions

Functions

Functions are chunks of code that go together. They are modular and reusable!

You can think of a function as a subsection of code for a specific purpose. This helps you break your code down into manageable chunks, so the logic is clearer.

You can re-use these chunks as many times as you want.

There are two uses of the word function.

For example, ellipse() is a function we can use. Someone wrote the code underlying this function so that we can call an ellipse and draw an ellipse to the screen.

We also can create our own user-defined functions. These are functions we write ourselves.

Just creating a function does not run that function. We define a function, and we must also call that function to use it.

void setup(){
  size(400,400);
}

void draw(){
  myFunction(); //we call our code here
}

void myFunction(){
  //code goes in here
}

In this above program our setup runs once and creates our canvas. Then draw begins running. It sees a function call for myFunction() and then jumps down to void myFunction(){ ... } to run the function code. After it runs the function, it jumps back to the following line of draw.

Generally it’s good practice to give your functions clear names, like void moveBall(){ ... }.

So a simple program may look like this:

  • start with global variables
  • then comes your setup function
  • then comes your looping draw function, which typically will call other functions
  • then you define all of your user-defined functions. Give them names that describe what they do.

Why use functions?

When you code your program using functions you can slowly build up your program will smaller modular parts, as if you are snapping together different functionality with legos. As you complete a function you can add a function call into your draw (for example) and test it. If the function doesn’t work, or you are getting bugs that you need to find, you can always comment out (turn off) a function call. This makes it easier to debug.

As your program grows more complex you can add more functions or update functions. This helps you build up more complex programs without getting lost in the code.

Arguments!

In a programming context, arguments are values that are passed into a function. They are input that will be used by a function. Not all functions have arguments (meaning that not all functions need an input).

Example

function drawToCorner(int x, int y){
  //the first argument gets passed to x as an int. 
  //The second gets passed to y as an int.
  line(x, y, 0, 0); //draws a line from x,y to the top left corner
}

drawToCorner(100,200); // 100 gets passed to x, 200 passed to y
drawToCorner(50,120); //50 gets passed to x, 120 passed to y

This is not an interesting example, but it shows how to pass in arguments.

See class code examples

More about Arguments

  • You must pass as many arguments as defined in the function’s parameters
  • Your argument’s types (the value you pass) must match the function’s parameter types
  • You can pass in literal values or variables

Stopping Draw with noLoop();

noLoop(); stops draw() so that it only executes once

You can restart it with loop();

Return Types

What does void mean?

Parts of a function

  1. Return type
  2. Function name
  3. Argument(s)

Return Type - what kind of result you want out of this function. A type is an integer, float, char, etc.

Name - self-explanatory. You give it a name of your choice.

Arguments - Optional data input to a function to be used by that function.

Here is a function:

returnType functionName(parameters){
  //code of function
}

The returnType is the type of output it expects to receive. If no output is needed, the return type is void.

Example

int multiplyMe(int a, int b){
    int total = a * b;
    return total; //A RETURN STATEMENT IS REQUIRED!
}

int gimmeTheNum = multiplyMe(7, 6);
println(gimmeTheNum); //42
int newNum = multiplyMe(2, 100);
println(newNum); //200

New commands

  • constrain()

Constrain limits a variable’s range.

  • map()

Map changes the range of a variable (or reverses it).

Example:

background(map(mouseX,0,width,0,255));

Another example:

background(map(mouseX,0,width,255,0));

Loops

In our previous class we talked about coding iteratively. Iteration is the process of repeating steps over and over. Sometimes when we code we want to repeat an action again and again. Sometimes when we code we want to repeat an action again and again.
Sometimes when we code we want to repeat an action again and again.
Sometimes when we code we want to repeat an action again and again.

Question: Why do we need loops?

Two main kinds - FOR Loops and WHILE Loops

Anatomy of a while loop

while (something == true) {
  //do this
}

Warning: Don’t get stuck in an infinite loop! Make sure there is an exit condition

Example

int y = 10;

while (y < height){
    rect(100, y, 100, 10);

    y = y + 20;
}

Anatomy of a for loop

(Initialization; Test; Iterate Expression)

for (int i = 0; i < 100; i++){
    println(i);
}

When to use an if statement or for loop

If you are testing whether something is true

When you are asking a question, use an if statement.

Examples: Is my ball off screen? Is the color black?

If you need to make lots of things, use a for a loop

Examples: I need 300 circles.

The difference between a loop and the draw cycle repeating

Variable Scope

Local vs Global variables

So far when we have written variables we have been declaring them at the top of our program before our setup(). When we create variables this way we are creating global variables. Like the name global implies, these are variables that can be used everywhere, at any time. They are the easiest variables to use.

In addition to global variables are local variables. To understand what this is, it’s important to understand what we mean by the term block of code. In programming, sections of our code can be broken down into chunks or blocks. The code inside of setup(){ } is a block of code. So is the code inside draw(){ } and the code inside mousePressed(){.

TL;DR

Variables declared inside a block are local! They can only be used inside that function.

Put your global variables at the top before setup!

Variables declared outside a function block are global. They can be be used by all functions.

More info on local vs global variables can be found in your book in Chapter 6 Section 5.

Building a more complex program: Pong

We’ll build off our previous work with a ball that wraps around our screen to turn it into a basic version of Pong.

Wrapping

How do we detect that our ball is off the screen? We need to look at its x and y position. We can break this down into 4 checks with if statements.

  • If our ball is offscreen to the left (the x position is what?)
  • If our ball is offscreen to the right (the x position is what?)
  • If our ball is offscreen to the top (the y position is what?)
  • If our ball is offscreen to the bottom (the y position is what?)
if (x > width){ //if our ball's x is offscreen to the right
  x = 0; //then we reset it to the left side of the screen
}

We can do this for all four sides.

Bouncing

Now that we have our 4 if statements to detect if we have hit the edge of the screen, we can modify our code to have the ball bounce instead of wrap.

To do this, we need to modify our ball’s movement.

How do we move our ball to the right?

x = x + 1;

What if we want to move left?

x = x - 1;

We can make a variable called xspeed that can change at different times.

float x = 100;
float xspeed = 1;
  
void draw(){
  x = x + xspeed

  if (x > width){ //if offscreen to the right
    xspeed = xspeed * -1; 
    //flips our xspeed between a negative and positive number
  }
}

We also want to have the ball flip direction if it goes offscreen to the left.

if (x < 0){ //if offscreen to the left
    xspeed = xspeed * -1; 
    //flips our xspeed between a negative and positive number
}

This code is almost exactly the same.

It’s best practice to combine them together.

if ((x > width) || (x < 0)){
    xspeed = xspeed * -1; 
    //flips our xspeed between a negative and positive number
}

We can do this for the ball’s y value as well. See uploaded starter pong code for example.

Controlling the player

We can use keyPressed() function to detect key presses.

void keyPressed(){
  if (key == CODED){
    if (keyCode == UP){
      println("you've pressed up");
      //code to move up goes here
    }
  }
}

The variable keyCode is used to detect special keys such as the arrow keys (UP, DOWN, LEFT, and RIGHT) as well as ALT, CONTROL, and SHIFT. Info from the reference page on keyCode.

When working with keyCodes it is useful to first check to make sure a key is coded. We do this by nesting our code inside an if statement to make sure the key is coded.

How do you move the player up? Decrease the player’s Y. And vice versa for moving down.

Homework

  • Read Chapter 6 - Loops
  • Read Chapter 7 - Functions

  • see Moodle for Pong homework assignment to create a complete 2 player version.

Start with our starter “boring pong” code from class.

  1. Add a score variable. Increase the score every time you hit the ball.

  2. Add a lives variable. Start with 3 lives. When you die, cover the screen in black. (Advanced: make an interesting kill/death screen).

  3. When you hit the ball, make the ball change to a new random color. Make the ball speed get a bit faster. (Advanced: try using some randomness to make the ball more unpredictable, but don’t make it too random or it gets too hard to play).

  4. Add a second player. Add a score for the second player. Have a different ending (maybe a different screen background color?) for each of the different players’ death.

  5. Advanced students: decrease a player’s paddle height each time they miss the ball. Add a win screen if either player gets a score of 10.

  6. OPTIONAL bonus for all: make an interesting design. Change colors, sizes or try out other changes to make the gameplay or design more unique.