pybeamshow/effects/bouncingspot.py
2023-02-23 01:56:05 +01:00

71 lines
2.2 KiB
Python

from effects.effect import MovingEffect
from typing import Any, Optional
from typing import Union, Generator
from util.color import Colors
import math
import pygame as pg
import random
from util.transform import PositionGenerator
class BouncingSpot(MovingEffect):
def __init__(
self,
bounds: pg.Rect,
color: Union[pg.Color, Generator[pg.Color, None, None]],
sizes=(10, 100),
velocity=(1, 10),
mover: Optional[PositionGenerator] = None,
*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
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
next(self.mover)
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"]))
self.image.fill(Colors.Black)
pg.draw.ellipse(
self.image,
self.color if isinstance(self.color, pg.Color) else next(self.color),
((0, 0), self.rect.size),
)
self.ticks += int(self.velocity / 180 * math.pi)
self.velocity = random.randint(self.min_velocity, self.max_velocity)