import pygame as pg from typing import Iterator, List 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 effects.crazypolys import CrazyPolys from effects.drops import Drops from effects.bouncingspot import BouncingSpot from effects.doublespot import DoubleSpot from effects.moonflower import Moonflower from effects.rainbowwave import RainbowWave from effects.rotatingpoly import RotatingPoly from effects.scanreticle import ScanReticle # from effects.spiro import Spiro from effects.starfield import Starfield from util.transform import ( transform_bounce, transform_falling, transform_oscillate, transform_static, ) class Presets: def __init__(self, bounds: pg.Rect, beat_reactive: bool = False) -> None: self.bounds = bounds self.beat_reactive = beat_reactive def default(self) -> List[Effect]: return self.FallingLine() def __getitem__(self, idx: str) -> List[Effect]: return getattr(self, idx)() def __contains__(self, idx: str) -> bool: return hasattr(self, idx) def __iter__(self) -> Iterator[str]: return ( func for func in dir(self) if callable(getattr(self, func)) and not func.startswith("__") ) def randomize(self) -> str: return choice( [ func for func in dir(self) if callable(getattr(self, func)) and not (func.startswith("__") or func == "randomize") ] ) def DoubleSpotRandomColor(self) -> List[Effect]: return [ DoubleSpot( bounds=self.bounds, color=color_wheel(increase=30), beat_adapt=self.beat_reactive, radius=100, fade_out=True, fade_in=True, hold=60, ) ] def DoubleBouncingSpotsColorWheel(self) -> List[Effect]: return [ BouncingSpot( bounds=self.bounds, color=color_wheel(), sizes=(self.bounds.height / 8, self.bounds.height / 6), mover=transform_bounce( bounds=self.bounds, velocity=(1, 1), x_factor=(1, 1), y_factor=(2.2, 2.2), on_beat_phase=90, ), ), BouncingSpot( bounds=self.bounds, color=color_wheel(hue=180), sizes=(self.bounds.height / 8, self.bounds.height / 6), mover=transform_bounce( bounds=self.bounds, velocity=(1, 1), x_factor=(1, 1), y_factor=(2.2, 2.2), on_beat_phase=180, ), ), ] def CollidingWaves(self) -> List[Effect]: return [ RainbowWave( bounds=pg.rect.Rect(0, 0, self.bounds.width, self.bounds.height), wave_count=5, wave_height=self.bounds.height // 6, thickness=30, mover=transform_oscillate(self.bounds, 60, (0, 0)), ), RainbowWave( bounds=pg.rect.Rect(0, 0, self.bounds.width, self.bounds.height), # hue=180, wave_count=5, wave_height=self.bounds.height // 6, start_phase=120, thickness=20, mover=transform_oscillate( self.bounds, 60, (0, self.bounds.height * 5 // 6) ), ), ] def RainbowWave(self) -> List[Effect]: return [ RainbowWave( bounds=pg.rect.Rect(0, 0, self.bounds.width, self.bounds.height), wave_count=1, color_inc=2, wave_height=self.bounds.height // 3, thickness=30, mover=transform_static(position=(0, 0)), ), ] def FallingWave(self) -> List[Effect]: bounds = pg.rect.Rect(0, 0, self.bounds.width, self.bounds.height // 2) return [ RainbowWave( bounds=bounds, wave_count=8, wave_height=self.bounds.height // 8, thickness=25, hue=30 * randrange(0, 12), color_inc=0, scroll_speed=0, mover=transform_falling( bounds, acceleration=0.8, initial_pos=(0, 0), initial_velocity=0.01, on_beat_reset=True, ), ), ] def BouncingSpotWhite(self) -> List[Effect]: return [ BouncingSpot( bounds=self.bounds, color=Colors.White, sizes=(self.bounds.height / 3, self.bounds.height / 3), velocity=(1, 1), mover=transform_bounce( bounds=self.bounds, velocity=(1, 1), x_factor=(1, 1), y_factor=(2.2, 2.2), on_beat_phase=180, ), ), ] def RotatingPoly(self) -> List[Effect]: return [ RotatingPoly( bounds=self.bounds, color=color_wheel(increase=(75 if self.beat_reactive else 0)), beat_color=self.beat_reactive, size=int(self.bounds.height * 0.8), outer=randint(3, 8), velocity=(0.5, 0.5), rot_speed=1, x_factor=(0.5, 1.5), y_factor=(0.5, 3), ) ] def Moonflower(self) -> List[Effect]: return [ Moonflower( bounds=self.bounds, colors=( color_wheel(increase=(75 if self.beat_reactive else 0)), color_wheel(hue=180, increase=(75 if self.beat_reactive else 0)), ), beat_color=self.beat_reactive, size=self.bounds.height // 2, outer=5, inner_factor=0.3, rot_speed=1.5, mover=transform_bounce( bounds=self.bounds, velocity=(0.5, 1.5), x_factor=(0.5, 1.5), y_factor=(0.5, 1.5), ), ) ] def DoubleMoonflower(self) -> List[Effect]: hue_left = randrange(0, 360) hue_right = randrange(0, 360) size = int(self.bounds.height * 0.75) return [ Moonflower( bounds=self.bounds, colors=( color_wheel( hue=hue_left, increase=(75 if self.beat_reactive else 0) ), color_wheel( hue=180 + hue_left, increase=(75 if self.beat_reactive else 0) ), ), beat_color=self.beat_reactive, size=size, outer=7, inner_factor=0.5, rot_speed=-1.5, mover=transform_static(position=(size // 2, self.bounds.height // 2)), ), Moonflower( bounds=self.bounds, colors=( color_wheel( hue=hue_right, increase=(75 if self.beat_reactive else 0) ), color_wheel( hue=180 + hue_right, increase=(75 if self.beat_reactive else 0) ), ), beat_color=self.beat_reactive, size=size, outer=7, inner_factor=0.5, rot_speed=1.7, mover=transform_static( position=(self.bounds.width - size // 2, self.bounds.height // 2) ), ), ] def NestedMoonflower(self) -> List[Effect]: hue_left = randrange(0, 12) * 30 hue_right = (hue_left + 180) % 360 # hue_right = randrange(0, 360) size = int(self.bounds.height * 0.8) return [ Moonflower( bounds=self.bounds, colors=( color_wheel( hue=hue_left, increase=(15 if self.beat_reactive else 0) ), color_wheel( hue=180 + hue_left, increase=(15 if self.beat_reactive else 0) ), ), beat_color=self.beat_reactive, size=size, outer=7, inner_factor=0.5, rot_speed=-1.5, mover=transform_static( position=(self.bounds.width // 2, self.bounds.height // 2) ), ), Moonflower( bounds=self.bounds, colors=( color_wheel( hue=hue_right, increase=(15 if self.beat_reactive else 0) ), color_wheel( hue=180 + hue_right, increase=(15 if self.beat_reactive else 0) ), ), beat_color=self.beat_reactive, size=int(size * 0.6), outer=7, inner_factor=0.3, rot_speed=1, mover=transform_static( position=(self.bounds.width // 2, self.bounds.height // 2) ), ), ] def WhiteStarfield(self) -> List[Effect]: return [ Starfield( bounds=self.bounds, color=Colors.White, # color=color_randomize(), fade_in=True, fade_out=True, # radius=30, star_factor=1, hold=60 * 2, # beat_adapt=True, ) ] def ColorStarfield(self) -> List[Effect]: return [ Starfield( bounds=self.bounds, color=color_randomize(), fade_in=True, fade_out=True, # radius=30, star_factor=1, hold=60 * 2, beat_adapt=True, ) ] def GreenBlueDrops(self) -> List[Effect]: return [ Drops( bounds=self.bounds, colors=(Colors.Green, color_darken(Colors.Blue, 0.2)), sizes=(self.bounds.width // 40, self.bounds.width // 35), drop_rate=0.1, drop_acceleration=0.3, ) ] def ScanReticle(self) -> List[Effect]: return [ ScanReticle( self.bounds, (Colors.Red, Colors.White), mover=transform_bounce( bounds=self.bounds, velocity=(0.5, 1), x_factor=(3, 3), y_factor=(0.5, 1), ), ) ] 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), ), ]