Lab 8: Animations

 


Introduction

The objective of this lab is to become familiar with using arrays, color functions, and sounds in animations.



Part 1: Using Arrays 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. This is similar to what is done in the textbook, where each picture in the sequence is saved as a new JPEG file. The following function takes an array 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/array 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)

  1. Copy the playMovie function into your .py file, and copy the function copyPictureInto from the Support Code, and test playMovie by setting up a short movie by hand. Just create an array that contains three pictures that are the same size:
    >>>pics = [0] * 3 #notation for creating an array containing three 0's
    >>>pics[0] = makePicture(pickAFile())
    >>>pics[1] = makePicture(pickAFile())
    >>>pics[2] = makePicture(pickAFile())
    
    Try playing your very short movie with different values for the frame rate.

  2. 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 an array. Copy the following code and run the function in JES. The function returns an array of pictures that can be passed to playMovie. (The explanation of what is happening is below.)
    def moveRectInLine():
      canvas = makeEmptyPicture(300,300, red)
      pict = duplicatePicture(canvas)
      rectSize = 20
    
      # Set up an array and initialize it to all zeros
      picArray = [0] * getWidth(pict)
      count = 0
    
      # Create the new pictures and save them in the array
      for x in range(0, getWidth(canvas) - rectSize, 3):
        addRectFilled(canvas, x, 10, rectSize, rectSize, white)
        copyOfCanvas = duplicatePicture(canvas)
        picArray[count] = copyOfCanvas
        addRectFilled(canvas, x, 10, rectSize, rectSize, red)
        count = count + 1
      return picArray
    
    

  3. So what did we do?

  4. Modify your function to move a box along the diagonal so that it saves all the pictures in an array first, and then returns the array.

    OR

  5. Modify your chromakey animation function so that it saves all the pictures in an array first, and then returns the array.

  6. To learn how to save this list of pictures to a set of files, see Final Programming Project Tips. Try to save one of your lists of pictures to your computer. (You do not need to save these pictures on your computer once you have figured out how to do this, unless you think you will need them later.)

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.

  1. Copy the following program, slowFadeOut, to JES. This function saves the new pictures in an array, and then returns the array. 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 an array and initialize it to all zeros
      picArray = [0] * 20
      count = 0
    
      # Only 20 frames or it takes too long
      for threshold in range (1, 101, 5):
        canvas = duplicatePicture(person) 
        printNow("Frame number: " + str(count))
        swapbg(canvas, background, newBackground, threshold)
        #copy the picture into the array
        copyOfCanvas = duplicatePicture(canvas)
        picArray[count] = copyOfCanvas
        count = count + 1
      return picArray
    
    
    # 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)
    
    

  2. Modify the following program, slowSunset, so that it creates an array of all zeros, saves the new pictures in this array, and then returns the array. You will need to copy the makeSunset function from the notes on Pictures and Loops. Modify makeSunset 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 20 frames or it takes too long
      for x in range (1, 101, 5): 
        printNow("Frame number: " + str(count))
        canvas = makeSunset(canvas)
        repaint(canvas)
        count = count + 1
    

Part 3: Adding Sounds To Animations (OPTIONAL)

  1. Create a modified version of the playMovie function that takes a sound as well as an array of pictures as parameters. Your modified function should play the sound during the animation. If the sound is shorter than the animation, it should be repeated as often as necessary. You will need to figure out the duration of the sound, and use the time.clock() function to determine whether or not enough time has passed to play the sound again.

Submit your results

  1. Submit the file you created in this lab via .