Extend PShape (again)

Hi,
For educational purpose I want to write a cleanly structured Pong game in processing.
For the Ball I’d liked to use PShape inside a class and still have access to all the PShape methods such as setVisibility() etc. Why do I want a wrapper? Because I’d like the Ball to behave like all the other objects in my game, with *.update() and *.display() methods etc.
I looked a the solution from GoToLoop. This is very smart, however, I’d like to stay in processing and rather don’t extend with *.java. Is there another pattern I can use?

Here are snippets from my main file:

void setup() {
  size(1600, 1200, P2D);
  paddle = new Paddle(width, height);
  ball = new Ball(width, height);
}
...

void draw() {
  background(255);
  paddle.update(deltaTime());  
  paddle.display();
  ball.update(deltaTime());
}

Here as example my Paddle class

class Paddle{
  int objWidth;
  int objHeight;
  color objColor;
  int screenWidth;
  int screenHeight;
  int speed;
  int maxSpeed;
  PVector position = new PVector();
 
 Paddle(int sW, int sH){
   objWidth = 300;
   objHeight = 60;
   objColor = color(100,100,50);
   screenWidth = sW;
   screenHeight = sH;
   speed = 0;
   maxSpeed = 50;
   position.x = 200;
   position.y = screenHeight - 100;
 }
 
 void display(){
   rectMode(CENTER);
   fill(objColor);
   rect(position.x, position.y, objWidth, objHeight);
 }
 
 void moveLeft(){
   speed = -maxSpeed;
 }
 
 void moveRight(){
   speed = maxSpeed;
 }
 
 void stop(){
   speed = 0; 
 } 
 

 void update(float deltaTime){
   int halfObjWidth = objWidth/2;
   position.x +=  speed;
   //keep in screen
   if(position.x < 0 + halfObjWidth){ position.x = 0 + halfObjWidth; }
   if(position.x > screenWidth - halfObjWidth ){ position.x = screenWidth - halfObjWidth;}
 } 
}

So, as stated above, my goal is to structure the Ball class in a similar way, but still using PShape methods.

1 Like

You could have a PSHape inside the ball class

1 Like

Here is the solution, as provided by KII
Relevant code snippets:

My main file:

Paddle paddle;
Ball ball; // the class is in a separate tab

void setup() {
  size(1600, 1200, P2D);
  paddle = new Paddle(width, height);
   ball = new Ball(width, height, 100); // 3rd param is ball diameter
}
...
void draw() {
  background(255);
  paddle.update(deltaTime());  
  paddle.display();
  ball.update(deltaTime());  
  ball.display();
}
...

Here my Ball class (abridged version)

class Ball{
  int diam, screenWidth, screenHeight;
  color objColor;
  PVector speed = new PVector();
  PVector position = new PVector();
  PShape ballshape;
  
  Ball(int _w, int _h, int _diam){
   diam = _diam;
   screenWidth = _w;
   screenHeight = _h;
   speed.set(0, 0);
   position.set(100, 100);
   objColor = color(255, 0, 0);
   ballshape = createShape(ELLIPSE, position.x, position.y, diam, diam);
   ballshape.setStrokeWeight(5.0);
   ballshape.setStroke(color(0,150,55));
   ballshape.setFill(objColor);
  }
  
  void display(){
   shape(ballshape);
  }
  
  void update(){
    // make it move
  }
}

I haven’t included the update method yet. I just will reply to my own post, in case someone follows.

for some reason I can’t use createShape() in my class.


class Ball {
  PShape ballshape;
  int x, y, diam;
  Ball(int _x, int _y, int _diam ) {
    x=_x;
    y=_y;
    diam=_diam;
    ballshape = createShape(ELLIPSE, x, y, diam, diam);
  }
  
  void display() {
    shape(ballshape);
  }
}

Ball ball;
void setup() {
  size(300, 300);
  ball = new Ball(width/2, height/2, 100);
  ball.ballshape.setFill(color(200,0,0));
}
void draw() {
  background(200, 200, 0);
  ball.display();
}


works here, can you try?

3 Likes

Great, that works! I will update my code for reference. Chapeau

2 Likes

Thanks for sharing these solutions!

Just a note for others in the future – the thread is called “Extend PShape”, but the solution(s) were to encapsulate PShape (put it inside a class) rather than extend it (https://processing.org/reference/extends.html). Encapsulating is usually the better way to go.

1 Like

I encountered the same problem and could not immediately find a solution. I had to look into it, and this is what I came up with.

You can easily extend a PShape, but you shall provide a PGraphics instance of your PApplet to constructor and then pass it to the superclass. So you have to call PShape(PGraphics g, int family) superclass constructor. A quick example:

Shape myshape;

void setup(){        
    size(400, 400);
    // here is the fun: 'this' is actual PApplet, 
    // and 'g' is a field with PGraphics instance
    myshape = new Shape(this.g);          
    myshape.beginShape();
    myshape.vertex(0,  0);
    myshape.vertex(100,0);
    myshape.vertex(100,100);
    myshape.vertex(0,  100);
    myshape.fill(200, 20, 20);
    myshape.endShape(CLOSE);
}

void draw(){
    shape(myshape, 10,10);
}

class Shape extends PShape{
    Shape(PGraphics g){        
        super(g, GEOMETRY);        
    }
    
    // and here comes all your weird stuff you want to add 
}

UPDATE: This will work for the standard renderer. But if you want to use something else, you’ll have to create your Shape objects in a completely different way.