grid_rain.py
  1  # SPDX-FileCopyrightText: 2020 Kattni Rembor for Adafruit Industries
  2  #
  3  # SPDX-License-Identifier: MIT
  4  
  5  """
  6  `adafruit_led_animation.animation.grid_rain`
  7  ================================================================================
  8  
  9  Rain animations for CircuitPython helper library for LED animations.
 10  
 11  * Author(s): Kattni Rembor
 12  
 13  Implementation Notes
 14  --------------------
 15  
 16  **Hardware:**
 17  
 18  * `Adafruit NeoPixels <https://www.adafruit.com/category/168>`_
 19  * `Adafruit DotStars <https://www.adafruit.com/category/885>`_
 20  
 21  **Software and Dependencies:**
 22  
 23  * Adafruit CircuitPython firmware for the supported boards:
 24    https://circuitpython.org/downloads
 25  
 26  """
 27  
 28  import random
 29  from adafruit_led_animation.animation import Animation
 30  
 31  __version__ = "0.0.0-auto.0"
 32  __repo__ = "https://github.com/adafruit/Adafruit_CircuitPython_LED_Animation.git"
 33  
 34  from adafruit_led_animation.color import BLACK, colorwheel, calculate_intensity, GREEN
 35  
 36  
 37  class Rain(Animation):
 38      """
 39      Droplets of rain.
 40  
 41      :param grid_object: The initialised PixelGrid object.
 42      :param float speed: Animation speed in seconds, e.g. ``0.1``.
 43      :param color: Animation color in ``(r, g, b)`` tuple, or ``0x000000`` hex format.
 44      :param count: Number of sparkles to generate per animation cycle.
 45      :param length: Number of pixels per raindrop (Default 3)
 46      :param background: Background color (Default BLACK).
 47      """
 48  
 49      # pylint: disable=too-many-arguments
 50      def __init__(
 51          self, grid_object, speed, color, count=1, length=3, background=BLACK, name=None
 52      ):
 53          self._count = count
 54          self._length = length
 55          self._background = background
 56          self._raindrops = []
 57          super().__init__(grid_object, speed, color, name=name)
 58  
 59      def draw(self):
 60  
 61          # Move raindrops down
 62          keep = []
 63          for raindrop in self._raindrops:
 64              pixels = []
 65              if raindrop[1][0][0] >= 0:
 66                  self.pixel_object[raindrop[0], raindrop[1][0][0]] = self._background
 67              for pixel in raindrop[1]:
 68                  pixel[0] += 1
 69                  if pixel[0] < self.pixel_object.height:
 70                      pixels.append(pixel)
 71              if pixels:
 72                  keep.append([raindrop[0], pixels])
 73          self._raindrops = keep
 74  
 75          # Add a raindrop
 76          if len(self._raindrops) < self._count:
 77              x = random.randint(0, self.pixel_object.width - 1)
 78              self._raindrops.append([x, self._generate_droplet(x, self._length)])
 79  
 80          # Draw raindrops
 81          for x, pixels in self._raindrops:
 82              for y, color in pixels:
 83                  if y >= 0:
 84                      self.pixel_object[x, y] = color
 85  
 86      def _generate_droplet(self, x, length):  # pylint: disable=unused-argument
 87          return [[n, self.color] for n in range(-length, 0)]
 88  
 89  
 90  class RainbowRain(Rain):
 91      """
 92      Rainbow Rain animation.
 93      """
 94  
 95      def __init__(  # pylint: disable=too-many-arguments
 96          self, grid_object, speed, count=1, length=3, background=BLACK, name=None
 97      ):
 98          super().__init__(grid_object, speed, BLACK, count, length, background, name)
 99  
100      def _generate_droplet(self, x, length):
101          color = colorwheel(random.randint(0, 255))
102          return [
103              [n, calculate_intensity(color, 1.0 - -((n + 1) / (length + 1)))]
104              for n in range(-length, 0)
105          ]
106  
107  
108  class MatrixRain(Rain):
109      """
110      The Matrix style animation.
111      """
112  
113      def __init__(  # pylint: disable=too-many-arguments
114          self,
115          grid_object,
116          speed,
117          color=GREEN,
118          count=1,
119          length=6,
120          background=(0, 32, 0),
121          name=None,
122      ):
123          super().__init__(grid_object, speed, color, count, length, background, name)
124  
125      def _generate_droplet(self, x, length):
126          return [
127              [n, calculate_intensity(self.color, random.randint(10, 100) * 1.0)]
128              for n in range(-length, 0)
129          ]