2023-02-23 00:19:20 +01:00
|
|
|
from typing import Any, Optional, Tuple
|
2023-02-18 23:16:49 +01:00
|
|
|
import pygame as pg
|
2023-02-23 00:19:20 +01:00
|
|
|
from effects.effect import MovingEffect
|
2023-02-24 18:21:21 +01:00
|
|
|
from util.color import Colors, ColorGenerator
|
2023-02-18 23:16:49 +01:00
|
|
|
import math
|
2023-02-23 02:10:50 +01:00
|
|
|
from typing import Generator
|
2023-02-18 23:16:49 +01:00
|
|
|
|
2023-02-23 00:19:20 +01:00
|
|
|
from util.transform import PositionGenerator
|
|
|
|
|
2023-02-18 23:16:49 +01:00
|
|
|
|
|
|
|
def calc_radii(size, f):
|
|
|
|
r_c = size / (5 * f + 2)
|
|
|
|
r_a = size / 2 - r_c
|
|
|
|
return r_c, r_a
|
|
|
|
|
|
|
|
|
2023-02-23 00:19:20 +01:00
|
|
|
class Moonflower(MovingEffect):
|
2023-02-18 23:16:49 +01:00
|
|
|
def __init__(
|
|
|
|
self,
|
|
|
|
bounds: pg.Rect,
|
|
|
|
colors: Tuple[
|
2023-02-24 18:21:21 +01:00
|
|
|
ColorGenerator,
|
|
|
|
ColorGenerator,
|
2023-02-18 23:16:49 +01:00
|
|
|
],
|
2023-02-23 00:19:20 +01:00
|
|
|
mover: Optional[PositionGenerator] = None,
|
2023-02-19 02:01:28 +01:00
|
|
|
beat_color: bool = False,
|
|
|
|
size: int = 100,
|
|
|
|
rot_speed: float = 5,
|
|
|
|
outer: int = 5,
|
2023-02-23 01:56:05 +01:00
|
|
|
inner_factor: float = 1,
|
2023-02-18 23:16:49 +01:00
|
|
|
*groups: pg.sprite.Group
|
|
|
|
) -> None:
|
|
|
|
self.rot_speed = rot_speed
|
2023-02-19 02:01:28 +01:00
|
|
|
self.rotation = 0.0
|
2023-02-18 23:16:49 +01:00
|
|
|
self.colors = colors
|
2023-02-19 02:01:28 +01:00
|
|
|
self.beat_color = beat_color
|
2023-02-18 23:16:49 +01:00
|
|
|
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)
|
2023-02-23 01:56:05 +01:00
|
|
|
self.i_radius = (self.o_radius - self.spot_radius) * 0.5 * inner_factor
|
2023-02-18 23:16:49 +01:00
|
|
|
|
|
|
|
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,
|
|
|
|
),
|
2023-02-23 00:19:20 +01:00
|
|
|
mover,
|
|
|
|
*groups,
|
2023-02-18 23:16:49 +01:00
|
|
|
)
|
|
|
|
self.bounds = bounds
|
2023-02-19 02:01:28 +01:00
|
|
|
self.o_color = (
|
2023-02-18 23:16:49 +01:00
|
|
|
self.colors[0]
|
|
|
|
if isinstance(self.colors[0], pg.Color)
|
|
|
|
else next(self.colors[0])
|
|
|
|
)
|
2023-02-19 02:01:28 +01:00
|
|
|
self.i_color = (
|
2023-02-18 23:16:49 +01:00
|
|
|
self.colors[1]
|
|
|
|
if isinstance(self.colors[1], pg.Color)
|
|
|
|
else next(self.colors[1])
|
|
|
|
)
|
2023-02-19 02:01:28 +01:00
|
|
|
self.update(is_beat=False)
|
|
|
|
|
|
|
|
def update(self, *args: Any, **kwargs: Any) -> None:
|
2023-02-23 00:19:20 +01:00
|
|
|
self.rect.center = self.mover.send((self.rect.size, kwargs["is_beat"]))
|
2023-02-19 02:01:28 +01:00
|
|
|
|
|
|
|
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])
|
2023-02-18 23:16:49 +01:00
|
|
|
|
|
|
|
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,
|
2023-02-19 02:01:28 +01:00
|
|
|
self.o_color,
|
2023-02-18 23:16:49 +01:00
|
|
|
(pos_x, pos_y),
|
|
|
|
self.spot_radius,
|
|
|
|
)
|
|
|
|
pg.draw.circle(
|
|
|
|
self.image,
|
2023-02-19 02:01:28 +01:00
|
|
|
self.i_color,
|
2023-02-18 23:16:49 +01:00
|
|
|
self.image.get_rect().center,
|
|
|
|
self.i_radius,
|
|
|
|
)
|
|
|
|
|
|
|
|
self.rotation += self.rot_speed
|