Examples

Different in-game menus

  1# pygamepopup simple demo
  2# Contains 2 menus, independently controllable by keyboard or button
  3import pygame
  4import pygamepopup
  5from pygamepopup.components import Button, InfoBox, TextElement
  6from pygamepopup.constants import BUTTON_SIZE
  7from pygamepopup.menu_manager import MenuManager
  8
  9MAIN_MENU_ID = "main_menu"
 10CLOSABLE_MENU_ID = "closable_menu"
 11CUSTOMIZED_MENU_ID = "customized_menu"
 12SIDE_MENU_ID = "side_menu"
 13
 14WINDOW_WIDTH = 800
 15WINDOW_HEIGHT = 600
 16FPS = 30
 17clock = pygame.time.Clock()
 18
 19BALL_RADIUS = 10
 20x_pos = 250
 21y_pos = 150
 22x_velocity = 5
 23y_velocity = -5
 24
 25# initialize pygame
 26pygame.init()
 27pygame.display.set_caption("Main Menu Example")
 28screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
 29
 30# initialize pygamepopup
 31pygamepopup.init()
 32menu_manager = MenuManager(screen)
 33
 34# Define a main menu popup, with 4 buttons and a close button
 35main_menu = InfoBox(
 36    "Main Menu",
 37    [
 38        [
 39            Button(
 40                title="Open side menu",
 41                callback=lambda: menu_manager.open_menu(side_menu),
 42                size=(320, BUTTON_SIZE[1]),
 43            )
 44        ],
 45        [
 46            Button(
 47                title="Open closable menu",
 48                callback=lambda: menu_manager.open_menu(closable_menu),
 49                size=(320, BUTTON_SIZE[1]),
 50            )
 51        ],
 52        [
 53            Button(
 54                title="Open customized menu",
 55                callback=lambda: menu_manager.open_menu(customized_menu),
 56                size=(320, BUTTON_SIZE[1]),
 57            )
 58        ],
 59        [Button(title="Exit App", callback=lambda: exit(), size=(320, BUTTON_SIZE[1]))],
 60    ],
 61    width=420,
 62    identifier=MAIN_MENU_ID,
 63)
 64
 65# Define submenu that can be closed by clicking outside
 66closable_menu = InfoBox(
 67    "Closable menu",
 68    [
 69        [
 70            TextElement(
 71                text="This menu can be close by clicking on the \"Close\" button but also by clicking outside of it."
 72            )
 73        ]
 74    ],
 75    width=350,
 76    identifier=CLOSABLE_MENU_ID,
 77)
 78
 79customized_menu = InfoBox(
 80    "Customized menu",
 81    [
 82        [
 83            TextElement(
 84                text="This menu has customized content, such as close button with different label"
 85            )
 86        ]
 87    ],
 88    width=400,
 89    identifier=CUSTOMIZED_MENU_ID,
 90    title_color=pygame.Color("red"),
 91    close_button_text="Shutdown!"
 92)
 93
 94# Define a side menu, with relative positioning and close button
 95side_menu = InfoBox(
 96    "Smaller menu",
 97    [
 98        [
 99            TextElement(
100                text="The text content of a menu is automatically split in multiple "
101                "parts "
102                "to fit in the box. To add a new paragraph, just create another "
103                "TextElement."
104            )
105        ]
106    ],
107    element_linked=pygame.Rect(0, WINDOW_HEIGHT // 2, 1, 1),
108    width=310,
109    identifier=SIDE_MENU_ID,
110)
111
112
113def display_main_screen():
114    global x_pos, y_pos, x_velocity, y_velocity
115    screen.fill(pygame.Color("tan"))
116    font = pygame.font.Font(None, 36)
117    text = font.render(
118        "Type M to open Main Menu or S to open Side Menu", True, (100, 100, 20)
119    )
120    screen.blit(text, (screen.get_width() // 2 - text.get_width() // 2, 40))
121
122    # Draw animated Ball
123    pygame.draw.circle(screen, pygame.Color("red"), (x_pos, y_pos), BALL_RADIUS, 0)
124    x_pos += x_velocity
125    y_pos += y_velocity
126
127    if x_pos > WINDOW_WIDTH - BALL_RADIUS or x_pos < BALL_RADIUS:
128        x_velocity *= -1
129    if y_pos > WINDOW_HEIGHT - BALL_RADIUS or y_pos < BALL_RADIUS:
130        y_velocity *= -1
131
132
133def show_menu(menu):
134    # display a menu if it is not already open
135    if menu_manager.active_menu is not None:
136        if menu_manager.active_menu.identifier == menu.identifier:
137            print("Given menu is already opened")
138            return
139        else:
140            menu_manager.close_active_menu()
141    menu_manager.open_menu(menu)
142
143
144def main():
145    while True:
146        for event in pygame.event.get():
147            if event.type == pygame.QUIT:
148                pygame.quit()
149                exit()
150            if event.type == pygame.KEYDOWN:
151                if event.key == pygame.K_s:
152                    show_menu(side_menu)
153                if event.key == pygame.K_m:
154                    show_menu(main_menu)
155                if event.key == pygame.K_b:
156                    print(
157                        f"Menus in the background stack: {menu_manager.background_menus}"
158                    )
159                if event.key == pygame.K_a:
160                    print(f"Active menu: {menu_manager.active_menu}")
161            elif event.type == pygame.MOUSEMOTION:
162                menu_manager.motion(event.pos)  # Highlight buttons upon hover
163            elif event.type == pygame.MOUSEBUTTONUP:
164                if event.button == 1 or event.button == 3:
165                    if menu_manager.active_menu.identifier == CLOSABLE_MENU_ID:
166                        if not menu_manager.active_menu.is_position_inside(event.pos):
167                            menu_manager.close_active_menu()
168                    menu_manager.click(event.button, event.pos)
169        display_main_screen()
170        menu_manager.display()
171        pygame.display.update()
172        clock.tick(FPS)
173
174
175if __name__ == "__main__":
176    main()