summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--[-rwxr-xr-x]bridge.py79
-rwxr-xr-xbrige.py100
-rw-r--r--color.py50
-rw-r--r--fish_show.py (renamed from fish_render.py)36
-rw-r--r--show.py39
-rw-r--r--sunrise.py28
6 files changed, 121 insertions, 211 deletions
diff --git a/bridge.py b/bridge.py
index 4d5d817..70adb99 100755..100644
--- a/bridge.py
+++ b/bridge.py
@@ -1,12 +1,7 @@
-#!/usr/bin/python2
-"""Simple demo of oscillating colors."""
-from __future__ import division, print_function
-import color
-import constants
-import fish_render
-import sunrise
-import time
-import random
+from fish_show import FishShow
+from sunrise import SunriseShow
+from constants import *
+
try:
import lumiversepython
except ImportError:
@@ -15,55 +10,35 @@ except ImportError:
else:
have_lumiversepython = True
+class Bridge(object):
+ WIDTH = 200
+ HEIGHT = 2
+ def __init__(self):
+ if have_lumiversepython:
+ self.rig = lumiversepython.Rig('/home/teacher/Lumiverse/PBridge.rig.json')
+ else:
+ self.rig = DummyRig(self.WIDTH, self.HEIGHT)
+ self.rig.init()
+ self.lights = self.get_lights()
+ def update(self):
+ self.rig.updateOnce()
-#fish_render = sunrise
-
-
-
-
-
-
-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 get_light(self, x, y):
+ return self.lights[x][y]
+ def get_lights(self):
+ return [ [ self.rig.select('$side={y}[$sequence={x}]'.format(y=y, x=x))
+ for y in ('bot', 'top') ]
+ for x in xrange(1, self.WIDTH+1)]
-def demo(lights, rig):
- """Do some light things."""
- #fish = fish_render.Fish(0, 0, 15, 1.5, color.black, 0.05 / constants.FRAME_RATE)
- #fish = fish_render.Fish(0, 0, 23, 1.5, color.RGB(193 / 255, 68 / 255, 227 / 255), 0.05 / constants.FRAME_RATE)
- fish = fish_render.Fish(0, 0, 23, 1.5, color.black, 0.05 / constants.FRAME_RATE)
- bridge = fish_render.Bridge(lights, fish, rig)
- current_time = time.time()
- count = 0
- while True:
- bridge.update()
- if count % constants.FRAME_RATE == 0:
- time_delta = time.time() - current_time
- print(time_delta)
- current_time = time.time()
- #time.sleep(1 / constants.FRAME_RATE)
- count += 1
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)
- demo(lights, rig)
+ bridge = Bridge()
+ show = FishShow(bridge)
+ #show = SunriseShow(bridge)
+ show.run(framerate=FRAME_RATE)
-if __name__ == '__main__':
- main()
+main() \ No newline at end of file
diff --git a/brige.py b/brige.py
deleted file mode 100755
index 314f9db..0000000
--- a/brige.py
+++ /dev/null
@@ -1,100 +0,0 @@
-#!/usr/bin/python2
-from __future__ import division, print_function
-import color
-import constants
-import curses
-import fish_render
-import time
-import random
-try:
- import lumiversepython
-except ImportError:
- have_lumiversepython = False
- from DummyRig import DummyRig
-else:
- have_lumiversepython = True
-
-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 colorSection(lights, color, *ranges):
- for start, end in ranges:
- map(lambda l: map(lambda x: x.light.setRGBRaw(*color), l), lights[start:end])
-
-def onSection(lights, *ranges):
- colorSection(lights, (1, 1, 1), *ranges)
-
-def offSection(lights, *ranges):
- colorSection(lights, (0, 0, 0), *ranges)
-
-def mapKey(key):
- if key == ord('a'):
- return (0, 20)
- if key == ord('o'):
- return (20, 40)
- if key == ord('e'):
- return (40, 60)
- if key == ord('u'):
- return (60, 80)
- if key == ord('i'):
- return (80, 100)
- if key == ord('d'):
- return (100, 120)
- if key == ord('h'):
- return (120, 140)
- if key == ord('t'):
- return (140, 160)
- if key == ord('n'):
- return (160, 180)
- if key == ord('s'):
- return (180, 200)
- return (0, 0)
-
-def demo(lights, rig, screen):
- """Do some light things."""
- sections = []
- while True:
- k = screen.getch()
- offSection(lights, *sections)
- r = mapKey(k)
- try:
- i = sections.index(r)
- except ValueError:
- sections.append(r)
- else:
- del sections[i]
- onSection(lights, *sections)
- rig.updateOnce()
-
-def main():
- """Run show."""
- if have_lumiversepython:
- rig = lumiversepython.Rig('/home/teacher/Lumiverse/PBridge.rig.json')
- else:
- rig = DummyRig(200, 2)
- rig.init()
- stdscr = curses.initscr()
- stdscr.keypad(1)
- curses.noecho()
-
- lights = get_all_lights(rig)
- try:
- demo(lights, rig, stdscr)
- except BaseException:
- curses.nocbreak()
- stdscr.keypad(0)
- curses.echo()
- curses.endwin()
- raise
-
-if __name__ == '__main__':
- main()
diff --git a/color.py b/color.py
index a38c28b..058abb4 100644
--- a/color.py
+++ b/color.py
@@ -4,41 +4,45 @@ import colorsys
import math
class Vector(object):
- """N-dimensional vector class."""
- def __init__(self, *components):
+ __slots__ = ('x', 'y', 'z')
+
+ """3-dimensional vector class."""
+ def __init__(self, x, y, z):
"""Create a vector from its components."""
- self.components = components
+ self.x = x
+ self.y = y
+ self.z = z
def __add__(self, other):
"""Add two vectors."""
- return self.__class__(
- *map(lambda (x, y): x + y, zip(self.components, other.components))
- )
+ return self.__class__(self.x + other.x, self.y + other.y, self.z + other.z)
def __sub__(self, other):
"""Subtract two vectors."""
- return self.__class__(
- *map(lambda (x, y): x - y, zip(self.components, other.components))
- )
+ return self.__class__(self.x - other.x, self.y - other.y, self.z - other.z)
- def __mul__(self, other):
+ def __mul__(self, scalar):
"""Multiply a vector by a constant."""
- return self.__class__(*map(lambda x: x * other, self.components))
+ return self.__class__(self.x * scalar, self.y * scalar, self.z * scalar)
- def __rmul__(self, other):
+ def __rmul__(self, scalar):
"""Multiply a constant by a vector."""
- return self * other
+ return self * scalar
def __abs__(self):
"""Return the 2-norm of the vector."""
- return math.sqrt(sum(map(lambda x: x * x, self.components)))
+ return math.sqrt(self.x * self.x + self.y * self.y + self.z * self.z)
def __truediv__(self, scalar):
"""Return self * 1 / scalar."""
return self * (1 / scalar)
def __eq__(self, other):
- return self.components == other.components
+ return self.x == other.x and self.y == other.y and self.z == other.z
+
+ @property
+ def components(self):
+ return (self.x, self.y, self.z)
class HSV(Vector):
@@ -49,19 +53,19 @@ class HSV(Vector):
def to_RGB(self):
"""Convert to an RGB vector."""
- return RGB(*colorsys.hsv_to_rgb(*self.components))
+ return RGB(*colorsys.hsv_to_rgb(self.x, self.y, self.z))
def h(self):
"""Return hue."""
- return self.components[0]
+ return self.x
def s(self):
"""Return saturation."""
- return self.components[1]
+ return self.y
def v(self):
"""Return value."""
- return self.components[2]
+ return self.z
class RGB(Vector):
@@ -72,19 +76,19 @@ class RGB(Vector):
def to_HSV(self):
"""Convert to HSV vector."""
- return HSV(*colorsys.rgb_to_hsv(*self.components))
+ return HSV(*colorsys.rgb_to_hsv(self.x, self.y, self.z))
def r(self):
"""Return red value."""
- return self.components[0]
+ return self.x
def g(self):
"""Return green value."""
- return self.components[1]
+ return self.y
def b(self):
"""Return blue value."""
- return self.components[2]
+ return self.z
red = RGB(1, 0, 0)
green = RGB(0, 1, 0)
diff --git a/fish_render.py b/fish_show.py
index 18aecac..cda4174 100644
--- a/fish_render.py
+++ b/fish_show.py
@@ -1,10 +1,10 @@
-"""Rendering classes and helper functions."""
-from __future__ import division, unicode_literals
+from __future__ import division
import color
import random
import constants
from constants import *
import math
+from show import Show
class Fish(object):
"""Object displayed on the bridge, probably a fish."""
@@ -28,7 +28,6 @@ class Fish(object):
#self.y += 0.01 * math.sin(theta)
#print(self.y)
-
class Light(object):
"""Represent a bridge light and its state."""
def __init__(self, x, y, light):
@@ -61,24 +60,6 @@ class Light(object):
*map(lambda x: clamp(0, x, 1), 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):
- self.fish.update()
- light.update(self.fish)
- self.rig.updateOnce()
-
-
def compute_coverage(fish, x, y):
"""Calculate the coverage of a fish over a box."""
middle_of_fish = fish.x + fish.width / 2
@@ -121,3 +102,16 @@ def random_change():
def clamp(low, x, high):
"""Return v such that low <= v <= high and |x - v| is minimal."""
return max(low, min(x, high))
+
+class FishShow(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.fish = Fish(0, 0, 23, 1.5, color.black, 1)
+
+
+ def update(self):
+ self.fish.update()
+ for light in self.lights:
+ light.update(self.fish) \ No newline at end of file
diff --git a/show.py b/show.py
new file mode 100644
index 0000000..f8544c9
--- /dev/null
+++ b/show.py
@@ -0,0 +1,39 @@
+from __future__ import division, print_function
+import time
+
+class Clock(object):
+ def __init__(self):
+ self.last_tick = time.time()
+
+ def tick(self, framerate):
+ sec_per_frame = 1.0 / framerate
+ diff = time.time() - self.last_tick
+ while diff < sec_per_frame:
+ diff = time.time() - self.last_tick
+
+ if diff > (1.05 * sec_per_frame):
+ print("WARN: tick is not being called fast enough\n",
+ "target {}, actual {}".format(sec_per_frame, diff))
+ self.last_tick = time.time()
+
+
+class Show(object):
+ def __init__(self, bridge):
+ self.bridge = bridge
+ self.clock = Clock()
+ self.running = True
+ self.init()
+
+ def run(self, framerate=40):
+ while self.running:
+ self.update()
+ self.bridge.update()
+ self.clock.tick(framerate)
+
+ def init(self):
+ """Override me"""
+ raise NotImplementedError
+
+ def update(self):
+ """Override me"""
+ raise NotImplementedError
diff --git a/sunrise.py b/sunrise.py
index 68a423c..7e11ee3 100644
--- a/sunrise.py
+++ b/sunrise.py
@@ -5,8 +5,9 @@ import random
import constants
from constants import *
import math
+from show import Show
-class Fish(object):
+class Sun(object):
"""Object displayed on the bridge, probably a fish."""
def __init__(self, x, y, width, height, c, step):
"""Create fish with default parameters."""
@@ -33,7 +34,7 @@ class Fish(object):
#theta = random.random() * math.pi / 2 - math.pi / 4
#self.y += 0.01 * math.sin(theta)
#print(self.y)
- self.y += 0.000005
+ self.y += 0.005
if self.y >= 1:
self.y = 1
self.wait += 1
@@ -66,21 +67,18 @@ class Light(object):
)
-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
+class SunriseShow(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(0, 0, 23, 1.5, color.black, 1)
+
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):
- self.fish.update()
- light.update(self.fish)
- self.rig.updateOnce()
+ self.sun.update()
+ for light in self.lights:
+ light.update(self.sun)
def compute_coverage(fish, x, y):