Hello. With Java 8 came a new and useful feature for interfaces - default methods. For those of you who don’t know, this is what they look like:
public interface Test {
default void test() {
System.out.println("Testing");
}
}
Simply put, they allow for methods in interfaces that are not static (i.e. that are inheritable) to write code. I have been using this to make something akin to the Component pattern, meaning each game object is made up of multiple unrelated parts and they all come together in such a way that, with some code in the actual object, they form a complete entity.
Here is an example:
public interface Collidable{
public int getXPixel();
public int getYPixel();
public Hitbox getHitbox();
default void renderHitbox() {
renderHitbox(0xFF0C00);
}
default void renderHitbox(int color) {
Hitbox hitbox = getHitbox();
int xPixel = getXPixel();
int yPixel = getYPixel();
Game.getRenderEngine().renderSquare(color, xPixel + hitbox.getXStart(), yPixel + hitbox.getYStart(), hitbox.getWidthPixels(), hitbox.getHeightPixels());
}
/**
* Called in the <tt>addToLevel</tt> method of the object
*/
default void addCollidable() {
Game.getLevel().addCollidable(this);
}
/**
* Called in the <tt>removeFromLevel</tt> method of the object
*/
default void removeCollidable() {
Game.getLevel().removeCollidable(this);
}
/**
* Call in <tt>MovingObject.onMove</tt>. Necessary for the proper storage of this object in certain data structures
*/
default void updatePosition() {
Game.getLevel().updateCollidable(this);
}
}
This would then be implemented, along with other interfaces, in a class such as this:
public abstract class MovingObject extends LevelObject implements Updateable, Collidable {
public static final int AIR_DRAG = 4;
public static final int MAX_SPEED = 20;
private int xVel, yVel, dir;
protected MovingObject(int xPixel, int yPixel) {
super(xPixel, yPixel);
}
@Override
public void update() {
move();
}
@Override
public void addToLevel() {
addUpdateable();
addCollidable();
}
@Override
public void removeFromLevel() {
removeUpdateable();
removeCollidable();
}
protected void onMove(int pXPixel, int pYPixel) {
updatePosition();
}
protected boolean getCollision(int moveX, int moveY) {
return false;
}
protected void move() {
//move...
}
public void addVel(int xVel, int yVel) {
//add velocity...
}
}
I have found this extremely helpful in my code. Tell me what you think of it and see if you can use it!
EDIT - however, funnily, I forgot to mention the largest and most obvious disadvantage about this - you cannot store instance variables. You can do what I did in Collidable and just force them to implement methods, but this is not always optimal.