Processing with objects

The idea

In this lab we are going to design an class representing a pumpkin and use it with the Processing PApplet to design a spooky application. We are not going to use the Processing IDE in this assignment, though I don’t see any reason why this could not be done with Processing by a determined person.

A couple of Processing caveats

Processing programs are transformed into Java before being interpreted by the Java Virtual Machine. (Interpretation by JavaScript is also possible.) However, Processing IDE does a few significant syntactic transformations before passing the code on to Java which surprise experienced programmers.

In Java the literal 3.14 is of type double. But, when the Processing IDE sees 3.14, it transforms 3.14 into a float, in particular 3.14f . Many of the arguments to PApplet methods, such as ellipse, are float’s. In the Processing IDE you can invoke the ellipse method as ellipse(5.0, 5.0, 5.0, 5.0) ; but, if you try this in Java, the compiler will report a compilation error because you are passing a double argument to a float parameter. However, ellipse(5.0f, 5.0f, 5.0f, 5.0f) or even ellipse(5, 5, 5, 5) work fine.

Processing allows literals, such as #FFA500, to be used as colors. While this syntax is familiar to HTML coders, it is not part of the Java standard, In Java, you need to use 0xFFFFA500 in this situation. (The extra FF is the alpha value for the color.) By the way, Processing colors are really just 32-bit int values.

Processing allows some type names, such as int, to be used a prefix operators for converting data types. This means that int(3.14) is 3 in Processing. In Java, int(3.14) is a syntax error. You need to use the more traditional C/C++/Java casting operators, for example (int)(3.14).

Finally, be warned that the PApplet class has lots of public fields and that you will be using them in your program. Because public fields are discouraged in object-oriented programming, you may find this to be a little disconcerting.

Getting started

In this section, we show you how to get Java working with Processing libraries.

Getting the library

Before starting you will need to download the Processing system to get a copy of the Processing library. Be sure to remember where you installed Processing.

This step should not to be done in the RRO223 lab.

Starting the sketch

Next, you need a class that starts the Processing “sketch.” The main method of this class must call the main method of the PApplet class with the name of your sketch. I suggest you accomplish this with a class that performs only this single activity, as shown in the following example:

package edu.unca.cs.csci202;

import processing.core.* ;
// add core.java in the core/library subdirectory of processing

public class Boo {
    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        PApplet.main(new String[]{"edu.unca.cs.csci202.Halloween"}) ;
    }
}

NetBeans will complain that it has no knowledge of the processing classes. To fix this problem go to the Properties tab for NetBeans and right-click on your project’s name. This will raise a Projects window. Go to the Libraries category and add a jar file core.jar that contains the needed Processing libraries. This library file is located in the core/library subdirectory of your Processing distribution. If you want to distribute your system, you should copy this library into your project’s src folder.

Writing the sketch

Your sketch is similar to an ordinary Processing sketch but it must follow the class syntax of Java, and it must extend PApplet. Also, the name of your class, prefixed with its package name, must match the String passed to PApplet.main in your launcher program. In our preceding example that was "edu.unca.cs.csci202.Halloween" .

Here is a class that satisfies these requirements.

package edu.unca.cs.csci202;

import processing.core.* ;

public class Halloween extends PApplet{
    int pumpkinXPosition ; 
    
    @Override
    public void setup() {
        size(800, 600) ;
        pumpkinXPosition = 0 ;
    }
    
    @Override
    public void draw() {
        clear() ;
        fill(255, 165, 0) ;                   // fill(0xFFFFA500) ;
        ++pumpkinXPosition ;
        if (pumpkinXPosition==width) {        // width is a public field of PApplet
            pumpkinXPosition=0 ;
        }
        ellipse(pumpkinXPosition, height/2, width/8, height/8) ;
    }
}

Use the two programs show above along with the core.jar file from the Processing distribution to run the sketch from NetBeans. On the RRO 223 workstations, the jar file is located at /opt/lib/processing-2.0.1/core/library/core.jar .

Also, take a look at the documentation for the Processing PApplet class. That is a lot of methods and fields.

Doing OOP

