In this homework assignment, you’ll be moving from making “static” pictures like in Ex 2 and Ex 3, to making live animations! Make sure to complete Tutorial 4 before attempting this homework. While in Tutorial 4, we had to manually delete our drawing at every step, in this assignment we’ll use the move function to make our lives a little easier.

LEARNING OBJECTIVES:

  1. Practice working with loops
  2. Practice working with if statements
  3. Practice working with modules

Note there are a number of functions in helper file that you can use but you only have to use move and cloud. You should not use any function that starts with an underscore. These are called “private functions” and are ONLY meant for use within that one particular file. In fact…don’t bother opening the .py file. Instead, you can click on the dope purple button below and see all the functions you have available to you and their documentation!

Exercise Starter File Exercise Module File Module Documentation (Link)

You need to make sure they are BOTH in the same folder (but you will only submit the exercise_5.py file.)


Part 1. Landscapes

In the module file you’ve downloadedt here’s a cloud function that accepts the following inputs:

'''
Name: cloud
Purpose: reporter function that draws a cloud to the screen.

Args:
    center (`tuple`): the point on which to center the cloud
    size (`int`): how big (roughly) the cloud is drawn
    color (`str`): which determines the color of the cloud
    tag (`str`): to give the cloud a name

Returns:
    `Shape`: The cloud that was created.
'''

In your exercise_5.py, find the setup function’s body. In it, you’ll find a call to a function called draw_clouds with an input of 30 which is right above setup. In it, you’ll see the cloud function called several times (which is repetitive). Your job is to rewrite the draw_clouds function using a loop (any kind of loop you want) which makes however many clouds is specified by the argument num_clouds, at the top portion of the screen. Each cloud must have a unique tag that cannot start with a number I recommend "cloud_0", "cloud_1", etc.. To randomly place the clouds you can use the randint function like in our previous exercise, but you can only import randint from the random module; no other functions in that module can be imported.

Hints!
  1. Use a loop
  2. To generate a unique tag, consider starting a variable called cloud_counter and making sure to add one to it every time you make a new cloud. Use that cloud_counter variable as the basis of your tag!
  3. remember the y-axis is flipped which means you'll use y-values CLOSE TO 0 because that will representative of the TOP of the screen.
Optional Enhancements
  1. Make a new function called storm_cloud to make storm clouds!
  2. Make a new function called realistic_cloud to make more realistic clouds!
  3. Animate your clouds

Part 2. Make Creature from Exercise 3 Animatable

Scroll through exercise_5.py until you see the section labeled: #### PUT YOUR CREATURE BELOW HERE ####.

Note: This assumes that your creature function worked correctly from Exercise 3. If it did not, we encourage you to go to office hours to get it working!

Now, copy and paste your function definition for creature from Exercise 3 into this space.


Adding a tag to your creature

Like in the tutorial this week, we’re going to encounter a problem: if we don’t tell python what shapes constitute a more compound shape (e.g. mario, your creature, etc.) it has no idea that they are connected.

We’ll rely on there being a tag (str) for each compound shape (i.e. shape group) in the window. You can think of it as a “name” for the shapes that make up your creature. If you wanted to make the individual shapes that make up your creature animate separately, each one would need a separate name. In this assignment, we want to animate all of the parts of our creature at once so we’re going to simplify the process a little by giving all of the constituent shapes in our creature the same tag. To do this, you’ll need to do the following:


Step 1

First, we need to add a new optional parameter to our creature function. Let’s call it tag and have it default to an empty string ("").


Step 2

Now comes the hard part. We need to go to each shape that makes up your creature and make sure it gets assigned a tag. The process of adding this tag depends on what sorts of shape you drew for each of your feature creatures. For each shape that makes up your creature…

oval(center=(450,450), radius_x=50, radius_y=100, color="green")
oval(center=(450,450), radius_x=50, radius_y=100, color="green", tag=some_value_thats_a_string)

Note, you don’t want to set that to one specific string…you want to set it to some string that’s specified when the function is called.

Example Say we had the following function:
def creature(center, size=25):
    big_square_width = size
    center_x = center[0]
    center_y = center[1]
    # face
    square(top_left=(center_x - size / 2, center_y - size / 2),
           size=width,
           color="green")
    # right eye
    square(top_left=(center_x - size / 3, center_y + size / 6),
           size=big_square_width / 6,
           color="purple")
    # left eye
    square(top_left=(center_x + size / 6, center_y + size / 6),
           size=big_square_width / 6,
           color="white")
    # nose
    square(top_left=(center_x - size / 60, center_y - size / 60),
           size=width / 30,
           color="white")
