OOP Approach in Processing

edited March 2017 in Questions about Code

Hello together,

I'm new here and I have a question about writing an OOP library for Processing. I played around with Processing in the last few days and I'm pretty convinced by it and its IDE. A problem I encounter still, is that there is no real object oriented approach. Let me give you an example: If I want to draw a point, I can simply call

point(30,30);

I could also write my own class like that:

class Point() {
  float xPos;
  float yPos;
  Point(float x, float y) {
    xPos = x;
    yPos = y;
    point(x,y);
  }
}

and I could add getters, setters or even a draw method that calls point(x,y) only after calling the draw-method itself. So by now everything is fine. What I'd like to to is create a library, in which I create such classes and can use them straight away in the Processing IDE without having to declare them everytime.

Example:

Point p = new Point(30,30);

This line should then draw a point at 30, 30;

My problem is: In the class declaration above I use functions of processing.core if I'm not completely wrong. Can I use these functions in the Java code I have to write in Eclipse when writing a library like that? I don't want to reimplement all these functions by reading through all the Java Docs at http://processing.github.io/processing-javadocs/core/ .

As far as I know I can call all of these functions on the PApplet object in Java, e.g.

PApplet parent;
parent.point(30,30);

When I'm trying to model my class Point in Eclipse in a seperate class now, I guess I need to specify the PApplet, so I can call the point function on it. Can anyone tell me how to do that?

package template.library;
import processing.core.*;

public class Point {
    float xPos;
    float yPos;
    PApplet parent;

    Point() {
        float xPos;
        float yPos;
        // I want to set parent = ... here
        // I want to call point(x, y) here
    }
}

My library class from the Wiki looks like that:

package template.library;

import processing.core.*;

public class BasicLibrary {
  PApplet parent;

  public BasicLibrary(PApplet parent) {
    this.parent = parent;
    parent.registerMethod("dispose", this);

  }

  public void dispose() {
    // Anything in here will be called automatically when 
    // the parent sketch shuts down. For instance, this might
    // shut down a thread used by this library.
  }
}
Tagged:

Answers

  • edited March 2017
    package template.library;
    import processing.core.*;
    
    public class Point {
        float xPos;
        float yPos;
        PApplet parent;
    
        //note the "public" declaration 
        public Point(PApplet p) {
            float xPos;
            float yPos;
            parent = p;//done
            // I want to set parent = ... here
            // I want to call point(x, y) here
        }
    }
    
  • You also need to be careful where you use any drawing function. You do know about the fact that you can only draw things inside setup() and draw() and mouse/key events?
    Or more technically speaking, only in between beginDraw() and endDraw() called on the graphics object (or whatever it is supposed to be called) g (a PGraphics) of the PApplet class.

  • edited March 2017

    @rikojir --

    So, if I'm understanding correctly, a drawing in Processing using this library would be represented by a collection of Point, Line, Ellipse, and Rect objects etc. How would you then keep track of them and actually render a mixed collection of such objects to the screen? Would they be added as a list to a container object, e.g. "OOPGraphics"?

    Currently the way that you programmatically encode point, line, polygon and other shape data as coordinates (rather than a pixel raster) into an object and then render it is PShape:

    loadShape() can also be used for loading scalable vector graphics (SVG) and object files (OBJ) into PShapes.

    Abstraction is an interesting approach, and can have a lot of power. Note however that some object based approaches to drawing can have very serious performance issues.

    For example, this simple sketch:

    void draw(){
      stroke(frameCount%255);
      strokeWeight(frameCount%5);
      line(mouseX-5,mouseY-5,mouseX+5,mouseY+5);
    }
    

    ...if reimplemented using a Line object approach would create an unbounded number of new Line objects -- about 60 new objects per second, 3600 new objects per minute, 216000 per hour -- until it slowed and eventually crashed. Each Line object would also have to include its complete style state -- stroke color, line weight, etc. etc.... By contrast, the normal raster sketch can run forever with constant memory usage.

  • @jeremydouglass That really depends on the programmer's approach. It's fairly easy to use a PGraphics in a class for this purpose, and you know that. Nonetheless, it is unwise to create a class for something as stupidly simple as that. Also note that using an OOP (more like, semi-OOP) approach is nescessary in almost any complex sketch. The performance issue is of less consequence than the readability issue - there's no point in creating classes if all you ever need is a single instance of it, and certainly no point in creating new classes when the code is simpler without them. That, I believe, is the point you were trying to get across.

  • Hey guys, thanks for your help.

    I finally got it to work like I want by using the github tutorial at

    https://github.com/processing/processing-library-template

    and the Processing in Eclipse tutorial at

    https://processing.org/tutorials/eclipse/

    I still have some questions I'm wondering about: I can now instantiate my own classes in the setup or draw function, but I can't access the variables instantiated in the setup function inside the draw function. Why is that and is there a workaround so that I don't have to write an animation / game loop by myself?

    The other question I was wondering about is: Is there a possibility I can instantiate my classes without passing this in the constructor everytime as the parent PApplet? You can see an example class below, whose constructor needs the PApplet as the parameter. It would be syntactic sugar if I could just call the constructor without that third parameter.

    `import processing.core.PApplet;

    class Point { float xPos; float yPos; PApplet sketch;

      Point(float x, float y, PApplet sketch) {
        xPos = x;
        yPos = y;
        this.sketch = sketch;
      }
    
      void drawMe(){
        sketch.point(xPos, yPos);
      }
    

    }`

  • edited March 2017

    Nope not possible. However, it is convention that the PApplet is the first parameter of the constructor. Also, name the variable inside the class as p, which is a short name, instead of sketch, which is long.

Sign In or Register to comment.