pybeamshow/effects/moonflower.py
2023-02-24 18:21:40 +01:00

98 lines
2.9 KiB
Python

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