Compare commits
25 Commits
master
...
feature/ba
Author | SHA1 | Date |
---|---|---|
informaniac | 77cb3516ca | 7 years ago |
informaniac | 16e895e390 | 7 years ago |
informaniac | b778375165 | 7 years ago |
informaniac | 90e1c5c9b8 | 7 years ago |
informaniac | b904fcc449 | 7 years ago |
informaniac | c805f6c71b | 7 years ago |
informaniac | 278f080e23 | 7 years ago |
informaniac | 397e4c323a | 7 years ago |
informaniac | 81de8409f2 | 7 years ago |
informaniac | 9bce3e7916 | 7 years ago |
informaniac | 8cb7470d22 | 7 years ago |
informaniac | ca848e9ba1 | 7 years ago |
informaniac | 5cad7825f3 | 7 years ago |
informaniac | 1e974a74d6 | 7 years ago |
informaniac | a5ae8985ce | 7 years ago |
informaniac | 29d0cfcb31 | 7 years ago |
informaniac | 038f33df2c | 7 years ago |
informaniac | 026f05c958 | 7 years ago |
informaniac | 16c4dcc8d6 | 7 years ago |
informaniac | 075e8c5c03 | 7 years ago |
informaniac | e34f76b22d | 7 years ago |
informaniac | 6da1b8cf13 | 7 years ago |
informaniac | 9c2d3cb33a | 7 years ago |
informaniac | 2b0bde627f | 7 years ago |
informaniac | 02cb0e8348 | 7 years ago |
27 changed files with 221 additions and 2026 deletions
@ -1,126 +0,0 @@ |
|||||||
#!/usr/bin/env python3 |
|
||||||
|
|
||||||
import sys |
|
||||||
import random |
|
||||||
import argparse |
|
||||||
import blup.frame |
|
||||||
import blup.output |
|
||||||
import blup.animation |
|
||||||
import blup.writebml |
|
||||||
import colorsys |
|
||||||
|
|
||||||
|
|
||||||
WIDTH = 22 |
|
||||||
HEIGHT = 16 |
|
||||||
DEPTH = 256 |
|
||||||
|
|
||||||
|
|
||||||
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(), 1, 1) |
|
||||||
|
|
||||||
|
|
||||||
def get_random_point(): |
|
||||||
return (random.randint(0, WIDTH-1), random.randint(0, HEIGHT-1)) |
|
||||||
|
|
||||||
|
|
||||||
def cap(x): |
|
||||||
return min(1, max(0, x)) |
|
||||||
|
|
||||||
|
|
||||||
def cyc(x): |
|
||||||
while x < 0: |
|
||||||
x += 1 |
|
||||||
while x > 1: |
|
||||||
x -= 1 |
|
||||||
return x |
|
||||||
|
|
||||||
|
|
||||||
class Point: |
|
||||||
def __init__(self, pos, color, evolve): |
|
||||||
self.pos = pos |
|
||||||
self.color = color |
|
||||||
self.neighbours = [] |
|
||||||
h, s, v = colorsys.rgb_to_hsv(*color) |
|
||||||
self.evolve = evolve |
|
||||||
if 'h' in evolve: |
|
||||||
h += (random.random()-.5) * 0.1 |
|
||||||
if 's' in evolve: |
|
||||||
s += (random.random()-.5) * 0.5 |
|
||||||
if 'v' in evolve: |
|
||||||
v += (random.random()-.5) * 0.5 |
|
||||||
self.ncolor = colorsys.hsv_to_rgb(cyc(h), cap(s), cap(v)) |
|
||||||
|
|
||||||
def __eq__(self, other): |
|
||||||
return self.pos == other.pos |
|
||||||
|
|
||||||
def __hash__(self): |
|
||||||
return self.pos.__hash__() |
|
||||||
|
|
||||||
def get_neighbours(self): |
|
||||||
for x in [-1, 0, 1]: |
|
||||||
for y in [-1, 0, 1]: |
|
||||||
n = (self.pos[0]+x, self.pos[1]+y) |
|
||||||
if n[0] >= 0 and n[1] >= 0 and n[0] < WIDTH and \ |
|
||||||
n[1] < HEIGHT and abs(x+y) < 2: |
|
||||||
yield Point(n, self.ncolor, self.evolve) |
|
||||||
|
|
||||||
|
|
||||||
class Blob: |
|
||||||
def __init__(self, pos, color): |
|
||||||
e = random.choice('hsv') |
|
||||||
if random.random() > 0.8: |
|
||||||
e += random.choice('hsv') |
|
||||||
p = Point(pos, color, e) |
|
||||||
self.points = set([p]) |
|
||||||
self.candids = set(p.get_neighbours()) |
|
||||||
self.completed = False |
|
||||||
|
|
||||||
def grow(self): |
|
||||||
if len(self.candids) == 0: |
|
||||||
self.completed = True |
|
||||||
return |
|
||||||
newp = random.sample(self.candids, 1)[0] |
|
||||||
self.candids.remove(newp) |
|
||||||
self.points.add(newp) |
|
||||||
self.candids = self.candids.union(set(newp.get_neighbours()) - |
|
||||||
self.points - self.candids) |
|
||||||
|
|
||||||
def draw(self, frame): |
|
||||||
for p in self.points: |
|
||||||
frame.setPixel(p.pos[0], p.pos[1], convert_color(p.color)) |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__': |
|
||||||
parser = argparse.ArgumentParser(description='Generate blob 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 |
|
||||||
blobs = [Blob(get_random_point(), get_random_color())] |
|
||||||
while t < args.time: |
|
||||||
t += args.delay / 1000 |
|
||||||
frame = blup.animation.AnimationFrame(dim, args.delay) |
|
||||||
|
|
||||||
for b in blobs: |
|
||||||
for i in range(4): |
|
||||||
b.grow() |
|
||||||
b.draw(frame) |
|
||||||
|
|
||||||
if len(blobs[-1].points) > WIDTH*HEIGHT*0.6 and len(blobs) < 3: |
|
||||||
blobs.append(Blob(get_random_point(), get_random_color())) |
|
||||||
if len(blobs) >=2 and blobs[0].completed and blobs[1].completed: |
|
||||||
blobs.remove(blobs[0]) |
|
||||||
|
|
||||||
anim.addFrame(frame) |
|
||||||
|
|
||||||
blup.writebml.writeBml(anim, args.output_file) |
|
@ -1,140 +0,0 @@ |
|||||||
#!/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) |
|
@ -1,107 +0,0 @@ |
|||||||
#!/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 |
|
||||||
import functools |
|
||||||
|
|
||||||
|
|
||||||
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 CurveFunction(): |
|
||||||
def __init__(self, p1, p2): |
|
||||||
self.p1, self.p2 = p1, p2 |
|
||||||
d = p2 - p1 |
|
||||||
self.pp = p1 + d/2 + d.n * (d.len * 0.8) |
|
||||||
|
|
||||||
def __call__(self, t): |
|
||||||
ret = (self.p1 - self.pp*2 + self.p2) * t**2 |
|
||||||
ret += (self.p1 * -2 + self.pp * 2) * t |
|
||||||
ret += self.p1 |
|
||||||
return ret |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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 |
|
||||||
while t < args.time: |
|
||||||
t += dt |
|
||||||
|
|
||||||
p1 = p2 = None |
|
||||||
while p1 == p2 or (p1 - p2).len < max(WIDTH, HEIGHT) / 2: |
|
||||||
p1 = Point(random.randint(0, WIDTH-1), random.randint(0, HEIGHT-1)) |
|
||||||
p2 = Point(random.randint(0, WIDTH-1), random.randint(0, HEIGHT-1)) |
|
||||||
cf = CurveFunction(p1, p2) |
|
||||||
color = convert_color(get_random_color()) |
|
||||||
tt = 0 |
|
||||||
points = [] |
|
||||||
while tt <= 1: |
|
||||||
t += dt |
|
||||||
tt += 0.025 |
|
||||||
p = cf(tt).intp |
|
||||||
points.append(p) |
|
||||||
frame = blup.animation.AnimationFrame(dim, args.delay) |
|
||||||
for p in points: |
|
||||||
try: |
|
||||||
frame.setPixel(p.x, p.y, color) |
|
||||||
except ValueError: |
|
||||||
pass |
|
||||||
anim.addFrame(frame) |
|
||||||
|
|
||||||
blup.writebml.writeBml(anim, args.output_file) |
|
@ -1,114 +0,0 @@ |
|||||||
#!/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(), 1, 1) |
|
||||||
|
|
||||||
|
|
||||||
class Disc: |
|
||||||
def __init__(self, worldsize, hue): |
|
||||||
self.worldsize = worldsize |
|
||||||
self.pos = Point(random.randint(0, worldsize.x - 1), |
|
||||||
random.randint(0, worldsize.y - 1)) |
|
||||||
self.hue = hue |
|
||||||
self.r = 1 |
|
||||||
self.speed = min(worldsize.x, worldsize.y) / 2 |
|
||||||
self.done = False |
|
||||||
|
|
||||||
def update(self, t, dt): |
|
||||||
self.r += self.speed * dt |
|
||||||
if self.r > max(self.worldsize.x, self.worldsize.y): |
|
||||||
self.done = True |
|
||||||
|
|
||||||
def draw(self, frame): |
|
||||||
color = colorsys.hsv_to_rgb(self.hue, 1, 1) |
|
||||||
for x in range(self.worldsize.x): |
|
||||||
for y in range(self.worldsize.y): |
|
||||||
p = Point(x, y) |
|
||||||
if (p - self.pos).len < self.r: |
|
||||||
frame.setPixel(p.x, p.y, convert_color(color)) |
|
||||||
|
|
||||||
|
|
||||||
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) |
|
||||||
|
|
||||||
discs = [] |
|
||||||
t = 0 |
|
||||||
dt = args.delay / 1000 |
|
||||||
while t < args.time: |
|
||||||
t += dt |
|
||||||
frame = blup.animation.AnimationFrame(dim, args.delay) |
|
||||||
|
|
||||||
if len(discs) == 0 or discs[-1].r > min(WIDTH, HEIGHT) / 2: |
|
||||||
hue = random.random() |
|
||||||
if len(discs) > 0: |
|
||||||
l = lambda d: hue - d.hue if d.hue < hue else d.hue - hue |
|
||||||
while not 0.2 < sorted(map(l, discs))[0] < 0.8: |
|
||||||
hue = random.random() |
|
||||||
discs.append(Disc(Point(WIDTH, HEIGHT), hue)) |
|
||||||
|
|
||||||
for d in discs: |
|
||||||
d.update(t, dt) |
|
||||||
d.draw(frame) |
|
||||||
|
|
||||||
if len(discs) > 2 and discs[0].done and discs[1].done: |
|
||||||
del discs[0] |
|
||||||
|
|
||||||
anim.addFrame(frame) |
|
||||||
|
|
||||||
blup.writebml.writeBml(anim, args.output_file) |
|
@ -1,141 +0,0 @@ |
|||||||
#!/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 |
|
||||||
import functools |
|
||||||
|
|
||||||
|
|
||||||
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) |
|
||||||
@property |
|
||||||
def len(self): |
|
||||||
return math.sqrt(self.x**2 + self.y**2) |
|
||||||
|
|
||||||
|
|
||||||
class PointLenOrder: |
|
||||||
def __init__(self, value): |
|
||||||
self.value = value |
|
||||||
def __eq__(self, other): |
|
||||||
return other.value.len == self.value.len |
|
||||||
def __lt__(self, other): |
|
||||||
return other.value.len < self.value.len |
|
||||||
|
|
||||||
|
|
||||||
DIRECTIONS = [ Point(x, y) for x in [-1, 1] for y in [-1, 1] ] |
|
||||||
|
|
||||||
|
|
||||||
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, worldsize): |
|
||||||
self.worldsize = worldsize |
|
||||||
self.line = [Point(random.randint(0, worldsize.x), |
|
||||||
random.randint(0, worldsize.y))] |
|
||||||
self.slen = 1 |
|
||||||
self.dir = random.choice(DIRECTIONS) |
|
||||||
self.color = get_random_color() |
|
||||||
diaglen = int(math.sqrt(worldsize.x**2 + worldsize.y**2)) |
|
||||||
self.maxlen = random.randint(diaglen, diaglen * 3) |
|
||||||
self.fadeout_time = 2 + random.random() * 2 |
|
||||||
self.fadeout_remaining = None |
|
||||||
self.finished = False |
|
||||||
|
|
||||||
def check_bounds(self, p): |
|
||||||
return p.x < self.worldsize.x and p.x >= 0 \ |
|
||||||
and p.y < self.worldsize.y and p.y >= 0 |
|
||||||
|
|
||||||
def update(self, t, dt): |
|
||||||
if len(self.line) < self.maxlen: |
|
||||||
if self.slen >= 3 and random.random() < 0.4: |
|
||||||
dirs = list(DIRECTIONS) |
|
||||||
dirs.remove(self.line[-1] - self.line[-2]) |
|
||||||
if self.check_bounds(self.line[-1]): |
|
||||||
newp = None |
|
||||||
while newp is None or newp == self.line[-2]: |
|
||||||
self.dir = random.choice(dirs) |
|
||||||
newp = self.line[-1] + self.dir |
|
||||||
else: |
|
||||||
dirs.sort(key=lambda d: ((self.line[-1]+d) - Point(0, 0)).len) |
|
||||||
self.dir = dirs[0] |
|
||||||
self.slen = 1 |
|
||||||
else: |
|
||||||
self.slen += 1 |
|
||||||
self.line.append(self.line[-1] + self.dir) |
|
||||||
else: |
|
||||||
if self.fadeout_remaining is None: |
|
||||||
self.fadeout_remaining = self.fadeout_time |
|
||||||
elif self.fadeout_remaining <= 0: |
|
||||||
self.finished = True |
|
||||||
else: |
|
||||||
self.fadeout_remaining -= dt |
|
||||||
|
|
||||||
def draw(self, frame): |
|
||||||
if self.fadeout_remaining is not None: |
|
||||||
if self.fadeout_remaining > 0: |
|
||||||
h, s, v = colorsys.rgb_to_hsv(*self.color) |
|
||||||
v = v * (self.fadeout_remaining / self.fadeout_time) |
|
||||||
color = colorsys.hsv_to_rgb(h, s, v) |
|
||||||
else: |
|
||||||
color = (0, 0, 0) |
|
||||||
else: |
|
||||||
color = self.color |
|
||||||
for p in self.line: |
|
||||||
if self.check_bounds(p): |
|
||||||
frame.setPixel(p.x, p.y, convert_color(color)) |
|
||||||
|
|
||||||
|
|
||||||
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 = [Line(Point(WIDTH, HEIGHT))] |
|
||||||
t = 0 |
|
||||||
dt = args.delay / 1000 |
|
||||||
while t < args.time: |
|
||||||
t += dt |
|
||||||
frame = blup.animation.AnimationFrame(dim, args.delay) |
|
||||||
|
|
||||||
for l in lines: |
|
||||||
l.update(t, dt) |
|
||||||
l.draw(frame) |
|
||||||
|
|
||||||
if lines[-1].fadeout_remaining is not None: |
|
||||||
lines.append(Line(Point(WIDTH, HEIGHT))) |
|
||||||
|
|
||||||
for l in lines: |
|
||||||
if l.finished: |
|
||||||
lines.remove(l) |
|
||||||
|
|
||||||
anim.addFrame(frame) |
|
||||||
|
|
||||||
blup.writebml.writeBml(anim, args.output_file) |
|
@ -1,150 +0,0 @@ |
|||||||
#!/usr/bin/env python3 |
|
||||||
|
|
||||||
import sys |
|
||||||
import random |
|
||||||
import argparse |
|
||||||
import collections |
|
||||||
import blup.frame |
|
||||||
import blup.output |
|
||||||
import blup.animation |
|
||||||
import blup.writebml |
|
||||||
import colorsys |
|
||||||
|
|
||||||
|
|
||||||
WIDTH = 22 |
|
||||||
HEIGHT = 16 |
|
||||||
DEPTH = 256 |
|
||||||
SMILEYSIZE = 5 |
|
||||||
|
|
||||||
Point = collections.namedtuple('Point', ['x', 'y']) |
|
||||||
|
|
||||||
|
|
||||||
def convert_color(c): |
|
||||||
return list(map(lambda x: int(round(x*(DEPTH-1))), c)) |
|
||||||
|
|
||||||
|
|
||||||
def expand(somepoints, allpoints): |
|
||||||
todo = set(somepoints) |
|
||||||
ret = set(somepoints) |
|
||||||
while len(todo) > 0: |
|
||||||
p = todo.pop() |
|
||||||
ret.add(p) |
|
||||||
adj = { Point(p.x + x, p.y + y) for x in [-1,0,1] for y in [-1,0,1] \ |
|
||||||
if abs(x) + abs(y) == 1 and p.x + x in range(0, SMILEYSIZE) \ |
|
||||||
and p.y + y in range(0, SMILEYSIZE) } |
|
||||||
adj = (allpoints - ret).intersection(adj) |
|
||||||
todo = todo.union(adj) |
|
||||||
return ret |
|
||||||
|
|
||||||
|
|
||||||
def gen_face_shape(): |
|
||||||
while True: |
|
||||||
i = random.randint(0, 2**(SMILEYSIZE * (SMILEYSIZE//2 + 1))) |
|
||||||
lpoints = { Point(x, y) for x in range(0, SMILEYSIZE // 2) \ |
|
||||||
for y in range(SMILEYSIZE) \ |
|
||||||
if i & 2**(x*SMILEYSIZE + y) > 0 } |
|
||||||
mpoints = { Point(SMILEYSIZE//2, y) for y in range(SMILEYSIZE) \ |
|
||||||
if i & 2**((SMILEYSIZE//2) * SMILEYSIZE + y) > 0 } |
|
||||||
rpoints = { Point(SMILEYSIZE - x - 1, y) \ |
|
||||||
for x in range(0, SMILEYSIZE // 2) \ |
|
||||||
for y in range(SMILEYSIZE) \ |
|
||||||
if i & 2**(x*SMILEYSIZE + y) > 0 } |
|
||||||
points = set.union(lpoints, mpoints, rpoints) |
|
||||||
|
|
||||||
eyes = { p for p in points if p.y < SMILEYSIZE // 2 and \ |
|
||||||
p.x != SMILEYSIZE // 2 } |
|
||||||
nose = { p for p in points if p.y >= SMILEYSIZE // 3 and \ |
|
||||||
p.y < SMILEYSIZE // 2 + 1 and p.x == SMILEYSIZE//2 } |
|
||||||
mouth = { p for p in points if p.y > SMILEYSIZE // 2 } |
|
||||||
|
|
||||||
nose = expand(nose, points) |
|
||||||
mouth = expand(mouth, points) |
|
||||||
|
|
||||||
face = True |
|
||||||
if len(eyes.intersection(nose)) > 0: |
|
||||||
face = False |
|
||||||
if len(eyes.intersection(mouth)) > 0: |
|
||||||
face = False |
|
||||||
if len(nose.intersection(mouth)) > 0: |
|
||||||
face = False |
|
||||||
if len(points - eyes - nose - mouth) > 0: |
|
||||||
face = False |
|
||||||
if len(eyes) == 0: |
|
||||||
face = False |
|
||||||
if len(mouth) == 0: |
|
||||||
face = False |
|
||||||
if len(nose) > 0: |
|
||||||
nosey = set(map(lambda p: p.y, nose)) |
|
||||||
if min(nosey) < SMILEYSIZE//3: |
|
||||||
face = False |
|
||||||
|
|
||||||
if face: |
|
||||||
return points |
|
||||||
|
|
||||||
|
|
||||||
class Face: |
|
||||||
def __init__(self, pos): |
|
||||||
self.pos = pos |
|
||||||
self.shape = gen_face_shape() |
|
||||||
self.lifetime = 0.7 |
|
||||||
self.fadetime = 0.1 + random.random() / 10 |
|
||||||
self.age = 0 |
|
||||||
self.done = False |
|
||||||
self.hue = random.random() |
|
||||||
|
|
||||||
def update(self, dt): |
|
||||||
self.age += dt |
|
||||||
if self.age > self.lifetime: |
|
||||||
self.done = True |
|
||||||
|
|
||||||
def draw(self, frame): |
|
||||||
if self.done: |
|
||||||
return |
|
||||||
if self.age < self.fadetime: |
|
||||||
v = self.age / self.fadetime |
|
||||||
elif self.age > self.lifetime - self.fadetime: |
|
||||||
v = (self.lifetime-self.age) / self.fadetime |
|
||||||
else: |
|
||||||
v = 1 |
|
||||||
for p in self.shape: |
|
||||||
frame.setPixel( |
|
||||||
p.x + self.pos.x, |
|
||||||
p.y + self.pos.y, |
|
||||||
convert_color(colorsys.hsv_to_rgb(self.hue, 1, v)) |
|
||||||
) |
|
||||||
|
|
||||||
|
|
||||||
def get_face_pos(): |
|
||||||
x = random.randint(0, WIDTH - SMILEYSIZE) |
|
||||||
y = random.randint(0, HEIGHT - SMILEYSIZE) |
|
||||||
return Point(x, y) |
|
||||||
|
|
||||||
if __name__ == '__main__': |
|
||||||
parser = argparse.ArgumentParser(description='Generate Face 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) |
|
||||||
|
|
||||||
f = Face(get_face_pos()) |
|
||||||
t = 0 |
|
||||||
dt = args.delay / 1000 |
|
||||||
while f is not None: |
|
||||||
t += dt |
|
||||||
frame = blup.animation.AnimationFrame(dim, args.delay) |
|
||||||
|
|
||||||
f.update(dt) |
|
||||||
f.draw(frame) |
|
||||||
if f.done: |
|
||||||
if t < args.time: |
|
||||||
f = Face(get_face_pos()) |
|
||||||
else: |
|
||||||
f = None |
|
||||||
|
|
||||||
anim.addFrame(frame) |
|
||||||
|
|
||||||
blup.writebml.writeBml(anim, args.output_file) |
|
@ -1,121 +0,0 @@ |
|||||||
#!/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) |
|
@ -1,222 +0,0 @@ |
|||||||
#!/usr/bin/env python3 |
|
||||||
|
|
||||||
import sys |
|
||||||
import random |
|
||||||
import argparse |
|
||||||
import collections |
|
||||||
import blup.frame |
|
||||||
import blup.output |
|
||||||
import blup.animation |
|
||||||
import blup.writebml |
|
||||||
import colorsys |
|
||||||
import math |
|
||||||
|
|
||||||
|
|
||||||
WIDTH = 22 |
|
||||||
HEIGHT = 16 |
|
||||||
DEPTH = 256 |
|
||||||
|
|
||||||
_ALLSHAPES = [ |
|
||||||
[[0, 1, 0, 1, 0], |
|
||||||
[1, 1, 1, 1, 1], |
|
||||||
[1, 1, 1, 1, 1], |
|
||||||
[0, 1, 1, 1, 0], |
|
||||||
[0, 0, 1, 0, 0]], |
|
||||||
|
|
||||||
[[1, 0, 0, 0, 1], |
|
||||||
[0, 0, 1, 0, 0], |
|
||||||
[0, 0, 1, 0, 0], |
|
||||||
[1, 0, 0, 0, 1], |
|
||||||
[0, 1, 1, 1, 0]], |
|
||||||
|
|
||||||
[[1, 0, 1, 0, 1], |
|
||||||
[0, 1, 1, 1, 0], |
|
||||||
[0, 1, 1, 1, 0], |
|
||||||
[0, 1, 0, 1, 0], |
|
||||||
[1, 1, 0, 1, 1]], |
|
||||||
] |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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) |
|
||||||
|
|
||||||
ALLSHAPES = [] |
|
||||||
for s in _ALLSHAPES: |
|
||||||
ALLSHAPES.append(set()) |
|
||||||
y = 0 |
|
||||||
for l in s: |
|
||||||
x = 0 |
|
||||||
for i in l: |
|
||||||
if i == 1: |
|
||||||
ALLSHAPES[-1].add(Point(x, y)) |
|
||||||
x += 1 |
|
||||||
y += 1 |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
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(), 1, 1) |
|
||||||
|
|
||||||
|
|
||||||
class Shape: |
|
||||||
def __init__(self, shape, pos, color): |
|
||||||
self.shape, self.pos, self.color = shape, pos, color |
|
||||||
self.period = 2 |
|
||||||
self.fadetime = 0.5 + random.random() / 5 |
|
||||||
self.t = random.random() * self.period |
|
||||||
self.t = 0 |
|
||||||
self.oldv = 1 |
|
||||||
self.v = 1 |
|
||||||
self.newshape = None |
|
||||||
|
|
||||||
def update(self, t, dt): |
|
||||||
self.t += dt |
|
||||||
if self.t > self.period: |
|
||||||
t = self.t - self.period |
|
||||||
if t >= self.fadetime: |
|
||||||
self.v = 1 |
|
||||||
self.t = random.random() * self.period |
|
||||||
else: |
|
||||||
self.v = math.cos(t * (math.pi / self.fadetime)) ** 2 |
|
||||||
if (self.newshape is not None \ |
|
||||||
and (self.oldv < self.v or self.v == 0)): |
|
||||||
self.shape = self.newshape |
|
||||||
self.color = self.newcolor |
|
||||||
self.newshape = None |
|
||||||
self.oldv = self.v |
|
||||||
|
|
||||||
def change_shape_and_color(self, newshape, newcolor): |
|
||||||
self.newshape = newshape |
|
||||||
self.newcolor = newcolor |
|
||||||
self.t = self.period |
|
||||||
|
|
||||||
def draw(self, frame, origin=Point(0, 0)): |
|
||||||
h, s, v = colorsys.rgb_to_hsv(*self.color) |
|
||||||
for p in self.shape: |
|
||||||
try: |
|
||||||
pos = self.pos + p - origin |
|
||||||
c = colorsys.hsv_to_rgb(h, s, v * self.v) |
|
||||||
frame.setPixel(pos.x, pos.y, convert_color(c)) |
|
||||||
except ValueError: |
|
||||||
pass |
|
||||||
|
|
||||||
|
|
||||||
class World: |
|
||||||
def __init__(self, size, allshapes, gap=2): |
|
||||||
self.size, self.allshapes, self.gap = size, allshapes, gap |
|
||||||
self.shapes = {} |
|
||||||
self.pos = Point(0, 0) |
|
||||||
self.cycletime = 60 |
|
||||||
self.curshape = random.choice(allshapes) |
|
||||||
self.curcolor = get_random_color() |
|
||||||
|
|
||||||
self.shapesize = Point(0, 0) |
|
||||||
for s in allshapes: |
|
||||||
assert min(map(lambda p: p.x, s)) >= 0 |
|
||||||
assert min(map(lambda p: p.y, s)) >= 0 |
|
||||||
shapesize = Point( |
|
||||||
max(map(lambda p: p.x, s)) + 1, |
|
||||||
max(map(lambda p: p.y, s)) + 1, |
|
||||||
) |
|
||||||
if shapesize.x > self.shapesize.x: |
|
||||||
self.shapesize = Point(shapesize.x, self.shapesize.y) |
|
||||||
if shapesize.y > self.shapesize.y: |
|
||||||
self.shapesize = Point(self.shapesize.x, shapesize.y) |
|
||||||
print (self.shapesize) |
|
||||||
|
|
||||||
@property |
|
||||||
def shape_space(self): |
|
||||||
ret = set() |
|
||||||
for x in range(self.size.x): |
|
||||||
for y in range(self.size.y): |
|
||||||
p = self.pos + Point(x, y) |
|
||||||
if (p.x % (self.shapesize.x + self.gap) >= self.gap |
|
||||||
and p.y % (self.shapesize.y + self.gap) >= self.gap): |
|
||||||
ret.add(p) |
|
||||||
return ret |
|
||||||
|
|
||||||
def get_shape_coverage(self, shape): |
|
||||||
return { shape.pos + Point(x, y) for x in range(self.shapesize.x) \ |
|
||||||
for y in range(self.shapesize.y) } |
|
||||||
|
|
||||||
def update(self, t, dt): |
|
||||||
self.pos = Point( |
|
||||||
int(math.sin((t * math.pi/self.cycletime)*4) * self.size.x), |
|
||||||
int(math.cos((t * math.pi/self.cycletime)*5) * self.size.y) |
|
||||||
) |
|
||||||
|
|
||||||
space = self.shape_space |
|
||||||
for s in self.shapes.values(): |
|
||||||
space -= self.get_shape_coverage(s) |
|
||||||
while len(space) > 0: # and len(self.shapes) < 1: |
|
||||||
print('...') |
|
||||||
p = space.pop() |
|
||||||
newpos = Point( |
|
||||||
(p.x // (self.shapesize.x + self.gap)) \ |
|
||||||
* (self.shapesize.x + self.gap) + self.gap, |
|
||||||
(p.y // (self.shapesize.y + self.gap)) \ |
|
||||||
* (self.shapesize.y + self.gap) + self.gap |
|
||||||
) |
|
||||||
print(p, newpos) |
|
||||||
# TODO improve shape and color selection |
|
||||||
newshape = Shape(self.curshape, newpos, self.curcolor) |
|
||||||
assert newpos in self.get_shape_coverage(newshape) |
|
||||||
print('covered', self.get_shape_coverage(newshape)) |
|
||||||
print('space before', len(space)) |
|
||||||
space -= self.get_shape_coverage(newshape) |
|
||||||
print('space after ', len(space)) |
|
||||||
assert newpos not in self.shapes |
|
||||||
self.shapes[newpos] = newshape |
|
||||||
print('new', len(self.shapes)) |
|
||||||
#print(space) |
|
||||||
|
|
||||||
newshape = None |
|
||||||
newcolor = None |
|
||||||
if round(t*1000) % 3000 == 0: |
|
||||||
newshape = random.choice(self.allshapes) |
|
||||||
self.curshape = newshape |
|
||||||
newcolor = get_random_color() |
|
||||||
self.curcolor = newcolor |
|
||||||
for s in self.shapes.values(): |
|
||||||
if newshape is not None: |
|
||||||
s.change_shape_and_color(newshape, newcolor) |
|
||||||
s.update(t, dt) |
|
||||||
|
|
||||||
def draw(self, frame): |
|
||||||
for s in self.shapes.values(): |
|
||||||
s.draw(frame, self.pos) |
|
||||||
|
|
||||||
|
|
||||||
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) |
|
||||||
|
|
||||||
w = World(Point(WIDTH, HEIGHT), ALLSHAPES) |
|
||||||
t = 0 |
|
||||||
dt = args.delay / 1000 |
|
||||||
while t < args.time: |
|
||||||
t += dt |
|
||||||
frame = blup.animation.AnimationFrame(dim, args.delay) |
|
||||||
|
|
||||||
w.update(t, dt) |
|
||||||
w.draw(frame) |
|
||||||
|
|
||||||
anim.addFrame(frame) |
|
||||||
|
|
||||||
blup.writebml.writeBml(anim, args.output_file) |
|
@ -1,122 +0,0 @@ |
|||||||
#!/usr/bin/env python3 |
|
||||||
|
|
||||||
import sys |
|
||||||
import random |
|
||||||
import numpy as np |
|
||||||
import argparse |
|
||||||
import blup.frame |
|
||||||
import blup.output |
|
||||||
import blup.animation |
|
||||||
import blup.writebml |
|
||||||
import colorsys |
|
||||||
|
|
||||||
|
|
||||||
WIDTH = 22 |
|
||||||
HEIGHT = 16 |
|
||||||
DEPTH = 256 |
|
||||||
|
|
||||||
|
|
||||||
def fill_trace(points): |
|
||||||
for i in range(len(points)): |
|
||||||
yield points[i] |
|
||||||
if i == len(points)-1: |
|
||||||
break |
|
||||||
v = points[i+1] - points[i] |
|
||||||
l = int(np.linalg.norm(v)) |
|
||||||
for j in range(l): |
|
||||||
yield points[i] + v * (j+1)/(l+1) |
|
||||||
|
|
||||||
|
|
||||||
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(), 1, 1) |
|
||||||
|
|
||||||
|
|
||||||
class Orb: |
|
||||||
def __init__(self, pos, speed, tracelen, color, tracecolor, boxsize): |
|
||||||
self.pos = pos |
|
||||||
self.speed = speed |
|
||||||
self.tracelen = tracelen |
|
||||||
self.color = color |
|
||||||
self.tracecolor = tracecolor |
|
||||||
self.boxsize = boxsize |
|
||||||
self.trace = [] |
|
||||||
|
|
||||||
def update(self, dt): |
|
||||||
newpos = self.pos + self.speed * dt |
|
||||||
#newpos = self.pos |
|
||||||
for dim in [0, 1]: |
|
||||||
if newpos[dim] >= self.boxsize[dim] or newpos[dim] <= 0: |
|
||||||
newpos[dim] = 0 if newpos[dim]<0 else self.boxsize[dim]-1 |
|
||||||
self.speed[dim] *= -1 |
|
||||||
self.speed += np.array([random.randint(-5, 6), random.randint(-5, 6)]) |
|
||||||
self.trace.insert(0, self.pos) |
|
||||||
self.trace = self.trace[:self.tracelen] |
|
||||||
self.pos = newpos |
|
||||||
|
|
||||||
def draw(self, frame): |
|
||||||
for i, p in enumerate(fill_trace([self.pos] + self.trace)): |
|
||||||
f = (self.tracelen - i) / self.tracelen |
|
||||||
try: |
|
||||||
c = colorsys.rgb_to_hsv(*self.tracecolor) |
|
||||||
s = 0.1 if random.random()>0.9 else c[1] |
|
||||||
c = colorsys.hsv_to_rgb(c[0], s, c[2]*f) |
|
||||||
frame.setPixel(int(p[0]), int(p[1]), convert_color(c)) |
|
||||||
except ValueError: |
|
||||||
pass |
|
||||||
|
|
||||||
offs = [ np.array([x,y]) for x in [-1,0,1] for y in [-1,0,1] ] |
|
||||||
points = [] |
|
||||||
for o in offs: |
|
||||||
p = self.pos.astype('int') + o |
|
||||||
if random.random() > 0.2 and not (p == np.array([0,0])).all(): |
|
||||||
points.append(p) |
|
||||||
for p in points: |
|
||||||
try: |
|
||||||
c = colorsys.rgb_to_hsv(*self.color) |
|
||||||
c = colorsys.hsv_to_rgb(c[0], c[1], c[2]*0.2) |
|
||||||
frame.setPixel(p[0], p[1], convert_color(c)) |
|
||||||
except ValueError: |
|
||||||
pass |
|
||||||
|
|
||||||
frame.setPixel(int(self.pos[0]), int(self.pos[1]), convert_color(self.color)) |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__': |
|
||||||
parser = argparse.ArgumentParser(description='Generate plasma animations') |
|
||||||
parser.add_argument('-d', '--delay', type=int, default=50) |
|
||||||
parser.add_argument('-t', '--time', type=int, default=15) |
|
||||||
parser.add_argument('-n', '--num-orbs', type=int, default=2) |
|
||||||
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) |
|
||||||
|
|
||||||
orbs = [] |
|
||||||
for i in range(args.num_orbs): |
|
||||||
orbs.append(Orb( |
|
||||||
np.array([random.randint(0, WIDTH-1),random.randint(0, HEIGHT-1)]), |
|
||||||
np.array([8,10]), |
|
||||||
20, |
|
||||||
get_random_color(), |
|
||||||
get_random_color(), |
|
||||||
np.array([WIDTH, HEIGHT]) |
|
||||||
)) |
|
||||||
|
|
||||||
t = 0 |
|
||||||
while t < args.time: |
|
||||||
t += args.delay / 1000 |
|
||||||
frame = blup.animation.AnimationFrame(dim, args.delay) |
|
||||||
|
|
||||||
for orb in orbs: |
|
||||||
orb.update(args.delay / 1000) |
|
||||||
orb.draw(frame) |
|
||||||
|
|
||||||
anim.addFrame(frame) |
|
||||||
|
|
||||||
blup.writebml.writeBml(anim, args.output_file) |
|
@ -1,232 +0,0 @@ |
|||||||
#!/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 |
|
||||||
import functools |
|
||||||
|
|
||||||
|
|
||||||
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 CurveFunction(): |
|
||||||
def __init__(self, p1, p2): |
|
||||||
self.p1, self.p2 = p1, p2 |
|
||||||
d = p2 - p1 |
|
||||||
self.pp = p1 + d/2 + d.n * (d.len * 0.8) |
|
||||||
|
|
||||||
def __call__(self, t): |
|
||||||
ret = (self.p1 - self.pp*2 + self.p2) * t**2 |
|
||||||
ret += (self.p1 * -2 + self.pp * 2) * t |
|
||||||
ret += self.p1 |
|
||||||
return ret |
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Box(): |
|
||||||
def __init__(self, pos, size, hue, swaptime, content=None, |
|
||||||
contentcolor=None): |
|
||||||
self.pos, self.size, self.hue, self.content, self.contentcolor = \ |
|
||||||
pos, size, hue, content, contentcolor |
|
||||||
self.swaptime = swaptime |
|
||||||
self.covered = False |
|
||||||
self.swapstart = None |
|
||||||
self.newpos = None |
|
||||||
self.cf = None |
|
||||||
self.colorcycletime = 1 |
|
||||||
|
|
||||||
def swap(self, other): |
|
||||||
self.newpos = other.pos |
|
||||||
other.newpos = self.pos |
|
||||||
|
|
||||||
def update(self, t, dt): |
|
||||||
self.hue += 0.05 # dt / self.colorcycletime |
|
||||||
if self.hue > 1: |
|
||||||
self.hue -= 1 |
|
||||||
if self.newpos is not None: |
|
||||||
if self.cf is None: |
|
||||||
self.cf = CurveFunction(self.pos, self.newpos) |
|
||||||
self.swapstart = t |
|
||||||
elif t - self.swapstart >= self.swaptime: |
|
||||||
self.pos = self.newpos |
|
||||||
self.newpos = None |
|
||||||
self.cf = None |
|
||||||
self.swapstart = None |
|
||||||
else: |
|
||||||
self.pos = (self.cf((t - self.swapstart) / self.swaptime)).intp |
|
||||||
|
|
||||||
def draw(self, frame): |
|
||||||
if self.covered: |
|
||||||
for x in range(self.size): |
|
||||||
for y in range(self.size): |
|
||||||
if x == 0 or x == self.size - 1 \ |
|
||||||
or y == 0 or y == self.size -1: |
|
||||||
color = (0.6, 0.6, 0.6) |
|
||||||
else: |
|
||||||
color = colorsys.hsv_to_rgb(self.hue, 1, 1) |
|
||||||
try: |
|
||||||
frame.setPixel(self.pos.x + x, self.pos.y + y, |
|
||||||
convert_color(color)) |
|
||||||
except ValueError: |
|
||||||
pass |
|
||||||
else: |
|
||||||
if self.content is not None: |
|
||||||
for p in self.content: |
|
||||||
try: |
|
||||||
frame.setPixel(self.pos.x + p.x + 1, |
|
||||||
self.pos.y + p.y + 1, |
|
||||||
convert_color(self.contentcolor)) |
|
||||||
except ValueError: |
|
||||||
pass |
|
||||||
|
|
||||||
|
|
||||||
class Game(): |
|
||||||
def __init__(self, size, boxsize, gap, content, contentcolor, swaptime): |
|
||||||
self.swaptime = swaptime |
|
||||||
self.boxes = [] |
|
||||||
boxbase = Point((size.x - (2*boxsize + gap)) / 2, |
|
||||||
(size.y - (2*boxsize + gap)) / 2) |
|
||||||
self.n_boxes = 4 |
|
||||||
for i in range(self.n_boxes): |
|
||||||
boxpos = boxbase + Point( |
|
||||||
(i % (self.n_boxes/2)) * (boxsize + gap), |
|
||||||
(i // (self.n_boxes/2)) * (boxsize + gap) |
|
||||||
) |
|
||||||
self.boxes.append(Box( |
|
||||||
boxpos.intp, |
|
||||||
boxsize, |
|
||||||
i * (1/self.n_boxes), |
|
||||||
swaptime |
|
||||||
)) |
|
||||||
winner = random.randint(0, self.n_boxes - 1) |
|
||||||
self.boxes[winner].content = content |
|
||||||
self.boxes[winner].contentcolor = contentcolor |
|
||||||
self.statetimes = [2, 1, 5, 2, 1, 2] |
|
||||||
self.statestarts = [0] |
|
||||||
for t in self.statetimes[:-1]: |
|
||||||
self.statestarts.append(self.statestarts[-1] + t) |
|
||||||
self.done = False |
|
||||||
|
|
||||||
def update(self, t, dt): |
|
||||||
state = 0 |
|
||||||
for i, st in enumerate(self.statestarts): |
|
||||||
if st < t: |
|
||||||
state = i |
|
||||||
else: |
|
||||||
break |
|
||||||
state_t = t - self.statestarts[state] |
|
||||||
|
|
||||||
if state == 1 or state == 4: |
|
||||||
for i, b in enumerate(self.boxes): |
|
||||||
if state_t >= i * (self.statetimes[state] / self.n_boxes): |
|
||||||
b.covered = (state == 1) |
|
||||||
elif state == 2: |
|
||||||
if True not in map(lambda b: b.newpos is not None, self.boxes) \ |
|
||||||
and random.random() > 0.2: |
|
||||||
b1 = random.randint(0, self.n_boxes - 1) |
|
||||||
b2 = random.randint(0, self.n_boxes - 1) |
|
||||||
while b1 == b2: |
|
||||||
b2 = random.randint(0, self.n_boxes - 1) |
|
||||||
self.boxes[b1].swap(self.boxes[b2]) |
|
||||||
|
|
||||||
if state > 0 and state < 5: |
|
||||||
for b in self.boxes: |
|
||||||
b.update(t, dt) |
|
||||||
|
|
||||||
if state == len(self.statetimes) - 1 and state_t > self.statetimes[-1]: |
|
||||||
self.done = True |
|
||||||
|
|
||||||
def draw(self, frame): |
|
||||||
for b in self.boxes: |
|
||||||
if b.newpos is None: |
|
||||||
b.draw(frame) |
|
||||||
for b in self.boxes: |
|
||||||
if b.newpos is not None: |
|
||||||
b.draw(frame) |
|
||||||
|
|
||||||
|
|
||||||
BOXCONTENT = { |
|
||||||
Point(0, 0), |
|
||||||
Point(3, 0), |
|
||||||
Point(0, 2), |
|
||||||
Point(3, 2), |
|
||||||
Point(1, 3), |
|
||||||
Point(2, 3), |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
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 |
|
||||||
gamestart = 0 |
|
||||||
game = None |
|
||||||
while t < args.time or not game.done: |
|
||||||
t += dt |
|
||||||
frame = blup.animation.AnimationFrame(dim, args.delay) |
|
||||||
|
|
||||||
if (game is None or game.done) and t < args.time: |
|
||||||
game = Game(Point(WIDTH, HEIGHT), 6, 2, BOXCONTENT, |
|
||||||
get_random_color(), 0.5) |
|
||||||
gamestart = t |
|
||||||
game.update(t - gamestart, dt) |
|
||||||
game.draw(frame) |
|
||||||
|
|
||||||
anim.addFrame(frame) |
|
||||||
|
|
||||||
|
|
||||||
blup.writebml.writeBml(anim, args.output_file) |
|
@ -1,124 +0,0 @@ |
|||||||
#!/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 Twister: |
|
||||||
def __init__(self, worldsize): |
|
||||||
self.worldsize = worldsize |
|
||||||
self.cycletime = 1.3 |
|
||||||
self.sat = 0.5 + random.random() / 2 |
|
||||||
self.hues = [random.random()] |
|
||||||
self.hues += [ self.hues[0] + (i+1) * 0.25 for i in range(3) ] |
|
||||||
random.shuffle(self.hues) |
|
||||||
self.width = worldsize.x // 2.9 |
|
||||||
|
|
||||||
def update(self, t, dt): |
|
||||||
# inspired by https://www.lexaloffle.com/bbs/?tid=3050 |
|
||||||
|
|
||||||
self.rows = [] |
|
||||||
a0 = t * math.pi / self.cycletime |
|
||||||
while len(self.rows) < self.worldsize.y: |
|
||||||
y = len(self.rows) |
|
||||||
a = a0 - y * math.pi / self.worldsize.y \ |
|
||||||
* (math.sin(t * math.pi / 10) * 0.7) |
|
||||||
ot1 = t * math.pi / 5 |
|
||||||
ot2 = y * math.pi / (self.worldsize.y * 2) |
|
||||||
offs = self.worldsize.x / 2 + math.sin(ot1 + ot2) * self.width / 2 |
|
||||||
x1 = int(round(offs + self.width * math.sin(a))) |
|
||||||
x2 = int(round(offs + self.width * math.sin(a+0.5*math.pi))) |
|
||||||
x3 = int(round(offs + self.width * math.sin(a+math.pi))) |
|
||||||
x4 = int(round(offs + self.width * math.sin(a+1.5*math.pi))) |
|
||||||
row = [] |
|
||||||
for i, (start, end) in enumerate([(x1, x2), (x2, x3), |
|
||||||
(x3, x4), (x4, x1)]): |
|
||||||
if start < end: |
|
||||||
row += [(x, i, (x - start) / (end - start - 1)) |
|
||||||
for x in range(start, end - 1)] |
|
||||||
self.rows.append(row) |
|
||||||
|
|
||||||
def draw(self, frame): |
|
||||||
for y, line in enumerate(self.rows): |
|
||||||
for point in line: |
|
||||||
x, i, j = point |
|
||||||
val = 1 - math.sin(j * math.pi) / 2.3 |
|
||||||
color = colorsys.hsv_to_rgb(self.hues[i], self.sat, val) |
|
||||||
try: |
|
||||||
frame.setPixel(x, 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) |
|
||||||
|
|
||||||
twister = Twister(Point(WIDTH, HEIGHT)) |
|
||||||
t = 0 |
|
||||||
dt = args.delay / 1000 |
|
||||||
while t < args.time: |
|
||||||
t += dt |
|
||||||
frame = blup.animation.AnimationFrame(dim, args.delay) |
|
||||||
|
|
||||||
twister.update(t, dt) |
|
||||||
twister.draw(frame) |
|
||||||
|
|
||||||
anim.addFrame(frame) |
|
||||||
|
|
||||||
blup.writebml.writeBml(anim, args.output_file) |
|
@ -1,133 +0,0 @@ |
|||||||
#!/usr/bin/env python3 |
|
||||||
|
|
||||||
import sys |
|
||||||
import random |
|
||||||
import argparse |
|
||||||
import blup.frame |
|
||||||
import blup.output |
|
||||||
import blup.animation |
|
||||||
import blup.writebml |
|
||||||
import colorsys |
|
||||||
|
|
||||||
|
|
||||||
WIDTH = 22 |
|
||||||
HEIGHT = 16 |
|
||||||
DEPTH = 256 |
|
||||||
|
|
||||||
|
|
||||||
def convert_color(c): |
|
||||||
return list(map(lambda x: int(round(x*(DEPTH-1))), c)) |
|
||||||
|
|
||||||
|
|
||||||
def get_random_color(): |
|
||||||
if random.random() < 0.5: |
|
||||||
s = 1 |
|
||||||
v = random.random() |
|
||||||
else: |
|
||||||
s = random.random() |
|
||||||
v = 1 |
|
||||||
return colorsys.hsv_to_rgb(random.random(), s, v) |
|
||||||
|
|
||||||
|
|
||||||
class Unrath: |
|
||||||
def __init__(self, world): |
|
||||||
self.world = world |
|
||||||
self.shape = set([(0, 0)]) |
|
||||||
shapesize = random.randint(2, 5) |
|
||||||
while len(self.shape) < shapesize: |
|
||||||
p = random.sample(self.shape, 1)[0] |
|
||||||
self.shape.add((p[0]+random.randint(-1, 1), |
|
||||||
p[1]+random.randint(-1, 1))) |
|
||||||
minx = min(map(lambda p: p[0], self.shape)) |
|
||||||
miny = min(map(lambda p: p[1], self.shape)) |
|
||||||
self.shape = {(p[0]+abs(minx), p[1]+abs(miny)) for p in self.shape} |
|
||||||
self.shapewidth = max(map(lambda p: p[0], self.shape)) |
|
||||||
shapeheight = max(map(lambda p: p[1], self.shape)) |
|
||||||
|
|
||||||
y = random.randint(0, HEIGHT-shapeheight) |
|
||||||
if random.random() > 0.5: |
|
||||||
d = 1 |
|
||||||
x = -self.shapewidth |
|
||||||
else: |
|
||||||
d = -1 |
|
||||||
x = WIDTH + self.shapewidth |
|
||||||
self.pos = (x, y) |
|
||||||
self.finished = False |
|
||||||
self.speed = d * random.randint(2, WIDTH/2) |
|
||||||
self.color = get_random_color() |
|
||||||
|
|
||||||
def update(self, dt, nocheck=False): |
|
||||||
if (self.pos[0] + self.shapewidth < 0 and self.speed < 0) or \ |
|
||||||
(self.pos[0] > WIDTH and self.speed > 0): |
|
||||||
self.finished = True |
|
||||||
return |
|
||||||
newpos = (self.pos[0] + dt*self.speed, self.pos[1]) |
|
||||||
newpoints = self.get_points(newpos) |
|
||||||
collision = False |
|
||||||
for unrath in self.world.unraethe - {self}: |
|
||||||
if len(unrath.get_points().intersection(newpoints)) > 0: |
|
||||||
collision = True |
|
||||||
if abs(unrath.speed) > abs(self.speed): |
|
||||||
fast = unrath |
|
||||||
slow = self |
|
||||||
else: |
|
||||||
slow = unrath |
|
||||||
fast = self |
|
||||||
slow.speed = fast.speed * (1.1 + random.random()/10) |
|
||||||
slow.update(dt, True) |
|
||||||
if not collision: |
|
||||||
self.pos = newpos |
|
||||||
|
|
||||||
def get_points(self, pos=None): |
|
||||||
if pos is None: |
|
||||||
pos = self.pos |
|
||||||
return {(int(pos[0] + s[0]), int(pos[1] + s[1])) for s in self.shape} |
|
||||||
|
|
||||||
def draw(self, frame): |
|
||||||
for p in self.get_points(): |
|
||||||
try: |
|
||||||
frame.setPixel(p[0], p[1], convert_color(self.color)) |
|
||||||
except ValueError: |
|
||||||
pass |
|
||||||
|
|
||||||
|
|
||||||
class World: |
|
||||||
def __init__(self, num_unraethe): |
|
||||||
self.num_unraethe = num_unraethe |
|
||||||
self.unraethe = {} |
|
||||||
|
|
||||||
def update(self, dt): |
|
||||||
self.unraethe = set(filter(lambda u: not u.finished, self.unraethe)) |
|
||||||
if len(self.unraethe) < self.num_unraethe: |
|
||||||
self.unraethe.add(Unrath(self)) |
|
||||||
|
|
||||||
for u in self.unraethe: |
|
||||||
u.update(dt) |
|
||||||
|
|
||||||
def draw(self, frame): |
|
||||||
for u in self.unraethe: |
|
||||||
u.draw(frame) |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__': |
|
||||||
parser = argparse.ArgumentParser(description='Generate Unrath animations') |
|
||||||
parser.add_argument('-d', '--delay', type=int, default=50) |
|
||||||
parser.add_argument('-t', '--time', type=int, default=15) |
|
||||||
parser.add_argument('-n', '--num-unraethe', type=int, default=5) |
|
||||||
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 |
|
||||||
w = World(args.num_unraethe) |
|
||||||
while t < args.time: |
|
||||||
t += args.delay / 1000 |
|
||||||
frame = blup.animation.AnimationFrame(dim, args.delay) |
|
||||||
w.update(args.delay / 1000) |
|
||||||
w.draw(frame) |
|
||||||
anim.addFrame(frame) |
|
||||||
|
|
||||||
blup.writebml.writeBml(anim, args.output_file) |
|
Loading…
Reference in new issue