Chess/src/APiece.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;
}
}