Created a separate UI package
- Renamed Chess to MainWindow - Moved MainWindow, BoardPanel and TextureUtil into the UI package
This commit is contained in:
160
src/dev/kske/chess/ui/BoardPanel.java
Normal file
160
src/dev/kske/chess/ui/BoardPanel.java
Normal file
@ -0,0 +1,160 @@
|
||||
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.awt.event.MouseAdapter;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import dev.kske.chess.Board;
|
||||
import dev.kske.chess.Move;
|
||||
import dev.kske.chess.Position;
|
||||
import dev.kske.chess.event.GameEvent;
|
||||
import dev.kske.chess.event.GameEventListener;
|
||||
|
||||
/**
|
||||
* Project: <strong>Chess</strong><br>
|
||||
* File: <strong>BoardPanel.java</strong><br>
|
||||
* Created: <strong>01.07.2019</strong><br>
|
||||
* Author: <strong>Kai S. K. Engelbart</strong><br>
|
||||
* <br>
|
||||
* 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 implements GameEventListener {
|
||||
|
||||
private static final long serialVersionUID = 6771148331334310216L;
|
||||
|
||||
private int tileSize;
|
||||
private Board board;
|
||||
|
||||
private List<Move> 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());
|
||||
|
||||
// Add a mouse adapter for testing piece movement
|
||||
addMouseListener(new MouseAdapter() {
|
||||
|
||||
private Position pos;
|
||||
|
||||
@Override
|
||||
public void mousePressed(MouseEvent evt) {
|
||||
if (pos == null) {
|
||||
pos = new Position(evt.getPoint().x / tileSize, evt.getPoint().y / tileSize);
|
||||
|
||||
if (board.get(pos) != null) {
|
||||
displayMoves.clear();
|
||||
displayMoves.addAll(board.getMoves(pos));
|
||||
repaint();
|
||||
}
|
||||
} else {
|
||||
Position dest = new Position(evt.getPoint().x / tileSize, evt.getPoint().y / tileSize);
|
||||
|
||||
if (board.attemptMove(new Move(pos, dest))) {
|
||||
displayMoves.clear();
|
||||
repaint();
|
||||
}
|
||||
pos = null;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@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);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onGameEvent(GameEvent evt) {
|
||||
switch (evt.getEventType()) {
|
||||
case CHECK:
|
||||
JOptionPane.showMessageDialog(this, evt.getColor().toString() + " in check!");
|
||||
break;
|
||||
case CHECKMATE:
|
||||
JOptionPane.showMessageDialog(this, evt.getColor().toString() + " in checkmate!");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 Board getBoard() { return board; }
|
||||
|
||||
public void setBoard(Board board) {
|
||||
this.board = board;
|
||||
|
||||
// Register this BoardPanel as a GameEventListener to the board
|
||||
board.registerGameEventListener(this);
|
||||
}
|
||||
}
|
68
src/dev/kske/chess/ui/MainWindow.java
Normal file
68
src/dev/kske/chess/ui/MainWindow.java
Normal file
@ -0,0 +1,68 @@
|
||||
package dev.kske.chess.ui;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.EventQueue;
|
||||
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JPanel;
|
||||
|
||||
import dev.kske.chess.Board;
|
||||
|
||||
|
||||
/**
|
||||
* Project: <strong>Chess</strong><br>
|
||||
* File: <strong>MainWindow.java</strong><br>
|
||||
* Created: <strong>01.07.2019</strong><br>
|
||||
* Author: <strong>Kai S. K. Engelbart</strong>
|
||||
*/
|
||||
public class MainWindow {
|
||||
|
||||
private JFrame mframe;
|
||||
|
||||
/**
|
||||
* Launch the application.
|
||||
*/
|
||||
public static void main(String[] args) {
|
||||
EventQueue.invokeLater(new Runnable() {
|
||||
|
||||
public void run() {
|
||||
try {
|
||||
MainWindow window = new MainWindow();
|
||||
window.mframe.setVisible(true);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Create the application.
|
||||
*/
|
||||
public MainWindow() {
|
||||
initialize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the contents of the frame.
|
||||
*/
|
||||
private void initialize() {
|
||||
mframe = new JFrame();
|
||||
mframe.setResizable(false);
|
||||
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);
|
||||
|
||||
JPanel toolPanel = new JPanel();
|
||||
mframe.getContentPane().add(toolPanel, BorderLayout.NORTH);
|
||||
|
||||
JButton btnRestart = new JButton("Restart");
|
||||
btnRestart.addActionListener((evt) -> boardPanel.reset());
|
||||
toolPanel.add(btnRestart);
|
||||
mframe.pack();
|
||||
}
|
||||
}
|
76
src/dev/kske/chess/ui/TextureUtil.java
Normal file
76
src/dev/kske/chess/ui/TextureUtil.java
Normal file
@ -0,0 +1,76 @@
|
||||
package dev.kske.chess.ui;
|
||||
|
||||
import java.awt.Image;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
|
||||
import dev.kske.chess.piece.Piece;
|
||||
|
||||
/**
|
||||
* Project: <strong>Chess</strong><br>
|
||||
* File: <strong>TextureUtil.java</strong><br>
|
||||
* Created: <strong>01.07.2019</strong><br>
|
||||
* Author: <strong>Kai S. K. Engelbart</strong>
|
||||
*/
|
||||
public class TextureUtil {
|
||||
|
||||
private static Map<String, Image> textures;
|
||||
|
||||
static {
|
||||
textures = new HashMap<>();
|
||||
loadPieceTextures();
|
||||
}
|
||||
|
||||
private TextureUtil() {}
|
||||
|
||||
/**
|
||||
* Loads a piece texture fitting to a piece object
|
||||
*
|
||||
* @param piece The piece from which the texture properties are taken
|
||||
* @return The fitting texture
|
||||
*/
|
||||
public static Image getPieceTexture(Piece piece) {
|
||||
String key = piece.getType().toString().toLowerCase() + "_" + piece.getColor().toString().toLowerCase();
|
||||
return textures.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Scales all piece textures to fit the current tile size
|
||||
*/
|
||||
public static void scalePieceTextures(int scale) {
|
||||
textures.replaceAll((key, img) -> img.getScaledInstance(scale, scale, Image.SCALE_SMOOTH));
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an image from a file.
|
||||
*
|
||||
* @param file The image file
|
||||
* @return The loaded image
|
||||
*/
|
||||
private static Image loadImage(File file) {
|
||||
BufferedImage in = null;
|
||||
try {
|
||||
in = ImageIO.read(file);
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return in;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load every PNG file inside the res/pieces directory.
|
||||
* The filenames without extensions are used as keys in the map textures.
|
||||
*/
|
||||
private static void loadPieceTextures() {
|
||||
File dir = new File("res/pieces");
|
||||
File[] files = dir.listFiles((File parentDir, String name) -> name.toLowerCase().endsWith(".png"));
|
||||
for (File file : files)
|
||||
textures.put(file.getName().replaceFirst("[.][^.]+$", ""), TextureUtil.loadImage(file));
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user