I'm trying to develop a java chess engine using Swing for the GUI and for the last couple of days I've found some setbacks. The engine is already fully functional and works perfectly with click moves (1 click on the Tile-JPanel with the piece you desire to move, another click on the Tile-JPanel where you want to place the piece). Now I'm willing to take it a step further and decided to implement drag and drop moves (click and hold mouse, drag, and release on desired JPanel).
This is where I find my problems. My move class has the following arguments: the chessboard configuration, the starting tile for the move, and the ending tile. It takes the source tile id when I press the mouse, but when I release it, what would be the destination tile id, is instead the source tile id as well. This makes my engine think that I am trying to move the pieces to the same tile resulting in an illegal move. I've tried using destinationTile = chessBoard.getTile(tileId)
the same concept I've used for the click moves but it takes de source tile instead. I've tried using TilePanel obj = (TilePanel)e.getSource(); destinationTile = chessBoard.getTile(obj.getTileId());
and with this, both source and destination tile get the value of the piece identifier? So if I try to drag and drop a pawn, they both get "P" as value, if I try to move the queen they get "Q". So yeah, I am completely lost.
The second problem I'm facing is when dragging the Piece-JLabel around, it is limited to the boundaries of the the Tile-JPanel in which it resides. That's was to be expected, so I tried using a JLayeredPane.
My approach was, clone the moved piece-JLabel, set the original one to invisible. Add the cloned one to the JLayeredPane.DRAG_LAYER
, drag it around following the mouse. And on release, if the given move was legal, place this JLabel on the destination tile JPanel and delete the invisible JLabel on the source tile. This was also to no success, as no matter how I tried to add the JLabel to the DRAG_LAYER I could not get it to work. No matter what I tried, I couldn't get a piece image to follow my cursor around over the board.
Here is the majority of my Tile class with all the MouseEvent Handlers:
private class TilePanel extends JPanel {
private final int tileId;
public int getTileId() {
return tileId;
}
TilePanel(final BoardPanel boardPanel, final int tileId) throws IOException {
super(new GridBagLayout());
this.tileId = tileId;
setPreferredSize(TILE_PANEL_DIMENSION);
assignTileColor();
assignTilePieceIcon(chessBoard);
highlightTileBorder(chessBoard);
addMouseListener(new MouseListener() {
@Override
public void mouseClicked(final MouseEvent e) {
if(isRightMouseButton(e)) {
sourceTile = null;
destinationTile = null;
humanMovedPiece = null;
try {
boardPanel.drawBoard(chessBoard);
} catch (IOException ioException) {
ioException.printStackTrace();
}
System.out.println("piece deselected");
}
else if (isLeftMouseButton(e)) {
if(sourceTile == null) {
//first click
sourceTile = chessBoard.getTile(tileId);
humanMovedPiece = sourceTile.getPiece();
if (humanMovedPiece == null) {
sourceTile = null;
}
System.out.println("piece selected");
}
else {
//second click
destinationTile = chessBoard.getTile(tileId);
final Move move = Move.MoveFactory.createMove(chessBoard, sourceTile.getTileCoordinate(), destinationTile.getTileCoordinate());
final MoveTransition transition = chessBoard.getCurrentPlayer().makeMove(move);
if (transition.getMoveStatus() == MoveStatus.DONE) {
chessBoard = transition.getTransitionBoard();
moveLog.addMove(move);
SFXUtils.playSound("move");
System.out.println(chessBoard);
System.out.println("█████ move done: " + move.toString() + " █████");
}
sourceTile = null;
destinationTile = null;
humanMovedPiece = null;
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
gameHistoryPanel.redo(chessBoard, moveLog);
takenPiecesPanel.redo(moveLog);
boardPanel.drawBoard(chessBoard);
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
});
}
}
@Override
public void mousePressed(final MouseEvent e) {
if(sourceTile == null) {
//first click
sourceTile = chessBoard.getTile(tileId);
System.out.println(tileId);
System.out.println(sourceTile.getTileCoordinate());
humanMovedPiece = sourceTile.getPiece();
if (humanMovedPiece == null) {
sourceTile = null;
}
System.out.println("piece selected");
}
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
gameHistoryPanel.redo(chessBoard, moveLog);
takenPiecesPanel.redo(moveLog);
boardPanel.drawBoard(chessBoard);
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
});
}
@Override
public void mouseReleased(final MouseEvent e) {
/* TilePanel obj = (TilePanel)e.getSource();
destinationTile = chessBoard.getTile(obj.getTileId());*/
destinationTile = chessBoard.getTile(tileId);
final Move move = Move.MoveFactory.createMove(chessBoard, sourceTile.getTileCoordinate(), destinationTile.getTileCoordinate());
final MoveTransition transition = chessBoard.getCurrentPlayer().makeMove(move);
if (transition.getMoveStatus() == MoveStatus.DONE) {
chessBoard = transition.getTransitionBoard();
moveLog.addMove(move);
SFXUtils.playSound("move");
System.out.println(chessBoard);
System.out.println("█████ move done: " + move.toString() + " █████");
}
sourceTile = null;
destinationTile = null;
humanMovedPiece = null;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
try {
gameHistoryPanel.redo(chessBoard, moveLog);
takenPiecesPanel.redo(moveLog);
boardPanel.drawBoard(chessBoard);
} catch (IOException ioException) {
ioException.printStackTrace();
}
}
});
}
@Override
public void mouseEntered(final MouseEvent e) {
}
@Override
public void mouseExited(final MouseEvent e) {
}
});
addMouseMotionListener(new MouseMotionListener() {
@Override
public void mouseDragged(final MouseEvent e) {
System.out.println("im draggin");
TilePanel obj = (TilePanel)e.getSource();
JLabel draggedPieceImageLabel = (JLabel) obj.getComponent(0);
//obj.getComponent(0).setVisible(false);
draggedPieceImageLabel.setLocation(e.getX()-25,e.getY()-25);
add(draggedPieceImageLabel);
}
@Override
public void mouseMoved(MouseEvent e) {
}
});
validate();
}