summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRaymond Hogenson <rayhogenson@openmailbox.org>2016-09-27 22:58:31 -0400
committerRaymond Hogenson <rayhogenson@openmailbox.org>2016-09-27 22:58:31 -0400
commitfea99295c9ca99d3f3abd41b9bfaac91f4bda6dd (patch)
treebf8c763b9cda0cf985614048758c35398b184126
parent78fde3bb014ecd8e2368f2cc088839aecd0ca1ed (diff)
downloadbridge-fea99295c9ca99d3f3abd41b9bfaac91f4bda6dd.tar.zst
Split files and finish render code
Although it is unlikely that this code will actually run, it is split up rather nicely such that it should be maintainable into the future. Right now only one fish is supported, and it moves at some fixed rate across the bridge. This is fine for a demo, but the rendering process will need to be changed significantly before the end.
-rw-r--r--bridge.py69
-rw-r--r--color.py11
-rw-r--r--constants.py10
-rw-r--r--fish_render.py91
4 files changed, 107 insertions, 74 deletions
diff --git a/bridge.py b/bridge.py
index 22d8da2..76f3043 100644
--- a/bridge.py
+++ b/bridge.py
@@ -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():
diff --git a/color.py b/color.py
index 71fbaaf..2b51701 100644
--- a/color.py
+++ b/color.py
@@ -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)