This is a perfect opportunity to learn interfaces. You want to be able to select enemies, items, obstacles, … whatever. In a level editor, you could do this with a Tile object, but using class inheritance with extends
is a real pain. Instead, use an interface with implements
.
- Create a simple infobox. What does it need to know about any clicked thing in your editor?
class InfoBox {
Info selected;
void select(Info selected) {
this.selected = selected;
}
void render() {
text("INFOBOX", 5, 10);
if (selected != null) {
text(selected.getName(), 5, 20);
text(str(selected.getX()) + ", " + str(selected.getY()), 5, 30);
}
}
}
Okay, so it wants the x, y, and name of any Info object. What is an info object? It is any object – of any class – that promises to answer those methods by implementing the Info interface.
interface Info {
String getName();
float getX();
float getY();
}
Great, now that we have defined it we can define any class that implements Info
. This means it must contain the promised methods – getName(), getX(), and getY(). Because those are promised, InfoBox can use anything that implements Info
and know that it will have those methods – no matter what class it is.
class Square implements Info {
float x, y, s;
String name;
Square(float x, float y, float s, String name) {
this.x = x;
this.y = y;
this.s = s;
this.name = name;
}
String getName() {
return name;
}
float getX() {
return x;
}
float getY() {
return y;
}
void render() {
rect(x, y, s, s);
}
}
Okay, let’s put the two classes and one interface them together in a quick sketch and run it.
void setup(){
Square sqr = new Square(50, 50, 40, "squarename");
InfoBox ibx = new InfoBox();
ibx.select(sqr);
sqr.render();
ibx.render();
}

As you can see, we selected the Square, and – because it implements Info – its data was displayed by the InfoBox. We can create a bunch of other classes – either totally unrelated, or extended from our Square class – and as long each one implements Info
then we can ibx.select(foo) to show its data.
How do we make this interactive with the mouse? We click the mouse, then check to see if we hit an object. If we did, we pass it on to ibx.select().
if (sqr.hit(mouseX, mouseY)) ibx.select(sqr);
But in order for that to work, we need to add a boolean hit(float x, float y)
method to our class. It will tell us the answer using collision detection.
boolean hit(float mx, float my) {
if (mx >= x && mx <= x + s && my >= y && my <= y + s) {
return true;
}
return false;
}
Okay, to wrap it all up, let’s make an interactive sketch with two different class objects, a Square and a Bounce (which moves). When the mouse is pressed we will check them with collision detection and, if there is a hit, we will select that object with the infobox.
InfoBox ibx = new InfoBox();
Square sqr = new Square(60, 120, 60, "squarename");
Bounce bnc = new Bounce(100, 60, 80, "bouncename");
void setup() {
size(200, 200);
}
void draw() {
background(128);
sqr.render();
bnc.render();
ibx.render();
if (mousePressed) {
// reset infobox and detect
ibx.select(null);
if (sqr.hit(mouseX, mouseY)) ibx.select(sqr);
if (bnc.hit(mouseX, mouseY)) ibx.select(bnc);
}
}
interface Info {
String getName();
float getX();
float getY();
}
class InfoBox {
Info selected;
void select(Info selected) {
this.selected = selected;
}
void render() {
text("INFOBOX", 5, 10);
if (selected != null) {
text(selected.getName(), 5, 20);
text(str(selected.getX()) + ", " + str(selected.getY()), 5, 30);
}
}
}
class Square implements Info {
float x, y, s;
String name;
Square(float x, float y, float s, String name) {
this.x = x;
this.y = y;
this.s = s;
this.name = name;
}
String getName() {
return name;
}
float getX() {
return x;
}
float getY() {
return y;
}
// point-rect collision detection
// see http://www.jeffreythompson.org/collision-detection/point-rect.php
boolean hit(float mx, float my) {
if (mx >= x && mx <= x + s && my >= y && my <= y + s) {
return true;
}
return false;
}
void render() {
rect(x, y, s, s);
}
}
class Bounce extends Square {
int dy;
Bounce(float x, float y, float s, String name) {
super(x, y, s, name);
this.dy = 1;
}
String getName() {
return name;
}
float getX() {
return x;
}
float getY() {
return y;
}
@Override
void render() {
super.render() ;
y+=dy;
if (y<0||y+s>width) dy*=-1;
}
}
