In the previous lab, you built animations by overriding methods that Processing calls automatically during animation. In this lab, you’ll build and call methods of your own.

Defining Methods

It is often useful to bundle sets of actions into a procedural abstraction. Consider the stick figure shown on the left and the code we might have written in the last lab to produce it.

void setup() {
  size(255, 255);
  smooth();
  background(255);
  noLoop();  // Execute draw() only once.
}

void draw() {
  int x, y, radius;
  
  // Draw the Sun.
  x = 25; y = 25; radius = 15;
  stroke(250,100,10);
  fill(244,244,90);
  ellipse(x, y, radius*2, radius*2); // sun's body
  
  // Draw stick figure.
  x = 100; y = 100;
  stroke(0);
  strokeWeight(2);
  line(x+27, y+50, x+27, y+80);      // trunk
  line(x+17, y+68, x+37, y+68);      // arms
  line(x+27, y+80, x+17, y+95);      // leg 1
  line(x+27, y+80, x+37, y+95);      // leg 2
  image(loadImage("zim.gif"), x, y); // head
}

While this code works properly, the draw() method must draw both the Sun and the stick figure. We’ve used comments to separate these two portions of the code, but it would be nicer if we could “box them up” into neat blocks, one for drawing the Sun and the other for drawing the stick figure. To do this, we can define our own methods. Here is an example of a method to draw our stick figure. Note that the pattern is the same as the pattern we used to override methods in the last lab.

void drawStickFigure() {
  int x = 100, y = 100;
  stroke(0);
  strokeWeight(2);
  line(x+27, y+50, x+27, y+80);      // trunk   
  line(x+17, y+68, x+37, y+68);      // arms
  line(x+27, y+80, x+17, y+95);      // leg 1
  line(x+27, y+80, x+37, y+95);      // leg 2
  image(loadImage("zim.gif"), x, y); // head
}
returnType methodName(parameterList) {
  statementBlock
}
  • returnType - The return type indicates the type of the value that this method returns, if any. void indicates that this method doesn’t return anything.
  • methodName - The method is named using an standard identifier. Processing requires that we use these names for animations.
  • parameterList - The parameter list specifies the data that the method requires to do its work. These methods require no data so the lists are empty (()).
  • statementBlock - The statement block is the set of statements, surrounded by braces ({ }), that are executed when the method is called.

Calling Methods

Now that the method is defined, we must initiate it. This process is referred to as calling the method. In the last lab, we didn’t have to call the draw(), setup() and mousePressed() because Processing makes those calls automatically.

In our example, we must call the method for drawing the Sun and the method for drawing the stick figure in the draw() method. In this example, we show the complete program (including the method calls to drawSun and drawStickFigure()) as well as the general pattern for calling methods.

void setup() {
  size(255, 255);
  smooth();
  background(255);
  noLoop();  // Execute draw() only once.
}

void draw() {
  drawSun();
  drawStickFigure();
}

void drawSun() {
  int x = 25, y = 25, radius = 15;
  stroke(250,100,10);
  line(x-radius-5,y,x+radius+5,y);   // radiance beams
  line(x,y-radius-5,x,y+radius+5);
  float delta = (radius+5)/sqrt(2);
  line(x-delta,y+delta,x+delta,y-delta);
  line(x-delta,y-delta,x+delta,y+delta);
  fill(244,244,90);
  ellipse(x, y, radius*2, radius*2); // sun's body
}

void drawStickFigure() {
  int x = 100, y = 100;
  stroke(0);
  strokeWeight(2);
  line(x+27, y+50, x+27, y+80);      // trunk
  line(x+17, y+68, x+37, y+68);      // arms
  line(x+27, y+80, x+17, y+95);      // leg 1
  line(x+27, y+80, x+37, y+95);      // leg 2
  image(loadImage("zim.gif"), x, y); // head
}
methodName(argumentList);
  • methodName - The method name of the call must match the name in the definition (exactly!).
  • arugmentList - The argument list specifies the data to be given to the method so that it can do its work. These methods require no data so the argument lists are empty (()).

Exercise 3.d.1. Create an agent of your own design and build a method that draws it. Here are some examples:

Passing Parameters

The use of methods has allowed us to pack the complexity of drawing the Sun and drawing the stick figure away into special-purpose methods. This helps us clean up the draw() method considerably, but it only takes us so far with our procedural abstraction.

