I am trying to write simple chess application based on this tutorial: https://proghammer.wordpress.com/2010/08/10/chess01-dragging-game-pieces/ I use this code with some changes, and it doesn't work. I am really new in Java GUI programming, can someone tell me what I do wrong.
UPDATE:
I am trying to correct my mistakes, when I asked this question, I tryed to debug this. And I think that problem is in ChessGame
class. Methods like mouseDragged()
are working but nothing changed. Pieces did't drag. And I asking for helping with this.
There is too much code, but this code only for providing full information. I repeat, I think that problem is in ChessGame
or (maybe in ChessView
), other code is only for understanding structure.
This is my code:
public class ChessView extends JPanel {
ChessBoard board;
private static final int BOARD_START_X = 220;
private static final int BOARD_START_Y = 120;
private static final int TILE_WIDTH = 45;
private static final int TILE_HEIGHT = 45;
private Image background;
public ChessView() {
board = new ChessBoard();
// load and set background image
URL backgroundImg = getClass().getClassLoader().getResource("background.jpg");
this.background = new ImageIcon(backgroundImg).getImage();
// add mouse listeners to enable drag and drop
ChessGame game = new ChessGame(board, this);
this.addMouseListener(game);
this.addMouseMotionListener(game);
// create application frame and set visible
//
JFrame f = new JFrame();
f.setVisible(true);
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.setResizable(false);
f.setSize(this.background.getWidth(null), this.background.getHeight(null));
}
public static void main(String[] args) {
new ChessView();
}
@Override
protected void paintComponent(Graphics g) {
g.drawImage(this.background, 0, 0, null);
int row;
for(int i = 0; i < board.getHeight(); i++) {
for(int j = 0; j < board.getWidth(); j++) {
Piece piece = board.getBoardAsArray()[i][j];
if (piece.getClass() != EmptySquare.class) {
if (piece.getColor() == other.Color.WHITE) {
if (piece.getClass() != Pawn.class) row = 7;
else row = 6;
} else {
if (piece.getClass() != Pawn.class) row = 0;
else row = 1;
}
int x = BOARD_START_X + (TILE_WIDTH * j);
int y = BOARD_START_Y + (TILE_HEIGHT * row);
piece.setX(x);
piece.setY(y);
g.drawImage(piece.getImage(), x, y, null);
}
}
}
}
public ChessBoard getBoard() {
return board;
}
}
This is my Listener:
public class ChessGame implements MouseListener, MouseMotionListener {
private ChessBoard board;
private ChessView view;
private Piece dragPiece;
private int dragOffsetX;
private int dragOffsetY;
public ChessGame(ChessBoard board, ChessView chessGui) {
this.board = board;
this.view = chessGui;
}
@Override
public void mousePressed(MouseEvent e) {
int x = e.getPoint().x;
int y = e.getPoint().y;
for(int i = 0; i < view.getBoard().getHeight(); i++) {
for(int j = 0; j < view.getBoard().getWidth(); j++) {
Piece piece = view.getBoard().getBoardAsArray()[i][j];
if (piece.getClass() != EmptySquare.class) {
if (mouseOverPiece(piece, x, y)) {
this.dragOffsetX = x - piece.getX();
this.dragOffsetY = y - piece.getY();
this.dragPiece = piece;
break;
}
}
}
}
}
/**
* check whether the mouse is currently over this piece
* @param piece the playing piece
* @param x x coordinate of mouse
* @param y y coordinate of mouse
* @return true if mouse is over the piece
*/
private boolean mouseOverPiece(Piece piece, int x, int y) {
return piece.getX() <= x
&& piece.getX()+piece.getWidth() >= x
&& piece.getY() <= y
&& piece.getY()+piece.getHeight() >= y;
}
@Override
public void mouseReleased(MouseEvent arg0) {
this.dragPiece = null;
}
@Override
public void mouseDragged(MouseEvent evt) {
if(this.dragPiece != null){
this.dragPiece.setX(evt.getPoint().x - this.dragOffsetX);
this.dragPiece.setY(evt.getPoint().y - this.dragOffsetY);
this.view.repaint();
}
}
@Override
public void mouseClicked(MouseEvent arg0) {}
@Override
public void mouseEntered(MouseEvent arg0) {}
@Override
public void mouseExited(MouseEvent arg0) {}
@Override
public void mouseMoved(MouseEvent arg0) {}
}
This is my board representation:
public class ChessBoard {
private Piece[][] board = new Piece[8][8];
private final int WIDTH = 8;
private final int HEIGHT = 8;
//Write a NullPiece class or contain nulls is 2-5 rows?
public ChessBoard () {
setStartBoard(); //rewrite
}
public int getHeight() {
return HEIGHT;
}
public int getWidth() {
return WIDTH;
}
public Piece[][] getBoardAsArray() {
return board;
}
public ArrayList<Piece> getBoardAsArrayList() {
ArrayList<Piece> list = new ArrayList<Piece>();
for (int i = 0; i < WIDTH; i++) {
for (int j = 0; j < HEIGHT; j++) {
list.add(board[i][j]);
}
}
return list;
}
Piece firstWhiteRook = new Rook(Color.WHITE);
Piece secondWhiteRook = new Rook(Color.WHITE);
Piece firstWhiteKnight = new Knight(Color.WHITE);
Piece secondWhiteKnight = new Knight(Color.WHITE);
Piece firstWhiteBishop = new Bishop(Color.WHITE);
Piece secondWhiteBishop = new Bishop(Color.WHITE);
Piece whiteQueen = new Queen(Color.WHITE);
Piece whiteKing = new King(Color.WHITE);
Piece firstWhitePawn = new Pawn(Color.WHITE);
Piece secondWhitePawn = new Pawn(Color.WHITE);
Piece thirdWhitePawn = new Pawn(Color.WHITE);
Piece fourthWhitePawn = new Pawn(Color.WHITE);
Piece fifthWhitePawn = new Pawn(Color.WHITE);
Piece sixthWhitePawn = new Pawn(Color.WHITE);
Piece seventhWhitePawn = new Pawn(Color.WHITE);
Piece eighthWhitePawn = new Pawn(Color.WHITE);
Piece firstBlackRook = new Rook(Color.BLACK);
Piece secondBlackRook = new Rook(Color.BLACK);
Piece firstBlackKnight = new Knight(Color.BLACK);
Piece secondBlackKnight = new Knight(Color.BLACK);
Piece firstBlackBishop = new Bishop(Color.BLACK);
Piece secondBlackBishop = new Bishop(Color.BLACK);
Piece blackQueen = new Queen(Color.BLACK);
Piece blackKing = new King(Color.BLACK);
Piece firstBlackPawn = new Pawn(Color.BLACK);
Piece secondBlackPawn = new Pawn(Color.BLACK);
Piece thirdBlackPawn = new Pawn(Color.BLACK);
Piece fourthBlackPawn = new Pawn(Color.BLACK);
Piece fifthBlackPawn = new Pawn(Color.BLACK);
Piece sixthBlackPawn = new Pawn(Color.BLACK);
Piece seventhBlackPawn = new Pawn(Color.BLACK);
Piece eighthBlackPawn = new Pawn(Color.BLACK);
//TODO: make this more beautiful?
public void setStartBoard() {
//set color for each piece
//add all pieces to board
board[0][0] = firstBlackRook;
board[0][1] = firstBlackKnight;
board[0][2] = firstBlackBishop;
board[0][3] = blackQueen;
board[0][4] = blackKing;
board[0][5] = secondBlackBishop;
board[0][6] = secondBlackKnight;
board[0][7] = secondBlackRook;
board[1][0] = firstBlackPawn;
board[1][1] = secondBlackPawn;
board[1][2] = thirdBlackPawn;
board[1][3] = fourthBlackPawn;
board[1][4] = fifthBlackPawn;
board[1][5] = sixthBlackPawn;
board[1][6] = seventhBlackPawn;
board[1][7] = eighthBlackPawn;
board[7][0] = firstWhiteRook;
board[7][1] = firstWhiteKnight;
board[7][2] = firstWhiteBishop;
board[7][3] = whiteQueen;
board[7][4] = whiteKing;
board[7][5] = secondWhiteBishop;
board[7][6] = secondWhiteKnight;
board[7][7] = secondWhiteRook;
board[6][0] = firstWhitePawn;
board[6][1] = secondWhitePawn;
board[6][2] = thirdWhitePawn;
board[6][3] = fourthWhitePawn;
board[6][4] = fifthWhitePawn;
board[6][5] = sixthWhitePawn;
board[6][6] = seventhWhitePawn;
board[6][7] = eighthWhitePawn;
for(int i = 2; i < 6; i++) {
for(int j = 0; j < 8; j++) {
board[i][j] = new EmptySquare(Color.EMPTY);
}
}
}
}
This is my Piece implementation:
public class PieceImpl implements Piece {
private int x;
private int y;
private static final String NAME = ""; // Only for getName(). Don't use.
private Color color;
private Image image;
public PieceImpl(Color color) {
this.color = color;
}
public void setColor(Color color) {
this.color = color;
}
public Color getColor() {
return color;
}
public Image getImage() {
return image;
}
public void setImage(Image image) {
this.image = image;
}
public String toString() {
if (this.getColor() == Color.BLACK) {
return "b" + NAME;
} else {
return "w" + NAME;
}
}
public int getX() {
return x;
}
public void setX(int x) {
this.x = x;
}
public int getY() {
return y;
}
public void setY(int y) {
this.y = y;
}
public int getWidth() {
return image.getWidth(null);
}
public int getHeight() {
return image.getHeight(null);
}
}
This is example of king implementation:
public class King extends PieceImpl implements Piece{
private static final String NAME = "K";
public King(Color color) {
super(color);
if (this.getColor() == Color.WHITE) {
URL urlToImage = getClass().getClassLoader().getResource("wk.png");
setImage(new ImageIcon(urlToImage).getImage());
} else if (this.getColor() == Color.BLACK) {
URL urlToImage = getClass().getClassLoader().getResource("bk.png");
setImage(new ImageIcon(urlToImage).getImage());
}
}
public String toString() {
if (this.getColor() == Color.BLACK) {
return "b" + NAME;
} else {
return "w" + NAME;
}
}
I represent color by enum class:
public enum Color {
BLACK("black", 0),
WHITE("white", 1),
EMPTY("empty", -1);
private final String name;
private final int id;
private Color(String name, int id) {
this.name = name;
this.id = id;
}
public String getName() {
return this.name;
}
public int getID() {
return this.id;
}
}
This is not only me code, as I say I am trying to study with tutorial. But I want to use my board representation. When I am running application, it's run, and I see the GUI, but mouse events don't work. Can someone tell me where I make a mistake, why mouse events don't work?
I feel from your comments and debugging information that you have shared is that your mouseListener
is working perfectly. So the problem lies somewhere else. Studying your code I find that in your ChessView
class' paintComponent
method resigns the piece
variable's x
and y
in the code :
int x = BOARD_START_X + (TILE_WIDTH * j);
int y = BOARD_START_Y + (TILE_HEIGHT * row);
piece.setX(x);
piece.setY(y);
And draws it on the the board in position x
and y
. So this is basically undoing what you have done in your mouseListener
:
this.dragPiece.setX(evt.getPoint().x - this.dragOffsetX);
this.dragPiece.setY(evt.getPoint().y - this.dragOffsetY);
So you should have a way of setting the the piece
in the board
class' new location
OR
you should have a system to store the initial values of x
and y
for each piece and should not reset the x
and y
values in the paintComponent
and should call
g.drawImage(piece.getImage(), piece.getX(), piece.getY(), null);