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:
- Practice working with loops
- Practice working with if statements
- 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
Hints!
- Use a loop
- 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 thatcloud_counter variable as the basis of your tag! - 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
- Make a new function called
storm_cloud
to make storm clouds! - Make a new function called
realistic_cloud
to make more realistic clouds! - 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…
- Find the function call in the body of
creature
that creates the shape. For instance, you might see a call to theoval
function.
oval(center=(450,450), radius_x=50, radius_y=100, color="green")
- The new version of the
oval
function included incs110_hw5
supports an input calledtag
that allows you to give that shape a tag.
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")
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")
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
'''
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…
- Animate creature tagged
"creature_1"
so that it moves across the screen smoothly from left to right. - 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.
- 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!
- To reset the creatures position, you need to use a conditional to check the creatures's position each time it moves.
- To find the left-most or right-most x-coordinate of a tagged object, you can use the
get_left
andget_right
functions. - 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... - 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... - 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!- Make the creatures accelerate over time (start off slow and gradually move faster)
- Use loops and the random module to make many moving creatures.
- 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!