from typing import Any, Optional, Tuple import pygame as pg from effects.effect import MovingEffect from util.color import Colors, ColorGenerator import math from typing import Generator from util.transform import PositionGenerator def calc_radii(size, f): r_c = size / (5 * f + 2) r_a = size / 2 - r_c return r_c, r_a class Moonflower(MovingEffect): def __init__( self, bounds: pg.Rect, colors: Tuple[ ColorGenerator, ColorGenerator, ], mover: Optional[PositionGenerator] = None, beat_color: bool = False, size: int = 100, rot_speed: float = 5, outer: int = 5, inner_factor: float = 1, *groups: pg.sprite.Group ) -> None: self.rot_speed = rot_speed self.rotation = 0.0 self.colors = colors self.beat_color = beat_color self.o_count = outer self.o_f = 1 / math.sin(math.pi / self.o_count) self.spot_radius, self.o_radius = calc_radii(size, self.o_f) self.i_radius = (self.o_radius - self.spot_radius) * 0.5 * inner_factor image = pg.Surface((size, 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.o_color = ( self.colors[0] if isinstance(self.colors[0], pg.Color) else next(self.colors[0]) ) self.i_color = ( self.colors[1] if isinstance(self.colors[1], pg.Color) else next(self.colors[1]) ) self.update(is_beat=False) def update(self, *args: Any, **kwargs: Any) -> None: self.rect.center = self.mover.send((self.rect.size, kwargs["is_beat"])) self.image.fill(Colors.Black) if not self.beat_color or kwargs["is_beat"]: if isinstance(self.colors[0], Generator): self.o_color = next(self.colors[0]) if isinstance(self.colors[1], Generator): self.i_color = next(self.colors[1]) for phi in range(0, 360, 360 // self.o_count): rads = math.pi * (phi + self.rotation) / 180 pos_x = self.rect.width // 2 + self.o_radius * math.cos(rads) pos_y = self.rect.height // 2 + self.o_radius * math.sin(rads) pg.draw.circle( self.image, self.o_color, (pos_x, pos_y), self.spot_radius, ) pg.draw.circle( self.image, self.i_color, self.image.get_rect().center, self.i_radius, ) self.rotation += self.rot_speed