all colors are Generator

This commit is contained in:
Patrick Moessler 2023-02-24 18:21:21 +01:00
parent a9c9582180
commit 92730bee9a
17 changed files with 257 additions and 96 deletions

View file

@ -1,6 +1,6 @@
from effects.effect import MovingEffect
from typing import Any, Optional
from util.color import Colors, DynamicColor
from util.color import Colors, ColorGenerator
import math
import pygame as pg
import random
@ -12,10 +12,11 @@ class BouncingSpot(MovingEffect):
def __init__(
self,
bounds: pg.Rect,
color: DynamicColor,
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]
@ -26,6 +27,8 @@ class BouncingSpot(MovingEffect):
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
@ -58,10 +61,13 @@ class BouncingSpot(MovingEffect):
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.color if isinstance(self.color, pg.Color) else next(self.color),
self.spot_color,
((0, 0), self.rect.size),
)

View file

@ -1,6 +1,6 @@
from effects.effect import Effect
from typing import Any
from util.color import Colors, DynamicColor
from util.color import Colors, ColorGenerator
from util.transform import transform_bounce
import math
import pygame as pg
@ -11,7 +11,7 @@ class CrazyPolys(Effect):
def __init__(
self,
bounds: pg.Rect,
color: DynamicColor,
color: ColorGenerator,
sizes=(100, 500),
velocity=(0.1, 1),
x_factor=(0.1, 1),
@ -106,7 +106,7 @@ class CrazyPolys(Effect):
new_cursor = self.calc_pos()
pg.draw.line(
self.image,
self.color if isinstance(self.color, pg.Color) else next(self.color),
next(self.color),
self.cursor,
new_cursor,
width=30,
@ -115,7 +115,7 @@ class CrazyPolys(Effect):
# pg.draw.ellipse(
# self.image,
# self.color if isinstance(self.color, pg.Color) else next(self.color),
# next(self.color),
# ((0, 0), self.rect.size),
# )

View file

@ -1,7 +1,8 @@
from typing import Any, List, Tuple
import pygame as pg
from effects.effect import Effect
from util.color import Colors, DynamicColor
from util import XYCoord
from util.color import Colors, ColorGenerator
import random
from typing import Generator
@ -22,7 +23,7 @@ class Spot(pg.sprite.Sprite):
def __init__(
self,
color: pg.Color,
position: Tuple[int, int],
position: XYCoord,
radius: int,
fade_in: int,
hold: int,
@ -57,7 +58,7 @@ class DoubleSpot(Effect):
def __init__(
self,
bounds: pg.Rect,
color: DynamicColor,
color: ColorGenerator,
radius: int = 200,
hold: int = 60 * 1,
fade_out: bool = False,
@ -127,13 +128,13 @@ class DoubleSpot(Effect):
and len(self.spots) == 2
):
spot_color = (
self.color if isinstance(self.color, pg.Color) else next(self.color)
next(self.color),
)
self.add_spot(spot_color)
self.add_spot(spot_color)
elif kwargs["is_beat"]:
spot_color = (
self.color if isinstance(self.color, pg.Color) else next(self.color)
next(self.color),
)
self.add_spot(spot_color)
self.add_spot(spot_color)

View file

@ -1,7 +1,7 @@
from typing import Any, List, Tuple
import pygame as pg
from effects.effect import Effect
from util.color import Colors, color_fade, DynamicColor
from util.color import Colors, color_fade, ColorGenerator
from util.transform import transform_falling
import random
from typing import Generator
@ -11,7 +11,7 @@ class Drop(pg.sprite.Sprite):
def __init__(
self,
bounds: pg.rect.Rect,
color: DynamicColor,
color: ColorGenerator,
acceleration=1.0,
) -> None:
@ -28,7 +28,7 @@ class Drop(pg.sprite.Sprite):
self.color = color
pg.draw.ellipse(
self.image,
next(self.color) if isinstance(self.color, Generator) else self.color,
next(self.color),
((0, 0), self.rect.size),
)
@ -65,8 +65,8 @@ class Drops(Effect):
self,
bounds: pg.Rect,
colors: Tuple[
DynamicColor,
DynamicColor,
ColorGenerator,
ColorGenerator,
],
sizes=(10, 100),
drop_rate=0.2,

View file

@ -27,3 +27,28 @@ class MovingEffect(Effect):
super().__init__(image, rect, *groups)
self.mover = mover or transform_static(rect.center)
next(self.mover)
"""
ring chase two colors
square
square two color
line falling
line scan vh
starfield spawn chance
rainbow circle rotate
spot row
alles größer
fix double spot 4 spots
"""

45
effects/line.py Normal file
View file

@ -0,0 +1,45 @@
from effects.effect import MovingEffect
from typing import Any, Iterable, Optional, Tuple
from util import XYCoord
from util.color import Colors, ColorGenerator
from util.transform import PositionGenerator
import pygame as pg
class Lines(MovingEffect):
def __init__(
self,
bounds: pg.Rect,
vectors: Iterable[Tuple[XYCoord, XYCoord, ColorGenerator]],
thickness: int,
mover: Optional[PositionGenerator],
*groups: pg.sprite.Group,
) -> None:
self.vectors = vectors
self.thickness = thickness
image = pg.Surface(bounds.size)
image.fill(Colors.Black)
image.set_colorkey(Colors.Black)
super().__init__(
image,
pg.Rect(bounds),
mover,
*groups,
)
self.bounds = bounds
self.update(is_beat=False)
def update(self, *args: Any, **kwargs: Any) -> None:
self.rect.topleft = self.mover.send((self.rect.size, kwargs["is_beat"]))
self.image.fill(Colors.Black)
for line in self.vectors:
pg.draw.line(
self.image,
next(line[2]),
line[0],
line[1],
width=self.thickness,
)

View file

@ -1,7 +1,7 @@
from typing import Any, Optional, Tuple
import pygame as pg
from effects.effect import MovingEffect
from util.color import Colors, DynamicColor
from util.color import Colors, ColorGenerator
import math
from typing import Generator
@ -19,8 +19,8 @@ class Moonflower(MovingEffect):
self,
bounds: pg.Rect,
colors: Tuple[
DynamicColor,
DynamicColor,
ColorGenerator,
ColorGenerator,
],
mover: Optional[PositionGenerator] = None,
beat_color: bool = False,

View file

@ -99,7 +99,7 @@ class MovingWave(MovingEffect):
# pg.draw.ellipse(
# self.image,
# self.color if isinstance(self.color, pg.Color) else next(self.color),
# next(self.color),
# ((0, 0), self.rect.size),
# )

View file

@ -6,7 +6,14 @@ from random import choice, randint, randrange
from effects.effect import Effect
from effects.line import Lines
from util.color import color_darken, color_randomize, color_strobe, color_wheel, Colors
from util.color import (
color_darken,
color_randomize,
color_static,
color_strobe,
color_wheel,
Colors,
)
# from effects.crazypolys import CrazyPolys
from effects.drops import Drops
@ -33,7 +40,7 @@ class Presets:
self.beat_reactive = beat_reactive
def default(self) -> List[Effect]:
return self.FallingLine()
return self.SpotRow()
def __getitem__(self, idx: str) -> List[Effect]:
return getattr(self, idx)()
@ -158,7 +165,7 @@ class Presets:
return [
BouncingSpot(
bounds=self.bounds,
color=Colors.White,
color=color_static(Colors.White),
sizes=(self.bounds.height / 3, self.bounds.height / 3),
velocity=(1, 1),
mover=transform_bounce(
@ -179,10 +186,13 @@ class Presets:
beat_color=self.beat_reactive,
size=int(self.bounds.height * 0.8),
outer=randint(3, 8),
velocity=(0.5, 0.5),
rot_speed=1,
mover=transform_bounce(
bounds=self.bounds,
velocity=(0.5, 0.5),
x_factor=(0.5, 1.5),
y_factor=(0.5, 3),
),
)
]
@ -301,7 +311,7 @@ class Presets:
return [
Starfield(
bounds=self.bounds,
color=Colors.White,
color=color_static(Colors.White),
# color=color_randomize(),
fade_in=True,
fade_out=True,
@ -330,7 +340,10 @@ class Presets:
return [
Drops(
bounds=self.bounds,
colors=(Colors.Green, color_darken(Colors.Blue, 0.2)),
colors=(
color_static(Colors.Green),
color_static(color_darken(Colors.Blue, 0.2)),
),
sizes=(self.bounds.width // 40, self.bounds.width // 35),
drop_rate=0.1,
drop_acceleration=0.3,
@ -341,7 +354,7 @@ class Presets:
return [
ScanReticle(
self.bounds,
(Colors.Red, Colors.White),
(color_static(Colors.Red), color_static(Colors.White)),
mover=transform_bounce(
bounds=self.bounds,
velocity=(0.5, 1),
@ -351,29 +364,89 @@ class Presets:
)
]
def Spiro(self) -> List[Effect]:
def FallingLine(self) -> List[Effect]:
bounds = pg.rect.Rect(0, 0, self.bounds.width, 30)
return [
Spiro(
bounds=self.bounds,
color=color_wheel(increase=2),
sizes=(self.bounds.height, self.bounds.height),
velocity=(0.1, 0.4),
mover=transform_bounce(
self.bounds,
velocity=(0.1, 0.4),
x_factor=(1, 1),
y_factor=(0.5, 1.5),
Lines(
bounds=bounds,
vectors=(((0, 15), (self.bounds.width, 15), color_wheel()),),
thickness=30,
mover=transform_falling(
bounds,
acceleration=0.8,
initial_pos=(0, 0),
initial_velocity=0.01,
on_beat_reset=True,
),
),
]
def CrazyPolys(self) -> List[Effect]:
def StrobeLine(self) -> List[Effect]:
bounds = pg.rect.Rect(0, 0, self.bounds.width, 30)
return [
CrazyPolys(
bounds=self.bounds,
color=color_wheel(increase=2),
sizes=(self.bounds.height, self.bounds.height),
velocity=(0.1, 0.4),
y_factor=(0.5, 1.5),
Lines(
bounds=bounds,
vectors=(
(
(0, 15),
(self.bounds.width, 15),
color_strobe(color=color_wheel(), rate=(2, 8)),
),
),
thickness=30,
mover=transform_falling(
bounds,
acceleration=0.8,
initial_pos=(0, 0),
initial_velocity=0.01,
on_beat_reset=True,
),
),
]
# def Spiro(self) -> List[Effect]:
# return [
# Spiro(
# bounds=self.bounds,
# color=color_wheel(increase=2),
# sizes=(self.bounds.height, self.bounds.height),
# velocity=(0.1, 0.4),
# mover=transform_bounce(
# self.bounds,
# velocity=(0.1, 0.4),
# x_factor=(1, 1),
# y_factor=(0.5, 1.5),
# ),
# ),
# ]
# def CrazyPolys(self) -> List[Effect]:
# return [
# CrazyPolys(
# bounds=self.bounds,
# color=color_wheel(increase=2),
# sizes=(self.bounds.height, self.bounds.height),
# velocity=(0.1, 0.4),
# y_factor=(0.5, 1.5),
# ),
# ]
def SpotRow(self) -> List[Effect]:
count = 8
size = self.bounds.width // (count * 2)
return [
BouncingSpot(
bounds=self.bounds,
color=color_wheel(hue=3 * 360 // count * i, increase=60),
sizes=(size, size),
velocity=(1, 1),
on_beat_color=True,
mover=transform_static(
(
size + size * 2 * i,
size,
)
),
)
for i in range(count)
]

View file

@ -98,7 +98,7 @@ class RainbowWave(MovingEffect):
# pg.draw.ellipse(
# self.image,
# self.color if isinstance(self.color, pg.Color) else next(self.color),
# next(self.color),
# ((0, 0), self.rect.size),
# )

View file

@ -1,8 +1,8 @@
from typing import Any, Tuple
from typing import Any, Optional, Tuple
import pygame as pg
from effects.effect import Effect
from util.color import Colors, DynamicColor
from util.transform import transform_bounce
from effects.effect import MovingEffect
from util.color import Colors, ColorGenerator
from util.transform import PositionGenerator, transform_bounce
import math
from typing import Generator
@ -13,27 +13,22 @@ def calc_radii(size, f):
return r_c, r_a
class RotatingPoly(Effect):
class RotatingPoly(MovingEffect):
def __init__(
self,
bounds: pg.Rect,
color: DynamicColor,
color: ColorGenerator,
beat_color: bool = False,
size: int = 100,
velocity: Tuple[float, float] = (1, 10),
rot_speed: float = 5,
outer: int = 5,
spot_factor: float = 0.5,
x_factor: Tuple[float, float] = (0.1, 1),
y_factor: Tuple[float, float] = (0.1, 1),
mover: Optional[PositionGenerator] = None,
*groups: pg.sprite.Group
) -> None:
# self.min_velocity = velocity[0]
# self.max_velocity = velocity[1]
self.rot_speed = rot_speed
self.rotation = 0.0
# self.velocity = random.uniform(self.min_velocity, self.max_velocity)
self.color = color
self.beat_color = beat_color
self.o_count = outer
@ -42,7 +37,6 @@ class RotatingPoly(Effect):
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)
@ -55,20 +49,15 @@ class RotatingPoly(Effect):
size,
size,
),
mover,
*groups
)
self.bounds = bounds
self.bouncer = transform_bounce(
bounds=bounds, velocity=velocity, x_factor=x_factor, y_factor=y_factor
)
next(self.bouncer)
self.o_color = (
self.color if isinstance(self.color, pg.Color) else next(self.color)
)
self.o_color = next(self.color)
self.update(is_beat=False)
def update(self, *args: Any, **kwargs: Any) -> None:
self.rect.center = self.bouncer.send((self.rect.size, kwargs["is_beat"]))
self.rect.center = self.mover.send((self.rect.size, kwargs["is_beat"]))
self.image.fill(Colors.Black)
@ -96,5 +85,3 @@ class RotatingPoly(Effect):
)
self.rotation += self.rot_speed
# self.ticks += int(self.velocity / 180 * math.pi)
# self.velocity = random.uniform(self.min_velocity, self.max_velocity)

View file

@ -1,7 +1,7 @@
from typing import Any, Optional, Tuple
import pygame as pg
from effects.effect import MovingEffect
from util.color import Colors, DynamicColor
from util.color import Colors, ColorGenerator
from util.transform import PositionGenerator
@ -10,8 +10,8 @@ class ScanReticle(MovingEffect):
self,
bounds: pg.Rect,
colors: Tuple[
DynamicColor,
DynamicColor,
ColorGenerator,
ColorGenerator,
],
mover: Optional[PositionGenerator] = None,
*groups: pg.sprite.Group

View file

@ -1,7 +1,7 @@
from typing import Any, Optional
import pygame as pg
from effects.effect import MovingEffect
from util.color import Colors, DynamicColor
from util.color import Colors, ColorGenerator
from util.transform import PositionGenerator
import random
import math
@ -11,7 +11,7 @@ class Spiro(MovingEffect):
def __init__(
self,
bounds: pg.Rect,
color: DynamicColor,
color: ColorGenerator,
sizes=(100, 500),
velocity=(0.1, 1),
segments=100,
@ -84,7 +84,7 @@ class Spiro(MovingEffect):
new_cursor = self.calc_pos()
pg.draw.line(
self.image,
self.color if isinstance(self.color, pg.Color) else next(self.color),
next(self.color),
self.cursor,
new_cursor,
width=15,

View file

@ -1,7 +1,8 @@
from typing import Any, List, Tuple
import pygame as pg
from effects.effect import Effect
from util.color import Colors, DynamicColor
from util import XYCoord
from util.color import Colors, ColorGenerator
import random
from typing import Generator
@ -22,7 +23,7 @@ class Spot(pg.sprite.Sprite):
def __init__(
self,
color: pg.Color,
position: Tuple[int, int],
position: XYCoord,
radius: int,
fade_in: int,
hold: int,
@ -57,7 +58,7 @@ class Starfield(Effect):
def __init__(
self,
bounds: pg.Rect,
color: DynamicColor,
color: ColorGenerator,
radius: int = 20,
star_factor: float = 0.2,
hold: int = 60 * 3,
@ -138,7 +139,7 @@ class Starfield(Effect):
missing_stars = self.num_stars - len(self.stars)
for _ in range(random.randint(missing_stars // 3, missing_stars // 2)):
star_color = (
self.color if isinstance(self.color, pg.Color) else next(self.color)
next(self.color),
)
self.add_star(star_color)

View file

@ -0,0 +1,3 @@
from typing import Tuple
XYCoord = Tuple[int, int]

View file

@ -1,11 +1,10 @@
from dataclasses import dataclass
import random
from typing import Generator, Literal, Sequence, Union
from typing import Generator, Literal, Sequence, Tuple
import pygame as pg
ColorGenerator = Generator[pg.Color, None, None]
DynamicColor = Union[pg.Color, ColorGenerator]
def copy_color(source: pg.Color) -> pg.Color:
@ -24,13 +23,19 @@ class Colors:
Magenta = pg.Color(255, 0, 255)
def color_wheel(hue=0, increase=1) -> ColorGenerator:
def color_static(color: pg.Color) -> ColorGenerator:
while True:
yield color
def color_wheel(hue: int = 0, increase: int = 1, repeat: int = 1) -> ColorGenerator:
color = copy_color(Colors.Red)
h, s, l, a = color.hsla
h = hue % 360
while True:
color.hsla = h, s, l, a
for _ in range(repeat):
yield color
h = (h + increase) % 360
@ -104,6 +109,21 @@ def color_darken(color: pg.Color, factor: float) -> pg.Color:
return new_color
def color_strobe(
color: ColorGenerator,
rate: Tuple[int, int],
phase: int = 0,
flash_color: ColorGenerator = color_static(Colors.Black),
) -> ColorGenerator:
counter = phase
while True:
if counter < rate[0]:
yield from flash_color
else:
yield from color
counter = (counter + 1) % rate[1]
def rainbow_surface(
image: pg.Surface,
orientation: Literal["h", "v"] = "h",
@ -113,9 +133,9 @@ def rainbow_surface(
wheel = color_wheel(hue, increase)
if orientation == "h":
h = image.get_height()
for x in range(image.get_width()):
pg.draw.line(image, next(wheel), (x, 0), (x, h))
for x in range(image.get_width() // 5):
pg.draw.line(image, next(wheel), (x * 5, 0), (x * 5, h), width=5)
elif orientation == "v":
w = image.get_width()
for y in range(image.get_height()):
pg.draw.line(image, next(wheel), (0, y), (w, y))
for y in range(image.get_height() // 5):
pg.draw.line(image, next(wheel), (0, y * 5), (w, y * 5), width=5)

View file

@ -3,12 +3,12 @@ import random
from typing import Generator, Optional, Tuple
import pygame as pg
PositionGenerator = Generator[
Tuple[int, int], Tuple[Tuple[int, int], Optional[bool]], None
]
from util import XYCoord
PositionGenerator = Generator[XYCoord, Tuple[XYCoord, Optional[bool]], None]
def transform_static(position: Tuple[int, int]) -> PositionGenerator:
def transform_static(position: XYCoord) -> PositionGenerator:
while True:
_ = yield (position)
@ -52,7 +52,7 @@ def transform_bounce(
def transform_oscillate(
bounds: pg.Rect,
period: int,
initial_pos: Tuple[int, int] = (-1, -1),
initial_pos: XYCoord = (-1, -1),
) -> PositionGenerator:
pos_x = float(initial_pos[0] if initial_pos[0] > 0 else bounds.left)
pos_y = float(initial_pos[1] if initial_pos[1] > 0 else bounds.top)
@ -85,7 +85,7 @@ def transform_oscillate(
def transform_falling(
bounds: pg.Rect,
acceleration: float,
initial_pos: Tuple[int, int],
initial_pos: XYCoord,
initial_velocity: float = 1.0,
on_beat_reset: bool = False,
) -> PositionGenerator: