diff --git a/src/dev/kske/chess/game/Game.java b/src/dev/kske/chess/game/Game.java
index 5c2f5f2..cbe4ba8 100644
--- a/src/dev/kske/chess/game/Game.java
+++ b/src/dev/kske/chess/game/Game.java
@@ -6,7 +6,7 @@ import dev.kske.chess.board.Board;
import dev.kske.chess.board.GameState;
import dev.kske.chess.board.Move;
import dev.kske.chess.board.Piece.Color;
-import dev.kske.chess.ui.BoardPanel;
+import dev.kske.chess.ui.BoardComponent;
/**
* Project: Chess
@@ -18,12 +18,12 @@ public class Game {
private Map players;
private Board board;
- private BoardPanel boardPanel;
+ private BoardComponent boardComponent;
- public Game(Map players, Board board, BoardPanel boardPanel) {
- this.players = players;
- this.board = board;
- this.boardPanel = boardPanel;
+ public Game(Map players, BoardComponent boardComponent) {
+ this.players = players;
+ this.boardComponent = boardComponent;
+ this.board = boardComponent.getBoard();
// Initialize the game variable in each player
players.values().forEach(player -> player.setGame(this));
@@ -45,13 +45,10 @@ public class Game {
case CHECK:
System.out.printf("%s in check!%n", player.color.opposite());
default:
- boardPanel.repaint();
+ boardComponent.repaint();
players.get(player.color.opposite()).requestMove();
}
- } else {
- System.out.printf("%s: Illegal move!%n", player.getColor());
- player.requestMove();
- }
+ } else player.requestMove();
}
}
diff --git a/src/dev/kske/chess/game/NaturalPlayer.java b/src/dev/kske/chess/game/NaturalPlayer.java
index 9229096..63a6f96 100644
--- a/src/dev/kske/chess/game/NaturalPlayer.java
+++ b/src/dev/kske/chess/game/NaturalPlayer.java
@@ -2,12 +2,14 @@ package dev.kske.chess.game;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
+import java.util.List;
+import java.util.stream.Collectors;
import dev.kske.chess.board.Board;
import dev.kske.chess.board.Move;
import dev.kske.chess.board.Piece.Color;
import dev.kske.chess.board.Position;
-import dev.kske.chess.ui.BoardPanel;
+import dev.kske.chess.ui.OverlayComponent;
/**
* Project: Chess
@@ -19,10 +21,10 @@ public class NaturalPlayer extends Player {
private boolean moveRequested;
- public NaturalPlayer(Board board, Color color, BoardPanel boardPanel) {
+ public NaturalPlayer(Board board, Color color, OverlayComponent overlayComponent) {
super(board, color);
moveRequested = false;
- boardPanel.addMouseListener(new MouseAdapter() {
+ overlayComponent.addMouseListener(new MouseAdapter() {
private Position pos;
@@ -30,21 +32,25 @@ public class NaturalPlayer extends Player {
public void mousePressed(MouseEvent evt) {
if (!moveRequested) return;
if (pos == null) {
- pos = new Position(evt.getPoint().x / boardPanel.getTileSize(),
- evt.getPoint().y / boardPanel.getTileSize());
+ pos = new Position(evt.getPoint().x / overlayComponent.getTileSize(),
+ evt.getPoint().y / overlayComponent.getTileSize());
Board board = (Board) NaturalPlayer.this.board.clone();
- if (board.get(pos) != null && board.get(pos).getColor() == color)
- boardPanel.displayMoves(board.getMoves(pos));
- else pos = null;
+ if (board.get(pos) != null && board.get(pos).getColor() == color) {
+ List positions = board.getMoves(pos)
+ .stream()
+ .map(move -> move.dest)
+ .collect(Collectors.toList());
+ overlayComponent.displayDots(positions);
+ } else pos = null;
} else {
- Position dest = new Position(evt.getPoint().x / boardPanel.getTileSize(),
- evt.getPoint().y / boardPanel.getTileSize());
+ Position dest = new Position(evt.getPoint().x / overlayComponent.getTileSize(),
+ evt.getPoint().y / overlayComponent.getTileSize());
- boardPanel.clearDisplayMoves();
+ overlayComponent.clearDots();
moveRequested = false;
game.onMove(NaturalPlayer.this, new Move(pos, dest));
- pos = null;
+ pos = null;
}
}
});
diff --git a/src/dev/kske/chess/ui/BoardComponent.java b/src/dev/kske/chess/ui/BoardComponent.java
new file mode 100644
index 0000000..09b97d7
--- /dev/null
+++ b/src/dev/kske/chess/ui/BoardComponent.java
@@ -0,0 +1,62 @@
+package dev.kske.chess.ui;
+
+import java.awt.Color;
+import java.awt.Graphics;
+
+import javax.swing.JComponent;
+
+import dev.kske.chess.board.Board;
+
+/**
+ * Project: Chess
+ * File: BoardComponent.java
+ * Created: 01.07.2019
+ * Author: Kai S. K. Engelbart
+ *
+ * A square panel for rendering the chess board. To work correctly,
+ * this must be added to a parent component that allows the child to decide the
+ * size.
+ */
+public class BoardComponent extends JComponent {
+
+ private static final long serialVersionUID = 6771148331334310216L;
+
+ private final BoardPane boardPane;
+
+ private Board board;
+
+ public BoardComponent(BoardPane boardPane) {
+ this.boardPane = boardPane;
+ setSize(boardPane.getPreferredSize());
+ }
+
+ @Override
+ protected void paintComponent(Graphics g) {
+ super.paintComponent(g);
+
+ final int tileSize = getTileSize();
+
+ // Draw the board
+ g.setColor(Color.white);
+ for (int i = 0; i < 8; i++)
+ for (int j = 0; j < 8; j++) {
+ if (j > 0) g.setColor(g.getColor().equals(Color.white) ? Color.lightGray : Color.white);
+ g.fillRect(tileSize * i, tileSize * j, tileSize, tileSize);
+ }
+
+ // Draw the pieces if a board is present
+ if (board != null) for (int i = 0; i < 8; i++)
+ for (int j = 0; j < 8; j++)
+ if (board.getBoardArr()[i][j] != null) g.drawImage(TextureUtil
+ .getPieceTexture(board.getBoardArr()[i][j]), i * tileSize, j * tileSize, this);
+ }
+
+ public int getTileSize() { return boardPane.getTileSize(); }
+
+ public Board getBoard() { return board; }
+
+ public void setBoard(Board board) {
+ this.board = board;
+ repaint();
+ }
+}
diff --git a/src/dev/kske/chess/ui/BoardPane.java b/src/dev/kske/chess/ui/BoardPane.java
new file mode 100644
index 0000000..a2349db
--- /dev/null
+++ b/src/dev/kske/chess/ui/BoardPane.java
@@ -0,0 +1,55 @@
+package dev.kske.chess.ui;
+
+import java.awt.Dimension;
+import java.awt.event.ComponentAdapter;
+import java.awt.event.ComponentEvent;
+
+import javax.swing.JLayeredPane;
+
+/**
+ * Project: Chess
+ * File: BoardPane.java
+ * Created: 08.07.2019
+ * Author: Kai S. K. Engelbart
+ */
+public class BoardPane extends JLayeredPane {
+
+ private static final long serialVersionUID = -5415058382478806092L;
+
+ private final BoardComponent boardComponent;
+ private final OverlayComponent overlayComponent;
+
+ private int tileSize;
+
+ public BoardPane() {
+ boardComponent = new BoardComponent(this);
+ overlayComponent = new OverlayComponent(this);
+
+ add(boardComponent, Integer.valueOf(1));
+ add(overlayComponent, Integer.valueOf(2));
+
+ /*
+ * Add a component listener for adjusting the tile size on resizing.
+ * The size of the board is assumed to be 8x8, as well as the both the board and
+ * the tiles being square.
+ */
+ addComponentListener(new ComponentAdapter() {
+
+ @Override
+ public void componentResized(ComponentEvent e) {
+ tileSize = getWidth() / 8;
+ TextureUtil.scalePieceTextures(tileSize);
+ }
+ });
+ setSize(getPreferredSize());
+ }
+
+ @Override
+ public Dimension getPreferredSize() { return new Dimension(480, 480); }
+
+ public BoardComponent getBoardComponent() { return boardComponent; }
+
+ public OverlayComponent getOverlayComponent() { return overlayComponent; }
+
+ public int getTileSize() { return tileSize; }
+}
diff --git a/src/dev/kske/chess/ui/BoardPanel.java b/src/dev/kske/chess/ui/BoardPanel.java
deleted file mode 100644
index 5cf4b3c..0000000
--- a/src/dev/kske/chess/ui/BoardPanel.java
+++ /dev/null
@@ -1,131 +0,0 @@
-package dev.kske.chess.ui;
-
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Graphics;
-import java.awt.event.ComponentAdapter;
-import java.awt.event.ComponentEvent;
-import java.util.ArrayList;
-import java.util.List;
-
-import javax.swing.JPanel;
-
-import dev.kske.chess.board.Board;
-import dev.kske.chess.board.Move;
-
-/**
- * Project: Chess
- * File: BoardPanel.java
- * Created: 01.07.2019
- * Author: Kai S. K. Engelbart
- *
- * A square panel for rendering the chess board. To work correctly,
- * this must be added to a parent component that allows the child to decide the
- * size.
- */
-public class BoardPanel extends JPanel {
-
- private static final long serialVersionUID = 6771148331334310216L;
-
- private int tileSize;
- private Board board;
-
- private List displayMoves;
-
- public BoardPanel(Board board) {
- this();
- setBoard(board);
- }
-
- public BoardPanel() {
- displayMoves = new ArrayList<>();
-
- /*
- * Add a component listener for adjusting the tile size on resizing.
- * The size of the board is assumed to be 8x8, as well as the both the board and
- * the tiles being square.
- */
- addComponentListener(new ComponentAdapter() {
-
- @Override
- public void componentResized(ComponentEvent e) {
- tileSize = getWidth() / 8;
- TextureUtil.scalePieceTextures(tileSize);
- }
- });
-
- setSize(getPreferredSize());
- }
-
- @Override
- protected void paintComponent(Graphics g) {
- super.paintComponent(g);
-
- // Draw the board
- g.setColor(Color.white);
- for (int i = 0; i < 8; i++)
- for (int j = 0; j < 8; j++) {
- if (j > 0) g.setColor(g.getColor().equals(Color.white) ? Color.lightGray : Color.white);
- g.fillRect(tileSize * i, tileSize * j, tileSize, tileSize);
- }
-
- // Draw the pieces if a board is present
- if (board != null) for (int i = 0; i < 8; i++)
- for (int j = 0; j < 8; j++)
- if (board.getBoardArr()[i][j] != null) g.drawImage(TextureUtil
- .getPieceTexture(board.getBoardArr()[i][j]), i * tileSize, j * tileSize, this);
-
- // Draw possible moves if a piece was selected
- if (!displayMoves.isEmpty()) {
- g.setColor(Color.green);
- int radius = tileSize / 4;
- for (Move move : displayMoves)
- g.fillOval(move.dest.x * tileSize + tileSize / 2 - radius / 2,
- move.dest.y * tileSize + tileSize / 2 - radius / 2,
- radius,
- radius);
- }
- }
-
- /**
- * Displays move destinations on the board.
- *
- * @param moves The moves to display
- */
- public void displayMoves(List moves) {
- displayMoves.clear();
- displayMoves.addAll(moves);
- repaint();
- }
-
- /**
- * Clears all display moves.
- */
- public void clearDisplayMoves() {
- displayMoves.clear();
- repaint();
- }
-
- /**
- * Reverts the board to its initial state.
- */
- public void reset() {
- board.initializeDefaultPositions();
- repaint();
- }
-
- @Override
- public Dimension getMinimumSize() { return getPreferredSize(); }
-
- @Override
- public Dimension getMaximumSize() { return getPreferredSize(); }
-
- @Override
- public Dimension getPreferredSize() { return new Dimension(480, 480); }
-
- public int getTileSize() { return tileSize; }
-
- public Board getBoard() { return board; }
-
- public void setBoard(Board board) { this.board = board; }
-}
diff --git a/src/dev/kske/chess/ui/GameModeDialog.java b/src/dev/kske/chess/ui/GameModeDialog.java
index aee5471..f9d7dcf 100644
--- a/src/dev/kske/chess/ui/GameModeDialog.java
+++ b/src/dev/kske/chess/ui/GameModeDialog.java
@@ -7,6 +7,7 @@ import java.util.Map;
import javax.swing.JButton;
import javax.swing.JDialog;
+import dev.kske.chess.board.Board;
import dev.kske.chess.board.Piece.Color;
import dev.kske.chess.game.Game;
import dev.kske.chess.game.NaturalPlayer;
@@ -26,7 +27,7 @@ public class GameModeDialog extends JDialog {
/**
* Create the dialog.
*/
- public GameModeDialog(BoardPanel boardPanel) {
+ public GameModeDialog(BoardPane boardPane) {
super();
setModal(true);
setTitle("Game Mode Selection");
@@ -34,12 +35,16 @@ public class GameModeDialog extends JDialog {
setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
getContentPane().setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
+ final BoardComponent boardComponent = boardPane.getBoardComponent();
+ final OverlayComponent overlayComponent = boardPane.getOverlayComponent();
+ final Board board = boardComponent.getBoard();
+
JButton btnNatural = new JButton("Game against natural opponent");
btnNatural.addActionListener((evt) -> {
Map players = new HashMap<>();
- players.put(Color.WHITE, new NaturalPlayer(boardPanel.getBoard(), Color.WHITE, boardPanel));
- players.put(Color.BLACK, new NaturalPlayer(boardPanel.getBoard(), Color.BLACK, boardPanel));
- new Game(players, boardPanel.getBoard(), boardPanel).start();
+ players.put(Color.WHITE, new NaturalPlayer(board, Color.WHITE, overlayComponent));
+ players.put(Color.BLACK, new NaturalPlayer(board, Color.BLACK, overlayComponent));
+ new Game(players, boardComponent).start();
dispose();
});
getContentPane().add(btnNatural);
@@ -47,24 +52,21 @@ public class GameModeDialog extends JDialog {
JButton btnAI = new JButton("Game against AI");
btnAI.addActionListener((evt) -> {
Map players = new HashMap<>();
- players.put(Color.WHITE, new NaturalPlayer(boardPanel.getBoard(), Color.WHITE, boardPanel));
- players.put(Color.BLACK, new AIPlayer(boardPanel.getBoard(), Color.BLACK, 4));
- startGame(players, boardPanel);
+ players.put(Color.WHITE, new NaturalPlayer(board, Color.WHITE, overlayComponent));
+ players.put(Color.BLACK, new AIPlayer(board, Color.BLACK, 4));
+ new Game(players, boardComponent).start();
+ dispose();
});
getContentPane().add(btnAI);
JButton btnAI2 = new JButton("AI against AI");
btnAI2.addActionListener((evt) -> {
Map players = new HashMap<>();
- players.put(Color.WHITE, new AIPlayer(boardPanel.getBoard(), Color.WHITE, 4));
- players.put(Color.BLACK, new AIPlayer(boardPanel.getBoard(), Color.BLACK, 3));
- startGame(players, boardPanel);
+ players.put(Color.WHITE, new AIPlayer(board, Color.WHITE, 4));
+ players.put(Color.BLACK, new AIPlayer(board, Color.BLACK, 3));
+ new Game(players, boardComponent).start();
+ dispose();
});
getContentPane().add(btnAI2);
}
-
- private void startGame(Map players, BoardPanel boardPanel) {
- new Game(players, boardPanel.getBoard(), boardPanel).start();
- dispose();
- }
}
diff --git a/src/dev/kske/chess/ui/MainWindow.java b/src/dev/kske/chess/ui/MainWindow.java
index 8784f42..9948987 100644
--- a/src/dev/kske/chess/ui/MainWindow.java
+++ b/src/dev/kske/chess/ui/MainWindow.java
@@ -53,19 +53,19 @@ public class MainWindow {
mframe.setBounds(100, 100, 494, 565);
mframe.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
- BoardPanel boardPanel = new BoardPanel(new Board());
- boardPanel.setLayout(null);
- mframe.getContentPane().add(boardPanel, BorderLayout.CENTER);
+ BoardPane boardPane = new BoardPane();
+ boardPane.getBoardComponent().setBoard(new Board());
+ mframe.getContentPane().add(boardPane, BorderLayout.CENTER);
JPanel toolPanel = new JPanel();
mframe.getContentPane().add(toolPanel, BorderLayout.NORTH);
JButton btnRestart = new JButton("Restart");
- btnRestart.addActionListener((evt) -> boardPanel.reset());
+ btnRestart.addActionListener((evt) -> System.err.println("Resetting not implemented!"));
toolPanel.add(btnRestart);
mframe.pack();
// Display dialog for game mode selection
- new GameModeDialog(boardPanel).setVisible(true);
+ new GameModeDialog(boardPane).setVisible(true);
}
}
diff --git a/src/dev/kske/chess/ui/OverlayComponent.java b/src/dev/kske/chess/ui/OverlayComponent.java
new file mode 100644
index 0000000..86557ad
--- /dev/null
+++ b/src/dev/kske/chess/ui/OverlayComponent.java
@@ -0,0 +1,62 @@
+package dev.kske.chess.ui;
+
+import java.awt.Color;
+import java.awt.Graphics;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.swing.JComponent;
+
+import dev.kske.chess.board.Position;
+
+/**
+ * Project: Chess
+ * File: OverlayComponent.java
+ * Created: 08.07.2019
+ * Author: Kai S. K. Engelbart
+ */
+public class OverlayComponent extends JComponent {
+
+ private static final long serialVersionUID = -7326936060890082183L;
+
+ private final BoardPane boardPane;
+
+ private List dots;
+
+ public OverlayComponent(BoardPane boardPane) {
+ this.boardPane = boardPane;
+ setSize(boardPane.getPreferredSize());
+ dots = new ArrayList<>();
+ }
+
+ @Override
+ protected void paintComponent(Graphics g) {
+ super.paintComponent(g);
+
+ final int tileSize = getTileSize();
+
+ // Draw possible moves if a piece was selected
+ if (!dots.isEmpty()) {
+ g.setColor(Color.green);
+ int radius = tileSize / 4;
+ for (Position dot : dots)
+ g.fillOval(dot.x * tileSize + tileSize / 2 - radius / 2,
+ dot.y * tileSize + tileSize / 2 - radius / 2,
+ radius,
+ radius);
+ }
+ }
+
+ public void displayDots(List dots) {
+ this.dots.clear();
+ this.dots.addAll(dots);
+ repaint();
+ }
+
+ public void clearDots() {
+ dots.clear();
+ repaint();
+ }
+
+ public int getTileSize() { return boardPane.getTileSize(); }
+}