Project 4: Turtle race

In this project, you will practice creating objects that have unique roles and properties. You will be making a scene where two turtles are racing each other in a race course that you design. Aside from the Screen object, you will create different Turtle objects, each of whom perform different roles:

Extension points are awarded for complex scenes, especially those that show me that you can integrate concepts from lecture into making your scenes and take things to the next level!


Tasks

0. Design your race course

Decide on the shape of your race course. It doesn't need to be fancy. Keep in mind that your turtles will need to be able to go around the race course multiple times (i.e. to complete "laps"). Some ideas are:

1. Create object_shapelib.py

Just like better_shapelib from last week, object_shapelib.py will contain all your functions that draw shapes and the race scene. You're welcome to add as much complexity as you would like, but minimally it should contain the following functions.

For full credit, all these functions should only use a Turtle object to do the drawing. I should not see turtle.<blah> anywhere, except on the line where you create your Turtle object!

1a. goto function

Copy-and-paste the goto function that you have from better_shapelib, and update it to have the function signature:

def goto(turt, x, y, heading=0):

Do the following:

1b. Create functions that you need to draw your race track scene

The ones you need depend on your race track design and your concept for your race scene. For example, if you were using a circular track, you might use a circle function to draw the racing lanes (e.g. their outlines, fill, inner and outer lane dividers, road markers, etc.):

def circle(turt, x, y, radius, penWidth=3, fill=True, fillColor='brown'):

Keep it simple! You can always add complexity later. At minimum, each of your shape functions should have:

Feel free to copy-and-paste and adapt code from previous projects!

1c. draw_race_scene

This is the function that should draw your race track scene. It does NOT need to have (x, y, scale) parameters — I suggest only putting in the work to do this if you plan to take advantage of repositioning and scaling your scene as part of a larger extension.

Here is an overview of what the draw_race_scene function should do:

1d. Test your race track scene

Copy-and-paste your make_screen function from lab into object_shapelib.py.

Add main code to if __name__ == '__main__': in object_shapelib.py to test out your race scene. It should make a Screen object and draw your race scene.

Run object_shapelib.py to produce your race scene. Take a screenshot — this is Required Image 1 in your project report.


2. Create race.py

This file will place your turtles in their racing lanes and have them race. The following subtasks walk you through the general setup.

2a. Copy over make_turtle from lab into race.py

Call this function when you need to create a Turtle object.

2b. Make a main function

Your function should:

Important notes:

Add a if __name__ == '__main__': statement in race.py that calls your main function.

If you run your code now, you should see your racing scene drawn on the screen and your two racing turtles should show up at the starting line in their respective lanes.

2c. Create the move_turtle function

Each racing turtle will move at a different speed, which means that you move them speed units on each time step of your simulation (e.g. in a loop coming up later). The move_turtle function should have one of your turtles (turt) take one "step" (the size of step is speed) and should have a signature that looks like:

def move_turtle(turt, speed):
    '''Moves the `Turtle` object `turt` `speed` units
    '''

Feel free to customize the parameters to suit your race course concept.

Hint (if using a circular course): The turtle circle method has a keyword argument that allows you to specify how much of a circle (angle) that you want to move around.

2d. Move your racing turtles around the track

After the code that you have already written in main, move each of the racing turtles 1000 times. Give Turtle 1 a speed of 5 and Turtle 2 a speed of 4.9.

If you run your code, you should see each turtle move around the track (not deviating from it). Turtle 1 should complete laps faster than Turtle 2.

Hint: If your race course requires the turtles or go back-and-forth or turn corners, you will need to change their heading after they move a certain distance or reach the end of the screen.


3. Race!

Make the race more interesting by adding the following elements.

3a. Randomly jitter each racing turtle's speed

Every time that you move one of the turtles, randomly shift its speed by at most ±1\pm1 unit.

3b. Keep score

Create variables to keep track of each turtle's "score": how many laps each turtle has completed.

Detect when a turtle completes a lap, increment the appropriate turtle's score, and display the updated score on the screen (somewhere in your scene). You may repurpose any relevant code from lab.

Take a screenshot of your final race scene in action (showing two turtles racing on your track with their scores shown). This is Required Image 2 to be included in your report.


Check reproducibility

In order to grade your project, we need to be able to run your code and get the same results as you do! Here is a summary of the expected outputs from each of the source code files that you created:

If you use command-line arguments in an extension, explain what they are and provide an example way to run your code in both code comments and your report.


Extensions

Congratulations on completing the core tasks! If your code and report meet the above expectations, you’ve already earned up to 26/30 points for this project.

The remaining 4/30 are a chance for you to earn credit for exploring parts of this project and digging deeper to express your creativity! This is entirely optional; 26/30 is a B and is a perfectly respectable place to stop. Extensions are open-ended and exist to compliment the structured core project. Explore and learn something new that interests you! Concentrating your energy on 1-2 "deep" extensions that challenge you will earn you more points than many small, "shallow" extensions.

You can pick your own topics that interest you. Here are a few examples:

  1. Creative or complex scenes above and beyond the basic expectations count as extensions.
  2. Make the animation of your turtles making the collage from lab look more like code rain. Some ideas are to draw letters and numbers rather than turtle shapes, randomize which letters or numbers are drawn, have the "stamps" disappear after each the turtle has moved a certain number of times.
  3. Learn about lists and use them to improve the conciseness of your code.
  4. Add additional racing turtles.
  5. Design a more complex race track shape (e.g. a spiral, maze, etc.)
  6. Designate a winning turtle: the first turtle to complete N laps. Analyze how differences in the turtle speeds and the amount of randomness influences the chance that they win.
  7. Related to the previous extension, learn about the Gaussian distribution and use it to generate the random variations in the turtle speed. Analyze how factors related to how randomness is created influences the chance that either turtle wins.
  8. Make it so that you can position and scale your race scene. Do something interesting that takes advantage of this.
  9. Create a new scene and/or scenario that involves multiple Turtle objects in an interesting way.

Submission checklist

To turn in your project, make sure you do all of the following:

© 2020 Oliver Layton - modified by Naser Al Madi