I'm trying to re-write a chess game with some improvements and am having problems since i added sprites. In the original game i drew black or white circles with initials to represent the pieces. These were meant to be temporary and were enough to help me test piece movement etc. Now that i'm linking images to the piece objects, when i try to copy the list they are in, i get the following error:
TypeError: cannot pickle 'pygame.surface.Surface' object
I've never used sprites before and frankly, i don't understand what i'm reading when i google this error message. The parts of the code i think are relevant are below.
There is a super class called Piece:
class Piece():
def __init__(self, color):
# when making a new piece, establish which row, column and colour it is
self.row = 0
self.col = 0
self.color = color
# drawing co-ordinates of piece
self.x = 0
self.y = 0
self.calculate_position()
# calculates x and y drawing co-ordinates of a piece based on the row and column it's in
def calculate_position(self):
# find exact centre of the square (as circles are drawn from the centre out)
self.x = SQUARE_SIZE * self.col + SQUARE_SIZE // 2 + PADDING
self.y = SQUARE_SIZE * self.row + SQUARE_SIZE // 2 + PADDING
# keep track of piece location when they move
def assign_location(self, row, col):
# self.row and col must equal the row and col of the new position
self.row = row
self.col = col
# use the above method to calculate where in the new square to draw the piece
self.calculate_position()
# draw image from assets according to piece self.image
def draw_piece(self, win):
x = self.x - self.image.get_width()//2
y = self.y - self.image.get_height()//2
if self.initial == "P":
y = self.y - 21
if self.initial == "R":
y = self.y - 26
win.blit(self.image, (x, y))
This is inherited by a King, Queen, Rook etc class which all look something like this:
class King(Piece):
def __init__(self, color):
super().__init__(color)
self.row = 0
self.col = 0
self.initial = "K"
self.value = 0
self.moves_made = 0
if self.color == WHITE:
self.image = W_KING
else:
self.image = B_KING
The self.image referred to here is imported:
W_KING = pygame.transform.scale(pygame.image.load('assets/w_king.png'), (60, 60))
The Board class creates an array to store the piece objects and is ultimately responsible for moving them around within the array:
class Board():
def __init__(self, win):
self.board = []
self.flipped_board = False
self.initialize_starting_position(win)
# create initial layout of board with pieces in starting position
def initialize_starting_position(self, win):
# create a two-dimensional array comprising 8 lists, each to represent a row on the board
for _ in range(ROWS):
self.board.append([])
# assign starting position of pieces within self.board
self.board[0] = [Rook(BLACK), Knight(BLACK), Bishop(BLACK), Queen(BLACK), King(BLACK), Bishop(BLACK), Knight(BLACK), Rook(BLACK)]
self.board[1] = [Pawn(BLACK), Pawn(BLACK), Pawn(BLACK), Pawn(BLACK), Pawn(BLACK), Pawn(BLACK), Pawn(BLACK), Pawn(BLACK)]
self.board[2] = [0, 0, 0, 0, 0, 0, 0, 0]
self.board[3] = [0, 0, 0, 0, 0, 0, 0, 0]
self.board[4] = [0, 0, 0, 0, 0, 0, 0, 0]
self.board[5] = [0, 0, 0, 0, 0, 0, 0, 0]
self.board[6] = [Pawn(WHITE), Pawn(WHITE), Pawn(WHITE), Pawn(WHITE), Pawn(WHITE), Pawn(WHITE), Pawn(WHITE), Pawn(WHITE)]
self.board[7] = [Rook(WHITE), Knight(WHITE), Bishop(WHITE), Queen(WHITE), King(WHITE), Bishop(WHITE), Knight(WHITE), Rook(WHITE)]
# iterate through self.board assigning pieces their row and column location
for row in range(ROWS):
for col in range(COLS):
square = self.board[row][col]
if square != 0:
square.assign_location(row, col)
The draw_board method then uses the index of each list to draw the pieces to the correct part of the board on the screen:
# draw the squares and pieces to the board
def draw_board(self, win):
# Draw chequered pattern of board
win.fill(BACKGROUND)
# draw a large dark brown rectangle to form base colour of board - co-ordinates (x, y, w, h)
pygame.draw.rect(win, DARK, (PADDING, PADDING, HEIGHT - (PADDING * 2), HEIGHT - (PADDING * 2)))
# draw small squares on top of large rectangle to form chequered pattern
for row in range(ROWS):
# when 'row' is even, start drawing light squares from that column, then move accross 2 columns
for col in range(row % 2, COLS, 2):
pygame.draw.rect(win, LIGHT, (row * SQUARE_SIZE + PADDING, col * SQUARE_SIZE + PADDING, SQUARE_SIZE, SQUARE_SIZE))
# Draw notation to squares on board
letters = ["a", "b", "c", "d", "e", "f", "g", "h"]
numbers = ["8", "7", "6", "5", "4", "3", "2", "1"]
# reverse order of number and letter lists if board flipped
if self.flipped_board == True:
letters.reverse()
numbers.reverse()
# assign location for notation depending on orientation of board
for row in range(ROWS):
letter = letters[row]
letter_img = NOTATION_FONT.render(letter, True, WHITE)
win.blit(letter_img, (row * SQUARE_SIZE + (SQUARE_SIZE + 6), HEIGHT - (PADDING + 16)))
number = numbers[row]
img = NOTATION_FONT.render(number, True, WHITE)
win.blit(img, (PADDING + 1, row * SQUARE_SIZE + PADDING + 1))
# Draw pieces to squares on board
# if board flipped, copy self.board, reverse its contents and re-assign row and col to copied piece objects
# for the purpose of obtaining x, y co-ordinates for drawing pieces on flipped board
**if self.flipped_board == True:
board_copy = copy.deepcopy(self.board)
for row in board_copy:
row.reverse()
board_copy.reverse()
board = board_copy
# iterate through board_copy assigning pieces their row and column location
for row in range(ROWS):
for col in range(COLS):
square = board[row][col]
if square != 0:
square.assign_location(row, col)**
else:
board = self.board
# iterate through rows and columns drawing pieces as set out in board
for row in range(ROWS):
for col in range(COLS):
square = board[row][col]
if square != 0:
square.draw_piece(win)
It's the section in bold which is causing the problem. I'm trying to achieve a mirror-image of self.board purely for the purpose of displaying the pieces in the reverse order, to replicate viewing the chessboard from the other side. I don't want to affect the piece locations within the actual self.board which is why i'm making a deepcopy.
Could anyone explain what is happening that causes this error?