CS 107: Pictures and Sounds: Programming with Multimedia

Kalamazoo College

Winter 2009

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,1,1)
      repaint(canvas)
      time.sleep(toSleep)

  1. Copy the playMovie function into your .py file, and test it 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 range1(1, getWidth(canvas) - rectSize, 3):
        copyPictureInto(pict, canvas, 1, 1)
        addRectFilled(canvas, x, 10, rectSize, rectSize, white)
        copyOfCanvas = duplicatePicture(canvas)
        picArray[count] = copyOfCanvas
        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.

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 modified Recipe #107, slowFadeOut to JES. This function has been modified so that it 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 or you may use the files wallQtrSize.jpg, jungle2QtrSize.jpg and wall2PeopleQtrSize.jpg from the cls_compsci/cs107/Pictures directory on dragon.
    # Lab 8: Recipe 107 - Slow Fadeout modified to use an array
    # and have the original background, the new background and 
    # the original picture as 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.
    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 Recipe from book with a threshold
    def swapbg(person, bg, newbg, threshold):
    
      # get all pixels in the picture and their colors
      for x in range(1, getWidth(person) + 1):
        for y in range(1, getHeight(person) + 1):
          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 Recipe #106, slowsunset, so that it saves the new pictures in an array, and then returns that array. Modify the function to have a picture as the only parameter and only loop through 20 times. Also, modify makeSunset to multiply by 0.8 instead of by 0.99. When you call the function, use the file beach-smaller.jpg to save time.

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.

Print your results

  1. When you are finished, show your results to your instructor or a TA.

  2. Print the functions you created in this lab and hand them in.