@@ -55,6 +55,7 @@ def monotonic_ns():
5555 return int (time .time () * 1000000000 )
5656
5757import random
58+ from math import ceil , sin , radians
5859from .color import BLACK , RAINBOW
5960
6061__version__ = "0.0.0-auto.0"
@@ -339,6 +340,96 @@ def draw(self):
339340 self .show ()
340341
341342
343+ class Pulse (Animation ):
344+ """
345+ Pulse all pixels a single color.
346+
347+ :param pixel_object: The initialised LED object.
348+ :param int speed: Animation refresh rate in seconds, e.g. ``0.1``.
349+ :param color: Animation color in ``(r, g, b)`` tuple, or ``0x000000`` hex format.
350+ :param period: Period to pulse the LEDs over. Default 5.
351+ :param max_intensity: The maximum intensity to pulse, between 0 and 1.0. Default 1.
352+ :param min_intensity: The minimum intensity to pulse, between 0 and 1.0. Default 0.
353+ """
354+
355+ # pylint: disable=too-many-arguments
356+ def __init__ (self , pixel_object , speed , color , period = 5 , max_intensity = 1 , min_intensity = 0 ):
357+ self .max_intensity = max_intensity
358+ self .min_intensity = min_intensity
359+ self ._period = period
360+ self ._intensity_delta = max_intensity - min_intensity
361+ self ._radians_per_second = radians (180 / period )
362+ self ._bpp = len (pixel_object [0 ])
363+ self ._last_update = monotonic_ns ()
364+ self ._cycle_position = 0
365+ super (Pulse , self ).__init__ (pixel_object , speed , color )
366+
367+ def draw (self ):
368+ now = monotonic_ns ()
369+ time_since_last_draw = (now - self ._last_update ) / 1000000000
370+ self ._last_update = now
371+ self ._cycle_position = (self ._cycle_position + time_since_last_draw ) % self ._period
372+ intensity = self .min_intensity + (sin (self ._radians_per_second * self ._cycle_position ) * self ._intensity_delta )
373+
374+ color = [int (self ._color [n ] * intensity ) for n in range (self ._bpp )]
375+ self .fill (color )
376+ self .show ()
377+
378+
379+ class Chase (Animation ):
380+ """
381+ Chase pixels in one direction in a single color, like a theater marquee sign.
382+
383+ :param pixel_object: The initialised LED object.
384+ :param int speed: Animation speed rate in seconds, e.g. ``0.1``.
385+ :param color: Animation color in ``(r, g, b)`` tuple, or ``0x000000`` hex format.
386+ :param size: Number of pixels to turn on in a row.
387+ :param spacing: Number of pixels to turn off in a row.
388+ :param reverse: Reverse direction of movement.
389+ """
390+
391+ # pylint: disable=too-many-arguments
392+ def __init__ (self , pixel_object , speed , color , size = 2 , spacing = 3 , reverse = False ):
393+ self ._size = size
394+ self ._spacing = spacing
395+ self ._repeat_width = size + spacing
396+ self ._num_repeats = ceil (len (pixel_object ) / self ._repeat_width )
397+ self ._overflow = len (pixel_object ) % self ._repeat_width
398+ self ._direction = 1 if not reverse else - 1
399+ self ._reverse = reverse
400+ self ._n = 0
401+ super (Chase , self ).__init__ (pixel_object , speed , color )
402+
403+ @property
404+ def reverse (self ):
405+ """
406+ Whether the animation is reversed
407+ """
408+ return self ._reverse
409+
410+ @reverse .setter
411+ def reverse (self , value ):
412+ self ._reverse = value
413+ self ._direction = - 1 if self ._reverse else 1
414+
415+ def draw (self ):
416+ self .pixel_object .fill ((0 , 0 , 0 ))
417+ for i in range (self ._size ):
418+ n = (self ._n + i ) % self ._repeat_width
419+ num = self ._num_repeats + (1 if n < self ._overflow else 0 )
420+ self .pixel_object [n ::self ._repeat_width ] = [self .group_color (n ) for n in range (num )]
421+ self ._n = (self ._n + self ._direction ) % self ._repeat_width
422+ self .show ()
423+
424+ def group_color (self , n ): # pylint: disable=unused-argument
425+ """
426+ Generate the color for the n'th group
427+
428+ :param n: The pixel group to get the color for
429+ """
430+ return self .color
431+
432+
342433class AnimationSequence :
343434 """
344435 A sequence of Animations to run in sequence, looping forever.
0 commit comments