I'm trying to learn some things about collision detection, and I've never known how to cleanly detect this for multiple objects in multiple classes without just copy pasting a lot of code.
I now came up with all collisionable/solid things implementing a class and then using Java streams to return whether one or more things in the list of solid things is colliding with the thing you are checking. Is this the way to do this? Or is this really performance heavy or unconventional? I also didn't know a good way of getting the collisionable objects to the player/other creatures, so I simply used a getter, but that means that player class will get access to all the things in the arraylist and I don't know if this is save.
And are there good resources on collision detection for Java(8)?
And if this were to be for a partially grid based game with unwalkable positions in the grid, but also moving objects that cannot be walked through, would something like this still be the correct way to go about it?
Relevant code:
GameScreen.java
class GameScreen implements Screen {
private Stage stage;
private Game game;
private Player player;
private ArrayList<Solid> solids;
GameScreen(Game game) {
this.game = game;
stage = new Stage(new ScreenViewport());
solids = new ArrayList<>();
solids.add(new Wall(500, 0, 200, 200));
solids.add(new Rock(200, 600, 100, 100));
player = new Player(this);
stage.addActor(player);
}
public ArrayList<Solid> getSolids() {
return solids;
}
}
Rock.java (Wall.java is exactly the same but with Rock replaced by Wall)
class Rock extends Group implements Solid {
private int x;
private int y;
private int width;
private int height;
Rock(int x, int y, int width, int height) {
this.x = x;
this.y = y;
this.width = width;
this.height = height;
}
@Override
public boolean collidesWith(float oX, float oY, float oWidth, float oHeight) {
return (oX + oWidth > x && oX < x + width)
&& (oY + oHeight > y && oY < y + height);
}
}
Player.java
class Player extends Group {
private final float STEP = 10f;
private GameScreen gameScreen;
private int playerHeight = 130;
Player(Screen gameScreen) {
setBounds(300, 300, playerHeight / 6.5f * 5, playerHeight);
this.gameScreen = (GameScreen) gameScreen;
}
private boolean collidesWith(ArrayList<Solid> solids, float x, float y) {
return solids.stream().filter(o -> o.collidesWith(x, y, getWidth(), getHeight())).findAny().isPresent();
}
@Override
public void act(float delta) {
super.act(delta);
if(Gdx.input.isKeyPressed(Input.Keys.W)) {
if (!collidesWith(gameScreen.getSolids(), getX(), getY() + STEP)) {
this.setPosition(getX(), getY() + STEP);
}
}
if(Gdx.input.isKeyPressed(Input.Keys.S)) {
if (!collidesWith(gameScreen.getSolids(), getX(), getY() - STEP))
this.setPosition(getX(), getY() - STEP);
}
if(Gdx.input.isKeyPressed(Input.Keys.A)) {
if (!collidesWith(gameScreen.getSolids(), getX() - STEP, getY()))
this.setPosition(getX() - STEP, getY());
}
if(Gdx.input.isKeyPressed(Input.Keys.D)) {
if (!collidesWith(gameScreen.getSolids(), getX() + STEP, getY()))
this.setPosition(getX() + STEP, getY());
}
}
}
Solid.java
interface Solid {
boolean collidesWith(float oX, float oY, float oWidth, float oHeight);
}