9. Drawing With Functions¶

We learned how to draw in How to Draw with Your Computer. In Lab 2: Draw a Picture we applied that to create our own drawing. We learned how to create functions in Creating Functions. In this chapter, we’ll combine all that knowledge to create our own drawing functions.

We’ll do that by expanding on the code you wrote for Lab 2: Draw a Picture.

To show you how, I’m going to start with a similar program and convert it to using functions.

First the original program:

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 import arcade SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, "Drawing with Functions") arcade.set_background_color(arcade.color.DARK_BLUE) arcade.start_render() # Draw the ground arcade.draw_lrtb_rectangle_filled(0, SCREEN_WIDTH, SCREEN_HEIGHT / 3, 0, arcade.color.AIR_SUPERIORITY_BLUE) # Draw a snow person # Snow arcade.draw_circle_filled(300, 200, 60, arcade.color.WHITE) arcade.draw_circle_filled(300, 280, 50, arcade.color.WHITE) arcade.draw_circle_filled(300, 340, 40, arcade.color.WHITE) # Eyes arcade.draw_circle_filled(285, 350, 5, arcade.color.BLACK) arcade.draw_circle_filled(315, 350, 5, arcade.color.BLACK) # Finish and run arcade.finish_render() arcade.run() 

Ok, it isn’t very fancy, but that will make this process easier to follow.

9.1. Make The main Function¶

After copying the code into Lab 3, we’ll create a main() function. Put everything in it, and call the main function.

Are those too many lines to indent? You can indent groups of lines by selecting them, and then hitting “tab”. If you want to un-indent a group of lines, hit shift-tab.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import arcade SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 def main(): arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, "Drawing with Functions") arcade.set_background_color(arcade.color.DARK_BLUE) arcade.start_render() # Draw the ground arcade.draw_lrtb_rectangle_filled(0, SCREEN_WIDTH, SCREEN_HEIGHT / 3, 0, arcade.color.AIR_SUPERIORITY_BLUE) # Draw a snow person # Snow arcade.draw_circle_filled(300, 200, 60, arcade.color.WHITE) arcade.draw_circle_filled(300, 280, 50, arcade.color.WHITE) arcade.draw_circle_filled(300, 340, 40, arcade.color.WHITE) # Eyes arcade.draw_circle_filled(285, 350, 5, arcade.color.BLACK) arcade.draw_circle_filled(315, 350, 5, arcade.color.BLACK) # Finish and run arcade.finish_render() arcade.run() # Call the main function to get the program started. main() 

After this, run your program and make sure it still works before proceeding. If it doesn’t work, stop and get help. Continuing will only make the problem harder.

9.2. Make The Drawing Functions¶

Next, pick an item to move to a function. Start with an easy one if you have it.

9.2.1. Grass Function¶

I chose grass to start withbecause it was only one line of code, and I wasn’t going to ever try to position it with an x, y coordinate.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 import arcade SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 def draw_grass(): """ Draw the ground """ arcade.draw_lrtb_rectangle_filled(0, SCREEN_WIDTH, SCREEN_HEIGHT / 3, 0, arcade.color.AIR_SUPERIORITY_BLUE) def main(): arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, "Drawing with Functions") arcade.set_background_color(arcade.color.DARK_BLUE) arcade.start_render() draw_grass() # Draw a snow person # Snow arcade.draw_circle_filled(300, 200, 60, arcade.color.WHITE) arcade.draw_circle_filled(300, 280, 50, arcade.color.WHITE) arcade.draw_circle_filled(300, 340, 40, arcade.color.WHITE) # Eyes arcade.draw_circle_filled(285, 350, 5, arcade.color.BLACK) arcade.draw_circle_filled(315, 350, 5, arcade.color.BLACK) # Finish and run arcade.finish_render() arcade.run() # Call the main function to get the program started. main() 

Test, and make sure it is working.

9.2.2. Snow Person Function¶

Now let’s take the more complex snow person and put it in a function.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 import arcade SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 def draw_grass(): """ Draw the ground """ arcade.draw_lrtb_rectangle_filled(0, SCREEN_WIDTH, SCREEN_HEIGHT / 3, 0, arcade.color.AIR_SUPERIORITY_BLUE) def draw_snow_person(): """ Draw a snow person """ # Snow arcade.draw_circle_filled(300, 200, 60, arcade.color.WHITE) arcade.draw_circle_filled(300, 280, 50, arcade.color.WHITE) arcade.draw_circle_filled(300, 340, 40, arcade.color.WHITE) # Eyes arcade.draw_circle_filled(285, 350, 5, arcade.color.BLACK) arcade.draw_circle_filled(315, 350, 5, arcade.color.BLACK) def main(): arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, "Drawing with Functions") arcade.set_background_color(arcade.color.DARK_BLUE) arcade.start_render() draw_grass() draw_snow_person() # Finish and run arcade.finish_render() arcade.run() # Call the main function to get the program started. main() 

But this draws the snowman only at one spot. I want to draw lots of snowmen, anywhere I put them!

To do this, let’s add an x and y:

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 import arcade SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 def draw_grass(): """ Draw the ground """ arcade.draw_lrtb_rectangle_filled(0, SCREEN_WIDTH, SCREEN_HEIGHT / 3, 0, arcade.color.AIR_SUPERIORITY_BLUE) def draw_snow_person(x, y): """ Draw a snow person """ # Draw a point at x, y for reference arcade.draw_point(x, y, arcade.color.RED, 5) # Snow arcade.draw_circle_filled(300 + x, 200 + y, 60, arcade.color.WHITE) arcade.draw_circle_filled(300 + x, 280 + y, 50, arcade.color.WHITE) arcade.draw_circle_filled(300 + x, 340 + y, 40, arcade.color.WHITE) # Eyes arcade.draw_circle_filled(285 + x, 350 + y, 5, arcade.color.BLACK) arcade.draw_circle_filled(315 + x, 350 + y, 5, arcade.color.BLACK) def main(): arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, "Drawing with Functions") arcade.set_background_color(arcade.color.DARK_BLUE) arcade.start_render() draw_grass() draw_snow_person(50, 50) # Finish and run arcade.finish_render() arcade.run() # Call the main function to get the program started. main() 

