diff options
| -rw-r--r-- | bridge.py | 69 | ||||
| -rw-r--r-- | color.py | 11 | ||||
| -rw-r--r-- | constants.py | 10 | ||||
| -rw-r--r-- | fish_render.py | 91 |
4 files changed, 107 insertions, 74 deletions
@@ -1,76 +1,29 @@ #!/usr/bin/python """Simple demo of oscillating colors.""" -from __future__ import division +from __future__ import division, unicode_literals import color -import colorsys +import constants +import fish_render import lumiversepython -import math -import random import time -FRAME_RATE = 44 -MIN_VALUE = 0 -MAX_VALUE = 1 -MAX_TIME = 4 -MIN_TIME = 0.3 -MAX_HUE = 169 / 360 -MIN_HUE = 250 / 360 - def get_all_lights(rig): """Return a list of all panels.""" return [ - rig.select('$side={}[$sequence={}]'.format(j, i)) - for j in ['top', 'bot'] for i in range(1, 200) + [ + rig.select('$side={y}[$sequence={x}]'.format({'y': y, 'x': x})) + for y in ('top', 'bot') + ] for x in xrange(1, 200) ] -def pick_HSV(): - """Return a random color in an appropriate interval.""" - hue = random.random() * (MAX_HUE - MIN_HUE) + MIN_HUE - saturation = random.random() - value = random.random() - return color.HSV(hue, saturation, value) - - -def transition(start, end, step): - """Return a vector equal to (end - start) * step + start.""" - return (end - start) / abs(end - start) * step + start - - -def random_change(): - """Return a random amount that a light should change each frame.""" - min_time = int(MIN_TIME * FRAME_RATE) - max_time = int(MAX_TIME * FRAME_RATE) - return 1 / random.randint(min_time, max_time) - - def demo(lights, rig): """Do some light things.""" - light_status = [ - { - 'change': 0, - 'light': light, - 'current value': color.RGB(0, 0, 0), - 'transitioning to': color.RGB(0, 0, 0), - } - for light in lights - ] + fish = fish_render.Fish(0, 0, 2, 1, color.red, 1 / constants.FRAME_RATE) + bridge = fish_render.Bridge(lights, fish, rig) while True: - for light_s in light_status: - change = light_s['change'] - light = light_s['light'] - current_value = light_s['current value'] - transitioning_to = light_s['transitioning to'] - if abs(transitioning_to - current_value) < change: - change = random_change() - light_s['change'] = change - transitioning_to = pick_HSV().to_RGB() - light_s['transitioning to'] = transitioning_to - new_color = transition(current_value, transitioning_to, change) - light.setRGBRaw(*new_color.components) - light_s['current value'] = new_color - rig.updateOnce() - time.sleep(1 / FRAME_RATE) + bridge.update() + time.sleep(1 / constants.FRAME_RATE) def main(): @@ -1,5 +1,5 @@ """Color vector library containing HSV and RGB.""" -from __future__ import division +from __future__ import division, unicode_literals import colorsys import math @@ -82,3 +82,12 @@ def RGB(Vector): def b(self): """Return blue value.""" return self.components[2] + +red = RGB(1, 0, 0) +green = RGB(0, 1, 0) +blue = RGB(0, 0, 1) +cyan = RGB(0, 1, 1) +magenta = RGB(1, 0, 1) +yellow = RGB(1, 1, 0) +white = RGB(1, 1, 1) +black = RGB(0, 0, 0) diff --git a/constants.py b/constants.py new file mode 100644 index 0000000..162b3be --- /dev/null +++ b/constants.py @@ -0,0 +1,10 @@ +"""Constants that may be tweaked in the future.""" +from __future__ import division, unicode_literals + +FRAME_RATE = 44 +MIN_VALUE = 0 +MAX_VALUE = 1 +MAX_TIME = 4 +MIN_TIME = 0.3 +MAX_HUE = 169 / 360 +MIN_HUE = 250 / 360 diff --git a/fish_render.py b/fish_render.py index be94a23..becd8c1 100644 --- a/fish_render.py +++ b/fish_render.py @@ -1,29 +1,90 @@ +"""Rendering classes and helper functions.""" +from __future__ import division, unicode_literals +import color +import random class Fish(object): - def __init__(self, x, y, width, height, color): + """Object displayed on the bridge, probably a fish.""" + def __init__(self, x, y, width, height, color, step): + """Create fish with default parameters.""" self.x = x self.y = y self.width = width self.height = height self.color = color + self.speed = step + def update(self): + """Swim gently to the other side of the bridge.""" + self.x += self.step -class BridgeRender(object): - WIDTH_SEGMENTS = 200 - HEIGHT_SEGMENTS = 2 - SAMPLES_PER_SEGMENT = 4 # Actual samples is this squared - def __init__(self, fish): +class Light(object): + """Represent a bridge light and its state.""" + def __init__(self, x, y, light, start_color, step): + """Store all facts about a light.""" + self.light = light + self.color = start_color + self.transitioning_to = start_color + self.step = step + self.x = x + self.y = y + + def update(self, fish): + """Change color depending on where the fish is.""" + if abs(self.transitioning_to - self.color) < self.step: + self.step = random_change() + self.transitioning_to = pick_HSV().to_RGB() + new_background = transition( + self.color, self.transitioning_to, self.step + ) + coverage = compute_coverage(fish, self.x, self.y) + new_color = coverage * fish.color + (1 - coverage) * new_background + self.light.setRGBRaw(*new_color.components) + + +class Bridge(object): + """Store objects on the bridge.""" + def __init__(self, lights, fish, rig): + """Initialize with lights and fish.""" + self.lights = lights self.fish = fish + self.rig = rig + + def update(self): + """Compute fish coverages and push lights to bridge.""" + for x, light_col in enumerate(self.lights): + for y, light in enumerate(light_col): + fish.update() + light.update(fish) + self.rig.updateOnce() + + +def compute_coverage(fish, x, y): + """Calculate the coverage of a fish over a box.""" + min_x = max(x, fish.x) + max_x = min(x+1, fish.x + fish.width) + min_y = max(y, fish.y) + max_y = min(y+1, fish.y + fish.height) + coverage = (max_x - min_x) * (max_y - min_y) + return coverage + + +def pick_HSV(): + """Return a random color in an appropriate interval.""" + hue = random.random() * (MAX_HUE - MIN_HUE) + MIN_HUE + saturation = random.random() + value = random.random() + return color.HSV(hue, saturation, value) + - def compute_coverage(self, x, y): - min_x = max(x, self.fish.x - self.fish.width) - max_x = min(x+1, self.fish.x + self.fish.width) - min_y = max(y, self.fish.y - self.fish.height) - max_y = min(y+1, self.fish.y + self.fish.height) +def transition(start, end, step): + """Return a vector equal to (end - start) * step + start.""" + return (end - start) / abs(end - start) * step + start - return (max_x - min_x) * (max_y - min_y) - def compute_color(self, x, y, base_color): - cov = compute_coverage(x, y) - return (cov * self.fish.color) + ((1 - cov) * base_color) +def random_change(): + """Return a random amount that a light should change each frame.""" + min_time = int(MIN_TIME * FRAME_RATE) + max_time = int(MAX_TIME * FRAME_RATE) + return 1 / random.randint(min_time, max_time) |
