sep-pm-platformer/project/ui_elements/UiElement.py

79 lines
2.3 KiB
Python

import abc
import uuid
from typing import Optional
import pygame
from pygame import Surface
from sprite.BoundingBox import BoundingBox
from sprite.PositionScale import PositionScale
from physics.TickData import TickData
from ui_elements import CoordinateTransform
class UiElement:
def __init__(self):
self.position_scale = PositionScale()
self.visible = True
self.click_listeners = []
self.bounding_box = BoundingBox(0, 0, 0, 0)
self.uuid = uuid.uuid4()
self.last_image = None
self.last_scaled_image = None
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(click_event)
@abc.abstractmethod
def tick(self, tick_data: TickData):
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()
target_image = None
target_position = CoordinateTransform.transform_world_to_screen(self.position_scale.position,
screen_transform)
if not self.last_image == image or self.last_scaled_image is None:
if image is not None:
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)
self.last_scaled_image = target_image
self.last_image = image
else:
target_image = self.last_scaled_image
if target_image is not None:
screen.blit(target_image, target_position)
@staticmethod
def get_scaled_image(image, resize):
return pygame.transform.scale(image, resize)