Fixed UI bugs, added move drawing to OverlayComponent
This commit is contained in:
parent
d084e00c18
commit
ef8c43be1f
@ -7,6 +7,8 @@ import dev.kske.chess.board.GameState;
|
||||
import dev.kske.chess.board.Move;
|
||||
import dev.kske.chess.board.Piece.Color;
|
||||
import dev.kske.chess.ui.BoardComponent;
|
||||
import dev.kske.chess.ui.BoardPane;
|
||||
import dev.kske.chess.ui.OverlayComponent;
|
||||
|
||||
/**
|
||||
* Project: <strong>Chess</strong><br>
|
||||
@ -18,11 +20,13 @@ public class Game {
|
||||
|
||||
private Map<Color, Player> players;
|
||||
private Board board;
|
||||
private OverlayComponent overlayComponent;
|
||||
private BoardComponent boardComponent;
|
||||
|
||||
public Game(Map<Color, Player> players, BoardComponent boardComponent) {
|
||||
public Game(Map<Color, Player> players, BoardPane boardPane) {
|
||||
this.players = players;
|
||||
this.boardComponent = boardComponent;
|
||||
this.overlayComponent = boardPane.getOverlayComponent();
|
||||
this.boardComponent = boardPane.getBoardComponent();
|
||||
this.board = boardComponent.getBoard();
|
||||
|
||||
// Initialize the game variable in each player
|
||||
@ -42,6 +46,7 @@ public class Game {
|
||||
System.out.printf("%s in check!%n", player.color.opposite());
|
||||
default:
|
||||
boardComponent.repaint();
|
||||
overlayComponent.displayArrow(move);
|
||||
players.get(player.color.opposite()).requestMove();
|
||||
|
||||
}
|
||||
@ -56,6 +61,8 @@ public class Game {
|
||||
players.forEach((k, v) -> v.cancelMove());
|
||||
board.initializeDefaultPositions();
|
||||
boardComponent.repaint();
|
||||
overlayComponent.clearDots();
|
||||
overlayComponent.clearArrow();
|
||||
start();
|
||||
}
|
||||
}
|
||||
|
@ -27,15 +27,15 @@ public class AIPlayer extends Player {
|
||||
private int maxDepth;
|
||||
private int alphaBetaThreshold;
|
||||
|
||||
private volatile boolean exitRequested;
|
||||
private volatile boolean exitRequested;
|
||||
private volatile ExecutorService executor;
|
||||
|
||||
public AIPlayer(Board board, Color color, int maxDepth, int alphaBetaThreshold) {
|
||||
super(board, color);
|
||||
availableProcessors = Runtime.getRuntime().availableProcessors();
|
||||
this.maxDepth = maxDepth;
|
||||
availableProcessors = Runtime.getRuntime().availableProcessors();
|
||||
this.maxDepth = maxDepth;
|
||||
this.alphaBetaThreshold = alphaBetaThreshold;
|
||||
exitRequested = false;
|
||||
exitRequested = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -63,9 +63,8 @@ public class AIPlayer extends Player {
|
||||
for (int i = 0; i < numThreads; i++) {
|
||||
if (rem-- > 0) ++endIndex;
|
||||
endIndex += step;
|
||||
processors.add(
|
||||
new MoveProcessor((Board) board.clone(), moves.subList(beginIndex, endIndex), color, maxDepth,
|
||||
alphaBetaThreshold));
|
||||
processors.add(new MoveProcessor((Board) board.clone(), moves.subList(beginIndex, endIndex), color,
|
||||
maxDepth, alphaBetaThreshold));
|
||||
beginIndex = endIndex;
|
||||
}
|
||||
|
||||
@ -73,7 +72,7 @@ public class AIPlayer extends Player {
|
||||
* Execute processors, get the best result and pass it back to the Game class
|
||||
*/
|
||||
executor = Executors.newFixedThreadPool(numThreads);
|
||||
List<ProcessingResult> results = new ArrayList<>(numThreads);
|
||||
List<ProcessingResult> results = new ArrayList<>(numThreads);
|
||||
try {
|
||||
List<Future<ProcessingResult>> futures = executor.invokeAll(processors);
|
||||
for (Future<ProcessingResult> f : futures)
|
||||
@ -90,11 +89,13 @@ public class AIPlayer extends Player {
|
||||
@Override
|
||||
public void cancelMove() {
|
||||
exitRequested = true;
|
||||
executor.shutdownNow();
|
||||
try {
|
||||
executor.awaitTermination(500, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
if (executor != null) {
|
||||
executor.shutdownNow();
|
||||
try {
|
||||
executor.awaitTermination(500, TimeUnit.MILLISECONDS);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -23,24 +23,24 @@ public class AIConfigDialog extends JDialog {
|
||||
private boolean startGame = false;
|
||||
|
||||
public AIConfigDialog() {
|
||||
setSize(new Dimension(293, 212));
|
||||
setSize(new Dimension(337, 212));
|
||||
setModal(true);
|
||||
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
|
||||
setTitle("AI Configuration");
|
||||
getContentPane().setLayout(null);
|
||||
|
||||
JSpinner spAlphaBetaThreshold = new JSpinner();
|
||||
spAlphaBetaThreshold.setBounds(170, 0, 95, 28);
|
||||
spAlphaBetaThreshold.setBounds(222, 68, 95, 28);
|
||||
getContentPane().add(spAlphaBetaThreshold);
|
||||
spAlphaBetaThreshold.setModel(new SpinnerNumberModel(-10, -100, 100, 5));
|
||||
|
||||
JSpinner spMaxDepth = new JSpinner();
|
||||
spMaxDepth.setBounds(170, 68, 95, 28);
|
||||
spMaxDepth.setBounds(222, 6, 95, 28);
|
||||
getContentPane().add(spMaxDepth);
|
||||
spMaxDepth.setModel(new SpinnerNumberModel(4, 1, 10, 1));
|
||||
|
||||
JLabel lblAlphabetaThreshold = new JLabel("Alpha-Beta Threshold:");
|
||||
lblAlphabetaThreshold.setBounds(16, 68, 119, 28);
|
||||
lblAlphabetaThreshold.setBounds(16, 68, 194, 28);
|
||||
getContentPane().add(lblAlphabetaThreshold);
|
||||
|
||||
JButton btnOk = new JButton("OK");
|
||||
@ -55,13 +55,13 @@ public class AIConfigDialog extends JDialog {
|
||||
btnOk.setToolTipText("Start the game");
|
||||
|
||||
JButton btnCancel = new JButton("Cancel");
|
||||
btnCancel.setBounds(170, 137, 95, 28);
|
||||
btnCancel.setBounds(222, 137, 95, 28);
|
||||
getContentPane().add(btnCancel);
|
||||
btnCancel.addActionListener((evt) -> dispose());
|
||||
btnCancel.setToolTipText("Cancel the game start");
|
||||
|
||||
JLabel lblMaximalRecursionDepth = new JLabel("Maximal Recursion Depth:");
|
||||
lblMaximalRecursionDepth.setBounds(16, 6, 141, 16);
|
||||
lblMaximalRecursionDepth.setBounds(16, 12, 194, 16);
|
||||
getContentPane().add(lblMaximalRecursionDepth);
|
||||
|
||||
setLocationRelativeTo(null);
|
||||
|
@ -25,6 +25,7 @@ public class MenuBar extends JMenuBar {
|
||||
private static final long serialVersionUID = -7221583703531248228L;
|
||||
|
||||
private final MainWindow mainWindow;
|
||||
private final BoardPane boardPane;
|
||||
private final OverlayComponent overlayComponent;
|
||||
private final BoardComponent boardComponent;
|
||||
private final Board board;
|
||||
@ -32,8 +33,9 @@ public class MenuBar extends JMenuBar {
|
||||
|
||||
public MenuBar(MainWindow mainWindow) {
|
||||
this.mainWindow = mainWindow;
|
||||
overlayComponent = mainWindow.getBoardPane().getOverlayComponent();
|
||||
boardComponent = mainWindow.getBoardPane().getBoardComponent();
|
||||
boardPane = mainWindow.getBoardPane();
|
||||
overlayComponent = boardPane.getOverlayComponent();
|
||||
boardComponent = boardPane.getBoardComponent();
|
||||
board = boardComponent.getBoard();
|
||||
players = new HashMap<>();
|
||||
|
||||
@ -78,7 +80,8 @@ public class MenuBar extends JMenuBar {
|
||||
}
|
||||
|
||||
private void startGame() {
|
||||
Game game = new Game(players, boardComponent);
|
||||
// TODO: Re-init board and overlay component
|
||||
Game game = new Game(players, boardPane);
|
||||
mainWindow.setGame(game);
|
||||
game.start();
|
||||
}
|
||||
|
@ -2,11 +2,17 @@ package dev.kske.chess.ui;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Graphics;
|
||||
import java.awt.Graphics2D;
|
||||
import java.awt.Point;
|
||||
import java.awt.Polygon;
|
||||
import java.awt.Shape;
|
||||
import java.awt.geom.AffineTransform;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JComponent;
|
||||
|
||||
import dev.kske.chess.board.Move;
|
||||
import dev.kske.chess.board.Position;
|
||||
|
||||
/**
|
||||
@ -22,11 +28,12 @@ public class OverlayComponent extends JComponent {
|
||||
private final BoardPane boardPane;
|
||||
|
||||
private List<Position> dots;
|
||||
private Move arrow;
|
||||
|
||||
public OverlayComponent(BoardPane boardPane) {
|
||||
this.boardPane = boardPane;
|
||||
setSize(boardPane.getPreferredSize());
|
||||
dots = new ArrayList<>();
|
||||
dots = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -45,6 +52,43 @@ public class OverlayComponent extends JComponent {
|
||||
radius,
|
||||
radius);
|
||||
}
|
||||
|
||||
if (arrow != null) {
|
||||
g.setColor(new Color(255, 0, 0, 127));
|
||||
Point pos = new Point(arrow.pos.x * tileSize + tileSize / 2, arrow.pos.y * tileSize + tileSize / 2);
|
||||
Point dest = new Point(arrow.dest.x * tileSize + tileSize / 2, arrow.dest.y * tileSize + tileSize / 2);
|
||||
((Graphics2D) g).fill(createArrowShape(pos, dest));
|
||||
}
|
||||
}
|
||||
|
||||
private Shape createArrowShape(Point pos, Point dest) {
|
||||
Polygon arrowPolygon = new Polygon();
|
||||
arrowPolygon.addPoint(-6, 1);
|
||||
arrowPolygon.addPoint(3, 1);
|
||||
arrowPolygon.addPoint(3, 3);
|
||||
arrowPolygon.addPoint(6, 0);
|
||||
arrowPolygon.addPoint(3, -3);
|
||||
arrowPolygon.addPoint(3, -1);
|
||||
arrowPolygon.addPoint(-6, -1);
|
||||
|
||||
Point midPoint = midpoint(pos, dest);
|
||||
|
||||
double rotate = Math.atan2(dest.y - pos.y, dest.x - pos.x);
|
||||
double ptDistance = pos.distance(dest);
|
||||
double scale = ptDistance / 12.0; // 12 because it's the length of the arrow
|
||||
// polygon.
|
||||
|
||||
AffineTransform transform = new AffineTransform();
|
||||
|
||||
transform.translate(midPoint.x, midPoint.y);
|
||||
transform.rotate(rotate);
|
||||
transform.scale(scale, 5);
|
||||
|
||||
return transform.createTransformedShape(arrowPolygon);
|
||||
}
|
||||
|
||||
private Point midpoint(Point p1, Point p2) {
|
||||
return new Point((int) ((p1.x + p2.x) / 2.0), (int) ((p1.y + p2.y) / 2.0));
|
||||
}
|
||||
|
||||
public void displayDots(List<Position> dots) {
|
||||
@ -58,5 +102,15 @@ public class OverlayComponent extends JComponent {
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void displayArrow(Move arrow) {
|
||||
this.arrow = arrow;
|
||||
repaint();
|
||||
}
|
||||
|
||||
public void clearArrow() {
|
||||
arrow = null;
|
||||
repaint();
|
||||
}
|
||||
|
||||
public int getTileSize() { return boardPane.getTileSize(); }
|
||||
}
|
||||
|
Reference in New Issue
Block a user