17. PShape Objects

The Processing website has a good tutorial about PShape objects, so it’s advisable that you review that tutorial in order to have a basic understanding of PShape objects. The idea is that PShape allows us to create geometric primitives that we can use as objects. There are a variety of ways to use PShape, let’s start by creating a Star class.

17.1. Stars

In the Processing PShape tutorial, the authors create a Star class, and they use the createShape(), beginShape() and endShape() functions, along with a list of vertices in the Star constructor to create the geometry for the Star object.

However, they go on to describe a subtle concept; the idea of creating the star geometry one time in the main setup() function, and then passing that PShape object as an input parameter to the Star constructor. This can cut down on rendering costs, where Processing can essentially ‘memorize’ the geometry of the single PShape object, rather than having to render the geometry for each one.

For now, let’s ignore these suggestions, and we’ll create the geometry in the Star constructor function. Below are snippets of code for the Star class, where it inherits from the Drop class. For our current version of the RainDrop game, the Drop class does not inherit from any other class:

class Star extends Drop{
        PShape s;

        Star(float _x){  // constructor lets us set the x-position
                super(_x);  // call the Drop constructor as the first line of code

        // First create the shape
                s = createShape();
                s.beginShape();
                // You can set fill and stroke
                s.fill(102);
                s.stroke(255);
                s.strokeWeight(2);
                // Here, we are hardcoding a series of vertices
                s.vertex(0, -50);
                s.vertex(14, -20);
                s.vertex(47, -15);
                s.vertex(23, 7);
                s.vertex(29, 40);
                s.vertex(0, 25);
                s.vertex(-29, 40);
                s.vertex(-23, 7);
                s.vertex(-47, -15);
                s.vertex(-14, -20);
                s.endShape(CLOSE);
                }
        }

The code above is taken directly from the Processing PShape Tutorial, except that we’ve made the Star class a child class of the Drop class.

Because the Star class inherits from the Drop class, we don’t need to explicitly declare most of the instance variables. However, notice that in the first line of code in the constructor that we’re calling super(), this is the Drop class default constructor.

Shiffman notes in the PShape Tutorial that by default, a PShape geometry is defined relative to the canvas origin (0,0). Therefore, he notes that it’s we’ll almost always use pushMatrix(), popMatrix(), and translate() in order to locate our PShape objects on the canvas.

So, to write a display() method for our Star, we need to remember to translate the origin of the canvas to the x,y coordinates of our shape before displaying using the shape() function. Here’s a display method that also lets us set the color of the PShape object:

       void display(){
              pushMatrix();
              translate(x,y);    //x,y were given default settings
              s.setFill(color(0,200,127));   //we can change the fill color here if we want
              shape(s,0,0);
              popMatrix();
}

If we want to determine where the center of the PShape is, what code can we write? The easiest thing to do is to note that we’ve translated the origin to the x,y position, so if we create an ellipse at (0,0) then we’ll be able to observe where the center is.

17.2. PShape using SVG Image File

Another way that we can use PShape is to load an .svg file. There are may sources for .svg files, for this project, I’m using an svg file from The Noun Project. This site has lots of .svg icon files that are free for use if you provide proper attribution for the designer of the .svg file. I’m using an .svg file of a seahorse designed by: Agne Alesiute at http://thenounproject.com/ . I am also using an .svg file of a jellyfish designed by: Eli Ratner. Below is the jellyfish .svg file. We can see that the image has a text component where the designer’s name is listed. While we need to provide credit to the designers in our programs, we need to remove that text in order for this .svg file to work in our programs.

images/jellyfish.png

17.3. Edit SVG Files

There are 2 ways that we can edit .svg files. Since .svg files are a standardized data format file that list vertices for geometry and font elements, we can open the files in either a vector software system like Adobe Illustrator, or Inkscape. We can also open the files in any text editor like notePad or textEdit. If we open the file in a text editor, then we need to go to the bottom of the file and find the <text> </text> content section. We need to carefully select this content from the opening tag to the closing tag, and the delete that content, being careful not to delete anything else. In addition, if we look at the .svg file, we can determine the width and height of the object, in addition to other image details. Below is the .svg code for the image above:

