diff --git a/examples/examples.py b/examples/examples.py new file mode 100644 index 0000000..2d01766 --- /dev/null +++ b/examples/examples.py @@ -0,0 +1,108 @@ +#!/usr/bin/python3 + +import pygame +from pygame._sdl2 import Window +from dataclasses import dataclass +import gui + + +@dataclass +class Settings: + fps: int = 60 + window_size: tuple = (1000, 600) + + +class Examples: + def __init__(self): + pygame.init() + + self.screen = pygame.display.set_mode((1000, 600), pygame.RESIZABLE) + pygame.display.set_caption("Game") + self.window = Window.from_display_module() + + self.loading_surface = self.generate_loading_surface() + self.screen.blit(self.loading_surface, (0, 0)) + pygame.display.update() + + self.settings = Settings() + + self.fps = self.settings.fps + + # colors + self.gray = (20, 20, 20) + + # pygame objects + self.clock = pygame.time.Clock() + self.mouse = pygame.mouse + + self.big_font = pygame.font.Font(pygame.font.get_default_font(), 32) + + # loading finished + self.window.size = self.settings.window_size + + self.gui = gui.GUI(self) + + self.running = True + + def generate_loading_surface(self): + default_font = pygame.font.SysFont("ubuntu", 32, True) + loading_text = default_font.render("Loading...", True, (240, 240, 240)) + + w, h = self.screen.get_size() + + loading_surface = pygame.Surface((w, h), flags=pygame.SRCALPHA) + + loading_surface.fill((40, 40, 40)) + loading_surface.blit(loading_text, + (w // 2 - loading_text.get_width() // 2, h // 2 - loading_text.get_height() // 2)) + + return loading_surface + + def loop(self): + self.screen.fill(self.gray) + + self.get_events() + if not self.running: + return + + self.gui.draw() + + if self.loading_surface.get_alpha() > 0: + self.screen.blit(self.loading_surface, (0, 0)) + self.loading_surface.set_alpha(self.loading_surface.get_alpha() - 4) + + pygame.display.update() + self.clock.tick(self.fps) + + def get_events(self): + for event in pygame.event.get(): + if event.type == pygame.QUIT: + self.exit() + return + + elif event.type == pygame.VIDEORESIZE: + self.window_update(event.size) + + elif event.type == pygame.MOUSEBUTTONDOWN: + pos = self.mouse.get_pos() + pressed = self.mouse.get_pressed() + + if self.gui.current_page in self.gui.buttons: + for button in self.gui.buttons[self.gui.current_page]: + button.check(pos, pressed) + + def exit(self): + self.running = False + + print("Bye!") + + def window_update(self, size): + self.settings.window_size = size + self.gui.update() + + +if __name__ == "__main__": + examples = Examples() + + while examples.running: + examples.loop() diff --git a/examples/gui.py b/examples/gui.py new file mode 100644 index 0000000..099b48a --- /dev/null +++ b/examples/gui.py @@ -0,0 +1,139 @@ +#!/usr/bin/python3 + +import pygame +from wobbl_tools import pg + + +class GUI: + def __init__(self, app): + self.app = app + + self.buttons = {} + + self.example_menu = ExampleMenu(self) + self.multiline_text_example = MultilineTextExample(self) + + self.current_page = "example_menu" + + self.pages = self.get_list_of_pages() + + def draw(self): + page = getattr(self, self.current_page) + page.draw() + + def update(self): + for page_name in self.pages: + page = getattr(self, page_name) + page.update() + + def get_list_of_pages(self): + pages = [] + + for name, page in self.__dict__.items(): + if issubclass(type(page), Page): + pages.append(name) + + return pages + + def reload(self): + for page_name in self.pages: + page = getattr(self, page_name) + page.load() + + +class Page: + def __init__(self, gui): + self.gui = gui + self.app = gui.app + + self.surface = pygame.Surface(self.app.screen.get_size(), flags=pygame.SRCALPHA) + + self.load() + self.update() + + def draw(self): + self.app.screen.blit(self.surface, (0, 0)) + + def update(self): + pass + + def load(self): + pass + + +class ExampleMenu(Page): + def load(self): + button_texts = ["Multiline Text"] + + buttons = [] + + for button_text in button_texts: + name_lower = button_text.lower().replace(" ", "_") + + setattr(self, name_lower + "_button", len(buttons)) + + buttons.append(pg.TextButton(button_text, (0, 0), change_page, (self, name_lower + "_example"))) + + start_pos = (10, 10) + spacing = 10 + + x, y = start_pos + + i = 0 + + for button in buttons: + if x + button.surface.get_width() > self.app.screen.get_width(): + x = start_pos[0] + y += button.surface.get_height() + spacing + + button.position = (x, y) + + else: + button.position = (x, y) + + w, h = button.size + + button.rect = pygame.Rect((x, y), (w, h)) + button.button = pg.Button(button.rect, button.function, button.args, key=button.key) + + buttons[i] = button + + x += button.surface.get_width() + spacing + + i += 1 + + self.gui.buttons["example_menu"] = buttons + + def update(self): + self.surface.fill((20, 20, 20)) + + for button in self.gui.buttons["example_menu"]: + button.draw(self.surface) + + +class MultilineTextExample(Page): + def load(self): + self.heading = self.app.big_font.render("Multiline Text", True, pg.white) + + self.text = pg.MultilineText( + "If you want to create multiple lines of text in pygame, " + + "you have to create multiple text objects and blit them one another.\n" + + 'The class "MultilineText()" does this automatically. ' + + 'You can make new lines by adding "\\n" to the string. ' + + "It can also automatically create newlines if the line is longer than a given length.\n" + + "You can resize this window and the text will automatically fit on the window.", + max_width=self.app.screen.get_width() + ) + + def update(self): + self.surface = pygame.transform.scale(self.surface, self.app.screen.get_size()) + self.surface.fill((20, 20, 20)) + + self.load() + + self.surface.blit(self.heading, (self.app.screen.get_width() / 2 - self.heading.get_width() / 2, 10)) + self.surface.blit(self.text.surface, (10, 50)) + + +def change_page(self, page): + self.gui.current_page = page