Created a separate UI package

- Renamed Chess to MainWindow
- Moved MainWindow, BoardPanel and TextureUtil into the UI package
This commit is contained in:
2019-07-06 16:37:42 +02:00
parent 9354a83569
commit 612fb5fc9a
4 changed files with 15 additions and 8 deletions

View 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);
}
}

View 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();
}
}

View 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));
}
}