Разработка на коленке

"тут должна быть красивая цитата о программировании"

Кнопка с пререндеренным Surface

2024-03-03 23:00

Сниппет, в котором для кнопки создаются несколько объектов Surface. Рисуются они один раз, а потом блитятся (blit) на родительский Surface

Prerendered button

import pygame as pg

from pygame.surface import Surface
from pygame.font import Font


class Button:
    def __init__(self, parent_surface: Surface, position, size):
        self.parent_surface = parent_surface
        self.position = position
        self.size = size
        self.border_width = 3

        self.normal = self.make_normal_button()
        self.hover = self.make_hover_button()
        self.pressed = self.make_pressed_button()

        self.is_hover = False
        self.is_pressed = False

    def make_normal_button(self):
        surface = Surface(self.size, pg.SRCALPHA)

        bg_color = (255, 255, 255)
        border_color = (40, 40, 40)
        shadow_height = 5
        surface.fill(bg_color)
        pg.draw.rect(
            surface,
            border_color,
            pg.rect.Rect(0, 0, self.size[0], self.size[1]),
            self.border_width
        )
        pg.draw.rect(
            surface,
            border_color,
            pg.rect.Rect(0, self.size[1] - shadow_height, self.size[0], shadow_height)
        )

        return surface

    def make_hover_button(self):
        surface = Surface(self.size, pg.SRCALPHA)

        bg_color = (255, 255, 255)
        border_color = (80, 80, 80)
        shadow_height = 5
        surface.fill(bg_color)
        pg.draw.rect(
            surface,
            border_color,
            pg.rect.Rect(0, 0, self.size[0], self.size[1]),
            self.border_width
        )
        pg.draw.rect(
            surface,
            border_color,
            pg.rect.Rect(0, self.size[1] - shadow_height, self.size[0], shadow_height)
        )
        return surface

    def make_pressed_button(self):
        surface = Surface(self.size, pg.SRCALPHA)

        bg_color = (255, 255, 255)
        border_color = (80, 80, 80)
        surface.fill(bg_color)
        pg.draw.rect(
            surface,
            border_color,
            pg.rect.Rect(0, 0, self.size[0], self.size[1]),
            self.border_width + 3
        )
        return surface

    def render(self):
        surface = self.normal

        if self.is_hover:
            surface = self.hover
            if self.is_pressed:
                surface = self.pressed

        self.parent_surface.blit(surface, self.position)


class Game:
    def __init__(self, display_surface: Surface):
        self.display_surface = display_surface

        button_size = (200, 60)
        self.button = Button(
            self.display_surface,
            (
                (self.display_surface.get_width() - button_size[0]) // 2,
                (self.display_surface.get_height() - button_size[1]) // 2,
            ),
            button_size
        )

        self.working = True

    def process_events(self):
        for e in pg.event.get():
            if e.type == pg.QUIT or (e.type == pg.KEYDOWN and e.key == pg.K_ESCAPE):
                self.working = False

        mouse_pos = pg.mouse.get_pos()
        button_rect = pg.rect.Rect(
            self.button.position[0],
            self.button.position[1],
            self.button.size[0],
            self.button.size[1]
        )
        self.button.is_hover = button_rect.collidepoint(mouse_pos)
        self.button.is_pressed = pg.mouse.get_pressed()[0]

    def render(self):
        self.display_surface.fill((220, 220, 220))
        self.button.render()
        pg.display.update()

    def run(self):
        while self.working:
            self.process_events()
            self.render()


def main():
    pg.init()
    display_surface = pg.display.set_mode((800, 450))
    Game(display_surface).run()
    pg.quit()


if __name__ == "__main__":
    main()

3/prerendered_button_surface.py