Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 40 additions & 0 deletions src/main/java/org/example/MapVisualizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,46 @@ public void drawPlayers(List<int[]> players, int currentIndex, double totalWidth
}
}

public void drawPlayersInterpolated(List<double[]> players, int currentIndex, double totalWidth, double totalHeight) {
playerLayer.getChildren().clear();

double cellWidth = totalWidth / gridSize;
double cellHeight = totalHeight / gridSize;

for (int i = 0; i < players.size(); i++) {
double[] p = players.get(i);
double gridX = p[0];
double gridY = p[1];

double centerX = (gridX * cellWidth) + (cellWidth / 2);
double centerY = totalHeight - (gridY * cellHeight) - (cellHeight / 2);

double rPlayer = (cellWidth / 2) * 0.8;

if (i == currentIndex) {
Color c = colorForPlayer(i);
Circle halo = new Circle(centerX, centerY, rPlayer * 1.25);
halo.setFill(c.deriveColor(0, 1, 1, 0.25));
halo.setMouseTransparent(true);
playerLayer.getChildren().add(halo);
}

Circle token = new Circle(centerX, centerY, rPlayer);
token.setFill(colorForPlayer(i));

if (i == currentIndex) {
token.setStroke(Color.WHITE);
token.setStrokeWidth(3);
} else {
token.setStroke(Color.BLACK);
token.setStrokeWidth(1.5);
}

token.setMouseTransparent(true);
playerLayer.getChildren().add(token);
}
}

public void drawDestMarkers(List<Location> destinations, double w, double h) {
markerLayer.getChildren().clear();

Expand Down
86 changes: 54 additions & 32 deletions src/main/java/org/example/TravelGameController.java
Original file line number Diff line number Diff line change
Expand Up @@ -370,11 +370,56 @@ private void updateGraphics() {

redrawAllPathsFromDb(w, h);

List<int[]> positions = new ArrayList<>();
for (Traveler t : players) {
positions.add(new int[]{ clampToGrid(t.getPlayerPosX()), clampToGrid(t.getPlayerPosY()) });
List<double[]> positions = new ArrayList<>();
for (Traveler tRef : players) {
Traveler t = em != null && tRef.getId() != null ? em.find(Traveler.class, tRef.getId()) : tRef;
if (t == null) continue;
positions.add(computePlayerGridPos(t));
}
visualizer.drawPlayers(positions, currentPlayerIndex, w, h);
visualizer.drawPlayersInterpolated(positions, currentPlayerIndex, w, h);
}

private double[] computePlayerGridPos(Traveler t) {
double baseX = clampToGrid(t.getPlayerPosX());
double baseY = clampToGrid(t.getPlayerPosY());

if (!t.isTravelling() || t.getId() == null || em == null) {
return new double[]{baseX, baseY};
}

List<Journey> list = em.createQuery(
"select j from Journey j " +
"join fetch j.locationLink ll " +
"join fetch ll.fromLocation " +
"join fetch ll.toLocation " +
"where j.traveler.id = :id " +
"order by j.turnNumber desc, j.id desc",
Journey.class
)
.setParameter("id", t.getId())
.setMaxResults(1)
.getResultList();

if (list.isEmpty()) return new double[]{baseX, baseY};

Journey j = list.get(0);
LocationLink ll = j.getLocationLink();
int total = ll.getDistance();
if (total <= 0) return new double[]{baseX, baseY};

Location from = ll.getFromLocation();
Location to = ll.getToLocation();

int remainingAfter = j.getRemainingDistance();
double fracAfter = (double) (total - remainingAfter) / total;

double gx = from.getX() + (to.getX() - from.getX()) * fracAfter;
double gy = from.getY() + (to.getY() - from.getY()) * fracAfter;

gx = Math.max(0.0, Math.min(GRID_SIZE - 1, gx));
gy = Math.max(0.0, Math.min(GRID_SIZE - 1, gy));

return new double[]{gx, gy};
}

private void redrawAllPathsFromDb(double w, double h) {
Expand Down Expand Up @@ -441,21 +486,7 @@ private int clampToGrid(int v) {
return Math.max(0, Math.min(GRID_SIZE - 1, v));
}

public void startMockJourney() {
logList.getItems().add("📜 Demo path!");
if (players.isEmpty()) return;

Traveler current = players.get(currentPlayerIndex);
int px = clampToGrid(current.getPlayerPosX());
int py = clampToGrid(current.getPlayerPosY());

List<int[]> journeyPath = new ArrayList<>();
journeyPath.add(new int[]{px, py});
journeyPath.add(new int[]{10, 15});
journeyPath.add(new int[]{25, 20});
journeyPath.add(new int[]{40, 45});
visualizer.animateJourney(journeyPath, drawingPane.getWidth(), drawingPane.getHeight());
}

private void doMove(Long travelerId, PossibleMoves chosen) {
if (wonGame) return;
Expand Down Expand Up @@ -517,18 +548,6 @@ private void doesPlayerWin() {
}
}


private List<Location> distinctLocationsById(List<Location> locations) {
java.util.Map<Long, Location> byId = new java.util.LinkedHashMap<>();
for (Location l : locations) {
if (l != null && l.getId() != null) {
byId.putIfAbsent(l.getId(), l);
}
}
return new java.util.ArrayList<>(byId.values());
}


private void highlightSelectedMoveButton(Button selected) {
for (var node : movesBox.getChildren()) {
if (node instanceof Button b) b.setStyle("");
Expand All @@ -537,9 +556,12 @@ private void highlightSelectedMoveButton(Button selected) {
}

private Location getLocationByName(String name) {
return em.createQuery("select l from Location l where l.name = :n", Location.class)
List<Location> list = em.createQuery("select l from Location l where l.name = :n order by l.id", Location.class)
.setParameter("n", name)
.getSingleResult();
.setMaxResults(1)
.getResultList();
if (list.isEmpty()) throw new IllegalStateException("No location found with name: " + name);
return list.get(0);
}

private void doContinueJourney(Long travelerId) {
Expand Down