HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaMinor

Removing duplicate code from basic collision detection implementation

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
collisionremovingduplicatedetectioncodeimplementationfrombasic

Problem

The code is part of a very basic 2D platformer based on code from the book Killer Game Programming in Java.

The methods are part of a TileMapManager class which is handling basic collision detection.

-
The first method returns the greatest distance that an entity can travel in the y axis (up to deltaY) without colliding with a tile:

public int getMaxDeltaY(Point initialPoint, int deltaY){

    //validate params
    if(deltaY>=tileMap.getTileHeight()) throw new IllegalArgumentException("Cannot validate if deltaY is larger than brickHeight");
    if(deltaY==0) return deltaY;

    int x = initialPoint.x;
    int testY = initialPoint.y + deltaY;

    if(isInsideTile(x, testY)){

        //get which row we are colliding with
        int mapRow = testY/tileMap.getTileHeight();
        //the distance between our position and
        //the top of the tile we are colliding with
        int topOffset = testY - (mapRow * tileMap.getTileHeight());
        //get the amount we should move to place
        //ourselves just next to the tile (top or bottom)
        int maxDeltaY = 0;

        //moving up case
        if(deltaY 0){
            maxDeltaY = deltaY - topOffset;
        }
        return maxDeltaY;
    }
    //we won't collide so it's okay to move deltaY
    return deltaY;
}


-
The second method does the same thing in the x axis:

```
public int getMaxDeltaX(Point initialPoint, int deltaX){
//validate params
if(deltaX>=tileMap.getTileWidth()) throw new IllegalArgumentException("Cannot validate if moveStep is larger than brickWidth");
if(deltaX==0) return deltaX;

int testX = (initialPoint.x + deltaX);
int y = initialPoint.y;

//if we collide
if(isInsideTile(testX, y)){

//get which column we are colliding with
int mapCol = testX/tileMap.getTileWidth();
//the distance between our position and
//the left side of the tile we are colliding with
int leftOffset = testX - (mapCol * tileMap.getTile

Solution

It seems this is a job for a Parameter class.

public abstract class DeltaParameters{
  protected ? tileMap;
  protected int x, y;

  DeltaParameters(Point point, ? tileMap){
    this.x = point.x;
    this.y = point.y;
    this.tileMap = tileMap;
  }

  public int getX(){
    return x;
  }

  public int getY(){
    return y;
  }
  public abstract int getTileSideSize();
  public abstract int getMovingCoordinate();
  public abstract void offsetMovingCoordinate(int delta);
}

public class DeltaXParameters extends DeltaParameters{
  DeltaXParameters(Point point, ? tileMap){
    super(point, tileMap);
  }

  public int getTileSideSize(){
    return tileMap.getTileWidth();
  }
  public int getMovingCoordinate(){
    return x;
  }
  public void offsetMovingCoordinate(int delta){
    x += delta;
  }
}


I leave to you the job of guessing what would be DeltaYParameters :p

public int getMaxDelta(DeltaParameters dparams, int delta){
    if(delta>=dparams.getTileSideSize()) throw new IllegalArgumentException("This message is yet to be determined. It could be another method in DeltaParameters");
    if(delta==0) return delta;

    dparams.offsetMovingCoordinate(delta);
    if(isInsideTile(dparams.getX(), dparams.getY())){
        int map = dparams.getMovingCoordinate() /dparams.getTileSideSize() ;
        int offset = dparams.getMovingCoordinate() - (map * dparams.getTileSideSize() );
        int maxDelta = 0;

        if(delta  0){
            maxDelta = delta - offset;
        }

        return maxDelta;
    }
    return delta;
}


Now you could call getMaxDelta just like this

getMaxDelta(new DeltaXParameters(new Point(0, 0), tileMap), 5);


What I have done here is to take the advantage of polymorphism over DeltaParameters class. Which could not be a so straigthforward method to refactor is now proven to be in a quite simple fashion imho.

Code Snippets

public abstract class DeltaParameters{
  protected ? tileMap;
  protected int x, y;

  DeltaParameters(Point point, ? tileMap){
    this.x = point.x;
    this.y = point.y;
    this.tileMap = tileMap;
  }

  public int getX(){
    return x;
  }

  public int getY(){
    return y;
  }
  public abstract int getTileSideSize();
  public abstract int getMovingCoordinate();
  public abstract void offsetMovingCoordinate(int delta);
}

public class DeltaXParameters extends DeltaParameters{
  DeltaXParameters(Point point, ? tileMap){
    super(point, tileMap);
  }

  public int getTileSideSize(){
    return tileMap.getTileWidth();
  }
  public int getMovingCoordinate(){
    return x;
  }
  public void offsetMovingCoordinate(int delta){
    x += delta;
  }
}
public int getMaxDelta(DeltaParameters dparams, int delta){
    if(delta>=dparams.getTileSideSize()) throw new IllegalArgumentException("This message is yet to be determined. It could be another method in DeltaParameters");
    if(delta==0) return delta;

    dparams.offsetMovingCoordinate(delta);
    if(isInsideTile(dparams.getX(), dparams.getY())){
        int map = dparams.getMovingCoordinate() /dparams.getTileSideSize() ;
        int offset = dparams.getMovingCoordinate() - (map * dparams.getTileSideSize() );
        int maxDelta = 0;

        if(delta < 0){
            maxDelta = delta + (dparams.getTileSideSize() - offset);
        }
        else if(delta > 0){
            maxDelta = delta - offset;
        }

        return maxDelta;
    }
    return delta;
}
getMaxDelta(new DeltaXParameters(new Point(0, 0), tileMap), 5);

Context

StackExchange Code Review Q#48693, answer score: 3

Revisions (0)

No revisions yet.