<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" id="Layer_1" x="0px" y="0px" width="100px" height="100px" viewBox="5.0 -10.0 100.0 135.0" enable-background="new 0 0 100 100" xml:space="preserve">
<g id="Layer_1_1_">
<g id="Your_Icon">
</g>
</g>
<path fill="#000000" d="M50,8.806c-15.769,0-28.552,10.665-28.552,23.821c0,3.51,1.188,7.938,2.544,9.844  c0.215,0.48,1.37,0.916,3.2,1.295c-0.025,0.049-0.054,0.096-0.078,0.146l-0.67,1.557c-0.452,1.051-0.883,2.141-1.193,3.301  c-0.314,1.153-0.508,2.403-0.34,3.685c0.023,0.174,0.042,0.287,0.088,0.51c0.037,0.138,0.062,0.258,0.134,0.459  c0.124,0.367,0.275,0.639,0.445,0.92c0.342,0.547,0.73,0.984,1.053,1.406c0.324,0.414,0.571,0.83,0.656,1.232  c0.099,0.525,0.104,1.002,0.039,1.539c-0.128,1.053-0.515,2.117-0.831,3.217c-0.311,1.098-0.532,2.283-0.34,3.445  c0.022,0.146,0.055,0.299,0.093,0.43c0.048,0.152,0.104,0.293,0.171,0.426c0.132,0.268,0.303,0.5,0.442,0.738  c0.297,0.465,0.347,1.051-0.025,1.469c-0.112,0.127-0.169,0.305-0.139,0.484c0.054,0.316,0.354,0.531,0.672,0.479  c0.317-0.055,0.531-0.355,0.478-0.674l-0.023-0.135c-0.244-1.443-1.247-2.176-1.298-3.266c-0.121-1.09,0.156-2.172,0.551-3.205  c0.381-1.045,0.893-2.068,1.169-3.242c0.139-0.572,0.197-1.236,0.146-1.83c-0.069-0.727-0.384-1.326-0.698-1.836  c-0.317-0.506-0.635-0.953-0.848-1.393c-0.103-0.209-0.198-0.451-0.233-0.625c-0.023-0.066-0.046-0.225-0.068-0.361l-0.02-0.33  c-0.031-0.975,0.224-1.984,0.56-2.982c0.351-0.999,0.807-1.99,1.28-2.996l0.733-1.523c0.092-0.209,0.162-0.437,0.208-0.675  c0.696,0.104,1.443,0.204,2.242,0.296c-0.135,0.273-0.256,0.554-0.383,0.822c-0.45,1.025-0.804,2.096-1.046,3.194  c-0.495,2.193-0.506,4.501-0.041,6.692c0.454,2.189,1.385,4.176,2.161,6.059c0.795,1.883,1.358,3.75,1.363,5.713  c0.034,1.969-0.49,3.992-0.505,6.205c-0.005,1.096,0.157,2.219,0.52,3.258c0.386,1.074,0.951,1.979,1.467,2.873  c0.517,0.891,0.98,1.777,1.179,2.736c0.211,0.977,0.242,1.994,0.178,3.012c-0.066,1.021-0.227,2.043-0.399,3.068  c-0.17,1.029-0.387,2.043-0.772,3.066c-0.028,0.076-0.042,0.164-0.031,0.25c0.035,0.281,0.292,0.482,0.575,0.447  s0.483-0.293,0.448-0.576c-0.129-1.043,0.063-2.074,0.283-3.092c0.218-1.02,0.427-2.051,0.543-3.107  c0.113-1.055,0.13-2.141-0.052-3.213c-0.179-1.102-0.658-2.109-1.143-3.035c-0.481-0.93-0.994-1.83-1.251-2.744  c-0.267-0.947-0.348-1.924-0.286-2.908c0.117-1.961,0.772-3.998,0.879-6.209c0.126-2.225-0.436-4.461-1.157-6.443  c-0.718-1.998-1.429-3.875-1.772-5.787c-0.336-1.898-0.242-3.848,0.202-5.713c0.224-0.933,0.544-1.844,0.948-2.719  c0.23-0.547,0.558-1.003,0.732-1.58c1.026,0.092,2.106,0.175,3.227,0.25c-0.262,0.611-0.484,1.242-0.658,1.895  c-0.441,1.578-0.768,3.236-0.766,4.949c-0.037,1.738,0.485,3.504,1.275,4.961c0.774,1.482,1.72,2.768,2.525,4.086  c1.672,2.559,2.362,5.645,2.853,8.748l0.67,4.695c0.121,0.785,0.253,1.568,0.413,2.348c0.162,0.781,0.3,1.555,0.221,2.41  c-0.011,0.123,0.02,0.258,0.098,0.365c0.172,0.24,0.506,0.295,0.746,0.123c0.24-0.172,0.295-0.506,0.124-0.746  c-0.483-0.674-0.673-1.447-0.79-2.223c-0.12-0.777-0.212-1.559-0.293-2.344l-0.437-4.725c-0.169-1.58-0.344-3.174-0.698-4.752  c-0.335-1.578-0.896-3.172-1.678-4.598c-0.753-1.434-1.596-2.768-2.195-4.139c-0.598-1.377-0.956-2.746-0.879-4.183  c0.05-1.455,0.385-2.921,0.847-4.369c0.259-0.776,0.526-1.56,0.729-2.378c1.299,0.07,2.64,0.127,4.007,0.173  c-0.416,1.857-0.692,3.988-0.327,6.071c0.182,1.062,0.509,2.08,0.909,3.037c0.42,0.977,0.835,1.805,1.305,2.68  c0.921,1.719,1.863,3.326,2.479,5.023c0.649,1.707,0.882,3.479,1.122,5.43c0.256,1.912,0.568,3.854,1.127,5.742  c0.548,1.893,1.389,3.686,2.41,5.334c0.499,0.83,1.057,1.604,1.355,2.473c0.313,0.863,0.312,1.848-0.089,2.738  c-0.045,0.1-0.06,0.215-0.034,0.332c0.063,0.283,0.346,0.463,0.631,0.4c0.285-0.064,0.465-0.346,0.401-0.631l-0.002-0.008  c-0.226-1.012-0.211-1.988-0.473-2.967c-0.27-0.977-0.799-1.814-1.231-2.656c-0.892-1.678-1.578-3.441-1.98-5.27  c-0.406-1.832-0.515-3.719-0.607-5.625c-0.051-0.951-0.054-1.906-0.158-2.922c-0.098-1-0.29-2.002-0.563-2.98  c-0.547-1.969-1.427-3.762-2.183-5.49c-0.364-0.852-0.783-1.754-1.073-2.561c-0.299-0.828-0.513-1.664-0.622-2.499  c-0.256-1.67,0.034-3.352,0.443-5.187c0.025-0.127,0.048-0.258,0.072-0.388c2.275,0.045,4.588,0.056,6.87,0.028  c-0.04,0.302-0.072,0.607-0.093,0.919c-0.108,1.711-0.159,3.514,0.156,5.335c0.316,1.849,1.002,3.542,1.729,5.062  c0.713,1.535,1.454,2.959,1.907,4.418c1.034,2.854,0.114,6.096-0.254,9.496c-0.166,1.703-0.111,3.498,0.511,5.166  c0.3,0.826,0.822,1.545,1.228,2.242c0.411,0.699,0.682,1.465,0.567,2.211c-0.009,0.055-0.009,0.115,0.003,0.174  c0.054,0.277,0.321,0.457,0.598,0.404c0.276-0.055,0.457-0.322,0.403-0.6l-0.006-0.027c-0.367-1.887-1.606-3.17-2.023-4.684  c-0.444-1.506-0.374-3.137-0.056-4.713c0.302-1.59,0.822-3.168,1.17-4.865c0.173-0.834,0.307-1.748,0.334-2.639  c0.025-0.92-0.065-1.842-0.248-2.725c-0.356-1.777-1.015-3.398-1.588-4.928c-0.567-1.539-1.067-2.991-1.229-4.448  c-0.176-1.478-0.141-3.026,0.012-4.629c0.036-0.402,0.066-0.814,0.078-1.235c1.143-0.033,2.269-0.076,3.368-0.13  c0.006,0.46,0.045,0.915,0.108,1.377L60.32,49.9c0.2,2.252,0.441,4.522,0.707,6.797c0.142,1.139,0.301,2.275,0.497,3.41  c0.211,1.141,0.434,2.236,0.571,3.355c0.146,1.119,0.238,2.25,0.3,3.381c0.037,1.131,0.194,2.273-0.289,3.395  c-0.053,0.123-0.061,0.268-0.01,0.402c0.104,0.279,0.415,0.42,0.694,0.316c0.278-0.105,0.42-0.416,0.315-0.693  c-0.433-1.154-0.268-2.285-0.271-3.43c0.004-1.141-0.008-2.283-0.047-3.43c-0.049-1.15-0.146-2.307-0.227-3.42  c-0.069-1.125-0.098-2.254-0.118-3.385c-0.046-2.264,0.004-4.539-0.073-6.826c-0.023-1.145-0.103-2.291-0.178-3.441  c-0.023-0.429-0.079-0.863-0.163-1.293c1.365-0.088,2.676-0.195,3.914-0.32c-0.368,0.834-0.695,1.669-0.978,2.616  c-0.164,0.583-0.285,1.224-0.278,1.926c0,0.707,0.223,1.421,0.49,1.968c0.534,1.082,1.1,1.969,1.51,2.924  c0.409,0.953,0.674,1.99,0.839,3.059c0.149,1.07,0.212,2.168,0.215,3.27c-0.006,1.104,0.094,2.207-0.367,3.311  c-0.051,0.121-0.058,0.266-0.007,0.4c0.105,0.277,0.416,0.418,0.694,0.312s0.418-0.418,0.312-0.695  c-0.42-1.105-0.197-2.207-0.127-3.311c0.077-1.105,0.168-2.221,0.15-3.354c-0.001-1.133-0.109-2.289-0.404-3.432  c-0.302-1.141-0.793-2.203-1.104-3.162c-0.147-0.475-0.193-0.855-0.167-1.255c0.03-0.404,0.158-0.852,0.32-1.321  c0.319-0.93,0.811-1.945,1.224-2.918c0.097-0.216,0.194-0.432,0.291-0.648c1.137-0.157,2.181-0.334,3.113-0.534  c-0.216,0.735-0.35,1.503-0.392,2.288c-0.107,1.377,0.165,2.771,0.621,4.012c0.437,1.253,0.993,2.424,1.463,3.631  c0.231,0.604,0.486,1.203,0.67,1.807c0.193,0.592,0.277,1.275-0.183,1.822c-0.138,0.162-0.183,0.395-0.098,0.605  c0.122,0.307,0.47,0.455,0.775,0.332c0.306-0.121,0.455-0.469,0.332-0.775l-0.018-0.043c-0.297-0.742-0.341-1.369-0.487-2.027  c-0.157-0.646-0.378-1.254-0.574-1.871c-0.399-1.233-0.785-2.479-1.074-3.713c-0.282-1.239-0.378-2.457-0.21-3.664  c0.135-0.914,0.391-1.809,0.59-2.748c1.753-0.486,2.928-1.075,3.296-1.781c1.112-2.063,2.168-5.891,2.168-9.122  C78.552,19.471,65.77,8.806,50,8.806z"/>
<text x="0.0" y="117.5" font-size="5.0" font-weight="bold" font-family="Helvetica Neue, Helvetica, Arial-Unicode, Arial, Sans-serif" fill="#000000">Created by Eli Ratner</text><text x="0.0" y="122.5" font-size="5.0" font-weight="bold" font-family="Helvetica Neue, Helvetica, Arial-Unicode, Arial, Sans-serif" fill="#000000">from the Noun Project</text>
</svg>

