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

75 lines
2.2 KiB
Python

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