Fr3deric
7 years ago
1 changed files with 150 additions and 0 deletions
@ -0,0 +1,150 @@
@@ -0,0 +1,150 @@
|
||||
#!/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) |
Loading…
Reference in new issue