I'm creating a 2D tile based platformer with AABB (Axis aligned bounding boxes), and it works, I just want to organize and optimize my setup. Here are methods in my player class and entity class that are relevant to the collision. How could I make this better? I'm harshly looking at that public boolean[]
method, but I cant figure out another way without using state.
AbstractEntity.java
public boolean[] getCornersAreSolid(double x, double y) {
int leftTile = (int)(x / Tile.SIZE);
int rightTile = (int)((x + this.collisionBox.getWidth()) / Tile.SIZE);
int topTile = (int)(y / Tile.SIZE);
int bottomTile = (int)((y + this.collisionBox.getHeight()) / Tile.SIZE);
boolean topLeft;
boolean topRight;
boolean bottomLeft;
boolean bottomRight;
if(leftTile < 0 || leftTile >= map.getWidth() || topTile < 0 || topTile >= map.getHeight())
topLeft = false;
else
topLeft = map.getTileAt(leftTile, topTile).getAttribute(Attribute.SOLID);
if(rightTile < 0 || rightTile >= map.getWidth() || topTile < 0 || topTile >= map.getHeight())
topRight = false;
else
topRight = map.getTileAt(rightTile, topTile).getAttribute(Attribute.SOLID);
if(leftTile < 0 || leftTile >= map.getWidth() || bottomTile < 0 || bottomTile >= map.getHeight())
bottomLeft = false;
else
bottomLeft = map.getTileAt(leftTile, bottomTile).getAttribute(Attribute.SOLID);
if(rightTile < 0 || rightTile >= map.getWidth() || bottomTile < 0 || bottomTile >= map.getHeight())
bottomRight = false;
else
bottomRight = map.getTileAt(rightTile, bottomTile).getAttribute(Attribute.SOLID);
return new boolean[]{topLeft, topRight, bottomLeft, bottomRight};
}
/*
* @return next position
*/
public Vec2D getNextPosition() {
int currCol = (int)getX() / Tile.SIZE;
int currRow = (int)getY() / Tile.SIZE;
double xdest = getX() + this.velocity.x;
double ydest = getY() + this.velocity.y;
double xtemp = getX();
double ytemp = getY();
boolean[] corners = getCornersAreSolid(getX(), ydest);
boolean topLeft = corners[0];
boolean topRight = corners[1];
boolean bottomLeft = corners[2];
boolean bottomRight = corners[3];
if(this.velocity.y < 0) {
if(topLeft || topRight) {
this.velocity.y = 0;
ytemp = currRow * Tile.SIZE;
}
else {
ytemp += this.velocity.y;
}
}
else if(this.velocity.y > 0) {
if(bottomLeft || bottomRight) {
this.velocity.y = 0;
ytemp = (currRow + 1) * Tile.SIZE - this.collisionBox.getHeight() % Tile.SIZE - 1 ;
}
else {
ytemp += this.velocity.y;
}
}
corners = getCornersAreSolid(xdest, getY());
topLeft = corners[0];
topRight = corners[1];
bottomLeft = corners[2];
bottomRight = corners[3];
if(this.velocity.x < 0) {
if(topLeft || bottomLeft) {
this.velocity.x = 0;
xtemp = currCol * Tile.SIZE;
}
else {
xtemp += this.velocity.x;
}
}
if(this.velocity.x > 0) {
if(topRight || bottomRight) {
this.velocity.x = 0;
xtemp = (currCol + 1) * Tile.SIZE - this.collisionBox.getWidth() % Tile.SIZE -1 ;
}
else {
xtemp += this.velocity.x;
}
}
return new Vec2D(xtemp, ytemp);
}
PlayerEntity.java extends Abstract Entity
@Override
public void update() {
this.setPosition(this.getNextPosition());
if(this.movingLeft)
this.velocity.x = -WALK_SPEED;
if(!this.movingLeft && this.velocity.x < 0)
this.velocity.x *= COEF_FRIC;
if(this.movingRight)
this.velocity.x = WALK_SPEED;
if(!this.movingRight && this.velocity.x > 0)
this.velocity.x *= COEF_FRIC;
animations.update();
}
@Override
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_A:
this.movingLeft = true;
break;
case KeyEvent.VK_D:
this.movingRight = true;
break;
case KeyEvent.VK_W:
this.velocity.y = -5;
break;
}
}
@Override
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_A:
this.movingLeft = false;
break;
case KeyEvent.VK_D:
this.movingRight = false;
break;
}
}