374 lines
10 KiB
Java
374 lines
10 KiB
Java
import java.awt.*;
|
|
import java.awt.geom.Ellipse2D;
|
|
import java.awt.geom.Path2D;
|
|
import java.util.Timer;
|
|
import java.util.TimerTask;
|
|
|
|
/**
|
|
* Abstract piece class
|
|
*/
|
|
public abstract class APiece {
|
|
|
|
/**
|
|
* Chessboard instance
|
|
*/
|
|
protected Chessboard chessboard;
|
|
|
|
/**
|
|
* Piece's X location
|
|
*/
|
|
protected int x;
|
|
|
|
/**
|
|
* Piece's Y location
|
|
*/
|
|
protected int y;
|
|
|
|
/**
|
|
* Piece's X override location
|
|
*/
|
|
public double overrideX;
|
|
|
|
/**
|
|
* Piece's Y override location
|
|
*/
|
|
public double overrideY;
|
|
|
|
/**
|
|
* Piece's color
|
|
*/
|
|
protected PieceColor color;
|
|
|
|
protected Player player;
|
|
|
|
public int moveCount = 0;
|
|
|
|
public double scale = 1;
|
|
|
|
/**
|
|
* Create new piece
|
|
* @param player player
|
|
* @param x piece's X location
|
|
* @param y piece's Y location
|
|
*/
|
|
public APiece(Player player, int x, int y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.player = player;
|
|
this.chessboard = player.getChessboard();
|
|
this.color = player.getColor();
|
|
chessboard.addPiece(this, x, y);
|
|
}
|
|
|
|
/**
|
|
* Create Path2D object from points
|
|
* @param points object's points
|
|
* @return Path2D object
|
|
*/
|
|
public Path2D getObject(double[][] points) {
|
|
Path2D object = new Path2D.Double();
|
|
object.moveTo(points[0][0], points[0][1]);
|
|
for (int i = 1; i < points.length; i++) {
|
|
if(points[i].length == 2) object.lineTo(points[i][0], points[i][1]);
|
|
if(points[i].length == 6) object.curveTo(points[i][2], points[i][3], points[i][4], points[i][5], points[i][0], points[i][1]);
|
|
}
|
|
object.closePath();
|
|
return object;
|
|
}
|
|
|
|
/**
|
|
* Create Path2D object from points
|
|
* @param xPoints object's X points
|
|
* @param yPoints object's Y points
|
|
* @return Path2D object
|
|
*/
|
|
public Path2D getObject(double[] xPoints, double[] yPoints) {
|
|
double[][] points = new double[xPoints.length][];
|
|
for (int i = 0; i < points.length; i++) {
|
|
points[i] = new double[2];
|
|
points[i][0] = xPoints[i];
|
|
points[i][1] = yPoints[i];
|
|
}
|
|
return getObject(points);
|
|
}
|
|
|
|
/**
|
|
* Create Ellipse2D from specified coordinates
|
|
* @param x ellipse's X coordinate
|
|
* @param y ellipse's Y coordinate
|
|
* @param w ellipse width
|
|
* @param h ellipse height
|
|
* @return Ellipse2D object
|
|
*/
|
|
public Ellipse2D getEllipse(double x, double y, double w, double h) {
|
|
return new Ellipse2D.Double(x, y, w, h);
|
|
}
|
|
|
|
/**
|
|
* Create piece's stand
|
|
* @return Path2D stand
|
|
*/
|
|
public Path2D getStand() {
|
|
|
|
double[] xStand = new double[]{30, 70, 70, 60, 90, 90, 10, 10, 40, 30};
|
|
double[] yStand = new double[]{64, 64, 69, 69, 87, 100, 100, 87, 69, 69};
|
|
|
|
double[][] points = new double[xStand.length][];
|
|
for (int i = 0; i < points.length; i++) {
|
|
if(i == 4) {
|
|
points[i] = new double[]{xStand[i], yStand[i], 69+3, 80-5, 69-3, 80+5};
|
|
} else if(i == 8) {
|
|
points[i] = new double[]{xStand[i], yStand[i], 31+3, 80+5, 31-3, 80-5};
|
|
} else {
|
|
points[i] = new double[2];
|
|
points[i][0] = xStand[i];
|
|
points[i][1] = yStand[i];
|
|
}
|
|
}
|
|
|
|
|
|
return getObject(points);
|
|
|
|
}
|
|
|
|
/**
|
|
* Paint specified objects
|
|
* @param g2 Graphics2D
|
|
* @param objects painted objects
|
|
*/
|
|
public void paintObjects(Graphics2D g2, Shape[] objects) {
|
|
g2.setStroke(new BasicStroke(8));
|
|
for (Shape object : objects) {
|
|
g2.setColor(color.draw);
|
|
g2.draw(object);
|
|
g2.setColor(color.fill);
|
|
g2.fill(object);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Set piece's new position
|
|
* @param pos piece position
|
|
*/
|
|
public void setPosition(PiecePosition pos) {
|
|
setPosition(pos, true);
|
|
}
|
|
|
|
/**
|
|
* Set piece's new position
|
|
* @param pos piece position
|
|
* @param animate animate piece's move
|
|
*/
|
|
public void setPosition(PiecePosition pos, boolean animate) {
|
|
if(animate) animateMove(x, y, pos.x, pos.y);
|
|
moveCount++;
|
|
chessboard.removePiece(x, y);
|
|
APiece piece = chessboard.getPiece(pos.x, pos.y);
|
|
if(piece != null) {
|
|
piece.remove(animate);
|
|
}
|
|
x = pos.x;
|
|
y = pos.y;
|
|
chessboard.addPiece(this, x, y);
|
|
}
|
|
|
|
public boolean isFloating() {
|
|
return overrideX != 0 && overrideY != 0;
|
|
}
|
|
|
|
/**
|
|
* Set override location if piece is floating
|
|
* @param x floating piece's X location
|
|
* @param y floating piece's Y location
|
|
*/
|
|
public void setOverride(double x, double y) {
|
|
overrideX = x;
|
|
overrideY = y;
|
|
}
|
|
|
|
/**
|
|
* Get piece's override X location
|
|
* @return override X location
|
|
*/
|
|
public double getOverrideX() {
|
|
return (overrideX-chessboard.startX)/chessboard.boardScale;
|
|
}
|
|
|
|
/**
|
|
* Get piece's override Y location
|
|
* @return override Y location
|
|
*/
|
|
public double getOverrideY() {
|
|
return (overrideY-chessboard.startY)/chessboard.boardScale;
|
|
}
|
|
|
|
public double getRealX() {
|
|
if(overrideX != 0) return getOverrideX();
|
|
return chessboard.SQUARE_SIZE*x;
|
|
}
|
|
|
|
public double getRealY() {
|
|
if(overrideY != 0) return getOverrideY();
|
|
return chessboard.SQUARE_SIZE*y;
|
|
}
|
|
|
|
/**
|
|
* Get piece's X location
|
|
* @return piece's X location
|
|
*/
|
|
public int getX() {
|
|
return x;
|
|
}
|
|
|
|
/**
|
|
* Get piece's Y location
|
|
* @return piece's Y location
|
|
*/
|
|
public int getY() {
|
|
return y;
|
|
}
|
|
|
|
public PieceColor getColor() {
|
|
return color;
|
|
}
|
|
|
|
public void setPossibleMove(boolean[][] moves, int x, int y) {
|
|
|
|
if(x == this.x && y == this.y) return;
|
|
if(x < 0 || x >= moves.length || y < 0 || y >= moves.length) return;
|
|
APiece piece = chessboard.getPiece(x, y);
|
|
if(piece != null && player == piece.getPlayer()) return;
|
|
if(tryMove(piece, x, y)) return;
|
|
moves[y][x] = true;
|
|
|
|
}
|
|
|
|
public boolean tryMove(APiece piece, int x, int y) {
|
|
chessboard.removePiece(this.x, this.y);
|
|
chessboard.addPiece(this, x, y);
|
|
int xBefore = this.x;
|
|
int yBefore = this.y;
|
|
this.x = x;
|
|
this.y = y;
|
|
boolean inCheck = player.inCheck();
|
|
this.x = xBefore;
|
|
this.y = yBefore;
|
|
chessboard.addPiece(piece, x, y);
|
|
chessboard.addPiece(this, this.x, this.y);
|
|
return inCheck;
|
|
}
|
|
|
|
public boolean isEndangered() {
|
|
return chessboard.isEndangered(x, y);
|
|
}
|
|
|
|
public void move(PiecePosition pos) {
|
|
move(pos, true);
|
|
}
|
|
|
|
public void move(PiecePosition pos, boolean animate) {
|
|
boolean[][] lastMove = new boolean[chessboard.SQUARE_COUNT][chessboard.SQUARE_COUNT];
|
|
lastMove[y][x] = true;
|
|
lastMove[pos.y][pos.x] = true;
|
|
setPosition(pos, animate);
|
|
chessboard.showLastMove(lastMove);
|
|
}
|
|
|
|
public Rectangle getRepaintRectangle() {
|
|
return getRepaintRectangle(Chess.menuBar.getHeight());
|
|
}
|
|
|
|
public Rectangle getRepaintRectangle(int offsetY) {
|
|
int rectSize = (int) (chessboard.SQUARE_SIZE*chessboard.boardScale);
|
|
double x = getRealX()*chessboard.boardScale+chessboard.startX;
|
|
double y = getRealY()*chessboard.boardScale+chessboard.startY;
|
|
return new Rectangle(
|
|
(int) x - 10, (int) y + offsetY - 10,
|
|
rectSize + 20, rectSize + 20
|
|
);
|
|
}
|
|
|
|
public void tracePath(boolean[][] moves, int xDirection, int yDirection) {
|
|
int i = x + xDirection;
|
|
int j = y + yDirection;
|
|
while(i >= 0 && i < moves.length && j >= 0 && j < moves.length) {
|
|
setPossibleMove(moves, i, j);
|
|
APiece piece = chessboard.getPiece(i, j);
|
|
if(piece != null && piece != chessboard.getSelectedPiece()) break;
|
|
i += xDirection;
|
|
j += yDirection;
|
|
}
|
|
}
|
|
|
|
public boolean[][] getPossibleMoves() {
|
|
return getPossibleMoves(false);
|
|
}
|
|
|
|
abstract public boolean[][] getPossibleMoves(boolean attack);
|
|
|
|
abstract public void paint(Graphics2D g2);
|
|
|
|
public Player getPlayer() {
|
|
return player;
|
|
}
|
|
|
|
public int getMoveCount() {
|
|
return moveCount;
|
|
}
|
|
|
|
public void setMoveCount(int moveCount) {
|
|
this.moveCount = moveCount;
|
|
}
|
|
|
|
public void animateMove(int fromX, int fromY, int toX, int toY) {
|
|
double startX = chessboard.startX + (fromX*chessboard.SQUARE_SIZE)*chessboard.boardScale;
|
|
double startY = chessboard.startY + (fromY*chessboard.SQUARE_SIZE)*chessboard.boardScale;
|
|
double endX = chessboard.startX + (toX*chessboard.SQUARE_SIZE)*chessboard.boardScale;
|
|
double endY = chessboard.startY + (toY*chessboard.SQUARE_SIZE)*chessboard.boardScale;
|
|
double stepX = (endX-startX)/250;
|
|
double stepY = (endY-startY)/250;
|
|
Timer timer = new Timer();
|
|
timer.scheduleAtFixedRate(new TimerTask() {
|
|
int i = 1;
|
|
double currentX = 0;
|
|
double currentY = 0;
|
|
public void run() {
|
|
chessboard.repaintRootPane(getRepaintRectangle());
|
|
if(i > 250) {
|
|
timer.cancel();
|
|
setOverride(0, 0);
|
|
} else {
|
|
currentX = i * stepX + startX;
|
|
currentY = i * stepY + startY;
|
|
setOverride(currentX, currentY);
|
|
}
|
|
chessboard.repaintRootPane(getRepaintRectangle());
|
|
i++;
|
|
}
|
|
}, 2, 2);
|
|
}
|
|
|
|
public void remove(boolean animate) {
|
|
chessboard.removePiece(x, y);
|
|
if(!animate) return;
|
|
Timer timer = new Timer();
|
|
scale = .99;
|
|
timer.scheduleAtFixedRate(new TimerTask() {
|
|
double decrement = .01;
|
|
public void run() {
|
|
scale -= decrement;
|
|
decrement *= 1.1;
|
|
if(scale < 0) {
|
|
timer.cancel();
|
|
scale = 0;
|
|
}
|
|
chessboard.repaintRootPane(getRepaintRectangle());
|
|
}
|
|
}, 10, 10);
|
|
}
|
|
|
|
public double getScale() {
|
|
return scale;
|
|
}
|
|
|
|
} |