174 lines
4.2 KiB
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(); }
|
|
}
|