Difference between revisions of "CSC111 Animating A Stick Figure"

From dftwiki3
Jump to: navigation, search
(A Possible Finished Version)
 
(2 intermediate revisions by the same user not shown)
Line 291: Line 291:
 
</source>
 
</source>
 
<br />
 
<br />
==Step 1==
+
==Step 6: Forward and Backward==
  
 
<br />
 
<br />
 
<source lang="python">
 
<source lang="python">
 +
from graphics import *
 +
import random
 +
 +
W = 800
 +
H = 600
 +
 +
class StickFig:
 +
    def __init__( self, x, y, index=0 ):
 +
        self.index = ( abs( index ) )%10  # frame index
 +
        self.image = Image( Point( x, y ), "walk0.gif" )
  
</source>
+
    def draw( self, win ):
<br />
+
        self.win = win
==Step 1==
+
        self.image.draw( win )
 +
       
 +
    def move( self, dx=5 ):
 +
        global W, H
 +
        dx = dx + random.choice( [-1, -2, 1, 2 ] )
 +
        x = self.image.getAnchor().getX()
 +
        y = self.image.getAnchor().getY()
  
<br />
+
        # make figure "wrap around edge of window"
<source lang="python">
+
        if x > W + self.image.getWidth():
 +
            dx = -W -self.image.getWidth()
 +
        elif x < -self.image.getWidth():
 +
            dx = +W +self.image.getWidth()
 +
        # keep track of the old image
 +
        tempImage = self.image
 +
 +
        # draw a new image on top of old one
 +
        if dx > 0:
 +
            self.index = (self.index+1) % 10
 +
        else:
 +
            self.index = (self.index-1) % 10
 +
        self.image = Image( Point( x+dx, y ), "walk%d.gif" % self.index )
 +
        self.image.draw( self.win )
 +
       
 +
        # erase the old image (this avoids the flicker)
 +
        tempImage.undraw()
 +
       
  
</source>
 
<br />
 
==Step 1==
 
  
<br />
+
def main():
<source lang="python">
+
    global H, W
 +
    win = GraphWin( "Stick Figure", W, H )
  
</source>
+
    sticks = []
<br />
+
    for i in range( 4 ):
==Step 1==
+
        stick = StickFig( W/4, (i+1)*H / 5, i*3 )
 +
        stick.draw( win )
 +
        sticks.append( stick )
  
<br />
+
    while True:
<source lang="python">
+
        for i,stick in enumerate( sticks ):
 +
            if i==0:
 +
                stick.move( -5 )
 +
            else:
 +
                stick.move()
 +
           
 +
        if win.checkMouse() != None:
 +
            break
 +
       
 +
    win.getMouse()
 +
    win.close()
  
</source>
 
<br />
 
==Step 1==
 
  
<br />
+
main()
<source lang="python">
 
  
 
</source>
 
</source>
 
<br />
 
<br />
==Step 1==
 
  
<br />
 
<source lang="python">
 
  
</source>
 
<br />
 
  
=Finished Source Code=
+
=A Possible Finished Version=
 
<source lang="python">
 
<source lang="python">
 +
# Animation.py
 +
# D. Thiebaut
 +
# Demonstrates how to use the frames of a gif file to do simple
 +
# animation with Zelle's python module.
 +
#
 
from graphics import *
 
from graphics import *
 
import time
 
import time
 
import random
 
import random
 +
  
 
class Walker:
 
class Walker:
 
+
    """A class for the stick figure.  It uses 10 frames of a gif file, all
 +
    defined by a gif image of the form walk30_n.gif, where n is 0 to 9.
 +
    The walker can go forward or backward, and will use the correct
 +
    sequence of frames.  The walker can also be instantiated to start
 +
    at a given frame."""
 
     def __init__( self, x, y, index=0 ):
 
     def __init__( self, x, y, index=0 ):
 
         self.current = index
 
         self.current = index
