from typing import Any import pygame as pg from effects.effect import Effect, Colors, transform_bounce import random import math from typing import Union, Generator class BouncingSpot(Effect): def __init__( self, bounds: pg.Rect, color: Union[pg.Color, Generator[pg.Color, None, None]], sizes=(10, 100), velocity=(1, 10), x_factor=(0.1, 1), y_factor=(0.1, 1), *groups: pg.sprite.Group ) -> None: self.min_size = sizes[0] self.max_size = sizes[1] self.min_velocity = velocity[0] self.max_velocity = velocity[1] self.velocity = random.randint(self.min_velocity, self.max_velocity) self.ticks = random.randint(0, 360) self.color = color size = (math.sin(self.ticks) / 2 + 0.5) * ( self.max_size - self.min_size ) + self.min_size image = pg.Surface((self.max_size, self.max_size)) image.fill(Colors.Black) image.set_colorkey(Colors.Black) super().__init__( image=image, rect=pg.Rect( bounds.centerx - size / 2, bounds.centery - size / 2, size, size, ), *groups ) self.bounds = bounds self.bouncer = transform_bounce( bounds=bounds, velocity=velocity, x_factor=x_factor, y_factor=y_factor ) next(self.bouncer) self.update() def update(self, *args: Any, **kwargs: Any) -> None: new_size = (math.sin(self.ticks) / 2 + 0.5) * ( self.max_size - self.min_size ) + self.min_size new_scale = new_size - self.rect.width self.rect.inflate_ip(new_scale, new_scale) self.rect.center = self.bouncer.send(self.rect.size) self.image.fill(Colors.Black) pg.draw.ellipse( self.image, self.color if isinstance(self.color, pg.Color) else next(self.color), ((0, 0), self.rect.size), ) self.ticks += self.velocity / 180 * math.pi self.velocity = random.randint(self.min_velocity, self.max_velocity)