From ea7b66d166bd460e230429472144ed0fb72766c9 Mon Sep 17 00:00:00 2001 From: Patrick Moessler Date: Sat, 18 Feb 2023 23:16:49 +0100 Subject: [PATCH] add moonflower --- beamshow.py | 44 +++++++++--------- effects/moonflower.py | 104 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 23 deletions(-) create mode 100644 effects/moonflower.py diff --git a/beamshow.py b/beamshow.py index 909d492..1f4c9ef 100644 --- a/beamshow.py +++ b/beamshow.py @@ -1,15 +1,11 @@ from argparse import ArgumentParser -from typing import Iterable, List, Tuple -from pygame.locals import * -import math -import pygame as pg -import random -import sys -import time +from typing import Generator, Iterable, Tuple -from effects.bouncingspot import BouncingSpot -from effects.doublespot import DoubleSpot -from effects.effect import Effect, color_randomize, color_wheel, Colors +import pygame as pg +import sys + +from effects.effect import Effect, color_wheel, Colors +from effects.moonflower import Moonflower from effects.presets import Presets @@ -49,17 +45,17 @@ def initialize( def render_loop_normal( window: pg.Surface, - background: pg.surface, + background: pg.Surface, effects: Iterable[Effect], clock: pg.time.Clock, -) -> None: +) -> Generator[None, None, None]: blackout = False while True: for event in pg.event.get(): - if event.type == K_SPACE: + if event.type == pg.K_SPACE: blackout = not blackout - if event.type == QUIT: + if event.type == pg.QUIT: pg.quit() sys.exit() @@ -73,10 +69,10 @@ def render_loop_normal( def render_loop_3d( window: pg.Surface, - background: pg.surface, + background: pg.Surface, effects: Iterable[Effect], clock: pg.time.Clock, -) -> None: +) -> Generator[None, None, None]: stage = pg.Surface(size=window.get_size()) stage.fill(Colors.Black) @@ -91,7 +87,7 @@ def render_loop_3d( while True: for event in pg.event.get(): - if event.type == QUIT: + if event.type == pg.QUIT: pg.quit() sys.exit() @@ -147,9 +143,9 @@ def main() -> None: # print some nice output after the pygame banner to separate our stuff from theirs print("") - print("-" * (len(argparser.description) + 4)) + print("-" * (len(str(argparser.description)) + 4)) print(f" {argparser.description} ") - print("-" * (len(argparser.description) + 4)) + print("-" * (len(str(argparser.description)) + 4)) print("") args = argparser.parse_args() @@ -166,12 +162,14 @@ def main() -> None: effects = presets.randomize() else: effects = [ - BouncingSpot( + Moonflower( bounds=window.get_rect(), - color=Colors.White, - # color=color_wheel(), - sizes=(window.get_height() / 8, window.get_height() / 8), + # colors=(Colors.Red,Colors.Blue), + colors=(color_wheel(), color_wheel(hue=180)), + size=window.get_height() / 4, + outer=5, velocity=(1, 1), + rot_speed=1.5, x_factor=(1, 1), y_factor=(2.2, 2.2), ), diff --git a/effects/moonflower.py b/effects/moonflower.py new file mode 100644 index 0000000..5a9f987 --- /dev/null +++ b/effects/moonflower.py @@ -0,0 +1,104 @@ +from typing import Any, Tuple +import pygame as pg +from effects.effect import Effect, Colors, transform_bounce +import random +import math +from typing import Union, Generator + + +def calc_radii(size, f): + r_c = size / (5 * f + 2) + r_a = size / 2 - r_c + return r_c, r_a + + +class Moonflower(Effect): + def __init__( + self, + bounds: pg.Rect, + colors: Tuple[ + Union[pg.Color, Generator[pg.Color, None, None]], + Union[pg.Color, Generator[pg.Color, None, None]], + ], + size=100, + velocity=(1, 10), + rot_speed=5, + outer=5, + x_factor=(0.1, 1), + y_factor=(0.1, 1), + *groups: pg.sprite.Group + ) -> None: + self.min_velocity = velocity[0] + self.max_velocity = velocity[1] + + self.rot_speed = rot_speed + self.rotation = 0 + self.velocity = random.randint(self.min_velocity, self.max_velocity) + self.ticks = random.randint(0, 360) + self.colors = colors + 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) + self.i_radius = (self.o_radius - self.spot_radius) * 0.5 + + 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, + ), + *groups + ) + self.bounds = bounds + self.bouncer = transform_bounce( + bounds=bounds, velocity=velocity, x_factor=x_factor, y_factor=y_factor + ) + next(self.bouncer) + self.update() + + def update(self, *args: Any, **kwargs: Any) -> None: + self.rect.center = self.bouncer.send(self.rect.size) + + self.image.fill(Colors.Blue) + pg.draw.rect( + self.image, Colors.Black, (1, 1, self.rect.width - 2, self.rect.height - 2) + ) + + o_color = ( + self.colors[0] + if isinstance(self.colors[0], pg.Color) + else next(self.colors[0]) + ) + i_color = ( + self.colors[1] + if isinstance(self.colors[1], pg.Color) + else next(self.colors[1]) + ) + + 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, + o_color, + (pos_x, pos_y), + self.spot_radius, + ) + pg.draw.circle( + self.image, + i_color, + self.image.get_rect().center, + self.i_radius, + ) + + self.rotation += self.rot_speed + self.ticks += int(self.velocity / 180 * math.pi) + self.velocity = random.randint(self.min_velocity, self.max_velocity)