import abc from typing import Optional import pygame from pygame import Surface from sprite.BoundingBox import BoundingBox from sprite.PositionScale import PositionScale class UiElement: def __init__(self): self.position_scale = PositionScale() self.visible = True self.click_listeners = [] def add_click_listener(self, listener): self.click_listeners.append(listener) def remove_click_listener(self, listener): self.click_listeners.remove(listener) def click(self, click_event): for listener in self.click_listeners: listener(self, click_event) @abc.abstractmethod def tick(self, dt: float): pass @abc.abstractmethod def render_sprite_image(self) -> Optional[Surface]: pass @abc.abstractmethod def get_bounding_box(self) -> BoundingBox: pass def draw(self, screen: pygame.Surface, screen_transform: PositionScale): if not self.visible: return image = self.render_sprite_image() if image is not None: target_position = UiElement.transform_world_to_screen(self.position_scale.position, screen_transform) screen_scale = screen_transform.scale object_scale = self.position_scale.scale target_size = (int(screen_scale[0] * object_scale[0] * image.get_width()), int(screen_scale[1] * object_scale[1] * image.get_height())) target_image = UiElement.get_scaled_image(image, target_size) screen.blit(target_image, target_position) @staticmethod def get_scaled_image(image, resize): return pygame.transform.scale(image, resize) @staticmethod def transform_screen_to_world(convert_position: tuple, screen_transform: PositionScale): screen_scale = screen_transform.scale screen_position = screen_transform.position object_position = (convert_position[0] / screen_scale[0] - screen_position[0], convert_position[1] / screen_scale[1] - screen_position[1]) return object_position @staticmethod def transform_world_to_screen(convert_position: tuple, screen_transform: PositionScale): screen_scale = screen_transform.scale screen_position = screen_transform.position object_position = (int((convert_position[0] + screen_position[0]) * screen_scale[0]), (int(convert_position[1] + screen_position[1]) * screen_scale[1])) return object_position