Line 349: Line 393:
 
          
 
          
 
     def move( self, dx, dy ):
 
     def move( self, dx, dy ):
 +
        """move the walker by dx dy on the window and select
 +
        a new frame/image automatically"""
 
         x, y = self.x, self.y
 
         x, y = self.x, self.y
 
         if self.image != None:
 
         if self.image != None:
Line 355: Line 401:
 
             self.image.undraw()
 
             self.image.undraw()
  
 +
        # decide which image to pick depending on direction
 
         if dx > 0:
 
         if dx > 0:
 
             self.current = ( self.current + 1 ) % 10
 
             self.current = ( self.current + 1 ) % 10
 
         else:
 
         else:
             self.current = ( self.current + 10 - 1 ) % 10
+
             self.current = ( self.current + 10 - 1 ) % 10          
           
+
 
 
         self.image = Image( Point( x+dx, y+dy ),
 
         self.image = Image( Point( x+dx, y+dy ),
 
                             "walk30_%d.gif" % self.current )
 
                             "walk30_%d.gif" % self.current )
Line 365: Line 412:
  
 
     def draw( self, win ):
 
     def draw( self, win ):
 +
        """draw the stick figure on the window"""
 
         self.win = win
 
         self.win = win
 
         if self.image == None:
 
         if self.image == None:
Line 374: Line 422:
  
 
def justOne():
 
def justOne():
 +
    """animates just 1 stick figure on the screen"""
 
     W = 800
 
     W = 800
 
     H = 600
 
     H = 600
Line 388: Line 437:
 
     win.close()
 
     win.close()
  
def several():
+
def several( n ):
 +
    """animate several stick figures on the screen"""
 
     W = 800
 
     W = 800
 
     H = 600
 
     H = 600
Line 394: Line 444:
  
 
     walkers = []
 
     walkers = []
     for i in range( 4 ):
+
     for i in range( n ):
 
         walkers.append( Walker( W/2, 140 * i + 70, (i*2)%10 ) )
 
         walkers.append( Walker( W/2, 140 * i + 70, (i*2)%10 ) )
  
Line 412: Line 462:
 
def main():
 
def main():
 
     #justOne()
 
     #justOne()
     several()
+
     several( 4 )
 
                          
 
                          
 
main()
 
main()

Latest revision as of 09:30, 6 December 2011

--D. Thiebaut 21:49, 2 December 2011 (EST)



StickFigureCapture.png

Original Image


WalkerAnimatedGif.gif
Taken from www.eracewalk.com


Split into frames

Resulting 10 Gif Images

  • Once split, the individual images are transformed into individual gif files, and reduced in size:

Walk0.gif Walk1.gif Walk2.gif Walk3.gif Walk4.gif Walk5.gif Walk6.gif Walk7.gif Walk8.gif Walk9.gif

Step by Step Approach

Step 1: Make the figure appear


from graphics import *
W = 800
H = 600

class StickFig:
    def __init__( self, x, y ):
        self.index = 0   # frame index
        self.image = Image( Point( x, y ), "walk0.gif" )

    def draw( self, win ):
        self.image.draw( win )
        
    def move( self, dx ):
        return


def main():
    global H, W
    win = GraphWin( "Stick Figure", W, H )
    
    stick = StickFig( W/4, H/2 )
    stick.draw( win )

    win.getMouse()
    win.close()


main()



Step 2: Make figure walk

  • Note: we capture the graphics window win in draw() so that we can draw a new image in the move() method. We could also have passed win to move, but it's less logical if we do so...


from graphics import *
W = 800
H = 600

class StickFig:
    def __init__( self, x, y ):
        self.index = 0   # frame index
        self.image = Image( Point( x, y ), "walk0.gif" )

    def draw( self, win ):
        self.win = win
        self.image.draw( win )
        
    def move( self, dx ):
        x = self.image.getAnchor().getX()
        y = self.image.getAnchor().getY()
        self.image.undraw()
        self.index = (self.index+1) % 10
        self.image = Image( Point( x+dx, y ), "walk%d.gif" % self.index )
        self.image.draw( self.win )