First we add the new tag parameter to creature:
def creature(center, size=25, tag=""):
    big_square_width = size
    center_x = center[0]
    center_y = center[1]
    # face
    square(top_left=(center_x - size / 2, center_y - size / 2),
           size=width,
           color="green")
    # right eye
    square(top_left=(center_x - size / 3, center_y + size / 6),
           size=big_square_width / 6,
           color="purple")
    # left eye
    square(top_left=(center_x + size / 6, center_y + size / 6),
           size=big_square_width / 6,
           color="white")
    # nose
    square(top_left=(center_x - size / 60, center_y - size / 60),
           size=width / 30,
           color="white")
Then we tackle the constituent shapes. Since my creature is relatively simple, I just need to go through each square, and label it with whatever tag someone has asked me to use!
def creature(center, size=25, tag=""):
    big_square_width = size
    center_x = center[0]
    center_y = center[1]
    # face
    square(top_left=(center_x - size / 2, center_y - size / 2),
           size=width,
           color="green",
           tag=tag)
    # right eye
    square(top_left=(center_x - size / 3, center_y + size / 6),
           size=big_square_width / 6,
           color="purple",
           tag=tag)
    # left eye
    square(top_left=(center_x + size / 6, center_y + size / 6),
           size=big_square_width / 6,
           color="white",
           tag=tag)
    # nose
    square(top_left=(center_x - size / 60, center_y - size / 60),
           size=width / 30,
           color="white",)
           tag=tag)

Part 3. Instantiate (draw) your Creatures

In the setup function, below your clouds, call your newly improved creature function twice. The first creature needs to be in the bottom left hand portion of the screen and must have the tag "creature_1". The second creature needs to be in the bottom right hand portion of the screen and must have the tag "creature_2". Make sure to use different colors, sizes, etc., for the two creature calls like my two cars in the below screenshot.


Part 4. Animate your Creatures

In the tutorial you had to manually delete Mario, then redraw him in a new place to move him across the screen. For the exercise, since we don’t need to “change” the version of the creature you’re drawing each time–just update its position–we can make this process a little simpler. Rather than doing the two step process of ERASE and DRAW, in this exercise you can move your creature by using the move function.

'''
Name: move
Purpose: Move the x and y position of all shapes that have been tagged
with the tag argument

Args:
    shape (`Shape` or Tag): The shape in question.
    x_shift (`int`; optional): amount to move in the x direction
    y_shift (`int`; optional): amount to move in the y direction
'''

That means to move, say, an object tagged "mario" 10 units in the x direction we’d just say:

move("mario", x_shift=10)

Find the function definition called go near the bottom of the file. This is a function that is called using a while loop all the way at the bottom of the file. You can assume two things about this function: 1. it is continuously called when your program runs (i.e. once go finishes…it gets called again without any intervention on your part!); 2. there exists a global variable called ticks that counts how many times the go function has been called that you can use anywhere in your go function if you’d like.

Your job for this task is to…

  1. Animate creature tagged "creature_1" so that it moves across the screen smoothly from left to right.
  2. If the creature gets to the end of the screen, it should seamlessly be moved (i.e. don't make a new one) to the beginning of the screen.
  3. Animate the creature tagged "creature_2" opposite direction, and also loops back around when it gets to the end of the screen (see the video below where I use a car as my creature)
Hints!
  1. To reset the creatures position, you need to use a conditional to check the creatures's position each time it moves.
  2. To find the left-most or right-most x-coordinate of a tagged object, you can use the get_left and get_right functions.
  3. If you need to find the width of your object...get this...there's a function called get_width. Now why might that be useful...
  4. In order to "reset" each creature once they go off the screen, you can still use move. The screen is 800 pixels wide but note that your creature also has a width...
  5. If you find only PART(s) of your creature moving but not others, it means you missed tagging one of the shapes earlier! Double check you've tagged all those shapes!
Optional Enhancements The more you practice, the better you'll get!
  1. Make the creatures accelerate over time (start off slow and gradually move faster)
  2. Use loops and the random module to make many moving creatures.
  3. Animate your clouds

What to Submit

If your program is working correctly, you should see something like the above linked video. Make sure to submit ONLY your exercise_5.py file to Canvas by the deadline.


Submission Details

Remember, close IDLE before you submit to ensure that you’ve saved your latest work. Once you’ve successfully submitted you should receive feedback from the autograder in 30 or so minutes. If you fail one of the checks, you’re welcome to resubmit (up to the Canvas resubmit limit for that assignment). If you’re confused on how to fix one of the checks, then bring your submission and the test results to office hours!

Submission FAQ
Late Penalty Waiver