Let’s get you started in adding some objects to your program. Do this by creating a Pumpkin class that represents a pumpkin. The Pumpkin class should “know” its position and size. Later it may even learn a little about its eye color and the direction in which it is moving.

Once the Pumpkin knows who to keep up with itself, we can create many Pumpkin’s and leave the details of being a pumpkin to a Pumpkin.

Making a model of the pumpkin

Create a new class called Pumpkin in your project. At a minimum, do the following:

If you want to make absoultely sure you have the right methods; you can start with an outline of a Pumpkin class, or you can place a ProcessingDrawable2D interface in your project and add implements ProcessingDrawable2D to the header of your own Pumpkin class.

Complete the accessor and mutator methods. Postpone work on the draw method.

It would also be a good idea to add some constructors.

Now the class provides a model of a pumpkin.

Using the pumpkin model

The ultimate result of this next effort will look unimpressive, but it will start the objectification of our pumpkin: We are going to use an instance of the Pumpkin class in our Halloween sketch class.

Declare a single Pumpkin object in your Halloween class. In the setup method initialize your Pumpkin object by calling the appropriate mutator methods of the Pumpkin class.

In the draw method of Halloween, read and update the x position of your Pumpkin using the getX and setX methods. You will need to use the accessor methods of Pumpkin to generate arguments to PApplet’s ellipse method.

Run your updated code. It should look the same.

Making and using a view of the pumpkin

It would be very tedious to call ellipse with all those arguments every time we need to draw a pumpkin. We are going to give Pumpkin the responsibility of drawing itself. It particular, we are going to make the draw method provide a view of the pumpkin.

In a real application of the Model-View-Controller (MVC) paradigm, the view would be handled by a separate class; but that just seems a big too much for our pumpkin. We are just going to assign this task to the draw method of Pumpkin.

There is one twist to this. Normally, Processing sketches are extensions of the PApplet class. This means that a call such as fill(255, 165, 0) is really an invocation of a method of the PApplet superclass, in particular super.fill(255, 165, 0).

Halloween is a subclass of PApplet, but Pumpkin is not; so super.fill is not available. This means you’ll need method calls like pa.fill(255, 165, 0) inside your Pumpkin draw method.

Complete the draw method of Pumpkin so that it invokes PApplet methods to draw a pumpkin. Modify the draw method of Halloween to call the draw method of Pumpkin. At this point, there should be no fill or ellipse calls in Halloween. Your pumpkin needs to be nothing more than a single oval.

Getting fancy

Improving the view

Once the draw of Pumpkin is working good enough to show a orange oval, add some more features to your pumpkin such as a pair of eyes or a nose or a disturbing grin.

More pumpkins

Create an array of several pumpkins inside the Halloween class. Have the draw method of Halloween call the draw method of Pumpkin for each element of the array. This is a natural place to use the enhanced for loop.

Saving the environment

Your program is probably making many side effects on PApplet’s environment. It is certainly changing the fill color, and it may be modifying more obscure settings like the color mode and ellipse mode.

I started my draw method with a few statements to save these settings.

    public void draw(processing.core.PApplet pa) {
        int oldColorMode = pa.g.colorMode ;
        int oldEllipseMode = pa.g.ellipseMode ;
        boolean oldFill = pa.g.fill ;
        int oldFillColor = pa.g.fillColor ;

And I ended my draw with a few statements to restore these settings.

        pa.g.fillColor = oldFillColor ;
        pa.g.fill = oldFill ;
        pa.g.ellipseMode = oldEllipseMode ;
        pa.g.colorMode = oldColorMode ;
    }

Perhaps this is excessive, but it doesn’t do any harm.

Swapping pumpkins

If you have created the suggested set of methods for the pumpkin, you should be able to drop your Pumpkin into someone else’s project.

You can try this, but it would be easier if everyone was extending a common class or interface so that we could be displaying several different pumpkins at the same time. That sounds like the next lab to me.

Adding control

Right now our MVC implementation doesn’t have much C (control). We could ask the Halloween class to provide control by adding variables to keep up with, for example, trajectory information to each Pumpkin. Alternatively, we could add trajectory to each pumpkin. This might (or should) be done in new classes of pumpkins created by extension or aggregation.

You can think start working on this today if time permits.