But that’s not perfect. If you’ll note, I added a dot at the x and y. The snowman draws way off from the dot, because originally I didn’t try to draw it at 0, 0. I need to recenter the snowman on the dot.

We need to re-center the shape onto the spot we are drawing. Typically you’ll need to subtract from all the x and y values the same amount.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import arcade SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 def draw_grass(): """ Draw the ground """ arcade.draw_lrtb_rectangle_filled(0, SCREEN_WIDTH, SCREEN_HEIGHT / 3, 0, arcade.color.AIR_SUPERIORITY_BLUE) def draw_snow_person(x, y): """ Draw a snow person """ # Draw a point at x, y for reference arcade.draw_point(x, y, arcade.color.RED, 5) # Snow arcade.draw_circle_filled(x, 60 + y, 60, arcade.color.WHITE) arcade.draw_circle_filled(x, 140 + y, 50, arcade.color.WHITE) arcade.draw_circle_filled(x, 200 + y, 40, arcade.color.WHITE) # Eyes arcade.draw_circle_filled(x - 15, 210 + y, 5, arcade.color.BLACK) arcade.draw_circle_filled(x + 15, 210 + y, 5, arcade.color.BLACK) def main(): arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, "Drawing with Functions") arcade.set_background_color(arcade.color.DARK_BLUE) arcade.start_render() draw_grass() draw_snow_person(150, 140) draw_snow_person(450, 180) # Finish and run arcade.finish_render() arcade.run() # Call the main function to get the program started. main() 

9.3. How To Animate A Drawing Function¶

We can animate our drawing if we want. Here are the steps.

9.3.1. Create An on_draw Method¶

Right now our program only draws our image once. We need to move all the drawing code in our main to an on_draw function. Then we’ll tell the computer to draw that over and over.

Continuing from our last example, our program will look like:

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 import arcade SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 def draw_grass(): """ Draw the ground """ arcade.draw_lrtb_rectangle_filled(0, SCREEN_WIDTH, SCREEN_HEIGHT / 3, 0, arcade.color.AIR_SUPERIORITY_BLUE) def draw_snow_person(x, y): """ Draw a snow person """ # Draw a point at x, y for reference arcade.draw_point(x, y, arcade.color.RED, 5) # Snow arcade.draw_circle_filled(x, 60 + y, 60, arcade.color.WHITE) arcade.draw_circle_filled(x, 140 + y, 50, arcade.color.WHITE) arcade.draw_circle_filled(x, 200 + y, 40, arcade.color.WHITE) # Eyes arcade.draw_circle_filled(x - 15, 210 + y, 5, arcade.color.BLACK) arcade.draw_circle_filled(x + 15, 210 + y, 5, arcade.color.BLACK) def on_draw(delta_time): """ Draw everything """ arcade.start_render() draw_grass() draw_snow_person(150, 140) draw_snow_person(450, 180) def main(): arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, "Drawing with Functions") arcade.set_background_color(arcade.color.DARK_BLUE) # Call on_draw every 60th of a second. arcade.schedule(on_draw, 1/60) arcade.run() # Call the main function to get the program started. main() 

Do this with your own program. Nothing will move, but it should still run.

9.3.2. Add Variable To Control Where We Draw Our Item¶

Next, we are going to create a variable inside of the on_draw function. This variable will hold our x value. Each time we call on_draw, we’ll change x so that it moves to the right.

  1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 import arcade SCREEN_WIDTH = 800 SCREEN_HEIGHT = 600 def draw_grass(): """ Draw the ground """ arcade.draw_lrtb_rectangle_filled(0, SCREEN_WIDTH, SCREEN_HEIGHT / 3, 0, arcade.color.AIR_SUPERIORITY_BLUE) def draw_snow_person(x, y): """ Draw a snow person """ # Draw a point at x, y for reference arcade.draw_point(x, y, arcade.color.RED, 5) # Snow arcade.draw_circle_filled(x, 60 + y, 60, arcade.color.WHITE) arcade.draw_circle_filled(x, 140 + y, 50, arcade.color.WHITE) arcade.draw_circle_filled(x, 200 + y, 40, arcade.color.WHITE) # Eyes arcade.draw_circle_filled(x - 15, 210 + y, 5, arcade.color.BLACK) arcade.draw_circle_filled(x + 15, 210 + y, 5, arcade.color.BLACK) def on_draw(delta_time): """ Draw everything """ arcade.start_render() draw_grass() draw_snow_person(on_draw.snow_person1_x, 140) draw_snow_person(450, 180) # Add one to the x value, making the snow person move right # Negative numbers move left. Larger numbers move faster. on_draw.snow_person1_x += 1 # Create a value that our on_draw.snow_person1_x will start at. on_draw.snow_person1_x = 150 def main(): arcade.open_window(SCREEN_WIDTH, SCREEN_HEIGHT, "Drawing with Functions") arcade.set_background_color(arcade.color.DARK_BLUE) # Call on_draw every 60th of a second. arcade.schedule(on_draw, 1/60) arcade.run() # Call the main function to get the program started. main()