0

I'm building a chess gui using pygame, in which the main game loop calls a method in a seperate class (Move in GameState class), which then further calls another method in the same class(pawn_promotion). In the pawn_promotion method, a surface, promotion_menu, is being blit into the window.

But it only appears on screen for one frame. Please correct me if I'm wrong here but what I think is happening is that the surface is being blit but when the game loop iterates again it gets covered up with the chess board being blit onto to the window.

class GameWindow:
    def __init__(self):
        load()
        gs = GameState()
        m = MoveList
        run = True
        square_selected = ()
        clicks = []
        while run:
            win.blit(board_surface, (467, 132))
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    run = False
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_ESCAPE:
                        MainMenu()
                        run = False
                # Mouse ui
                if event.type == pygame.MOUSEBUTTONDOWN:  # checking for clicks
                    location = (pygame.mouse.get_pos()[0] - 467, pygame.mouse.get_pos()[1] - 132)
                    if 600 >= location[0] >= 0 and 600 >= location[1] >= 0:
                        column = location[0] // Square_size
                        row = location[1] // Square_size
                    # checking for repeat clicks
                        if square_selected == (row, column):
                            square_selected = ()
                            clicks = []  # if click is repeat, clear previous click
                        else:
                            # Player selects a square
                            square_selected = (row, column)
                            clicks.append(square_selected)

                        if len(clicks) == 2:
                            # second click moves the piece
                            self.move = m(clicks[0], clicks[1], gs.board)
                            gs.Move(self.move)
                            square_selected = ()
                            clicks = []
                            if gs.close_window:
                                run = False
class GameState:
...irrelavant code...
    def pawn_promotion(self, move):
        print(move.endrow, move.endcol)
        self.is_prmt = True
        promotion_menu = pygame.Surface((int(Square_size), int(Square_size * 4)))
        promotion_menu.fill(white)
        prmt_confirm = ''
        if self.white_turn:
            prmt_white_queen = Button(board_surface, (move.endcol + 1) * Square_size, 50, pieces_dict['wQ'], 1)
            prmt_white_rook = Button(board_surface, (move.endcol + 1) * Square_size, 50 + Square_size,
                                     pieces_dict['wR'], 1)
            prmt_white_knight = Button(board_surface, (move.endcol + 1) * Square_size, 50 + (2 * Square_size),
                                       pieces_dict['wN'], 1)
            prmt_white_bishop = Button(board_surface, (move.endcol + 1) * Square_size, 50 + (3 * Square_size),
                                       pieces_dict['wB'], 1)

            if self.run_promote_menu:
                print(self.run_promote_menu)
                board_surface.blit(promotion_menu, ((move.endcol + 1) * Square_size, (move.endrow * Square_size) + 50))
                prmt_queen = Button.draw(prmt_white_queen)
                prmt_rook = Button.draw(prmt_white_rook)
                prmt_knight = Button.draw(prmt_white_knight)
                prmt_bishop = Button.draw(prmt_white_bishop)

                if prmt_queen:
                    prmt_confirm = 'wQ'
                    # run_promote_menu = False
                if prmt_rook:
                    prmt_confirm = 'wR'
                    # run_promote_menu = False
                if prmt_knight:
                    prmt_confirm = 'wN'
                    # run_promote_menu = False
                if prmt_bishop:
                    prmt_confirm = 'wB'
                    # run_promote_menu = False
                for event in pygame.event.get():
                    if event.type == pygame.QUIT:
                        self.run_promote_menu = False
                        close_window = True
                    if event.type == pygame.KEYDOWN:
                        if event.key == pygame.K_z:
                            self.run_promote_menu = False
                if prmt_confirm != '':
                    self.run_promote_menu = False
                    self.board[move.endrow][move.endcol] = prmt_confirm
                pygame.display.update()

I'm creating 4 buttons on the surface using the following class

class Button:
    def __init__(self, surface, x, y, image, scale):
        image_width = image.get_width()
        image_height = image.get_height()
        self.image = pygame.transform.scale(image, (int(image_width * scale), int(image_height * scale)))
        self.image_rect = image.get_rect(topleft=(x, y))
        self.surface = surface
        self.clicked = False
        self.image_bg = pygame.Surface((self.image_rect.width + 10, self.image_rect.height + 5))
        self.image_bg.set_alpha(0)

    def draw(self):
        action = False
        pos = pygame.mouse.get_pos()
        if self.image_rect.collidepoint(pos):
            self.image_bg.set_alpha(1)
            for event in pygame.event.get():
                if pygame.mouse.get_pressed()[0] == 1 and not self.clicked:
                    self.clicked = True
                    action = True
                if pygame.mouse.get_pressed()[1] == 0:
                    self.clicked = False
        else:
            self.image_bg.set_alpha(0)
        self.surface.blit(self.image_bg, (self.image_rect.x - 5, self.image_rect.y))
        self.surface.blit(self.image, (self.image_rect.x, self.image_rect.y))
        return action

I'm having another small issue with this class, the set_alpha() lines seem to be increasing value of alpha each frame rather than setting it to a constant value. Is there another command for keeping alpha constant?

If I use a while loop inside pawn_promotion, it works perfectly but since it's essentially two nested while loops, it creates a lot of lag. I tried to reduce this lag by using clock.tick() but it doesn't get rid of it entirely.

ouflak
  • 2,458
  • 10
  • 44
  • 49
  • Yes, `surface.blit` draws something transient that gets overwritten on the next refresh. To have something last, you need to use sprites. – Tim Roberts Feb 23 '22 at 22:49
  • Thank you! I didn't use sprites because the surface has four additional objected being blit on top of it, do i just use 5 sprites? Also could you please look into my second question? – BlueCheese Feb 23 '22 at 22:54
  • That's way too much code for `GameWindow.__init__`, which should only get the window *ready* for the game. Pretty much the entire loop should be in a separate method that gets called after you create the window. – chepner Feb 23 '22 at 22:55
  • GameWindow used to be a global function. The window is being created globally too. I switched to a class since I was experimenting with namespaces and trying to figure out a solution. I could do another method but I might just revert back to a regular function. – BlueCheese Feb 23 '22 at 23:00
  • `alpha` may change if you blit again in the same place without redrawing background - so you may draw the same (transparent) element many times and it cummulate alpha. – furas Feb 24 '22 at 01:24
  • in Pygame most (dynamic) games have to redraw all elements in every loop. Sometimes it is simpler if you use list to keep all objects and later you draw background and runs `for`-loop to redraw all objects. The same way you can update all objects in all loop. It is easier when all objects have the same functions with the same arguments - like `draw()` , `update()`, `handle_event(event)`, And you want to add new element on screen then you have to only add to list, and if you want to remove from screen then you have to remove from list. – furas Feb 24 '22 at 01:27

0 Answers0