# shape.py
# -*- coding: utf-8 -*-
from typing import Tuple
from abc import ABC
import copy
import numpy
import contextlib
with contextlib.redirect_stdout(None):
import pygame
# TODO: AA shapes
# todo: change _start_... to _orig_...
[docs]def rotate(surface: pygame.Surface, angle: float):
"""Rotates shape by angle
Notes:
Only exists because of `pygame issue 2464 <https://github.com/pygame/pygame/issues/2464>`__.
"""
if bool(sum((True if size > 1 else False for size in surface.get_size()))) and angle != 0:
return pygame.transform.rotate(surface, angle)
else:
return surface
[docs]class Shape(object):
def __init__(self, alpha: float = 255, angle: float = 0):
self._orig_alpha = alpha
self.alpha = self._orig_alpha
self.angle = angle
self._orig_angle = self.angle
self.surface: pygame.Surface = None
self.rect: pygame.Rect = None
@property
def orig_alpha(self):
return self._orig_alpha
@property
def orig_angle(self):
return self._orig_angle
[docs] def check_size_above_zero(self) -> bool:
raise NotImplementedError
[docs] def get_progress(self) -> Tuple[float, float]:
raise NotImplementedError
[docs] def decrease(self, delta: float):
raise NotImplementedError
[docs] def make_surface(self) -> pygame.Surface:
self.make_shape()
[docs] def make_shape(self):
raise NotImplementedError
[docs]class Circle(BaseForm, ABC):
"""Circle shape class. Is subclass of :class:`BaseShape` and inherits all attributes and methods
Args:
radius (float): Radius of shape
color (Tuple[int, int, int]): Color of shape
alpha (int, optional): Transparency of shape `(0 - 255)`, defaults to `255`
angle (float, optional): Degrees of rotation of shape, defaults to `0`
Attributes:
radius (float): Radius of shape
_start_radius (float): Radius of shape when being instanced. Property is :func:`BaseShape.start_radius`
angle (int): Degrees of rotation of shape
color (List[int, int, int]): Color of shape
_start_color (Tuple[int, int, int]): Color of shape when being instanced. Property is :func:`BaseShape.start_color`
alpha (int): Transparency of shape, ranges from `0` to `255`
_start_alpha (int): Transparency of shape when being instanced. Property is :func:`BaseShape.start_alpha`
surface (:class:`pygame.Surface`): Pygame surface of shape
"""
def __init__(self, radius: float, color: Tuple[int, int, int], alpha: int = 255, angle: float = 0):
super(Circle, self).__init__(radius, color, alpha, angle)
[docs] def make_shape(self):
"""Makes a circle
"""
pygame.draw.circle(self.surface, self.color, (self.radius, self.radius), self.radius)
[docs]class Rect(BaseForm, ABC):
"""Rectangle shape class. Is subclass of :class:`BaseShape` and inherits all attributes and methods
Args:
radius (float): Radius of shape
color (Tuple[int, int, int]): Color of shape
alpha (int, optional): Transparency of shape `(0 - 255)`, defaults to `255`
angle (float, optional): Degrees of rotation of shape, defaults to `0`
Attributes:
radius (float): Radius of shape
_start_radius (float): Radius of shape when being instanced. Property is :func:`BaseShape.start_radius`
angle (int): Degrees of rotation of shape
color (List[int, int, int]): Color of shape
_start_color (Tuple[int, int, int]): Color of shape when being instanced. Property is :func:`BaseShape.start_color`
alpha (int): Transparency of shape, ranges from `0` to `255`
_start_alpha (int): Transparency of shape when being instanced. Property is :func:`BaseShape.start_alpha`
surface (:class:`pygame.Surface`): Pygame surface of shape
"""
def __init__(self, radius: float, color: Tuple[int, int, int], alpha: int = 255, angle: float = 0):
super(Rect, self).__init__(radius, color, alpha, angle)
[docs] def make_shape(self):
"""Makes a rectangle
"""
self.surface.fill(self.color)
[docs]class Image(Shape, ABC):
# todo: copy
def __init__(self, surface: pygame.Surface, size: Tuple[int, int], alpha: int = 255, angle: float = 0):
super(Image, self).__init__(alpha=alpha, angle=angle)
self._orig_size = tuple(size)
self.size = list(self._orig_size)
self._orig_surface = surface.copy()
self.surface = None
self.rect = None
self.make_surface()
@property
def orig_size(self):
return self._orig_size
@property
def orig_surface(self):
return self._orig_surface
[docs] def check_size_above_zero(self) -> bool:
if (self.size[0] > 0) and (self.size[1] > 0):
return True
else:
return False
[docs] def get_progress(self) -> Tuple[float, float]:
progress = (self.size[0] - numpy.diff(self.size) / 2) / (self._orig_size[0] - numpy.diff(self._orig_size) / 2)
return progress, 1 - progress
[docs] def decrease(self, delta: float):
for i in range(2):
self.size[i] -= delta
if self.size[i] <= 0:
self.size[i] = 0
[docs] def make_surface(self) -> pygame.Surface:
self.make_shape()
if self.alpha < 255:
self.surface.set_alpha(self.alpha)
return self.surface
[docs] def make_shape(self):
if self.size != self._orig_size:
self.surface = pygame.transform.scale(self._orig_surface, (int(self.size[0]), int(self.size[1])))
self.surface = rotate(surface=self.surface, angle=self.angle)
self.rect = self.surface.get_rect()