Refactor CollisionChecker for cleaner boundary handling
Streamlined collision logic by introducing helper methods for boundary calculations and movement validation. Replaced commented-out code with efficient implementations, improving readability and maintainability. Added clear documentation for new methods to better convey their purpose and usage.
This commit is contained in:
@ -2,105 +2,93 @@ package se.urmo.game.collision;
|
||||
|
||||
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import se.urmo.game.util.MyPoint;
|
||||
import se.urmo.game.main.GamePanel;
|
||||
import se.urmo.game.util.Direction;
|
||||
import se.urmo.game.map.GameMap;
|
||||
import se.urmo.game.util.Direction;
|
||||
import se.urmo.game.util.MyPoint;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
@Slf4j
|
||||
public class CollisionChecker {
|
||||
private GameMap map;
|
||||
private final GameMap map;
|
||||
|
||||
public CollisionChecker(GameMap map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
// public Point getValidDestination(Direction direction, Point position, int agent_width, int agent_height) {
|
||||
// List<Point> boundaries = switch (direction) {
|
||||
// case NONE -> Collections.emptyList();
|
||||
// case RIGHT, LEFT -> List.of(
|
||||
// new Point(position.x + (direction.dx * agent_width/2), position.y - agent_height/2),
|
||||
// new Point(position.x + (direction.dx * agent_width/2), position.y + agent_height/2)
|
||||
// );
|
||||
// case UP, DOWN -> List.of(
|
||||
// new Point(position.x - agent_width/2, position.y + (direction.dy * agent_height/2)),
|
||||
// new Point(position.x + agent_width/2, position.y + (direction.dy * agent_height/2))
|
||||
// );
|
||||
// };
|
||||
//
|
||||
// List<Pair> bs = boundaries.stream().map(p -> new Pair(p.x, p.y, GameMap.screenToRow(p.y), GameMap.screenToCol(p.x))).toList();
|
||||
// log.debug("{} boundaries for {} are {}", direction, position, bs);
|
||||
//
|
||||
// List<Point> normalized = boundaries.stream()
|
||||
// .map(p -> normalizePosition(direction, p, agent_width, agent_height))
|
||||
// .toList();
|
||||
//
|
||||
// if (map.isPassable(normalized)) {
|
||||
// return normalizePosition(direction, position, agent_width, agent_height);
|
||||
// }
|
||||
// return null; // Blocked
|
||||
// }
|
||||
public MyPoint getValidDestination(Direction direction, MyPoint position, int agentWidth, int agentHeight) {
|
||||
List<MyPoint> boundaries = getBoundariesForDirection(direction, position, agentWidth / 2, agentHeight / 2);
|
||||
|
||||
// /**
|
||||
// * Applies specific rules to movement
|
||||
// * This, for instance, makes sure the tunnel left/right works.
|
||||
// *
|
||||
// * @param dir
|
||||
// * @param pos
|
||||
// * @param agent_width
|
||||
// * @param agent_height
|
||||
// * @return
|
||||
// */
|
||||
// public Point normalizePosition(Direction dir, Point pos, int agent_width, int agent_height) {
|
||||
// int x = pos.x;
|
||||
// int y = pos.y;
|
||||
// int width = GamePanel.SCREEN_WIDTH;
|
||||
// int height = GamePanel.SCREEN_HEIGHT;
|
||||
//
|
||||
// // tunnel
|
||||
// if (x < GameMap.OFFSET_X) x = width - agent_width/2 - GameMap.OFFSET_X; // right
|
||||
// if (x >= (width - GameMap.OFFSET_X)) x = GameMap.OFFSET_X; // left
|
||||
//
|
||||
// return new Point(x, y);
|
||||
// }
|
||||
return canMoveInDirection(agentWidth, boundaries)
|
||||
? normalizePosition(position, agentWidth)
|
||||
: null; // Blocked
|
||||
}
|
||||
|
||||
public MyPoint getValidDestination(Direction direction, MyPoint position, int agent_width, int agent_height) {
|
||||
List<MyPoint> boundaries = switch (direction) {
|
||||
/**
|
||||
* Determines whether boundaries (corners) are in a passible i.e., not blocked, position
|
||||
*
|
||||
* @param agentWidth The width of the entity attempting to move.
|
||||
* @param boundaries The boundary points representing the edges of the area occupied by the entity.
|
||||
* @return {@code true} if movement in the specified direction is possible; {@code false} otherwise.
|
||||
*/
|
||||
private boolean canMoveInDirection(int agentWidth, List<MyPoint> boundaries) {
|
||||
return boundaries.stream()
|
||||
.map(boundary -> normalizePosition(boundary, agentWidth))
|
||||
.allMatch(myPoint -> map.isPassable((int) myPoint.x, (int) myPoint.y));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the boundary points of a given position based on a specified direction
|
||||
* and horizontal and vertical offsets. The resulting boundaries represent the edges
|
||||
* of the area occupied by the entity moving in the specified direction.
|
||||
*
|
||||
* @param direction The direction of movement (e.g., UP, DOWN, LEFT, RIGHT, or NONE).
|
||||
* @param position The current position represented as a {@code MyPoint}.
|
||||
* @param horizontalOffset The horizontal offset to determine the boundary width.
|
||||
* @param verticalOffset The vertical offset to determine the boundary height.
|
||||
* @return A list of boundary points in the form of {@code MyPoint} objects. If the
|
||||
* direction is {@code NONE}, an empty list is returned.
|
||||
*/
|
||||
private static List<MyPoint> getBoundariesForDirection(Direction direction, MyPoint position, int horizontalOffset, int verticalOffset) {
|
||||
return switch (direction) {
|
||||
case NONE -> Collections.emptyList();
|
||||
case RIGHT, LEFT -> List.of(
|
||||
new MyPoint(position.x + (direction.dx * agent_width/2), position.y - agent_height/2),
|
||||
new MyPoint(position.x + (direction.dx * agent_width/2), position.y + agent_height/2)
|
||||
new MyPoint(position.x + ((double) (direction.dx * horizontalOffset) / 2), position.y - (double) verticalOffset / 2),
|
||||
new MyPoint(position.x + ((double) (direction.dx * horizontalOffset) / 2), position.y + (double) verticalOffset / 2)
|
||||
);
|
||||
case UP, DOWN -> List.of(
|
||||
new MyPoint(position.x - agent_width/2, position.y + (direction.dy * agent_height/2)),
|
||||
new MyPoint(position.x + agent_width/2, position.y + (direction.dy * agent_height/2))
|
||||
new MyPoint(position.x - (double) horizontalOffset / 2, position.y + ((double) (direction.dy * verticalOffset) / 2)),
|
||||
new MyPoint(position.x + (double) horizontalOffset / 2, position.y + ((double) (direction.dy * verticalOffset) / 2))
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
List<MyPoint> normalized = boundaries.stream()
|
||||
.map(p -> normalizePosition(direction, p.x, p.y, agent_width, agent_height))
|
||||
.toList();
|
||||
|
||||
boolean passable = normalized.stream().allMatch(myPoint -> map.isPassable((int) myPoint.x, (int) myPoint.y));
|
||||
if (passable) {
|
||||
return normalizePosition(direction, position.x, position.y, agent_width, agent_height);
|
||||
/**
|
||||
* Normalizes the position of an agent when it reaches screen boundaries,
|
||||
* implementing tunnel-like behavior when crossing horizontal boundaries.
|
||||
*
|
||||
* @param position The current position to normalize
|
||||
* @param agentWidth The width of the agent
|
||||
* @return Normalized position as MyPoint
|
||||
*/
|
||||
private MyPoint normalizePosition(MyPoint position, int agentWidth) {
|
||||
if (isLeftBoundary(position.x)) {
|
||||
return new MyPoint(GamePanel.SCREEN_WIDTH - (double) agentWidth / 2 - GameMap.OFFSET_X, position.y);
|
||||
}
|
||||
return null; // Blocked
|
||||
if (isRightBoundary(position.x)) {
|
||||
return new MyPoint(GameMap.OFFSET_X, position.y);
|
||||
}
|
||||
return position;
|
||||
}
|
||||
|
||||
private MyPoint normalizePosition(Direction direction, double x, double y, int agent_width, int agent_height) {
|
||||
double x1 = x;
|
||||
double y1 = y;
|
||||
int width = GamePanel.SCREEN_WIDTH;
|
||||
int height = GamePanel.SCREEN_HEIGHT;
|
||||
|
||||
// tunnel
|
||||
if (x < GameMap.OFFSET_X) x1 = width - agent_width/2 - GameMap.OFFSET_X; // right
|
||||
if (x>= (width - GameMap.OFFSET_X)) x1 = GameMap.OFFSET_X; // left
|
||||
|
||||
return new MyPoint(x1, y1);
|
||||
private boolean isLeftBoundary(double x) {
|
||||
return x < GameMap.OFFSET_X;
|
||||
}
|
||||
|
||||
private boolean isRightBoundary(double x) {
|
||||
return x >= (GamePanel.SCREEN_WIDTH - GameMap.OFFSET_X);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user