pythonpygamepygame-surface

Moving pygame surface doesn't move thorpy buttons


I'm working on a Pygame project using Thorpy for GUI elements. I've created Thorpy buttons attached to a Pygame surface. When I move the surface using the blit function, the visual representation of the buttons moves, but their hitboxes remain fixed, causing clicking issues.

In this example, the Thorpy buttons are attached to the blue surface and their visual representation is 100 pixels to the right of their hitboxes.

import pygame
import thorpy as tp

pygame.init()
def GUI_elements():
    tp.init(surface, tp.theme_round)
    
    button1 = tp.Button('Main Menu')
    button2 = tp.Button('Exit Game')
    group = tp.Group([button1, button2], 'v')
    game_GUI = group.get_updater()

    return game_GUI

screen = pygame.display.set_mode((800, 600))
pygame.display.set_caption("Pygame Window")
surface = pygame.Surface((400, 800))

def main_loop():
    game_GUI = GUI_elements()
    menu_button = game_GUI.element.children[0]
    menu_button.at_unclick = exit

    exit_button = game_GUI.element.children[1]
    exit_button.at_unclick = exit

    while True:
        game_GUI.update()
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                running = False

        screen.fill((255, 0, 0))
        screen.blit(surface, (100, 0))  # (100, 0) is the offset
        surface.fill((0, 0, 200))

        pygame.display.flip()

if __name__ == '__main__':
    main_loop()
    pygame.quit()

I've tried moving the Thorpy group or buttons which works fine but I don't see how that would fix my problem because I still have to move the Pygame surface to it's ideal location which would then offset everything.


Solution

  • The first argument of tp.init is supposed to be the screen, but not a surface that is moved on the screen. If you move the surface, you would also have to move the mouse position, respectively the UI would have to evaluate the mouse position relative to the surface. But I don't see any possibility for this.
    I suggest drawing the menu on the screen and marking the center of the menu with:

    tp.init(screen, tp.theme_round)
    ...
    group.set_center(300, 400)
    

    For this to work, you need to update the UI after drawing the scene, but right before updating the display. You can even use the center of the surface to align the UI. e.g.:

    screen.fill((255, 0, 0))
    surface_rect = screen.blit(surface, (100, 0))
    game_GUI.element.set_center(*surface_rect.center)
    game_GUI.update()
    pygame.display.flip()
    

    Complete example:

    import pygame
    import thorpy as tp
    
    pygame.init()
    def GUI_elements():
        tp.init(screen, tp.theme_round)
        button1 = tp.Button('Main Menu')
        button2 = tp.Button('Exit Game')
        group = tp.Group([button1, button2], 'v')
        game_GUI = group.get_updater()
        return game_GUI
    
    screen = pygame.display.set_mode((800, 600))
    pygame.display.set_caption("Pygame Window")
    surface = pygame.Surface((400, 800))
    surface.fill((0, 0, 200))
    
    def main_loop():
        game_GUI = GUI_elements()
        menu_button = game_GUI.element.children[0]
        menu_button.at_unclick = exit
        exit_button = game_GUI.element.children[1]
        exit_button.at_unclick = exit
    
        running = True
        while running:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    running = False
    
            screen.fill((255, 0, 0))
            surface_rect = screen.blit(surface, (100, 0))
            game_GUI.element.set_center(*surface_rect.center)
            game_GUI.update()
            pygame.display.flip()
    
    if __name__ == '__main__':
        main_loop()
        pygame.quit()