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 lombok.extern.slf4j.Slf4j;
|
||||||
import se.urmo.game.util.MyPoint;
|
|
||||||
import se.urmo.game.main.GamePanel;
|
import se.urmo.game.main.GamePanel;
|
||||||
import se.urmo.game.util.Direction;
|
|
||||||
import se.urmo.game.map.GameMap;
|
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.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@Slf4j
|
@Slf4j
|
||||||
public class CollisionChecker {
|
public class CollisionChecker {
|
||||||
private GameMap map;
|
private final GameMap map;
|
||||||
|
|
||||||
public CollisionChecker(GameMap map) {
|
public CollisionChecker(GameMap map) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public Point getValidDestination(Direction direction, Point position, int agent_width, int agent_height) {
|
public MyPoint getValidDestination(Direction direction, MyPoint position, int agentWidth, int agentHeight) {
|
||||||
// List<Point> boundaries = switch (direction) {
|
List<MyPoint> boundaries = getBoundariesForDirection(direction, position, agentWidth / 2, agentHeight / 2);
|
||||||
// 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
|
|
||||||
// }
|
|
||||||
|
|
||||||
// /**
|
return canMoveInDirection(agentWidth, boundaries)
|
||||||
// * Applies specific rules to movement
|
? normalizePosition(position, agentWidth)
|
||||||
// * This, for instance, makes sure the tunnel left/right works.
|
: null; // Blocked
|
||||||
// *
|
}
|
||||||
// * @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);
|
|
||||||
// }
|
|
||||||
|
|
||||||
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 NONE -> Collections.emptyList();
|
||||||
case RIGHT, LEFT -> List.of(
|
case RIGHT, LEFT -> List.of(
|
||||||
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 + (direction.dx * agent_width/2), position.y + agent_height/2)
|
new MyPoint(position.x + ((double) (direction.dx * horizontalOffset) / 2), position.y + (double) verticalOffset / 2)
|
||||||
);
|
);
|
||||||
case UP, DOWN -> List.of(
|
case UP, DOWN -> List.of(
|
||||||
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 + agent_width/2, position.y + (direction.dy * agent_height/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);
|
|
||||||
}
|
|
||||||
return null; // Blocked
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private MyPoint normalizePosition(Direction direction, double x, double y, int agent_width, int agent_height) {
|
/**
|
||||||
double x1 = x;
|
* Normalizes the position of an agent when it reaches screen boundaries,
|
||||||
double y1 = y;
|
* implementing tunnel-like behavior when crossing horizontal boundaries.
|
||||||
int width = GamePanel.SCREEN_WIDTH;
|
*
|
||||||
int height = GamePanel.SCREEN_HEIGHT;
|
* @param position The current position to normalize
|
||||||
|
* @param agentWidth The width of the agent
|
||||||
// tunnel
|
* @return Normalized position as MyPoint
|
||||||
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
|
private MyPoint normalizePosition(MyPoint position, int agentWidth) {
|
||||||
|
if (isLeftBoundary(position.x)) {
|
||||||
return new MyPoint(x1, y1);
|
return new MyPoint(GamePanel.SCREEN_WIDTH - (double) agentWidth / 2 - GameMap.OFFSET_X, position.y);
|
||||||
}
|
}
|
||||||
|
if (isRightBoundary(position.x)) {
|
||||||
|
return new MyPoint(GameMap.OFFSET_X, position.y);
|
||||||
|
}
|
||||||
|
return position;
|
||||||
|
}
|
||||||
|
|
||||||
|
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