PythonでアニメGIF その2 手描きアニメ編

[pukiwiki]
[[昨日の記事のつづき:http://boxheadroom.com/2009/05/20/py_animated_gif]]

ありがちですけれども、マウスでイラストを描いた様子をアニメで再現するツール。
たとえばこんなGIFアニメを作れます

http://boxheadroom.com/wp/wp-content/uploads/2009/05/ehenmusi.gif

若い人は[[エヘン虫>ググる:エヘン虫 ヴィックスドロップ]]って知らないかも(汗
[/pukiwiki]

[pukiwiki]
ほんとはTkinterに移植したかったのですけれども、、、いまだにTkinterがよくわからないので、PyGameで(汗
—-
つかいかた

-動作させると、ボタンも何も無い、真っ白なPyGameのウィンドウが開きます。
-マウスボタンを押して絵を描きます
-ウィンドウを閉じるとGIFアニメを保存します。
-4分の1に縮小されます。
ファイル名は animated.gif 固定。
-ロード、修正機能など一切ありません。書き損なったら最初から(^^;

—-
動作 Vista , Python2.5
使用ライブラリ PIL , PyGame

参考ページ
[[Pythonでゲーム作りますが何か?:http://pygame.skr.jp/index.php?FrontPage]]

まだまだ未完成ですが、たぶん、改良する時間がとれないかも(汗

[/pukiwiki]

# -*- coding: utf-8 -*-
import pygame
from pygame.locals import *
import Image
import easygui
import sys
from gifmaker2 import GifMaker
W,H=640,480
W4,H4=W//4,H//4
SCR_RECT = Rect(0, 0, W,H)

def load_image(filename):
    image = pygame.image.load(filename)
    return image.convert_alpha()

class Pen(pygame.sprite.Sprite):
    def __init__(self):
        #ペン用の画像を作成
        
        pygame.sprite.Sprite.__init__(self, self.containers)
        image=pygame.Surface((16,16))
        image.fill((255, 255, 255))
        pygame.draw.ellipse(image,(0,0,0),(1,1,14,14))
        self.image1 = image.convert()
        colorkey = image.get_at((0,0))
        self.image1.set_colorkey(colorkey, RLEACCEL)

        image=pygame.Surface((16,16))
        image.fill((255, 255, 255))
        pygame.draw.ellipse(image,(0,0,0),(1,1,14,14),1)
        self.image2 = image.convert()
        colorkey = image.get_at((0,0))
        self.image2.set_colorkey(colorkey, RLEACCEL)

        self.image=self.image2
        self.rect=self.image.get_rect()
        self.pos=self.rect.center=SCR_RECT.center
    def move(self,pos):
        self.rect.center=self.pos=pos
    def update(self):
        self.rect.center=self.pos
        self.rect.clamp_ip(SCR_RECT)
def save():
    fname=easygui.filesavebox(msg="Save as Animated GIF",
		    title="Input Save File Name",
		    default="animated.gif",filetypes=["gif"])
def deco(f):
    return f()

def test(fname="animated.gif", speed=8,wait=3000):
    global gm
    gm=GifMaker(mode="1",duration=0,loop=0,cls=GifMaker.cls_bg,trans=False)
    @deco
    def eventhandler():
        def case_QUIT (event): 
            if event.type == QUIT:
                pygame.quit()
                raise "QUIT"
                #sys.exit()
        @deco
        def case_KEYDOWN():
            def case_K_ESCAPE(event):
                pygame.quit()
                raise "QUIT"
            
            def case_K_DELETE(event):
                gm.writeframe(Image.fromstring(
                    "RGBA",(W,H),str(sc.get_buffer().raw)).resize((W4,H4),0),
                    duration=100)
                sc.fill((255,255,255))
                gm.writeframe(Image.fromstring(
                    "RGBA",(W,H),str(sc.get_buffer().raw)).resize((W4,H4),0),
                    duration=100)
                
            case={K_ESCAPE:case_K_ESCAPE,
                  K_DELETE:case_K_DELETE}
            def keyhandler(event):
                case.get(event.key,default)(event)
            return keyhandler
        def case_MOUSEMOTION(event):
            #print event.pos, event.rel, event.buttons
            pen.move(event.pos)
                        
        def case_MOUSEBUTTONDOWN(event):
            #print event.pos, event.button
            pen.image=pen.image1
        def case_MOUSEBUTTONUP(event):
            #print event.pos, event.button
            pen.image=pen.image2
            
        def default(event):
            return
            #for k in dir(event) :
                #print getattr(event,k)
        case={QUIT:case_QUIT,
              KEYDOWN:case_KEYDOWN,
              MOUSEMOTION:case_MOUSEMOTION,
              MOUSEBUTTONDOWN:case_MOUSEBUTTONDOWN,
              MOUSEBUTTONUP:case_MOUSEBUTTONUP
              }
        def eventhandler():
            for event in pygame.event.get():
                c=event.type
                if c in case :
                    case[c](event)
                else :
                    for k in dir(event) :
                        print getattr(event,k)
                    default(event)
        return eventhandler
    pygame.init()
    screen = pygame.display.set_mode(SCR_RECT.size)
    # スプライトグループを作成して登録
    all = pygame.sprite.RenderUpdates()
    Pen.containers = all


        # スプライトの画像を登録
    
    
    pen=Pen()
    
    clock = pygame.time.Clock()
    


    f=0
    x,y=screen.get_rect().center
    sc=pygame.Surface((W,H))
    sc.fill((255, 255, 255))
    lastpos=None
    skip=0
    gm.writeframe(Image.fromstring("RGBA",(W,H),
        str(sc.get_buffer().raw)).resize((W4,H4),0))
    try:
     while True:
        
        clock.tick(60)
        if pen.image==pen.image1 and lastpos!=pen.pos:
            sc.blit(pen.image,pen.rect)
            lastpos=pen.pos
            if not skip:
                gm.writeframe(Image.fromstring(
                    "RGBA",(W,H),str(sc.get_buffer().raw)).resize((W4,H4),0))
            skip=(skip+1)%speed     
        screen.fill((255, 255, 255))
        #f=(f+1)%60
        #if f : continue
        #print plane.rect.center
        eventhandler()    
        #print [stick.direction,stick.button]                                         
        screen.blit(sc,(0,0))
        all.update()
        all.draw(screen)
        
        pygame.display.update()
    except "QUIT":
        gm.save(fname,wait=wait)

if __name__=="__main__":
    test()
        

<<デバッグ記録>>
2009-05-21
-キーイベント処理 (規定外のキーを押したとき)
-何も描かないうちにウィンドウを閉じたときの対処

コメントを残す

メールアドレスが公開されることはありません。