diff --git a/generators/lines.py b/generators/lines.py new file mode 100755 index 0000000..7aa2d8e --- /dev/null +++ b/generators/lines.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python3 + +import sys +import random +import math +import argparse +import collections +import blup.frame +import blup.output +import blup.animation +import blup.writebml +import colorsys + + +WIDTH = 22 +HEIGHT = 16 +DEPTH = 256 + + +class Point(collections.namedtuple('Point', ['x', 'y'])): + def __add__(self, other): + return Point(self.x + other.x, self.y + other.y) + def __sub__(self, other): + return Point(self.x - other.x, self.y - other.y) + def __mul__(self, other): + if isinstance(other, Point): + raise Exception('not implemented') + else: + return Point(self.x * other, self.y * other) + def __truediv__(self, other): + if isinstance(other, Point): + raise ValueError() + else: + return self * (1/other) + @property + def len(self): + return math.sqrt(self.x**2 + self.y**2) + @property + def n(self): + n = Point(self.y, -self.x) + return n / n.len + @property + def intp(self): + return Point(int(round(self.x)), int(round(self.y))) + + +def convert_color(c): + return list(map(lambda x: int(round(x*(DEPTH-1))), c)) + + +def get_random_color(): + return colorsys.hsv_to_rgb(random.random(), 0.5 + random.random() / 2, 1) + + +class Line: + def __init__(self, size): + self.size = size + r = random.choice([0, 1]) + s = random.choice([-1, 1]) + if r == 0: + self.pos = Point(size.x if s == -1 else 0, + random.randint(0, size.y - 1)) + else: + self.pos = Point(random.randint(0, size.x - 1), + size.y if s == -1 else 0) + self.dir = Point(s if r == 0 else 0, s if r == 1 else 0) + m = max(size.x, size.y) + self.length = random.randint(int(0.4 * m), int(1.1 * m)) + self.color = get_random_color() + self.speed = 10 + self.done = False + + def update(self, t, dt): + self.pos += self.dir * (dt * self.speed) + end = self.pos - self.dir * self.length + if self.dir.x > 0 and end.x > self.size.x \ + or self.dir.y > 0 and end.y > self.size.y \ + or self.dir.x < 0 and end.x < 0 \ + or self.dir.y < 0 and end.y < 0: + self.done = True + + def draw(self, frame): + if self.done: + return + for i in range(self.length): + p = self.pos.intp - self.dir * i + try: + frame.setPixel(p.x, p.y, convert_color(self.color)) + except ValueError: + pass + + +if __name__ == '__main__': + parser = argparse.ArgumentParser(description='Generate animations') + parser.add_argument('-d', '--delay', type=int, default=50) + parser.add_argument('-t', '--time', type=int, default=15) + parser.add_argument('output_file') + args = parser.parse_args() + + dim = blup.frame.FrameDimension(WIDTH, HEIGHT, DEPTH, 3) + anim = blup.animation.Animation(dim) + anim.tags['description'] = ' '.join(sys.argv) + + lines = [] + t = 0 + dt = args.delay / 1000 + while t < args.time or len(lines) > 0: + t += dt + frame = blup.animation.AnimationFrame(dim, args.delay) + + if len(lines) < 5 and t < args.time: + lines.append(Line(Point(WIDTH, HEIGHT))) + + for l in lines: + l.update(t, dt) + l.draw(frame) + lines = list(filter(lambda l: not l.done, lines)) + + anim.addFrame(frame) + + blup.writebml.writeBml(anim, args.output_file)