from typing import Any, Tuple import pygame as pg from effects.effect import Effect, Colors, transform_bounce import random import math from typing import Union, Generator def calc_radii(size, f): r_c = size / (5 * f + 2) r_a = size / 2 - r_c return r_c, r_a class Moonflower(Effect): def __init__( self, bounds: pg.Rect, colors: Tuple[ Union[pg.Color, Generator[pg.Color, None, None]], Union[pg.Color, Generator[pg.Color, None, None]], ], size=100, velocity=(1, 10), rot_speed=5, outer=5, x_factor=(0.1, 1), y_factor=(0.1, 1), *groups: pg.sprite.Group ) -> None: self.min_velocity = velocity[0] self.max_velocity = velocity[1] self.rot_speed = rot_speed self.rotation = 0 self.velocity = random.randint(self.min_velocity, self.max_velocity) self.ticks = random.randint(0, 360) self.colors = colors 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 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, ), *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: self.rect.center = self.bouncer.send(self.rect.size) self.image.fill(Colors.Blue) pg.draw.rect( self.image, Colors.Black, (1, 1, self.rect.width - 2, self.rect.height - 2) ) o_color = ( self.colors[0] if isinstance(self.colors[0], pg.Color) else next(self.colors[0]) ) i_color = ( self.colors[1] if isinstance(self.colors[1], pg.Color) else 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, o_color, (pos_x, pos_y), self.spot_radius, ) pg.draw.circle( self.image, i_color, self.image.get_rect().center, self.i_radius, ) self.rotation += self.rot_speed self.ticks += int(self.velocity / 180 * math.pi) self.velocity = random.randint(self.min_velocity, self.max_velocity)