we have nice looing gui now
BIN
res/black-bishop.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
res/black-king.png
Normal file
After Width: | Height: | Size: 3.5 KiB |
BIN
res/black-knight.png
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
res/black-pawn.png
Normal file
After Width: | Height: | Size: 734 B |
BIN
res/black-queen.png
Normal file
After Width: | Height: | Size: 2.7 KiB |
BIN
res/black-rook.png
Normal file
After Width: | Height: | Size: 1014 B |
BIN
res/trimmed.png
Normal file
After Width: | Height: | Size: 4.2 KiB |
BIN
res/white-bishop.png
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
res/white-king.png
Normal file
After Width: | Height: | Size: 3.0 KiB |
BIN
res/white-knight.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
res/white-pawn.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
res/white-queen.png
Normal file
After Width: | Height: | Size: 3.8 KiB |
BIN
res/white-rook.png
Normal file
After Width: | Height: | Size: 1.3 KiB |
@ -1,8 +1,17 @@
|
|||||||
import tkinter as tk
|
import tkinter as tk
|
||||||
|
from typing import Type
|
||||||
|
from PIL import ImageTk, Image
|
||||||
|
import os
|
||||||
|
|
||||||
from logic.board import Board
|
from logic.board import Board
|
||||||
from logic.move import Move
|
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.piece import Colour, Piece
|
||||||
|
from logic.pieces.queen import Queen
|
||||||
|
from logic.pieces.rook import Rook
|
||||||
from logic.position import Position
|
from logic.position import Position
|
||||||
from view.view import View
|
from view.view import View
|
||||||
|
|
||||||
@ -21,26 +30,55 @@ class GUI(View):
|
|||||||
|
|
||||||
self.canvas.bind("<Button-1>", self._on_canvas_click)
|
self.canvas.bind("<Button-1>", 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):
|
def _on_canvas_click(self, event):
|
||||||
x, y = event.x // self.tile_size, event.y // self.tile_size
|
x, y = event.x // self.tile_size, event.y // self.tile_size
|
||||||
y = 7 - y
|
y = 7 - y
|
||||||
|
|
||||||
self._controller.on_tile_selected(x, y)
|
self._controller.on_tile_selected(x, y)
|
||||||
|
|
||||||
|
|
||||||
def update_board(self, board: Board, selected_piece: Piece, legal_moves: list[Move]) -> None:
|
def update_board(self, board: Board, selected_piece: Piece, legal_moves: list[Move]) -> None:
|
||||||
self.canvas.delete("all")
|
self.canvas.delete("all")
|
||||||
self._draw_chess_board(board, selected_piece, legal_moves)
|
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 y in range(8):
|
||||||
for x in range(8):
|
for x in range(8):
|
||||||
colour = colours[(x + y) % 2]
|
colour = colours[(x + y) % 2]
|
||||||
if selected_piece is not None:
|
pos = Position(x, 7-y)
|
||||||
possible_positions = [move.pos for move in legal_moves]
|
if selected_piece is not None and pos == selected_piece.pos:
|
||||||
if Position(x, 7-y) in possible_positions:
|
colour = alt_colours[(x + y) % 2]
|
||||||
colour = "#ADD8E6" # Highlight legal moves
|
|
||||||
|
|
||||||
self.canvas.create_rectangle(
|
self.canvas.create_rectangle(
|
||||||
x * self.tile_size,
|
x * self.tile_size,
|
||||||
@ -51,16 +89,29 @@ class GUI(View):
|
|||||||
outline=colour,
|
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)
|
piece = board.piece_at(x, 7-y)
|
||||||
|
|
||||||
if piece:
|
if piece:
|
||||||
text_colour = "white" if piece.colour == Colour.WHITE else "black"
|
self.canvas.create_image(
|
||||||
self.canvas.create_text(
|
|
||||||
(x + 0.5) * self.tile_size,
|
(x + 0.5) * self.tile_size,
|
||||||
(y + 0.5) * self.tile_size,
|
(y + 0.9) * self.tile_size,
|
||||||
text=piece.__class__.__name__[0],
|
image=self._piece_images[type(piece)][piece.colour],
|
||||||
fill=text_colour,
|
anchor=tk.S,
|
||||||
font=("Arial", 32, "bold")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Cell annotations
|
# Cell annotations
|
||||||
@ -68,19 +119,19 @@ class GUI(View):
|
|||||||
|
|
||||||
if x == 0: # numbers in the top left of the first column
|
if x == 0: # numbers in the top left of the first column
|
||||||
self.canvas.create_text(
|
self.canvas.create_text(
|
||||||
(x + 0.15) * self.tile_size,
|
(x + .15) * self.tile_size,
|
||||||
(y + 0.15) * self.tile_size,
|
(y + .15) * self.tile_size,
|
||||||
text=8-y,
|
text=8-y,
|
||||||
fill=text_colour,
|
fill=text_colour,
|
||||||
font=("Arial", 10, "bold")
|
font=("Arial", 12, "bold")
|
||||||
)
|
)
|
||||||
if y == 7: # numbers in the top left of the first column
|
if y == 7: # numbers in the top left of the first column
|
||||||
self.canvas.create_text(
|
self.canvas.create_text(
|
||||||
(x + 0.85) * self.tile_size,
|
(x + .85) * self.tile_size,
|
||||||
(y + 0.85) * self.tile_size,
|
(y + .85) * self.tile_size,
|
||||||
text="abcdefgh"[x],
|
text="abcdefgh"[x],
|
||||||
fill=text_colour,
|
fill=text_colour,
|
||||||
font=("Arial", 10, "bold")
|
font=("Arial", 12, "bold")
|
||||||
)
|
)
|
||||||
|
|
||||||
def show(self) -> None:
|
def show(self) -> None:
|
||||||
|