Refactored Pacman positioning and speed - not uses Double x,y
This commit is contained in:
@ -2,6 +2,7 @@ package se.urmo.game.collision;
|
|||||||
|
|
||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
import se.urmo.game.entities.MyPoint;
|
||||||
import se.urmo.game.main.GamePanel;
|
import se.urmo.game.main.GamePanel;
|
||||||
import se.urmo.game.util.Direction;
|
import se.urmo.game.util.Direction;
|
||||||
import se.urmo.game.map.GameMap;
|
import se.urmo.game.map.GameMap;
|
||||||
@ -19,52 +20,89 @@ public class CollisionChecker {
|
|||||||
this.map = map;
|
this.map = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Point getValidDestination(Direction direction, Point position, int agent_width, int agent_height) {
|
// public Point getValidDestination(Direction direction, Point position, int agent_width, int agent_height) {
|
||||||
List<Point> boundaries = switch (direction) {
|
// 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
|
||||||
|
// }
|
||||||
|
|
||||||
|
// /**
|
||||||
|
// * 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);
|
||||||
|
// }
|
||||||
|
|
||||||
|
public MyPoint getValidDestination(Direction direction, MyPoint position, int agent_width, int agent_height) {
|
||||||
|
List<MyPoint> boundaries = switch (direction) {
|
||||||
case NONE -> Collections.emptyList();
|
case NONE -> Collections.emptyList();
|
||||||
case RIGHT, LEFT -> List.of(
|
case RIGHT, LEFT -> List.of(
|
||||||
new Point(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 Point(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)
|
||||||
);
|
);
|
||||||
case UP, DOWN -> List.of(
|
case UP, DOWN -> List.of(
|
||||||
new Point(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 Point(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))
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
List<Pair> bs = boundaries.stream().map(p -> new Pair(p.x, p.y, GameMap.screenToRow(p.y), GameMap.screenToCol(p.x))).toList();
|
List<MyPoint> normalized = boundaries.stream()
|
||||||
log.debug("{} boundaries for {} are {}", direction, position, bs);
|
.map(p -> normalizePosition(direction, p.x, p.y, agent_width, agent_height))
|
||||||
|
|
||||||
List<Point> normalized = boundaries.stream()
|
|
||||||
.map(p -> normalizePosition(direction, p, agent_width, agent_height))
|
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
if (map.isPassable(normalized)) {
|
boolean passable = normalized.stream().allMatch(myPoint -> map.isPassable((int) myPoint.x, (int) myPoint.y));
|
||||||
return normalizePosition(direction, position, agent_width, agent_height);
|
if (passable) {
|
||||||
|
return normalizePosition(direction, position.x, position.y, agent_width, agent_height);
|
||||||
}
|
}
|
||||||
return null; // Blocked
|
return null; // Blocked
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
private MyPoint normalizePosition(Direction direction, double x, double y, int agent_width, int agent_height) {
|
||||||
* Applies specific rules to movement
|
double x1 = x;
|
||||||
* This, for instance, makes sure the tunnel left/right works.
|
double y1 = y;
|
||||||
*
|
|
||||||
* @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 width = GamePanel.SCREEN_WIDTH;
|
||||||
int height = GamePanel.SCREEN_HEIGHT;
|
int height = GamePanel.SCREEN_HEIGHT;
|
||||||
|
|
||||||
// tunnel
|
// tunnel
|
||||||
if (x < GameMap.OFFSET_X) x = width - agent_width/2 - GameMap.OFFSET_X; // right
|
if (x < GameMap.OFFSET_X) x1 = width - agent_width/2 - GameMap.OFFSET_X; // right
|
||||||
if (x >= (width - GameMap.OFFSET_X)) x = GameMap.OFFSET_X; // left
|
if (x>= (width - GameMap.OFFSET_X)) x1 = GameMap.OFFSET_X; // left
|
||||||
|
|
||||||
return new Point(x, y);
|
return new MyPoint(x1, y1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
34
src/main/java/se/urmo/game/entities/MyPoint.java
Normal file
34
src/main/java/se/urmo/game/entities/MyPoint.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package se.urmo.game.entities;
|
||||||
|
|
||||||
|
public class MyPoint {
|
||||||
|
public final double x;
|
||||||
|
public final double y;
|
||||||
|
|
||||||
|
public MyPoint(double x, double y) {
|
||||||
|
this.x = x;
|
||||||
|
this.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "MyPoint{" +
|
||||||
|
"x=" + x +
|
||||||
|
", y=" + y +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (o == null || getClass() != o.getClass()) return false;
|
||||||
|
|
||||||
|
MyPoint myPoint = (MyPoint) o;
|
||||||
|
return Double.compare(x, myPoint.x) == 0 && Double.compare(y, myPoint.y) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = Double.hashCode(x);
|
||||||
|
result = 31 * result + Double.hashCode(y);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -22,16 +22,16 @@ public class PacMan {
|
|||||||
private static final int COLLISION_BOX_SIZE = 16;
|
private static final int COLLISION_BOX_SIZE = 16;
|
||||||
private static final int COLLISION_BOX_OFFSET = (PACMAN_SIZE - COLLISION_BOX_SIZE) / 2;
|
private static final int COLLISION_BOX_OFFSET = (PACMAN_SIZE - COLLISION_BOX_SIZE) / 2;
|
||||||
private final Game game;
|
private final Game game;
|
||||||
private final Point startPosition;
|
//private final Point startPosition;
|
||||||
|
private final MyPoint startPosition;
|
||||||
private int aniTick = 0;
|
private int aniTick = 0;
|
||||||
private int aniIndex = 0;
|
private int aniIndex = 0;
|
||||||
private static final int ANIMATION_UPDATE_FREQUENCY = 10;
|
private static final int ANIMATION_UPDATE_FREQUENCY = 10;
|
||||||
private int speed = 1;
|
private static final double BASE_SPEED = 0.40;
|
||||||
@Setter
|
@Setter
|
||||||
private boolean moving;
|
private boolean moving;
|
||||||
private final BufferedImage[][] movmentImages = new BufferedImage[4][4];
|
private final BufferedImage[][] movmentImages = new BufferedImage[4][4];
|
||||||
@Getter
|
private MyPoint position;
|
||||||
private Point position;
|
|
||||||
private static final BufferedImage COLLISION_BOX = MiscUtil.createOutlinedBox(COLLISION_BOX_SIZE, COLLISION_BOX_SIZE, Color.yellow, 2);
|
private static final BufferedImage COLLISION_BOX = MiscUtil.createOutlinedBox(COLLISION_BOX_SIZE, COLLISION_BOX_SIZE, Color.yellow, 2);
|
||||||
private final CollisionChecker collisionChecker;
|
private final CollisionChecker collisionChecker;
|
||||||
@Setter
|
@Setter
|
||||||
@ -41,9 +41,9 @@ public class PacMan {
|
|||||||
public PacMan(Game game, CollisionChecker collisionChecker) {
|
public PacMan(Game game, CollisionChecker collisionChecker) {
|
||||||
this.game = game;
|
this.game = game;
|
||||||
this.collisionChecker = collisionChecker;
|
this.collisionChecker = collisionChecker;
|
||||||
this.position = new Point(
|
this.position = new MyPoint(
|
||||||
26 * GameMap.MAP_TILESIZE + GameMap.OFFSET_X,
|
26 * GameMap.MAP_TILESIZE + GameMap.OFFSET_X,
|
||||||
13 * GameMap.MAP_TILESIZE + GameMap.OFFSET_Y + (GameMap.MAP_TILESIZE / 2));
|
13 * GameMap.MAP_TILESIZE + GameMap.OFFSET_Y + ((double) GameMap.MAP_TILESIZE / 2));
|
||||||
this.startPosition = this.position;
|
this.startPosition = this.position;
|
||||||
loadAnimation();
|
loadAnimation();
|
||||||
}
|
}
|
||||||
@ -72,8 +72,8 @@ public class PacMan {
|
|||||||
public void draw(Graphics g) {
|
public void draw(Graphics g) {
|
||||||
g.drawImage(
|
g.drawImage(
|
||||||
movmentImages[direction==Direction.NONE ? 0 : direction.ordinal()][aniIndex],
|
movmentImages[direction==Direction.NONE ? 0 : direction.ordinal()][aniIndex],
|
||||||
position.x - PACMAN_OFFSET,
|
(int) position.x - PACMAN_OFFSET,
|
||||||
position.y - PACMAN_OFFSET,
|
(int) position.y - PACMAN_OFFSET,
|
||||||
PACMAN_SIZE,
|
PACMAN_SIZE,
|
||||||
PACMAN_SIZE, null);
|
PACMAN_SIZE, null);
|
||||||
//g.drawImage(COLLISION_BOX, position.x - COLLISION_BOX_OFFSET, position.y - COLLISION_BOX_OFFSET, COLLISION_BOX_SIZE, COLLISION_BOX_SIZE, null);
|
//g.drawImage(COLLISION_BOX, position.x - COLLISION_BOX_OFFSET, position.y - COLLISION_BOX_OFFSET, COLLISION_BOX_SIZE, COLLISION_BOX_SIZE, null);
|
||||||
@ -84,15 +84,16 @@ public class PacMan {
|
|||||||
public void update() {
|
public void update() {
|
||||||
updateAnimationTick();
|
updateAnimationTick();
|
||||||
if(moving) {
|
if(moving) {
|
||||||
Point newPosition = switch (direction) {
|
log.debug("Moving to {}", direction);
|
||||||
case RIGHT -> new Point(position.x + speed, position.y);
|
MyPoint mpoint = switch (direction) {
|
||||||
case LEFT -> new Point(position.x - speed, position.y);
|
case RIGHT -> new MyPoint(position.x + getSpeed(), position.y);
|
||||||
case UP -> new Point(position.x, position.y - speed);
|
case LEFT -> new MyPoint(position.x - getSpeed(), position.y);
|
||||||
case DOWN -> new Point(position.x, position.y + speed);
|
case UP -> new MyPoint(position.x, position.y - getSpeed());
|
||||||
|
case DOWN -> new MyPoint(position.x, position.y + getSpeed());
|
||||||
default -> throw new IllegalStateException("Unexpected value: " + direction);
|
default -> throw new IllegalStateException("Unexpected value: " + direction);
|
||||||
};
|
};
|
||||||
log.debug("At: {},trying to move {} to {}", position, direction.name(), newPosition);
|
|
||||||
Point destination = collisionChecker.getValidDestination(direction, newPosition, COLLISION_BOX_SIZE, COLLISION_BOX_SIZE);
|
MyPoint destination = collisionChecker.getValidDestination(direction, mpoint, COLLISION_BOX_SIZE, COLLISION_BOX_SIZE);
|
||||||
|
|
||||||
if (destination != null) {
|
if (destination != null) {
|
||||||
position = destination;
|
position = destination;
|
||||||
@ -100,6 +101,10 @@ public class PacMan {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private double getSpeed() {
|
||||||
|
return BASE_SPEED * 0.8;
|
||||||
|
}
|
||||||
|
|
||||||
private void updateAnimationTick() {
|
private void updateAnimationTick() {
|
||||||
if (moving) {
|
if (moving) {
|
||||||
aniTick++;
|
aniTick++;
|
||||||
@ -115,7 +120,7 @@ public class PacMan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public double distanceTo(Point point) {
|
public double distanceTo(Point point) {
|
||||||
return position.distance(point);
|
return new Point((int) position.x, (int) position.y).distance(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void loseLife() {
|
public void loseLife() {
|
||||||
@ -131,6 +136,10 @@ public class PacMan {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Rectangle getBounds() {
|
public Rectangle getBounds() {
|
||||||
return new Rectangle(position.x - COLLISION_BOX_OFFSET, position.y - COLLISION_BOX_OFFSET, COLLISION_BOX_SIZE, COLLISION_BOX_SIZE);
|
return new Rectangle((int) (position.x - COLLISION_BOX_OFFSET), (int) (position.y - COLLISION_BOX_OFFSET), COLLISION_BOX_SIZE, COLLISION_BOX_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Point getPosition() {
|
||||||
|
return new Point((int) position.x, (int) position.y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user