from effects.effect import MovingEffect from typing import Any, Optional from util.color import Colors, ColorGenerator import math import pygame as pg import random from util.transform import PositionGenerator class BouncingSpot(MovingEffect): def __init__( self, bounds: pg.Rect, color: ColorGenerator, sizes=(10, 100), velocity=(1, 10), mover: Optional[PositionGenerator] = None, on_beat_color: bool = False, *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 self.spot_color = next(color) self.on_beat_color = on_beat_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, pg.Rect( bounds.centerx - size / 2, bounds.centery - size / 2, size, size, ), mover, *groups ) self.bounds = bounds self.update(is_beat=False) 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 if kwargs["is_beat"]: new_scale *= 1.5 self.rect.inflate_ip(new_scale, new_scale) self.rect.center = self.mover.send((self.rect.size, kwargs["is_beat"])) if (not self.on_beat_color) or kwargs["is_beat"]: self.spot_color = next(self.color) self.image.fill(Colors.Black) pg.draw.ellipse( self.image, self.spot_color, ((0, 0), self.rect.size), ) self.ticks += int(self.velocity / 180 * math.pi) self.velocity = random.randint(self.min_velocity, self.max_velocity)