Search code examples
pythonpygamegridchesspython-chess

Failure to properly load a chess board in Pygame


I am attempting to create a chess GUI. I was able to make it so that when the player is White, everything loads perfectly. However, when I try to load when the player is Black, it does not load anything on White's side. Here is the relevant code (Note: the screen is 800x800 and the piece pictures are 100x100):

for i in range(64):
     piece = board.piece_at(i)
     if piece is not None:
          x_value = (i%8)*100
          y_value = 700 - ((i // 8) * 100)
          if color == "W":
               scrn.blit(pieces[str(piece)], (x_value, y_value))
          else:
               scrn.blit(pieces[str(piece)], (700-x_value, 700-y_value))

Full function:


scrn = pygame.display.set_mode((800, 900))
board = chess.Board()
gui_update(scrn, board, color="W") # Last parameter can be "B"

def gui_update(scrn, board, index_moves=None, resign_button=False, confirmation=False, color="W"):
    LIGHT = (240, 217, 181)
    DARK = (181, 136, 99)
    BLUE = (50, 255, 255)

    pieces = {'p': pygame.image.load('Pieces/b_pawn.png').convert_alpha(),
              'n': pygame.image.load('Pieces/b_knight.png').convert_alpha(),
              'b': pygame.image.load('Pieces/b_bishop.png').convert_alpha(),
              'r': pygame.image.load('Pieces/b_rook.png').convert_alpha(),
              'q': pygame.image.load('Pieces/b_queen.png').convert_alpha(),
              'k': pygame.image.load('Pieces/b_king.png').convert_alpha(),
              'P': pygame.image.load('Pieces/w_pawn.png').convert_alpha(),
              'N': pygame.image.load('Pieces/w_knight.png').convert_alpha(),
              'B': pygame.image.load('Pieces/w_bishop.png').convert_alpha(),
              'R': pygame.image.load('Pieces/w_rook.png').convert_alpha(),
              'Q': pygame.image.load('Pieces/w_queen.png').convert_alpha(),
              'K': pygame.image.load('Pieces/w_king.png').convert_alpha(),
              }
    row_changer = 0

    for i in range(64):

        square = pygame.Rect((i % 8) * 100, 700 - (i // 8) * 100, 100, 100)
        if (i + row_changer) % 2 == 0:
            square_color = DARK
        else:
            square_color = LIGHT
        if (i + 1) % 8 == 0:
            if row_changer == 0:
                row_changer = 1
            else:
                row_changer = 0

        pygame.draw.rect(surface=scrn, color=square_color, rect=square)

        if index_moves is not None:
            if i in index_moves:
                x1 = (i % 8) * 100
                y1 = 700 - (i // 8) * 100
                if color == "B":
                    x1 = 700 - x1
                    y1 = 700 - y1
                x2 = x1 + 100
                y2 = y1
                x3 = x2
                y3 = y2 + 100
                x4 = x1
                y4 = y3
                pygame.draw.lines(scrn, BLUE, True, [(x1, y1), (x2, y2), (x3, y3), (x4, y4)], 5)

        piece = board.piece_at(i)
        if piece is None:
            pass
        else:
            x_value = (i % 8) * 100
            y_value = 700 - ((i // 8) * 100)
            if color == "W":
                scrn.blit(pieces[str(piece)], (x_value, y_value))
            else:
                print("X: {0} | Y: {1}".format(700 - x_value, 700 - y_value))
                scrn.blit(pieces[str(piece)], (700 - x_value, 700 - y_value))

    if resign_button:
        font = pygame.font.Font('freesansbold.ttf', 50)
        if not confirmation:
            text = font.render("Resign", True, (255, 255, 255))
        else:
            text = font.render("Are you sure? (Y/N)", True, (255, 255, 255))
        # pygame.draw.rect(scrn, (150, 150, 150), [0, 0, 100, 50])

        textRect = text.get_rect()
        textRect.center = (400, 850)
        scrn.blit(text, textRect)

    pygame.display.flip()

Functionally, the program runs fine. However, anything above the first rows (on White's side) is not loaded. If one of White's pieces makes it to Black's side, then it is loaded. Similarly, if a Black piece makes it to White's side, then it is unloaded visually. How can I prevent this from happening?


Solution

  • The problem is the order of drawing when color is not "W":. You draw the rectangles (pygame.draw.rect) on top of the pieces because the pieces are drawn from bottom to top and the rectangles from top to bottom in the same loop. So the bottom pieces are drawn first and later covered by the rectangles. Draw the pieces in a separate loop:

    def gui_update(scrn, board, index_moves=None, resign_button=False, confirmation=False, color="W"):
    
        # [...]
      
        # draw board
        for i in range(64):
            # draw rectangles and lines
            # [...]
    
        # draw pieces and the completely drawn board
        for i in range(64):
            piece = board.piece_at(i)
            if piece:
                x_value = (i % 8) * 100
                y_value = 700 - ((i // 8) * 100)
                if color == "W":
                    scrn.blit(pieces[str(piece)], (x_value, y_value))
                else:
                    scrn.blit(pieces[str(piece)], (700 - x_value, 700 - y_value))