So, delete the <text> </text> line in the code above, however, make sure not to delete the closing </svg> tag. Also, in the first line of code, if the view box is significantly different than the width and height, which are usually 100px by 100px, then this can cause problems. You will probably want to pick a different image.

In order to use an svg file for a PShape object, it’s necessary to use the following syntax in order to load the image.

  1. The .svg file must be put inside a folder named: data, inside your sketch folder
  2. PShape s= loadShape(“seaHorse2.svg”); // this loads the image
  3. shape(s, x, y, width, height) ; //this is used to display the svg.

17.4. SVG Origin

With SVG files, the x,y position refers to the top left corner of the svg file. If you open the svg file in a text editor, you can read the width and height dimensions of the svg. Those can help us when we try to determine the bounding box for collision detection. Below is the display function that is overriding the default style of the svg to allow us to reset the fill color. Below that I’ve added a rectangle to show the bounding box. Since we’re using translate(x,y) so that we’ve moved the canvas origin to the svg corner point, then we’ll draw the rectangle at (0,0).:

void display(){
        pushMatrix();
        translate(x,y);
        s.disableStyle();  // Ignore the colors in the SVG
        fill(c);    // Set the SVG fill to myColor
        stroke(55);          // Set the SVG fill to gray
        shape(s,0,0,sWidth,sHeight);
        noFill();
        rect(0,0,sWidth,sHeight);  //bounding box
        popMatrix();
        }

17.5. Bounding Box

In order to determine if we have a collision with the paddle, we need to define a bounding box for our PShape object that we’ll use to determine contact with the Paddle object. Shiffman’s game used circular objects, and determining intersection with circular objects is a bit easier than it is with rectangular objects. As noted above, we’ve translated the origin to the x,y position of our .svg file, this corresponds to the upper-upper left corner of the shape.