From 309231e304d4b29fde0a39c52ca7353d08eda93d Mon Sep 17 00:00:00 2001 From: ElnuDev Date: Fri, 10 Feb 2023 18:12:06 -0800 Subject: [PATCH] Add comments, clean up code --- src/Board.java | 81 +++++++++++++++++++++++++++++---------- src/BoardCoordinate.java | 19 +++++++-- src/Coordinate.java | 4 +- src/Piece.java | 11 ++++++ src/ScreenCoordinate.java | 14 ++++--- 5 files changed, 97 insertions(+), 32 deletions(-) diff --git a/src/Board.java b/src/Board.java index 5020cfa..f228800 100644 --- a/src/Board.java +++ b/src/Board.java @@ -1,32 +1,49 @@ -import java.awt.*; +import java.awt.Color; +import java.awt.Graphics; public class Board { + // Width and height of each board tile static final int TILE_SIZE = 64; + // Width and height of board in tiles static final int BOARD_SIZE = 8; + // Width and height of window in pixels static final int DIMENSION = TILE_SIZE * BOARD_SIZE; // Colors from Lost Century 24 // https://lospec.com/palette-list/lost-century-24 + // new Color() takes in an integer representing the color + // Colors are represented in hexadecimal, so we can write the hex literal by prefixing the color code with 0x static final Color BLACK = new Color(0x6c595c); static final Color WHITE = new Color(0xab9b8e); final DrawingPanel panel; final Graphics graphics; + // The board is a two-dimensional array of nullable pieces Piece[][] board; + // The current board coordinate that's being dragged BoardCoordinate dragging = null; public Board() { + // Initialize DrawingPanel panel = new DrawingPanel(DIMENSION, DIMENSION); + graphics = panel.getGraphics(); + + // Connect up event handlers panel.onMouseDown(this::handleMouseDown); - panel.onMouseDrag(this::draw); + panel.onMouseDrag((x, y) -> { + // We want to re-render with new mouse position when dragging pieces + if (dragging != null) draw(x, y); + }); panel.onMouseUp(this::handleMouseUp); - graphics = panel.getGraphics(); + + // Initialize board board = new Piece[BOARD_SIZE][BOARD_SIZE]; - for (int y = 0; y < 2; y++) { + + // Initialize pieces + for (int y = 0; y < 2; y++) for (int x = 0; x < BOARD_SIZE; x++) { set(x, y, new Piece(true)); set(x, y + 6, new Piece(false)); } - } } public Piece get(int x, int y) { @@ -54,30 +71,46 @@ public class Board { move(from.x, from.y, to.x, to.y); } + // Mouse down event handler + // This sets the currently dragging piece void handleMouseDown(int x, int y) { + // Get board coordinate of mouse click BoardCoordinate coordinate = new ScreenCoordinate(x, y).toBoard(); + // If there's no piece there, return if (get(coordinate) == null) return; + // Set currently dragging piece to that coordinate dragging = coordinate; + // Redraw with dragging draw(x, y); } void handleMouseUp(int x, int y) { + // Get board coordinate of mouse release BoardCoordinate newCoordinate = new ScreenCoordinate(x, y).toBoard(); + // Only do something if new coordinate is different from the originating coordinate if (!dragging.equals(newCoordinate)) { + // Get piece on target coordinate Piece capturedPiece = get(newCoordinate); + // Only move piece to square if there's nothing there, or they are of differing colors if (capturedPiece == null || capturedPiece.black != get(dragging).black) { move(dragging, newCoordinate); } } + // Clear dragging dragging = null; + // Redraw without dragging draw(); } public void draw() { - draw(0, 0); + draw(null); } public void draw(int mouseX, int mouseY) { + draw(new ScreenCoordinate(mouseX, mouseY)); + } + + public void draw(ScreenCoordinate mousePosition) { // Draw board graphics.setColor(WHITE); graphics.fillRect(0, 0, DIMENSION, DIMENSION); @@ -85,21 +118,18 @@ public class Board { for (int y = 0; y < BOARD_SIZE; y++) for (int x = y % 2; x < BOARD_SIZE; x += 2) graphics.fillRect(x * TILE_SIZE, y * TILE_SIZE, TILE_SIZE, TILE_SIZE); - // Draw pieces - forEachPiece((coordinate, piece) -> { - int x, y; - if (coordinate.equals(dragging)) { - x = mouseX; - y = mouseY; - } else { - x = coordinate.x * TILE_SIZE + TILE_SIZE / 2; - y = coordinate.y * TILE_SIZE + TILE_SIZE / 2; - } - piece.draw(graphics, x, y); + // Draw pieces + forEachPiece((boardCoordinate, piece) -> { + // If piece is the one being dragged, render it at the mouse position + // Otherwise, render it at the center of the board tile + piece.draw(graphics, boardCoordinate.equals(dragging) ? mousePosition : boardCoordinate.toScreen()); }); } + // Functional interfaces for forEachPiece + // Provide ability to run code for each piece on board without having to duplicate nested for loop boilerplate + @FunctionalInterface interface PieceActionXY { void forEachTile(int x, int y, Piece piece); @@ -110,17 +140,26 @@ public class Board { void forEachTile(BoardCoordinate coordinate, Piece piece); } + // Run code on each tile on board + // Usage: + // forEachPiece((x, y, piece) -> { + // // do something with piece + // }); public void forEachPiece(PieceActionXY tileAction) { for (int y = 0; y < BOARD_SIZE; y++) for (int x = 0; x < BOARD_SIZE; x++) { - Piece piece = board[y][x]; + Piece piece = get(x, y); if (piece == null) continue; tileAction.forEachTile(x, y, piece); } } + // Run code on each tile on board + // Usage: + // forEachPiece((coordinate, piece) -> { + // // do something with piece + // }); public void forEachPiece(PieceActionCoordinate tileAction) { - forEachPiece((x, y, piece) -> tileAction.forEachTile(new BoardCoordinate(x, y), board[y][x])); + forEachPiece((x, y, piece) -> tileAction.forEachTile(new BoardCoordinate(x, y), get(x, y))); } -} - +} \ No newline at end of file diff --git a/src/BoardCoordinate.java b/src/BoardCoordinate.java index 87302ec..8669dcc 100644 --- a/src/BoardCoordinate.java +++ b/src/BoardCoordinate.java @@ -1,12 +1,23 @@ +// Board coordinate class. +// Provides tile coordinates for squares on the chess board. public class BoardCoordinate extends Coordinate { public BoardCoordinate(int x, int y) { - super(x, y); + super(x, y); // Execute superclass constructor + } + + // TODO: reimplement as casting + // Convert to screen coordinate by getting center pixel of tile + public ScreenCoordinate toScreen() { + return new ScreenCoordinate( + x * Board.TILE_SIZE + Board.TILE_SIZE / 2, + y * Board.TILE_SIZE + Board.TILE_SIZE / 2 + ); } @Override public boolean equals(Object obj) { - if (obj == this) return true; - if (!(obj instanceof BoardCoordinate other)) return false; - return other.x == x && other.y == y; + if (obj == this) return true; // Equals if same object + if (!(obj instanceof BoardCoordinate other)) return false; // If other is not BoardCoordinate, not equals + return other.x == x && other.y == y; // If is BoardCoordinate and x- and y-values match, equals } } diff --git a/src/Coordinate.java b/src/Coordinate.java index 223367e..cebccb2 100644 --- a/src/Coordinate.java +++ b/src/Coordinate.java @@ -1,5 +1,5 @@ -import java.util.Objects; - +// Generic abstract Coordinate class for storing an (x, y) pair. +// BoardCoordinate and ScreenCoordinate inherit from this. public abstract class Coordinate { public int x; public int y; diff --git a/src/Piece.java b/src/Piece.java index fd61c5a..8b42338 100644 --- a/src/Piece.java +++ b/src/Piece.java @@ -1,17 +1,28 @@ import java.awt.*; public class Piece { + // Width and height of placeholder rectangle graphic public static final int DIMENSION = 32; public boolean black; + // If no parameter, default to white public Piece() { } public Piece(boolean black) { this.black = black; } + // The Piece class doesn't store position, + // so when drawing we need to be provided this along with a graphics context when drawing public void draw(Graphics graphics, int x, int y) { graphics.setColor(black ? Color.BLACK : Color.WHITE); + // Drawing is performed from the top-left corner. + // We need the drawn rectangle to be offset by half of the width and height + // so it is centered on the provided position. graphics.fillRect(x - DIMENSION / 2, y - DIMENSION / 2, DIMENSION, DIMENSION); } + + public void draw(Graphics graphics, ScreenCoordinate coordinate) { + draw(graphics, coordinate.x, coordinate.y); + } } diff --git a/src/ScreenCoordinate.java b/src/ScreenCoordinate.java index 77baf45..e7ab1a7 100644 --- a/src/ScreenCoordinate.java +++ b/src/ScreenCoordinate.java @@ -1,17 +1,21 @@ +// Screen coordinate class. +// Holds pixel coordinates relative to window. public class ScreenCoordinate extends Coordinate { public ScreenCoordinate(int x, int y) { - super(x, y); + super(x, y); // Execute superclass constructor } + // TODO: reimplement as casting public BoardCoordinate toBoard() { + // We can convert to board coordinates by dividing by the tile size of each square on the board return new BoardCoordinate(x / Board.TILE_SIZE, y / Board.TILE_SIZE); } @Override public boolean equals(Object obj) { - if (obj == this) return true; - if (obj instanceof BoardCoordinate) return obj == toBoard(); - if (!(obj instanceof ScreenCoordinate other)) return false; - return other.x == x && other.y == y; + if (obj == this) return true; // Equals if same object + if (obj instanceof BoardCoordinate) return obj == toBoard(); // If other is BoardCoordinate, we can see if they match + if (!(obj instanceof ScreenCoordinate other)) return false; // If not BoardCoordinate or ScreenCoordinate, not equals + return other.x == x && other.y == y; // If is ScreenCoordinate and x- and y-values match, equals } } \ No newline at end of file