This repository has been archived on 2021-02-18. You can view files and clone it, but cannot push or open issues or pull requests.
chess/src/main/java/dev/kske/chess/ui/OverlayComponent.java

174 lines
4.2 KiB
Java

package dev.kske.chess.ui;
import java.awt.*;
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;
/**
* Project: <strong>Chess</strong><br>
* File: <strong>OverlayComponent.java</strong><br>
* Created: <strong>08.07.2019</strong><br>
*
* @since Chess v0.1-alpha
* @author Kai S. K. Engelbart
*/
public class OverlayComponent extends JComponent {
private static final long serialVersionUID = -7326936060890082183L;
private final BoardPane boardPane;
private List<Position> dots;
private Move arrow;
/**
* Creates an instance of {@link OverlayComponent}.
*
* @param boardPane the board pane inside which this overlay component is
* contained
*/
public OverlayComponent(BoardPane boardPane) {
this.boardPane = boardPane;
dots = new ArrayList<>();
setSize(boardPane.getPreferredSize());
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
final int tileSize = boardPane.getTileSize();
// Draw an arrow representing the last move and mark its position and
// destination
if (arrow != null) {
Point pos = new Point(
arrow.getPos().x * tileSize + tileSize / 2,
arrow.getPos().y * tileSize + tileSize / 2
);
Point dest = new Point(
arrow.getDest().x * tileSize + tileSize / 2,
arrow.getDest().y * tileSize + tileSize / 2
);
Graphics2D g2d = (Graphics2D) g;
g2d.setStroke(new BasicStroke(3));
g2d.setColor(Color.yellow);
g2d.drawRect(
arrow.getPos().x * tileSize,
arrow.getPos().y * tileSize,
tileSize,
tileSize
);
g2d.drawRect(
arrow.getDest().x * tileSize,
arrow.getDest().y * tileSize,
tileSize,
tileSize
);
Shape arrowShape = createArrowShape(pos, dest);
g.setColor(new Color(255, 0, 0, 127));
g2d.fill(arrowShape);
g2d.setColor(Color.black);
g2d.draw(arrowShape);
}
// 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
);
}
}
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)
);
}
/**
* Displays green dots at a list of positions.
*
* @param dots the positions at which the dots should be displayed
*/
public void displayDots(List<Position> dots) {
this.dots.clear();
this.dots.addAll(dots);
repaint();
}
/**
* Clears all dots displayed at some positions.
*/
public void clearDots() {
dots.clear();
repaint();
}
/**
* Displays an arrow from the position to the destination of a move.
*
* @param arrow the move indicating the arrows position and destination
*/
public void displayArrow(Move arrow) {
this.arrow = arrow;
repaint();
}
/**
* Clears the arrow displayed to indicate a move.
*/
public void clearArrow() {
arrow = null;
repaint();
}
/**
* @return the size of one board tile in pixels.
* @see dev.kske.chess.ui.BoardPane#getTileSize()
*/
public int getTileSize() { return boardPane.getTileSize(); }
}