Axhul
Axhul

Reputation: 47

Why won't pygame display my images or chessboard?

I'm using Pycharm Community 2020 for my IDE. I'm using Python 3.7.4. I have the Pygame 1.9.6. So I've been following a YouTube video on how to code a working chessboard, but it isn't display my board to me with the pieces on it or anything.

I have to separate python files to do this one for the Chess engine which is responsible for storing all the information about the current state of a chess game. Also will be responsible for determining the valid moves at the current state. It will also keep move log. Another is Chess Main which is the main driver file. It's responsible for handling user input and displaying the current game state object. Chess main code:

WIDTH = HEIGHT = 512  # 400 is another option
DIMENSION = 8  # dimensions of a chess board are 8x8
SQ_SIZE = HEIGHT // DIMENSION
MAX_FPS = 15  # for animations later on
IMAGES = {}

def loadImages():
    pieces = ['wp', 'wR', 'wN', 'wB', 'wK', 'wQ', 'bp', 'bR', 'bN', 'bB', 'bK', 'bQ']
    for piece in pieces:
        IMAGES[piece] = p.transform.scale(p.image.load("images/" + piece + ".png"), (SQ_SIZE, SQ_SIZE))
        
# Note: we can access an image saving "IMAGES"['wp']
def main():
    p.init()
    screen = p.display.set_mode((WIDTH, HEIGHT))
    clock = p.time.Clock()
    screen.fill(p.Color("white"))
    gs = ChessEngine.GameState()
    loadImages()  # only do this once, before the while loop
    running = True
    sqSelected = ()  # no square is selected, keep track of the last click of the user (tuple: (row, col))
    player_Clicks = []  # keep track of player clicks (two tuples [6,4), (4,4)]
    while running:
        for e in p.event.get():
            if e.type == p.QUIT:
                running = False
            elif e.type == p.MOUSEBUTTONDOWN:
                location = p.mouse.get_pos()  # (x, y) location of mouse
                col = location[0]//SQ_SIZE
                row = location[1]//SQ_SIZE
                if sqSelected == (row, col):  # the user clicked the same square twice
                    sqSelected = ()  # deselect
                    player_Clicks = []  # clear player clicks
                else:
                    sqSelected = (row, col)
                    player_Clicks.append(sqSelected)  # append for both 1st and 2nd clicks
                if len(player_Clicks) == 2:  # after 2nd click
                    move = ChessEngine.Move(player_Clicks[0], player_Clicks[1], gs.board)
                    print(move.getChessNotation())
                    gs.makeMove(move)
                    sqSelected = ()  # reset user clicks
                    player_Clicks = []

        drawGameState(screen, gs)
        clock.tick(MAX_FPS)
        p.display.flip()


def drawGameState(screen, gs):
    drawBoard(screen)  # draw squares on the board
    # add in piece highlighting or move suggestions (later)
    drawPieces(screen, gs.board)  # draw pieces on top of those squares

def drawBoard(screen):
    colors = [p.Color("white"), p.Color("gray")]
    for r in range(DIMENSION):
        for c in range(DIMENSION):
            color = colors[((r+c) % 2)]
            p.draw.rect(screen, color, p.Rect(c * SQ_SIZE, r * SQ_SIZE, SQ_SIZE, SQ_SIZE))

    def drawPieces(screen, board):
        for r in range(DIMENSION):
            for c in range(DIMENSION):
                piece = board[r][c]
                if piece != "--":  # not empty square
                    screen.blit(IMAGES)[piece], p.Rect(c * SQ_SIZE, r * SQ_SIZE, SQ_SIZE, SQ_SIZE)

if __name__ == " __main__":
    main()

Chess engine code:

class GameState:
    def __init__(self):
        # board is an 8x8 2d list, each element of lest has 2 character.
        # The first character represents the color of the piece, "b" or "w"
        # The second character represents the type of the piece, "K", "Q", "R", "B", "N", or "p"
        # "--" - represents an empty space with no piece.
        self.board = [
            ["bR", "bN", "bB", "bQ", "bK", "b8", "bN", "bR"],
            ["bp", "bp", "bp", "bp", "bp", "bp", "bp", "bp"],
            ["--", "--", "--", "--", "--", "--", "--", "--"],
            ["--", "--", "--", "--", "--", "--", "--", "--"],
            ["--", "--", "--", "--", "--", "--", "--", "--"],
            ["--", "--", "--", "--", "--", "--", "--", "--"],
            ["wp", "wp", "wp", "wp", "wp", "wp", "wp", "wp"],
            ["wR", "wN", "wB", "wQ", "wK", "w8", "wN", "wR"]]
        self.whiteToMove = True
        self.moveLog = []

    def makeMove(self, move):
        self.board[move.startRow][move.startCol] = "--"
        self.board[move.endRow][move.endCol] = move.pieceMoved
        self.moveLog.append(move)  # log the move so we can undo it later
        self.whiteToMove = not self.whiteToMove  # swap players


class Move():
    # maps key to values
    # key : value
    ranksToRows = {"1": 7, "2": 6, "3": 5, "4": 4,
                "5": 3, "6": 2, "7": 1, "8": 0}
    rowsToRanks = {v: k for k, v in ranksToRows.items()}
    filesToCols = {"a": 0, "b": 1, "c": 2, "d": 3,
                "e": 4, "f": 5, "g": 6, "h": 7}
    colsToFiles = {v: k for k, v in filesToCols.items()}

    def __init__(self, startSq, endSq, board):
        self.startRow = startSq[0]
        self.startCol = startSq[1]
        self.endRow = endSq[0]
        self.endCol = endSq[1]
        self.pieceMoved = board[self.startRow][self.startCol]
        self.pieceCaptured = board[self.endRow][self.endCol]

    def getChessNotation(self):
        # you can add to make this like real chess notation
        return self.getRankFile(self.startRow, self.startCol) * self.getRankFile(self.endRow, self.endCol)

    def getRankFile(self, r, c):
        return self.colsToFiles[c] * self.rowsToRanks[r]

So I don't know why Pycharm isn't displaying the board if you want the YouTube links for the first 2 videos I've seen of this:
Part 1: https://www.youtube.com/watch?v=EnYui0e73Rs

Part 2: https://www.youtube.com/watch?v=o24J3WcBGLg

Edit: I fixed the issues from the first answer and got it to work. Plus had to fix the if name == "main": (main). To just (main). Now it doesn't want to move the pieces properly or register the mouse clicks. I am now going threw the errors:

Traceback (most recent call last):
  line 105, in <module>
   main()
  line 58, in main
    print(move.getChessNotation())
   line 52, in getChessNotation
    return self.getRankFile(self.startRow, self.startCol) * 
 self.getRankFile(self.endRow, self.endCol)
  line 55, in getRankFile
    return self.colsToFiles[c] * self.rowsToRanks[r]
TypeError: can't multiply sequence by non-int of type 'str'
                             

Upvotes: 2

Views: 871

Answers (1)

Rabbid76
Rabbid76

Reputation: 211166

First of all the statement which blits the images is semantically wrong:

creen.blit(IMAGES)[piece], p.Rect(c * SQ_SIZE, r * SQ_SIZE, SQ_SIZE, SQ_SIZE)

screen.blit(IMAGES[piece], p.Rect(c * SQ_SIZE, r * SQ_SIZE, SQ_SIZE, SQ_SIZE))

Furthermore, the figures "b8" and ""w8" doesn't exist. You probably meant "bB" and "wB". Fix the figure names is attribute self.board in the class GameState.

Upvotes: 1

Related Questions