def main():
    global H, W
    win = GraphWin( "Stick Figure", W, H )
    
    stick = StickFig( W/4, H/2 )
    stick.draw( win )

    while True:
        stick.move( 3 )
        if win.checkMouse() != None:
            break
        
    win.getMouse()
    win.close()


main()


Step 3: remove flicker


from graphics import *
W = 800
H = 600

class StickFig:
    def __init__( self, x, y ):
        self.index = 0   # frame index
        self.image = Image( Point( x, y ), "walk0.gif" )

    def draw( self, win ):
        self.win = win
        self.image.draw( win )
        
    def move( self, dx ):
        x = self.image.getAnchor().getX()
        y = self.image.getAnchor().getY()
        # keep track of the old image
        tempImage = self.image

        # draw a new image
        self.index = (self.index+1) % 10
        self.image = Image( Point( x+dx, y ), "walk%d.gif" % self.index )
        self.image.draw( self.win )

        # erase the old image (this avoids the flicker)
        tempImage.undraw()


def main():
    global H, W
    win = GraphWin( "Stick Figure", W, H )
    
    stick = StickFig( W/4, H/2 )
    stick.draw( win )

    while True:
        stick.move( 3 )
        if win.checkMouse() != None:
            break
        
    win.getMouse()
    win.close()


main()


Step 4: Wrap Around Edges


from graphics import *
W = 800
H = 600

class StickFig:
    def __init__( self, x, y ):
        self.index = 0   # frame index
        self.image = Image( Point( x, y ), "walk0.gif" )

    def draw( self, win ):
        self.win = win
        self.image.draw( win )
        
    def move( self, dx ):
        global W, H
        x = self.image.getAnchor().getX()
        y = self.image.getAnchor().getY()

        # make figure "wrap around edge of window"
        if x > W + self.image.getWidth():
            dx = -W -self.image.getWidth()
        # keep track of the old image
        tempImage = self.image

        # draw a new image
        self.index = (self.index+1) % 10
        self.image = Image( Point( x+dx, y ), "walk%d.gif" % self.index )
        self.image.draw( self.win )

        # erase the old image (this avoids the flicker)
        tempImage.undraw()


def main():
    global H, W
    win = GraphWin( "Stick Figure", W, H )
    
    stick = StickFig( W/4, H/2 )
    stick.draw( win )

    while True:
        stick.move( 3 )
        if win.checkMouse() != None:
            break
        
    win.getMouse()
    win.close()


main()


Step 5: A Group of Stick Figures


from graphics import *
W = 800
H = 600

class StickFig:
    def __init__( self, x, y, index=0 ):
        # if index is != 0, then the figure starts with a frame other than
        # the first one.  Prevents figures from having same behavior when
        # a group of them is on the screen.
        self.index = ( abs( index ) )%10  # frame index
        self.image = Image( Point( x, y ), "walk0.gif" )

    def draw( self, win ):
        self.win = win
        self.image.draw( win )
        
    def move( self, dx ):
        global W, H
        x = self.image.getAnchor().getX()
        y = self.image.getAnchor().getY()

        # make figure "wrap around edge of window"
        if x > W + self.image.getWidth():
            dx = -W -self.image.getWidth()
        # keep track of the old image
        tempImage = self.image
 
        # draw a new image on top of old one
        self.index = (self.index+1) % 10
        self.image = Image( Point( x+dx, y ), "walk%d.gif" % self.index )
        self.image.draw( self.win )
        
        # erase the old image (this avoids the flicker)
        tempImage.undraw()
        


def main():
    global H, W
    win = GraphWin( "Stick Figure", W, H )

    sticks = []
    for i in range( 4 ):
        stick = StickFig( W/4, (i+1)*H / 5, i*3 )
        stick.draw( win )
        sticks.append( stick )

    while True:
        for stick in sticks:
            stick.move( 10 )
            
        if win.checkMouse() != None:
            break
        
    win.getMouse()
    win.close()


main()


Step 6: Forward and Backward


from graphics import *
import random

W = 800
H = 600

