Fr3deric
7 years ago
1 changed files with 140 additions and 0 deletions
@ -0,0 +1,140 @@ |
|||||||
|
#!/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 BlinkingCheckerboard: |
||||||
|
def __init__(self, size, fieldsize, h, num_fields, rounds): |
||||||
|
self.size, self.fieldsize, self.h, self.num_fields, self.rounds = \ |
||||||
|
size, fieldsize, h, num_fields, rounds |
||||||
|
self.roundtime = 0.5 |
||||||
|
|
||||||
|
self.fieldpoints = [ |
||||||
|
Point(random.randint(0, WIDTH-1), random.randint(0, HEIGHT-1)) |
||||||
|
] |
||||||
|
xm = self.fieldpoints[-1].x % (fieldsize * 2) |
||||||
|
ym = self.fieldpoints[-1].y % (fieldsize * 2) |
||||||
|
while len(self.fieldpoints) < self.num_fields: |
||||||
|
p = random.choice(self.fieldpoints) |
||||||
|
o = Point(random.randint(-2, 2), random.randint(-2, 2)) |
||||||
|
if abs(o.x) + abs(o.y) != 2: |
||||||
|
continue |
||||||
|
p += o * fieldsize |
||||||
|
if p.x < 0 or p.y < 0 or p.x >= size.x or p.y > size.y: |
||||||
|
continue |
||||||
|
if p not in self.fieldpoints: |
||||||
|
self.fieldpoints.append(p) |
||||||
|
self.done = False |
||||||
|
|
||||||
|
def update(self, t, dt): |
||||||
|
r = t / self.roundtime |
||||||
|
if r >= self.rounds + 1: |
||||||
|
self.done = True |
||||||
|
self.fieldvals = [0] * self.num_fields |
||||||
|
else: |
||||||
|
self.fieldvals = [] |
||||||
|
for i in range(self.num_fields): |
||||||
|
offs = i / (self.num_fields - 1) * 2 * math.pi |
||||||
|
pos = 2 * math.pi * r |
||||||
|
self.fieldvals.append(max(math.sin(offs + pos), 0)) |
||||||
|
if r > self.rounds and r < self.rounds + 1: |
||||||
|
if self.fieldvals[-1] < 0.01: |
||||||
|
self.fieldvals[-1] = 0 |
||||||
|
|
||||||
|
def draw(self, frame): |
||||||
|
for i, f in enumerate(self.fieldpoints): |
||||||
|
color = colorsys.hsv_to_rgb(self.h, 1, self.fieldvals[i]) |
||||||
|
for x in range(self.fieldsize): |
||||||
|
for y in range(self.fieldsize): |
||||||
|
try: |
||||||
|
p = f + Point(x, y) |
||||||
|
frame.setPixel(p.x, p.y, convert_color(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) |
||||||
|
|
||||||
|
t = 0 |
||||||
|
dt = args.delay / 1000 |
||||||
|
tt = 0 |
||||||
|
bc = None |
||||||
|
while t < args.time or not bc.done: |
||||||
|
t += dt |
||||||
|
tt += dt |
||||||
|
frame = blup.animation.AnimationFrame(dim, args.delay) |
||||||
|
|
||||||
|
if (bc is None or bc.done) and t < args.time: |
||||||
|
tt = 0 |
||||||
|
bc = BlinkingCheckerboard( |
||||||
|
Point(WIDTH, HEIGHT), |
||||||
|
2, |
||||||
|
random.random(), |
||||||
|
random.randint(13, 23), |
||||||
|
random.randint(3, 5) |
||||||
|
) |
||||||
|
|
||||||
|
bc.update(tt, dt) |
||||||
|
bc.draw(frame) |
||||||
|
|
||||||
|
anim.addFrame(frame) |
||||||
|
|
||||||
|
blup.writebml.writeBml(anim, args.output_file) |
Loading…
Reference in new issue