You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
121 lines
3.4 KiB
121 lines
3.4 KiB
#!/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)
|
|
|