class StickFig:
    def __init__( self, x, y, index=0 ):
        self.index = ( abs( index ) )%10  # frame index
        self.image = Image( Point( x, y ), "walk0.gif" )

    def draw( self, win ):
        self.win = win
        self.image.draw( win )
        
    def move( self, dx=5 ):
        global W, H
        dx = dx + random.choice( [-1, -2, 1, 2 ] )
        x = self.image.getAnchor().getX()
        y = self.image.getAnchor().getY()

        # make figure "wrap around edge of window"
        if x > W + self.image.getWidth():
            dx = -W -self.image.getWidth()
        elif x < -self.image.getWidth():
            dx = +W +self.image.getWidth()
        # keep track of the old image
        tempImage = self.image
 
        # draw a new image on top of old one
        if dx > 0:
            self.index = (self.index+1) % 10
        else:
            self.index = (self.index-1) % 10
        self.image = Image( Point( x+dx, y ), "walk%d.gif" % self.index )
        self.image.draw( self.win )
        
        # erase the old image (this avoids the flicker)
        tempImage.undraw()
        


def main():
    global H, W
    win = GraphWin( "Stick Figure", W, H )

    sticks = []
    for i in range( 4 ):
        stick = StickFig( W/4, (i+1)*H / 5, i*3 )
        stick.draw( win )
        sticks.append( stick )

    while True:
        for i,stick in enumerate( sticks ):
            if i==0:
                stick.move( -5 )
            else:
                stick.move()
            
        if win.checkMouse() != None:
            break
        
    win.getMouse()
    win.close()


main()



A Possible Finished Version

# Animation.py
# D. Thiebaut
# Demonstrates how to use the frames of a gif file to do simple
# animation with Zelle's python module.
#
from graphics import *
import time
import random


class Walker:
    """A class for the stick figure.  It uses 10 frames of a gif file, all
    defined by a gif image of the form walk30_n.gif, where n is 0 to 9.
    The walker can go forward or backward, and will use the correct
    sequence of frames.  The walker can also be instantiated to start
    at a given frame."""
    def __init__( self, x, y, index=0 ):
        self.current = index
        self.image = None
        self.x  = x
        self.y  = y
        
    def move( self, dx, dy ):
        """move the walker by dx dy on the window and select
        a new frame/image automatically"""
        x, y = self.x, self.y
        if self.image != None:
            x = self.image.getAnchor().getX()
            y = self.image.getAnchor().getY()
            self.image.undraw()

        # decide which image to pick depending on direction
        if dx > 0:
            self.current = ( self.current + 1 ) % 10
        else:
            self.current = ( self.current + 10 - 1 ) % 10            

        self.image = Image( Point( x+dx, y+dy ),
                            "walk30_%d.gif" % self.current )
        self.image.draw( self.win )

    def draw( self, win ):
        """draw the stick figure on the window"""
        self.win = win
        if self.image == None:
            self.image = Image( Point( self.x, self.y ),
                            "walk%d.gif" % self.current )
            self.image.draw( win )
                            
                            

def justOne():
    """animates just 1 stick figure on the screen"""
    W = 800
    H = 600
    win = GraphWin( "walker", W, H )
    
    walker = Walker( W/2, H/ 2 )
    walker.draw( win )
    
    while True:
        walker.move( 5, 0 )
        time.sleep( 0.2 )

    win.getMouse()
    win.close()

def several( n ):
    """animate several stick figures on the screen"""
    W = 800
    H = 600
    win = GraphWin( "walker", W, H )

    walkers = []
    for i in range( n ):
        walkers.append( Walker( W/2, 140 * i + 70, (i*2)%10 ) )

    for walker in walkers:
        walker.draw( win )
    
    while True:
        for i, walker in enumerate( walkers ):
            if i == 0:
                walker.move( -5, 0 )
            else:
                walker.move( 5+random.choice( [0,1,2,3] ), 0 )

    win.getMouse()
    win.close()

def main():
    #justOne()
    several( 4 )
                        
main()