0

I have this idea, in which I'd like to animate a pair of robot eyes, similar to Anki's Cozmo, but instead of displaying on a LED screen, I would like to run this in a python application, while still have a similar feel/effect (slight flickering, look pixelated). The problem here is that I have not a clue where to start. Must I have all the animation sprites for all the expressions (sad, happy, angry...) and transitions, then using tkinter or pygame. Or can I just draw directly from a set of configuration (e.g. array)? It would be great if you can suggest some approaches.

  • Python ascii art comes to mind here. Pyglet or asciimatics maybe? Sauce: https://pypi.org/project/asciimatics/ or https://pyglet.readthedocs.io/en/pyglet-1.3-maintenance/ Also this: https://stackoverflow.com/questions/2726343/how-to-create-ascii-animation-in-a-console-application-using-python-3-x – BoboDarph Oct 23 '18 at 13:25
  • @BoboDarph thank you for the suggestion. It looks interesting. I will check it out. – Cuong Nguyen Oct 23 '18 at 14:52

1 Answers1

3

An easy way is to store the data in a simple string, and then create your surfaces from those strings. It does not need much memory while being easy to read and modify and it can live inside your code.

Of course there are a lot of different ways to do what you want, but I guess something simple like this would be a good start (you'll get the idea):

enter image description here

import pygame
from itertools import cycle

TILE_SIZE = 32
SCREEN_SIZE = pygame.Rect((0, 0, 21*TILE_SIZE, 8*TILE_SIZE))


class Expression(pygame.sprite.Sprite):
    def __init__(self, data):
        super().__init__()
        self.image = pygame.Surface((len(data[0]), len(data)))
        x = y = 0
        for row in data:
            for col in row:
                if col == "O":
                    self.image.set_at((x, y), pygame.Color('dodgerblue'))
                x += 1
            y += 1
            x = 0
        self.image = pygame.transform.scale(self.image, (TILE_SIZE*len(data[0]), TILE_SIZE*len(data)))
        self.rect = self.image.get_rect()

REGULAR = Expression([
"                     ",
"                     ",
"    OOOO     OOOO    ",
"   OOOOOO   OOOOOO   ",
"   OOOOOO   OOOOOO   ",
"    OOOO     OOOO    ",
"                     ",
"                     ",
])

QUESTION = Expression([
"                     ",
"                     ",
"    OOOO             ",
"   OOOOOO    OOOO    ",
"   OOOOOO   OOOOOO   ",
"    OOOO     OOOO    ",
"                     ",
"                     ",
])

SAD = Expression([
"                     ",
"                     ",
"                     ",
"                     ",
"                     ",
"   OOOOOO   OOOOOO   ",
"                     ",
"                     ",
])

def main():
    pygame.init()
    screen = pygame.display.set_mode(SCREEN_SIZE.size)
    timer = pygame.time.Clock()
    expressions = cycle([REGULAR, QUESTION, REGULAR, QUESTION, SAD])
    current = next(expressions)
    pygame.time.set_timer(pygame.USEREVENT, 1000)

    while True:

        for e in pygame.event.get():
            if e.type == pygame.QUIT: 
                return
            if e.type == pygame.KEYDOWN and e.key == pygame.K_ESCAPE:
                return
            if e.type == pygame.USEREVENT:
                current = next(expressions)

        screen.fill((30, 30, 30))
        screen.blit(current.image, current.rect)
        timer.tick(60)
        pygame.display.update()

if __name__ == "__main__":
    main()

Where to go from here:

  • Use a smaller tile size and bigger strings to get a better resolution.

  • Or create the images for your animation outside of your program (in a drawing tool) and use these of you want.

  • Create different lists of expressions that define different animations, and change the current animation for each "mood".

sloth
  • 99,095
  • 21
  • 171
  • 219
  • Thank you very much. This is exactly with I had in mind. At first, I planned to store expressions in numpy array and then use pygame.surfarray.make_surface(), but this is much more simple and direct. – Cuong Nguyen Oct 23 '18 at 14:51
  • @CuongNguyen a numpy array would work to, but if you use a string array, it's easy to but the data in a simple text file and load it from there without much work. So using string arrays is usually a good compromise between size, efficiency, and ease to work with. – sloth Oct 23 '18 at 14:54