Examples
Main menu sample code
1import pygame
2import pygamepopup
3from pygamepopup.components import Button, InfoBox, TextElement
4from pygamepopup.menu_manager import MenuManager
5
6WINDOW_WIDTH = 600
7WINDOW_HEIGHT = 600
8
9
10class MainMenuScene:
11 def __init__(self, screen: pygame.Surface):
12 self.screen = screen
13 self.menu_manager = MenuManager(screen)
14 self.exit_request = False
15
16 self.create_main_menu_interface()
17
18 def create_main_menu_interface(self):
19 main_menu = InfoBox(
20 "Main Menu",
21 [
22 [
23 Button(
24 title="Open other menu",
25 callback=lambda: self.create_other_menu(),
26 )
27 ],
28 [Button(title="Exit", callback=lambda: self.exit())],
29 ],
30 has_close_button=False,
31 )
32 self.menu_manager.open_menu(main_menu)
33
34 def create_other_menu(self):
35 other_menu = InfoBox(
36 "Smaller menu",
37 [
38 [
39 TextElement(
40 text="The text content of a menu is automatically splitted in multiple "
41 "part "
42 "to fit in the box. To add a new paragraph, just create another "
43 "TextElement."
44 )
45 ]
46 ],
47 width=300,
48 )
49 self.menu_manager.open_menu(other_menu)
50
51 def exit(self):
52 self.exit_request = True
53
54 def display(self) -> None:
55 self.menu_manager.display()
56
57 def motion(self, position: pygame.Vector2) -> None:
58 self.menu_manager.motion(position)
59
60 def click(self, button: int, position: pygame.Vector2) -> bool:
61 self.menu_manager.click(button, position)
62 return self.exit_request
63
64
65def main() -> None:
66 pygame.init()
67 pygame.display.set_caption("Main Menu Example")
68
69 pygamepopup.init()
70
71 screen = pygame.display.set_mode((WINDOW_WIDTH, WINDOW_HEIGHT))
72 main_menu_scene = MainMenuScene(screen)
73
74 running = True
75 while running:
76 for event in pygame.event.get():
77 if event.type == pygame.QUIT:
78 running = False
79 elif event.type == pygame.MOUSEMOTION:
80 main_menu_scene.motion(event.pos)
81 elif event.type == pygame.MOUSEBUTTONUP:
82 if event.button == 1 or event.button == 3:
83 running = not main_menu_scene.click(event.button, event.pos)
84 screen.fill(pygame.Color("black"))
85 main_menu_scene.display()
86 pygame.display.update()
87 pygame.quit()
88 exit()
89
90
91if __name__ == "__main__":
92 main()
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()