diff --git a/res/black-bishop.png b/res/black-bishop.png new file mode 100644 index 0000000..c00730d Binary files /dev/null and b/res/black-bishop.png differ diff --git a/res/black-king.png b/res/black-king.png new file mode 100644 index 0000000..c3928dd Binary files /dev/null and b/res/black-king.png differ diff --git a/res/black-knight.png b/res/black-knight.png new file mode 100644 index 0000000..9f806a0 Binary files /dev/null and b/res/black-knight.png differ diff --git a/res/black-pawn.png b/res/black-pawn.png new file mode 100644 index 0000000..a2e480b Binary files /dev/null and b/res/black-pawn.png differ diff --git a/res/black-queen.png b/res/black-queen.png new file mode 100644 index 0000000..0a02a4d Binary files /dev/null and b/res/black-queen.png differ diff --git a/res/black-rook.png b/res/black-rook.png new file mode 100644 index 0000000..0128fae Binary files /dev/null and b/res/black-rook.png differ diff --git a/res/trimmed.png b/res/trimmed.png new file mode 100644 index 0000000..fe657c4 Binary files /dev/null and b/res/trimmed.png differ diff --git a/res/white-bishop.png b/res/white-bishop.png new file mode 100644 index 0000000..2db222c Binary files /dev/null and b/res/white-bishop.png differ diff --git a/res/white-king.png b/res/white-king.png new file mode 100644 index 0000000..dfe57d8 Binary files /dev/null and b/res/white-king.png differ diff --git a/res/white-knight.png b/res/white-knight.png new file mode 100644 index 0000000..bc515e6 Binary files /dev/null and b/res/white-knight.png differ diff --git a/res/white-pawn.png b/res/white-pawn.png new file mode 100644 index 0000000..36d4b80 Binary files /dev/null and b/res/white-pawn.png differ diff --git a/res/white-queen.png b/res/white-queen.png new file mode 100644 index 0000000..4084290 Binary files /dev/null and b/res/white-queen.png differ diff --git a/res/white-rook.png b/res/white-rook.png new file mode 100644 index 0000000..6564d81 Binary files /dev/null and b/res/white-rook.png differ diff --git a/src/view/gui.py b/src/view/gui.py index 5c6855d..c1f5b41 100644 --- a/src/view/gui.py +++ b/src/view/gui.py @@ -1,8 +1,17 @@ import tkinter as tk +from typing import Type +from PIL import ImageTk, Image +import os from logic.board import Board from logic.move import Move +from logic.pieces.bishop import Bishop +from logic.pieces.king import King +from logic.pieces.knight import Knight +from logic.pieces.pawn import Pawn from logic.pieces.piece import Colour, Piece +from logic.pieces.queen import Queen +from logic.pieces.rook import Rook from logic.position import Position from view.view import View @@ -21,26 +30,55 @@ class GUI(View): self.canvas.bind("", self._on_canvas_click) + self._piece_images = self._load_piece_images("res/") + + def _piece_svg(self, root: str, piece: Type[Piece], colour: Colour) -> ImageTk.PhotoImage: + piece_name = piece.__name__.lower() + + path = os.path.join(root, f"{"white" if colour == Colour.WHITE else "black"}-{piece_name}.png") + img = Image.open(path) + size = int(self.tile_size * .85) + # img = img.resize((size, size)) + + if img.mode == "LA": + img = img.convert(mode="RGBA") + img.save(path) + + return ImageTk.PhotoImage(img) + + def _load_piece_images(self, root: str) -> dict[Type[Piece], dict[Colour, ImageTk.PhotoImage]]: + ret = {} + for piece in [Pawn, Rook, Knight, Bishop, Queen, King]: + if piece not in ret: + ret[piece] = {} + ret[piece][Colour.WHITE] = self._piece_svg(root, piece, Colour.WHITE) + ret[piece][Colour.BLACK] = self._piece_svg(root, piece, Colour.BLACK) + + return ret + def _on_canvas_click(self, event): x, y = event.x // self.tile_size, event.y // self.tile_size y = 7 - y self._controller.on_tile_selected(x, y) + def update_board(self, board: Board, selected_piece: Piece, legal_moves: list[Move]) -> None: self.canvas.delete("all") self._draw_chess_board(board, selected_piece, legal_moves) - def _draw_chess_board(self, board, selected_piece = None, legal_moves = []): - colours = ["#F0D9B5", "#B58863"] # Light and dark squares + + def _draw_chess_board(self, board: Board, selected_piece = None, legal_moves = []): + colours = ["#EDD6B0", "#B88762"] # Light and dark squares + alt_colours = ["#F6EB72", "#DCC34B"] # Light and dark squares, when selected + circle_colours = ["#CCB897", "#9E7454"] # circles to show legal moves for y in range(8): for x in range(8): colour = colours[(x + y) % 2] - if selected_piece is not None: - possible_positions = [move.pos for move in legal_moves] - if Position(x, 7-y) in possible_positions: - colour = "#ADD8E6" # Highlight legal moves + pos = Position(x, 7-y) + if selected_piece is not None and pos == selected_piece.pos: + colour = alt_colours[(x + y) % 2] self.canvas.create_rectangle( x * self.tile_size, @@ -51,16 +89,29 @@ class GUI(View): outline=colour, ) + if selected_piece is not None: + possible_positions = [move.pos for move in legal_moves] + if pos in possible_positions: + radius = .15 * self.tile_size + colour = circle_colours[(x + y) % 2] + self.canvas.create_oval( + (x + .5) * self.tile_size - radius, + (y + .5) * self.tile_size - radius, + (x + .5) * self.tile_size + radius, + (y + .5) * self.tile_size + radius, + fill=colour, + outline=colour, + ) + + piece = board.piece_at(x, 7-y) if piece: - text_colour = "white" if piece.colour == Colour.WHITE else "black" - self.canvas.create_text( + self.canvas.create_image( (x + 0.5) * self.tile_size, - (y + 0.5) * self.tile_size, - text=piece.__class__.__name__[0], - fill=text_colour, - font=("Arial", 32, "bold") + (y + 0.9) * self.tile_size, + image=self._piece_images[type(piece)][piece.colour], + anchor=tk.S, ) # Cell annotations @@ -68,19 +119,19 @@ class GUI(View): if x == 0: # numbers in the top left of the first column self.canvas.create_text( - (x + 0.15) * self.tile_size, - (y + 0.15) * self.tile_size, + (x + .15) * self.tile_size, + (y + .15) * self.tile_size, text=8-y, fill=text_colour, - font=("Arial", 10, "bold") + font=("Arial", 12, "bold") ) if y == 7: # numbers in the top left of the first column self.canvas.create_text( - (x + 0.85) * self.tile_size, - (y + 0.85) * self.tile_size, + (x + .85) * self.tile_size, + (y + .85) * self.tile_size, text="abcdefgh"[x], fill=text_colour, - font=("Arial", 10, "bold") + font=("Arial", 12, "bold") ) def show(self) -> None: