summaryrefslogtreecommitdiffstats
path: root/twinkle.py
diff options
context:
space:
mode:
authorAaron Perley <aaron.perley@gmail.com>2016-10-16 23:47:08 -0400
committerAaron Perley <aaron.perley@gmail.com>2016-10-16 23:47:08 -0400
commitb8f9495e0cf2f500edb620f828aba2afab8f8f68 (patch)
treeab63a1ca457d6a63be848755633c75d25eac9ce0 /twinkle.py
parent0f54d73feea16124e92ff6baab78e3d3d3d97fa3 (diff)
downloadbridge-b8f9495e0cf2f500edb620f828aba2afab8f8f68.tar.zst
Basic twinkle
Diffstat (limited to 'twinkle.py')
-rwxr-xr-xtwinkle.py226
1 files changed, 127 insertions, 99 deletions
diff --git a/twinkle.py b/twinkle.py
index a2cb3d2..5a452a2 100755
--- a/twinkle.py
+++ b/twinkle.py
@@ -1,112 +1,140 @@
-#!/usr/bin/python2
-"""Simple demo of twinkle lights."""
+"""Rendering classes and helper functions."""
from __future__ import division
import color
+import random
import constants
-#from DummyRig import DummyRig
-from fish_render import *
-import fish_render
from constants import *
-import time
-import random
-try:
- import lumiversepython
-except ImportError:
- have_lumiversepython = False
-else:
- have_lumiversepython = True
+import math
+from show import Show
+
+class ShootingStar(object):
+ """Object displayed on the bridge, probably a fish."""
+ def __init__(self):
+ """Create fish with default parameters."""
+ self.x = 0
+ self.y = random.random() * 1.5
+ self.width = 5
+ self.height = 0.5
+ self.color = color.RGB(255/255, 210/255, 201/255)
-def get_all_lights(rig):
- """Return a list of all panels."""
- return [
- [
- fish_render.Light(
- x, int(y == 'top'),
- rig.select('$side={y}[$sequence={x}]'.format(y=y, x=x))
- ) for y in ('top', 'bot')
- ] for x in xrange(1, 200)
- ]
+ def update(self):
+ self.x += 0.1
-def flip():
- """Return 0 with 99.9% prob. & 1 with .1% prob."""
- # should be black most of the time
- return random.random() < 0.0005
+class Light(object):
+ """Represent a bridge light and its state."""
+ def __init__(self, x, y, light):
+ """Store all facts about a light."""
+ self.light = light
+ self.color = color.black
+ self.transitioning_to = self.color
+ self.step = 0
+ self.on = False
+ self.increasing = False
+ self.x = x
+ self.y = y
+ self.fade_step = 0
-def twinkle(lights, rig):
- """Try to do some light things."""
- light_status = [
- {
- 'is_increasing': True,
- 'is_on': False,
- 'change': random_change(),
- 'light': light,
- 'intensity': 0,
- }
- for light_col in lights for light in light_col
- ]
- shooting_stars = list()
- while True:
- if random.random() < 1:
- shooting_stars.append([random.randint(1, 180), random.random() < 0.5, 0])
- for light_s in light_status:
- is_increasing = light_s['is_increasing']
- is_on = light_s['is_on']
- change = light_s['change']
- light = light_s['light']
- intensity = light_s['intensity']
- # R and G are either 0 or 1
- if not is_on:
- if flip():
- is_on = True
- is_increasing = True
- change = 1.5 / FRAME_RATE
- light_s['is_on'] = is_on
- light_s['is_increasing'] = is_increasing
- light_s['change'] = change
+ def update(self):
+ """Change color depending on where the fish is."""
+ if not self.on and random.random() < 0.0005:
+ self.transitioning_to = color.RGB(1, 1, 1)
+ self.step = abs(self.transitioning_to - self.color) / (FRAME_RATE / 2)
+ self.increasing = True
+ self.on = True
+ self.color = transition(self.color, self.transitioning_to, self.step)
+ elif self.on:
+ if abs(self.transitioning_to - self.color) <= self.step:
+ if self.increasing == True:
+ self.transitioning_to = color.RGB(0, 0, 0)
+ self.step = abs(self.transitioning_to - self.color) / (FRAME_RATE / 2)
+ self.increasing = False
else:
- continue
- intensity = clamp(0, intensity + change * (int(is_increasing) * 2 - 1), 1)
- light.light.setRGBRaw(intensity, intensity, intensity)
- light_s['intensity'] = intensity
- if intensity == 0:
- light_s['is_on'] = False
- if intensity == 1:
- light_s['is_increasing'] = False
- for i, star in enumerate(shooting_stars):
- star[2] += 1
- if star[2] > 10:
- for dx in range(-6, 7):
- light_status[star[0] + dx]['light'].light.setRGBRaw(0, 0, 0)
- del shooting_stars[i]
- continue
- star[0] += int(star[1]) * 2 - 1
- for dx in range(-6, 7):
- intensity = 1 - 1 / 6 * abs(dx)
- light_status[star[0] + dx]['light'].light.setRGBRaw(intensity, intensity, intensity)
- rig.updateOnce()
- time.sleep(1 / FRAME_RATE)
+ self.increasing = False
+ self.on = False
+ self.color = transition(self.color, self.transitioning_to, self.step)
+
+ self.light.setRGBRaw(
+ *map(lambda x: clamp(0, x, 1), self.color.components)
+ )
+
+
+ def fade_to_black(self, steps):
+ hue = self.color.to_HSV().h()
+ sat = self.color.to_HSV().s()
+ value = self.color.to_HSV().v()
+ new_color = color.HSV(hue, sat, value - value / steps * self.fade_step).to_RGB()
+ self.fade_step += 1
+ self.light.setRGBRaw(*map(lambda x: clamp(0, x, 1), new_color.components))
+
+
+class TwinkleShow(Show):
+ def init(self):
+ self.lights = [Light(x, y, self.bridge.get_light(x, y))
+ for y in xrange(self.bridge.HEIGHT)
+ for x in xrange(self.bridge.WIDTH)]
+ #self.sun = Sun()
+ self.tick_count = 0
+
+
+ def update(self):
+ if self.tick_count > 1000:
+ fade_time = 3 # sec
+ if self.tick_count > 1000 + fade_time * FRAME_RATE:
+ self.stop()
+ return
+ for light in self.lights:
+ light.fade_to_black(fade_time * FRAME_RATE)
+ else:
+ for light in self.lights:
+ light.update()
+
+ self.tick_count += 1
+ print self.tick_count
+
+
+def compute_coverage(fish, x, y):
+ """Calculate the coverage of a fish over a box."""
+ middle_of_fish = fish.x + fish.width / 2
+ middle_of_panel = x + 0.5
+ diff = abs(middle_of_fish - middle_of_panel) / (fish.width / 2)
+ scale = 1 - diff
+ min_x = min(max(x, fish.x), x + 1)
+ max_x = max(min(x+1, fish.x + fish.width), x)
+ min_y = min(max(y, fish.y), y + 1)
+ max_y = max(min(y+1, fish.y + fish.height), y)
+ coverage = (max_x - min_x) * (max_y - min_y)
+ return coverage * scale
+
+
+def pick_ocean_HSV(sky_brightness):
+ """Return a random color in an appropriate interval."""
+ min_hue = 236 / 360
+ max_hue = 250 / 360
+ min_sat = 0.25
+ max_sat = 0.6
+ hue = random.random() * (max_hue - min_hue) + min_hue
+ saturation = random.random() * (max_sat - min_sat) + min_sat
+ return color.HSV(hue, saturation, sky_brightness)
+
+
+def transition(start, end, step):
+ """Return a vector equal to (end - start) * step + start."""
+ if start == end:
+ return start
+ diff_vector = end - start
+ step_vector = diff_vector / abs(diff_vector) * step
+ result = step_vector + start
+ return result
-def sunrise(lights, rig):
- #rig.select('$side={y}[$sequence={x}]'.format(y=y, x=x))
- rig.select("$side=top[$panel=27|$panel=28]")
- rig.updateOnce()
- time.sleep(1)
+def random_change():
+ """Return a random amount that a light should change each frame."""
+ min_time = int(2 * FRAME_RATE)
+ max_time = int(6 * FRAME_RATE)
+ return 1 / random.randint(min_time, max_time)
-def main():
- """Run show."""
- if have_lumiversepython:
- rig = lumiversepython.Rig('/home/teacher/Lumiverse/PBridge.rig.json')
- else:
- rig = DummyRig(200, 2)
- rig.init()
- lights = get_all_lights(rig)
- #for light in lights:
- # light.setRGBRaw(0, 0, 0)
- rig.updateOnce()
- time.sleep(3)
- twinkle(lights, rig)
-if __name__ == '__main__':
- main()
+def clamp(low, x, high):
+ """Return v such that low <= v <= high and |x - v| is minimal."""
+ return max(low, min(x, high))