Introduction
The objective of this lab is to become familiar with using lists in animations. (The heart of this lab is Part 2.)
Part 1: Using Lists to Display an Animation
We are going to experiment with another method for viewing animations. Up until this point, we have been repeatedly copying the background onto the canvas, calculating where we want to put some type of object or objects, copying them onto the canvas, and then showing the canvas. The disadvantage of this approach is that the rate the animation is displayed is impacted by the time spent setting up the canvas. An alternative is to set up all of the individual frames of our animation in advance, then show the animation by looping through the completed frames. The following function takes a list of pictures as a parameter, along with a frame rate, and displays the pictures as an animation:#---------------------------------------------------------------------- #playMovie - Play a list of pictures as a movie. #movie - A list of pictures. #frameRate - The number of frames that should be displayed per second. # Higher numbers will result in faster animations. #---------------------------------------------------------------------- def playMovie(movie, frameRate): import time canvas = duplicatePicture(movie[0]) toSleep = max(1.0/frameRate, 0) for index in range(len(movie)): if isinstance(movie[index], Picture): copyPictureInto(movie[index],canvas,0,0) repaint(canvas) time.sleep(toSleep)
- Copy the
playMovie
function into your .py file, and copy the function copyPictureInto from the Support Code. - Functions for setting up full animations will look very
similar to the animation functions we have been writing all along.
The only difference is that instead of displaying each frame in the
function, we will place the frames in a list. Copy the following
code and run the function in JES. The function returns a list of
pictures that can be passed to
playMovie
. (The explanation of what is happening is below.)def moveRectInLine(): canvas = makeEmptyPicture(300,300, red) rectSize = 20 # Set up a list and initialize it to all zeros picList = [0] * getWidth(canvas) count = 0 # Create the new pictures and save them in the list for x in range(0, getWidth(canvas) - rectSize, 10): addRectFilled(canvas, x, 10, rectSize, rectSize, white) copyOfCanvas = duplicatePicture(canvas) picList[count] = copyOfCanvas addRectFilled(canvas, x, 10, rectSize, rectSize, red) count = count + 1 return picList
- So what did we do?
- We first created an empty picture and specified the size of the box.
- We then set up a list, called
picList
, to be all zeros. The list was set up to begetWidth(pict)
elements long because that is the upper limit on how many times the box might move horizontally. - We set up a variable called
count
that keeps track of how many pictures have been added to the list. - In the loop that does the moving, we "painted" the rectangle on the canvas, then saved a copy of the canvas in the list at the next available index.
- We then "erased" the rectangle that was moving and incremented the count by 1.
- Finally, we returned the resulting list.
- Optional: Modify your function to move a box along the diagonal so that it saves all the pictures in a list first, and then returns the list.
Part 2: Colors and Animations
So far in our animations, we have only seen how to move objects on a canvas. In this section, we will experiment with a sunset animation and a fadeout animation.- Copy the following program,
slowFadeOut
, to JES. This function saves the new pictures in a list, and then returns the list.
This function takes a long time to process so you should run it on small files. You may use functions you have written previously to make your own files smaller.# Slow Fadeout # The original background, the new background and # the original picture are the parameters. # Be sure to try this out with small pictures! #PARAMETERS: # background - a picture of an empty background. # newBackground - a picture of some other scene that will become the # new background. # person - A picture that matches background, with the addition of a # person (or other object). def slowFadeOut(background, newBackground, person): # Set up a list and initialize it to all zeros picList = [0] * 10 count = 0 # Only 10 frames or it takes too long for threshold in range (1, 101, 10): canvas = duplicatePicture(person) printNow("Frame number: " + str(count)) swapbg(canvas, background, newBackground, threshold) #copy the picture into the list copyOfCanvas = duplicatePicture(canvas) picList[count] = copyOfCanvas count = count + 1 return picList # Swap Background Program with a threshold of closeness for colors def swapbg(person, bg, newbg, threshold): # get all pixels in the picture and their colors for x in range(getWidth(person)): for y in range(getHeight(person)): personPixel = getPixel(person, x, y) personColor = getColor(personPixel) bgpx = getPixel(bg, x, y) bgColor = getColor(bgpx) # check if the difference in color is within the threshold if (distance(personColor, bgColor) < threshold): # if so, change the color to the new background's color bgcolor = getColor(getPixel(newbg, x, y)) setColor(personPixel, bgcolor)
- Modify the following program,
slowSunset
, so that it creates a list of all zeros, saves the new pictures in this list, and then returns the list. You will need to copy themakeSunset
function from the notes on Pictures and Loops. ModifymakeSunset
to multiply by 0.8 instead of by 0.70. When you call the function, use a small file, such as the file beach-smaller.jpg file from the MediaSources directory to save time.def slowSunset(picture): count = 0 canvas = duplicatePicture(picture) show(canvas) # Only 10 frames or it takes too long for x in range (1, 101, 10): printNow("Frame number: " + str(count)) canvas = makeSunset(canvas) repaint(canvas) count = count + 1
Submit your results
- Submit the file you created in this lab to Kit.