Сниппет, в котором для кнопки создаются несколько объектов Surface. Рисуются они один раз, а потом блитятся (blit) на родительский Surface
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()