Week 5, Wednesday: Graphics, Using Objects

review

graphics image

What is the algorithm for drawing this picture? How do we create the crescent moon using just Circle objects?

create graphics window
set background to black
for loop to create stars
  pick random x from 0->width
  pick random y from 0->height
  create Point(x,y)
  draw Point, color it white
create and draw a white circle
clone circle, draw it, move it a little, color it black

We did not talk about the clone() method last time. It is very useful for creating lots of similar objects, like eyes for a face. Most graphics objects (e.g., Points, Circles, Rectangles, Text) have a clone method that works like this:

p = Point(100,200)
radius = 50
c = Circle(p, radius)
c.setFill("red")
c2 = c.clone()

So c2 is an exact copy of c, but it is not drawn on the screen yet.

graphics, functions, and more methods

Let's create the program for this next picture together.

graphics image

First, create the sky, grass, and sun:

from graphics import *

def main():
  width = 600
  height = 400
  gw = GraphWin("pretty forest picture...", width, height)
  # sky
  gw.setBackground("lightblue")
  # grass
  grassheight = 0.75*height
  p1 = Point(0,grassheight)
  p2 = Point(width,height)
  grass = Rectangle(p1,p2)
  grass.setFill("green")
  grass.setOutline("green")
  grass.draw(gw)
  # sun
  sun = Circle(Point(width*.15,height*.1), width*.05)
  sun.setFill("yellow")
  sun.setOutline("yellow")
  sun.draw(gw)

  # wait for user input before ending program/closing window
  click = gw.getMouse()

Notice that I use variables for width and height, and all other variables, like grassheight and the sun's radius, depend on them. If I go back and change width and/or height, the rest of my program should adjust accordingly.

Now let's add a drawTree(grassheight,gw) call to the above, to draw just one tree in the window gw at the given grassheight. The function definition with pseudo code looks like this:

def drawTree(grassheight, window):
  get width of window
  pick random x from 0->width
  create a Point object at x,grassheight
  make other Point objects for the trunk (a Rectangle)
  and the tree top (a Circle?)
  pick a random shade of brown for the trunk
  pick a random shade of green for the tree top
  draw the trunk and the top in the window

It may be helpful to sketch the tree on paper, to see where the points for the trunk and the top should be, relative to the starting point at x,grassheight. You might also want to use randrange() to pick the tree width/height, so not all trees are the exact same size (later, we will call this drawTree() function from main, and we will want trees with different heights and widths).

Here's one possible algorithm for creating the trunk, given an initial point at x,grassheight:

pt = Point(x, grassheight)
pick random tree width
treeheight = 2*treewidth
p1 = pt.clone()
move p1 half a treewidth left
p2 = pt.clone()
move p2 half a treewidth right, and -treeheight up
create trunk using Rectangle(p1,p2)

random colors

Almost any color can be made by mixing various amounts of red, green, and blue light. The color_rgb(r,g,b) function allows you to create colors this way, varying the amounts of each color from none (0) to full-on (255). Here is some code to create random colors:

r = randrange(0,256)
g = randrange(0,256)
b = randrange(0,256)
mycolor = color_rgb(r,g,b)
c = Circle(...)
c.setFill(mycolor)

How would you change the above to get a random greenish color?

Below is the full drawTree() function. Make sure you understand how it works, and how it should be called from main().

def drawTree(grassheight, window):
  """create and draw a tree at given height, in window"""

  width = window.getWidth()
  x = randrange(0, width)
  pt = Point(x, grassheight)
  treewidth = randrange(width*.05, width*.15)
  p1 = pt.clone()
  p1.move(-treewidth/2, 0)
  treeheight = 2*treewidth
  p2 = pt.clone()
  p2.move(treewidth/2,-treeheight)
  trunk = Rectangle(p1, p2)
  trunk.setFill("brown")
  trunk.setOutline("brown")
  trunk.draw(window)
  p2.move(-treewidth/2,0) # center of tree top
  radius = treewidth*.9
  treetop = Circle(p2, radius)
  r = randrange(0,100)
  g = randrange(200,256)
  b = randrange(0,80)
  treecolor = color_rgb(r,g,b)
  treetop.setFill(treecolor)
  treetop.setOutline(treecolor)
  treetop.draw(window)