From 3b9e279db1de5599106fb7a6150ae59bd9ed57d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20Rudowicz?= Date: Tue, 10 Sep 2024 17:10:06 +0200 Subject: [PATCH] Animated color change on button hover --- menu.py | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/menu.py b/menu.py index 2ddb1f9..f5da54a 100644 --- a/menu.py +++ b/menu.py @@ -36,6 +36,7 @@ class Action(TypedDict): class Button: PRESS_OFFSET = 2 + HOVER_ANIMATION_STEPS = 5 def __init__(self, position: pygame.Rect, text: str, cbk: Callable[[], None]): self.position: pygame.Rect @@ -47,6 +48,27 @@ class Button: self.text_pos = pygame.Rect((self.position.left + (self.position.width - text_rect.width)/2), (self.position.top + (self.position.height - text_rect.height)/2), text_rect.width, text_rect.height) + self.bg_color = pygame.Color("black") + self.hover_bg_color = pygame.Color("violetred4") + self.hover_animation_step = 0 + + def get_bg_color(self): + if self.pos_is_inside(pygame.mouse.get_pos()): + self.hover_animation_step = min(self.hover_animation_step + 1, self.HOVER_ANIMATION_STEPS) + else: + self.hover_animation_step = max(self.hover_animation_step - 1, 0) + + if self.hover_animation_step == self.HOVER_ANIMATION_STEPS: + return self.hover_bg_color + if self.hover_animation_step == 0: + return self.bg_color + + new_color = tuple(map(lambda v: v[0] + (((v[1]-v[0])/self.HOVER_ANIMATION_STEPS)*self.hover_animation_step), + zip(self.bg_color, self.hover_bg_color))) + return new_color + + def needs_redrawing(self) -> bool: + return self.hover_animation_step == self.HOVER_ANIMATION_STEPS or self.hover_animation_step == 0 def set_position(self, position: pygame.Rect): self.position = position @@ -64,7 +86,7 @@ class Button: return self.text_pos def draw(self, screen: pygame.Surface): - pygame.draw.rect(screen, "black", self.get_position(), 0) + pygame.draw.rect(screen, self.get_bg_color(), self.get_position(), 0) self.font.render_to(screen, self.get_text_pos(), self.text, fgcolor="pink") def pos_is_inside(self, pos: Tuple) -> bool: @@ -130,7 +152,7 @@ class MenuBoard(IBoard): b.handle_event(event) def draw(self, screen: pygame.Surface, force_redraw: bool): - if force_redraw: + if force_redraw or any(map(Button.needs_redrawing, self.buttons)): screen.fill(self.bg_color) for b in self.buttons: b.draw(screen)