Make comet simpler, faster, able to be longer than the number of pixels, and the length specified.

This commit is contained in:
Roy Hooper 2020-05-30 17:18:51 -04:00
parent 37e9190178
commit c9c7e1490a
2 changed files with 59 additions and 62 deletions

View file

@ -45,7 +45,7 @@ Implementation Notes
"""
from adafruit_led_animation.animation import Animation
from adafruit_led_animation.color import BLACK
from adafruit_led_animation.color import BLACK, calculate_intensity
class Comet(Animation):
@ -64,86 +64,64 @@ class Comet(Animation):
# pylint: disable=too-many-arguments
def __init__(
self,
pixel_object,
speed,
color,
tail_length=0,
reverse=False,
bounce=False,
name=None,
self,
pixel_object,
speed,
color,
tail_length=0,
reverse=False,
bounce=False,
name=None,
):
if tail_length == 0:
tail_length = len(pixel_object) // 4
else:
tail_length = max(2, min(tail_length, len(pixel_object)))
self._tail_length = tail_length
self._color_step = 0.9 / tail_length
self._color_offset = 0.1
self._comet_colors = None
self._reverse_comet_colors = None
self._initial_reverse = reverse
self.reverse = reverse
self.bounce = bounce
self._initial_reverse = reverse
self._tail_length = tail_length
self._color_step = 0.95 / tail_length
self._comet_colors = None
self._computed_color = color
self._generator = self._comet_generator()
self._num_pixels = len(pixel_object)
self._direction = -1 if reverse else 1
self._left_side = -self._tail_length - 1
self._right_side = self._num_pixels + self._tail_length + 1
self._tail_start = 0
self.reset()
super().__init__(pixel_object, speed, color, name=name)
on_cycle_complete_supported = True
def _recompute_color(self, color):
pass
self._comet_recompute_color(color)
def _comet_recompute_color(self, color):
self._comet_colors = [BLACK] + [
[
int(color[rgb] * ((n * self._color_step) + self._color_offset))
for rgb in range(len(color))
]
for n in range(self._tail_length - 1)
]
self._reverse_comet_colors = list(reversed(self._comet_colors))
self._comet_colors = [BLACK]
for n in range(self._tail_length):
self._comet_colors.append(calculate_intensity(color, n * self._color_step + 0.05))
self._computed_color = color
def _get_range(self, num_pixels):
if self.reverse:
return range(num_pixels, -self._tail_length - 1, -1)
return range(-self._tail_length, num_pixels + 1)
def _comet_generator(self):
num_pixels = len(self.pixel_object)
cycle_passes = 0
while True:
if self._color != self._computed_color or not self._comet_colors:
self._comet_recompute_color(self._color)
colors = self._reverse_comet_colors if self.reverse else self._comet_colors
for start in self._get_range(num_pixels):
if start + self._tail_length < num_pixels:
end = self._tail_length
else:
end = num_pixels - start
if start <= 0:
num_visible = self._tail_length + start
self.pixel_object[0:num_visible] = colors[
self._tail_length - num_visible :
]
else:
self.pixel_object[start : start + end] = colors[0:end]
yield
cycle_passes += 1
if self.bounce:
self.reverse = not self.reverse
if not self.bounce or cycle_passes == 2:
self.cycle_complete = True
cycle_passes = 0
print(self._comet_colors)
def draw(self):
next(self._generator)
for pixel_no in range(self._tail_length + 1):
draw_at = self._tail_start + (self._direction * pixel_no)
if draw_at < 0 or draw_at >= self._num_pixels:
continue
self.pixel_object[draw_at] = self._comet_colors[pixel_no]
self._tail_start += self._direction
if self._tail_start < self._left_side or self._tail_start > self._right_side:
self.reverse = not self.reverse
self._direction = - self._direction
self._tail_start += self._direction
def reset(self):
"""
Resets to the first color.
"""
self._generator = self._comet_generator()
self.reverse = self._initial_reverse
if self.reverse:
self._tail_start = self._num_pixels + self._tail_length + 1
else:
self._tail_start = -self._tail_length - 1

View file

@ -64,3 +64,22 @@ except ImportError:
return 0, int(255 - pos * 3), int(pos * 3)
pos -= 170
return int(pos * 3), 0, int(255 - (pos * 3))
def calculate_intensity(color, intensity=1.0):
"""
Takes a RGB[W] color tuple and adjusts the intensity.
:param float intensity:
:param color: color value (tuple, list or int)
:return: color
"""
if isinstance(color, int):
return ((int((color & 0xff0000) * intensity) & 0xff0000) |
(int((color & 0xff00) * intensity) & 0xff00) |
(int((color & 0xff) * intensity) & 0xff))
if len(color) == 3:
return int(color[0] * intensity), int(color[1] * intensity), int(color[2] * intensity)
elif len(color) == 4 and isinstance(color[3], float):
return int(color[0] * intensity), int(color[1] * intensity), int(color[2] * intensity), color[3]
return int(color[0] * intensity), int(color[1] * intensity), int(color[2] * intensity), int(color[3] * intensity)