What would happen in our example if we wanted to draw several stick figures in different coordinates (and perhaps two suns of different sizes!). drawStickFigure() is designed to draw the figure at any x-y coordinate but it always hard-codes the position to be (100,100). It would be nicer if the draw method could tell drawStickFigure() what coordinates to use (and the drawSun could specify the coordinates and the radius). This can be done using arguments/parameters.

A method definition can specify values that it wants to receive from it’s calling method by specifying parameters in its definition. Then, the calling method can specify values to be passed to that method by specifying arguments in the call.

void setup() {
  size(255, 255);
  smooth();
  background(255);
  noLoop();  // Execute draw() only once.
}

void draw() {
  drawSun(25, 25, 15);
  drawSun(225,30,20);
  drawStickFigure(100, 100);
  drawStickFigure(50,90);
  drawStickFigure(150,50);
}

void drawSun(int x, int y, int radius) {
  stroke(250,100,10);
  fill(244,244,90);
  ellipse(x, y, radius*2, radius*2); // sun's body  
}

void drawStickFigure(int x, int y) {
  stroke(0);
  strokeWeight(2);
  line(x+27, y+50, x+27, y+80);      // trunk
  line(x+17, y+68, x+37, y+68);      // arms
  line(x+27, y+80, x+17, y+95);      // leg 1
  line(x+27, y+80, x+37, y+95);      // leg 2
  image(loadImage("zim.gif"), x, y); // head
}
Parameter list pattern:
(type parameterName[, ...])
  • type - You must specify the type of the parameter
  • parameterName - You must specify the identifier to be used throughout the method to refer to the parameter.

Argument list pattern:

(argumentExpression[, ...])
  • argumentExpression - The list of argument expression must match the parameter list in number and type.

As you can see in the code, the parameters act just like variables, local to the procedure in which they are declared.

Exercise 3.d.2. Modify your agent method so that it receives x-y coordinates from its calling method and draws the agent anywhere on the output window.

Computing Return Values

The final element of the procedural abstraction provided by methods is the return value. The methods we have used so far have all had the return type of void, which indicates that the method doesn’t return any value. This simplification has served us well in that all of our methods have drawn things on the output window. There are occasions, however, when we would like to have a method that performs a calculation and returns the answer.

For example, the square root method, sqrt(), receives a numeric value from its calling method, computes the square root of that value, and returns the computed value. This call can be part of any compatible expression. The following example shows how calling sqrt() helps us compute the proper values for radiance beams on the sun (see the bolded code).

void drawSun(int x, int y, int radius) {
  stroke(250,100,10);

  // Draw the radiance beams.
  line(x-radius-5,y,x+radius+5,y);
  line(x,y-radius-5,x,y+radius+5);
  float delta = (radius+5)/sqrt(2);
  line(x-delta,y+delta,x+delta,y-delta);
  line(x-delta,y-delta,x+delta,y+delta);
  
  // Draw the fireball.
  fill(244,244,90);
  ellipse(x, y, radius*2, radius*2);
}

In the same manner, we can define our own functions to do useful computations. The following example includes a distance computation method distance(), that computes the Euclidean distance between any two points (as specified by their x-y coordinates). The program uses this distance to make the figure’s color more and more red as it approaches the location of the sun. Note that the distance() method specifies a return type of float, the type that can store a distance value, and ends with a return statement that specifies the value to return to the calling program (see the bolded code segments).

void drawStickFigure(int x, int y) {
  stroke(255-distance(x, y, sunX, sunY), 0, 0);
  strokeWeight(2);
  line(x+27, y+50, x+27, y+80);         // trunk
  line(x+17, y+68, x+37, y+68);         // arms
  line(x+27, y+80, x+17, y+95);         // leg 1
  line(x+27, y+80, x+37, y+95);         // leg 2
  tint(255, distance(x,y,sunX,sunY), 
            distance(x,y,sunX,sunY));
  image(zim, x, y);                     // head
}

float distance(float x1, float y1, float x2, float y2) {
  float dx = x1-x2;
  float dy = y1-y2;
  return sqrt(dx*dx + dy*dy);
}
The return pattern:
return expression;
  • expression - The method will return the value specified by this expression. The expression’s type must match the return type specified for the method.

Exercise 3.d.3. If you have time, modify your method to use distance in some meaningful way.

Checking In

Submit your code for the lab exercises and include a screen capture for each.