Difference between revisions of "CSC111 Animating A Stick Figure"
(→A Possible Finished Version) |
|||
(11 intermediate revisions by the same user not shown) | |||
Line 30: | Line 30: | ||
[[Image:walk9.gif]] | [[Image:walk9.gif]] | ||
− | = | + | =Step by Step Approach= |
+ | ==Step 1: Make the figure appear== | ||
+ | |||
+ | <br /> | ||
+ | <source lang="python"> | ||
+ | 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() | ||
+ | </source> | ||
+ | <br /> | ||
+ | |||
+ | |||
+ | ==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... | ||
+ | <br /> | ||
+ | <source lang="python"> | ||
+ | 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() | ||
+ | |||
+ | </source> | ||
+ | <br /> | ||
+ | |||
+ | ==Step 3: remove flicker== | ||
+ | |||
+ | <br /> | ||
<source lang="python"> | <source lang="python"> | ||
+ | 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() | ||
+ | |||
+ | </source> | ||
+ | <br /> | ||
+ | |||
+ | ==Step 4: Wrap Around Edges== | ||
+ | |||
+ | <br /> | ||
+ | <source lang="python"> | ||
+ | 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() | ||
+ | |||
+ | </source> | ||
+ | <br /> | ||
+ | |||
+ | ==Step 5: A Group of Stick Figures== | ||
+ | |||
+ | <br /> | ||
+ | <source lang="python"> | ||
+ | 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() | ||
+ | |||
+ | </source> | ||
+ | <br /> | ||
+ | ==Step 6: Forward and Backward== | ||
+ | |||
+ | <br /> | ||
+ | <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" ) | ||
+ | |||
+ | 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() | ||
+ | |||
+ | </source> | ||
+ | <br /> | ||
+ | |||
+ | |||
+ | |||
+ | =A Possible Finished Version= | ||
+ | <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 45: | 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 51: | 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 61: | 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 70: | Line 422: | ||
def justOne(): | def justOne(): | ||
+ | """animates just 1 stick figure on the screen""" | ||
W = 800 | W = 800 | ||
H = 600 | H = 600 | ||
Line 84: | 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 90: | Line 444: | ||
walkers = [] | walkers = [] | ||
− | for i in range( | + | 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 108: | 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)
Contents
Original Image
Taken from www.eracewalk.com
Split into frames
- Use an online splitter, such as gifninja.com
Resulting 10 Gif Images
- Once split, the individual images are transformed into individual gif files, and reduced in size:
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()