Difference between revisions of "CSC111 Lab 7 2015"

From dftwiki3
Jump to: navigation, search
(Created page with "--~~~~ ---- <br /> <bluebox> In this lab you will play with a graphics library that will allow you to draw simple shapes on the screen. </bluebox> <br /> <br /> <br /> = Set...")
 
 
(55 intermediate revisions by the same user not shown)
Line 4: Line 4:
 
<br />
 
<br />
 
<bluebox>
 
<bluebox>
In this lab you will play with a graphics library that will allow you to draw simple shapes on the screen.
+
In this lab you will play with a graphics library.  A graphic library typically allows the user to draw simple shapes on the screen.  You will also write some boolean functions that will help you control the dynamic movement of objects on the screen. 
 +
The lab is different from the previous labs, as you must demonstrate that you have finished and implemented the different challenges before being allowed to submit your program on Moodle.  When your programs for the challenges work, demonstrate your solutions to the lab instructor (or the TA), who will instruct you about the Moodle submission.  '''You must submit your solution program to Moodle before 3/13 at 11:00 a.m.
 
</bluebox>
 
</bluebox>
 
<br />
 
<br />
 
<br />
 
<br />
 +
{|
 +
|style="width: 50%;"|
 +
__TOC__
 +
|style="width: 50%;"|
 +
[[File:TaxiCabCSC111.png|150px]]
 +
|}
 
<br />
 
<br />
  
Line 14: Line 21:
 
==Step 1: Download the graphics.py Library==
 
==Step 1: Download the graphics.py Library==
 
<br />
 
<br />
* Copy/Paste the code from this [[Zelle's Graphics.py for Python 3| page]] to Idle and save it in the directory where you will save your programs for Week 7, under the name '''graphics.py'''.
+
* Copy/Paste the code from this [[Zelle's Graphics.py for Python 3| page]] to Idle and save it in the directory where you will save your programs for Week 7, under the name '''graphics.py'''.
 +
<br />
 +
==Step 2: Testing your installation==
 +
<br />
 +
* With '''graphics.py'''  in your Idle window, simply click '''run''' to run the library.  Normally libraries are not run by themselves, but this library has its own test program to help users verify that the library is working properly.
 +
* If everything goes well, you should see this simple window appear on your screen:
 +
<br />
 +
<center>[[Image:ZelleGraphics1.png]]</center>
 +
<br />
 +
* Click a few times on the window and verify that the window responds by changing the color or size of various graphic objects.
 +
<br />
 +
 
 +
<!--center>
 +
[[Image:MacGraphicsSetup.png | 750px]]
 +
</center-->
 +
<br />
 +
<br />
 +
Graphics programs have to be run from Idle to work correctly, and need the graphics.py library distributed by Zelle, the author of our textbook.
 +
<br />
 +
<showafterdate after="20150311 12:00" before "20150601 00:00">
 +
<br />
 +
==Step 3: A simple Graphics Program==
 +
<br />
 +
* Create a new program and call it '''lab7.py'''. 
 +
* '''Important''': save your program in the same directory/folder where you saved the graphics.py library.
 +
*  Copy the code below in it.
 +
<br />
 +
::<source lang="python">
 +
# lab7.py
 +
# your name
 +
# draws a circle in a window that is 600x400.
 +
 
 +
from graphics import *
 +
 
 +
def main():
 +
    win = GraphWin("My Circle", 600, 400)
 +
    c = Circle(Point(50,50), 10)
 +
    c.draw(win)
 +
    win.getMouse() # Pause to view result
 +
    win.close()    # Close window when done
 +
 
 +
main()
 +
</source>
 +
<br />
 +
* Run the program.  Verify that you see a single circle in the graphic window.
 +
* Click with the mouse on the graphics window to close it.
 +
<br />
 +
==Step 4: Explanations==
 +
<br />
 +
* Observe the program from Step 3 above and recognize the main features:
 +
*# First we open a new graphic window on our desktop with the <tt>win = GraphWin( ... )</tt> statement.  600 and 400 define how wide and high the window will be.  "My Circle" is the title that will appear at the top of the window.
 +
*# Next, we create a circle ''object'' with the statement <tt>c = Circle( Point(50,50), 10 )</tt>.  '''This does not draw the circle.'''  It simply creates one in memory, centered on the point of coordinates 50, 50, with a radius of 10.
 +
*# Once the circle is created in memory, we make it appear on the graphic window with <tt>c.draw( win )</tt>.
 +
*# Finally, we wait for the user to click on the graphic window, and then close the window.
 +
<br />
 +
 
 +
==Step 5: Modifications ==
 +
<br />
 +
* Modify your program, so that it looks like the code shown below:
 +
<br />
 +
::<source lang="python">
 +
# lab7.py
 +
# your name
 +
# Uses graphics.py from Zelle
 +
#
 +
# This program displays a red circle, a label
 +
# and a rectangle.
 +
from graphics import *
 +
 
 +
def main():
 +
    #open the graphic window.
 +
    win = GraphWin( "Lab 7 Demo", 600, 400 )
 +
 
 +
    # create and draw a red circle
 +
    center = Point( 100, 100 )
 +
    circ = Circle( center, 30 )
 +
    circ.setFill( 'red' )
 +
    circ.draw( win )
 +
 
 +
    # add a label inside the circle
 +
    label = Text( Point( 100, 100 ), "red circle" )
 +
    label.draw( win )
 +
 
 +
    # create and draw a rectangle
 +
    rect = Rectangle( Point( 30, 30 ), Point( 70, 70 ) )
 +
    rect.draw( win )
 +
 
 +
   
 +
    win.getMouse() # Pause to view result
 +
    win.close()    # Close window when done
 +
 
 +
main()
 +
</source>
 +
<br />
 +
* The program uses 2 new objects: a rectangle, defined by its upper-left and bottom-right corners, and a label (text) that simply is a string of characters drawn at a given point on the screen.  The string is automatically centered around the given point.
 +
*Using this new bit of knowledge, can you generate the figure below?  Note that the graphics system used here can recognize many different colors, all defined by ''strings'', such as <font color="red">'red'</font> used above.  You can find all the available colors on this [http://cs.smith.edu/dftwiki/index.php/Tk_Color_Names page].
 +
<br />
 +
<center>[[Image:taxiCrude.png]]</center>
 +
<br />
 +
<br />
 +
 
 +
=Simple Animation: Moving a Ball on the Graphic Window=
 +
<br />
 +
* Create a new program similar to the one covered in Monday's lecture.
 +
<br />
 +
::<source lang="python">
 +
# Uses graphics.py from Zelle
 +
#
 +
# This program displays the basic elements of a program
 +
#
 +
from graphics import *
 +
 
 +
def main():
 +
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )
 +
 
 +
    # create and draw a red circle
 +
    center = Point( 100, 100 )
 +
    circ = Circle( center, 30 )
 +
    circ.setFill( 'red' )
 +
    circ.draw( win )
 +
 
 +
    # define the direction the circle will start moving in.
 +
    # 5 pixels to the right every move, and 0.25 pixels down
 +
    # every move.
 +
    dx = 5
 +
    dy = 0.25
 +
 
 +
    # as long as the mouse hasn't been clicked on the window
 +
    # keep on looping.
 +
    while win.checkMouse() == None:
 +
 
 +
        # move the circle in the current direction.
 +
        circ.move( dx, dy )
 +
 
 +
        # get the x and y of the center of the circle.
 +
        x = circ.getCenter().getX()
 +
        y = circ.getCenter().getY()
 +
 
 +
        # if the center is outside the right or left boundary,
 +
        # reverse the x direction of movement.
 +
        if  x > 600 or x < 0:
 +
            dx = -dx
 +
 
 +
   
 +
    # if we're here, it's because the the user clicked on the graphic window.
 +
    # we can close everything and quit.
 +
    win.close()   
 +
 
 +
main()
 +
 
 +
</source>
 +
<br />
 +
* Run the program.  Verify that the circle/ball bounces off the left and right boundaries of the window, but disappears down the bottom of the screen.    If the ball is moving too fast (it does run at various speeds depending on what computer you're running on), you may want to change the values assigned to dx and dy to these values:
 +
<br />
 +
::<source lang="python">
 +
dx = 0.025
 +
dy = 0.025
 +
</source>
 +
<br />
 +
* You can stop the program by clicking on the graphic window a couple of times.
 +
<br />
 +
<br />
 +
<!-- ----------------------------------------------------------------------------------------------- -->
 +
{| style="width:100%; background:silver"
 +
|-
 +
 +
==Challenge 1==
 +
|}
 +
[[Image:QuestionMark1.jpg|right|120px]]
 +
<br />
 +
* Modify your program so that it makes the ball bounce off the bottom and top boundaries of the window.
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<!-- ----------------------------------------------------------------------------------------------- -->
 +
{| style="width:100%; background:silver"
 +
|-
 +
|
 +
 
 +
==Challenge 2==
 +
|}
 +
[[Image:QuestionMark2.jpg|right|120px]]
 +
<br />
 +
* Modify your program so that the ball bounces when its side (and not its center) touches the "walls" of the graphics window.
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
 
 +
=Adding an Obstacle=
 +
<br />
 +
* Add a rectangle in the middle of the graphic window.  You should declare it at the beginning of your main() function, as illustrated here:
 +
<br />
 +
::<source lang="python">
 +
def main():
 +
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )
 +
 
 +
    # create a green obstacle in the middle of the window
 +
    x1 = 200
 +
    y1 = 200
 +
    x2 = 250
 +
    y2 = 250
 +
    obstacle1 = Rectangle( Point( x1, y1 ), Point( x2, y2 ) )
 +
    obstacle1.setFill( "green" )
 +
    obstacle1.draw( win )
 +
 
 +
    # the remaining part of your code follows below...
 +
</source>
 +
<br />
 +
<br />
 +
<!-- ----------------------------------------------------------------------------------------------- -->
 +
{| style="width:100%; background:silver"
 +
|-
 +
 +
==Challenge 3==
 +
|}
 +
[[Image:QuestionMark3.jpg|right|120px]]
 +
<br />
 +
* Make your ball stop when its center enters the green rectangle.  The image below illustrates this situation.
 +
<br />
 +
<center>[[Image:ballStoppedOnGreenRect.png|300px]]</center>
 +
<br />
 +
<br />
 +
* Hints: to make an object stop, you can simply set its displacement to 0, so that the while-loop makes it move by 0 pixels every loop. 
 +
<br />
 +
<br />
 +
<!-- ----------------------------------------------------------------------------------------------- -->
 +
{| style="width:100%; background:silver"
 +
|-
 +
|
 +
 
 +
==Challenge 4==
 +
|}
 +
[[Image:QuestionMark4.jpg|right|120px]]
 +
<br />
 +
* Modify your program one more time, and this time the ball will bounce off the obstacle.  When you detect that the center of the ball is inside the green rectangle, change <tt>dx</tt> and <tt>dy</tt> to their opposite.  Note that this will make the ball bounce back on the same path it came from.  It is quite challenging to make the ball bounce in a realistic way, and you are welcome to try to make it happen, but it's trickier.  Bouncing off in the opposite direction is fine for this lab!
 +
<br />
 +
::<source lang="python">
 +
if  ... :
 +
    dx = -dx
 +
    dy = -dy
 +
</source>
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 +
<br />
 
<br />
 
<br />
  
This section deals with setting up your environment to run graphics programs.
+
=Adding a Second Obstacle=
 
<br />
 
<br />
The whole process is illustrated by the image below, step by step.
+
* Add a second rectangle in the graphic window.  Make it magenta in color.  You should declare it at the beginning of your main() function, as illustrated here:
 +
<br />
 +
::<source lang="python">
 +
def main():
 +
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )
 +
 
 +
    # create a green obstacle in the middle of the window
 +
    x1 = 200
 +
    y1 = 200
 +
    x2 = 250
 +
    y2 = 250
 +
    obstacle1 = Rectangle( Point( x1, y1 ), Point( x2, y2 ) )
 +
    obstacle1.setFill( "green" )
 +
    obstacle1.draw( win )
 +
 
 +
    # create another green rectangle on the right of the first one
 +
    x3 = 350
 +
    y3 = 200
 +
    x4 = 400
 +
    y4 = 250
 +
    obstacle2 = Rectangle( Point( x3, y3 ), Point( x4, y4 ) )
 +
    obstacle2.setFill( "magenta" )
 +
    obstacle2.draw( win )
 +
 
  
 +
    # the remaining part of your code follows below...
 +
</source>
 
<br />
 
<br />
 +
* Feel freel to position it at a different location than the one used above.
 +
<br />
 +
<!-- ----------------------------------------------------------------------------------------------- -->
 +
{| style="width:100%; background:silver"
 +
|-
 +
 +
==Challenge 5==
 +
|}
 +
[[Image:QuestionMark5.jpg|right|120px]]
 +
<br />
 +
* Make your ball stop when its center is fully inside the first green obstacle, and bounce off the magenta obstacle.  For this challenge, simply make the ball bounce off the second obstacle when its center enters the obstacle.
 +
* If you find that the ball never gets to hit both boxes, you may want to change the initial direction and add decimal digits to the dx and dy to create an angle that yields a path that eventually will hit the obstacles.  For example:
 
<br />
 
<br />
<center>
+
::<source lang="python">
[[Image:MacGraphicsSetup.png | 800px]]
+
    dx = 5.111
</center>
+
    dy = -2.51
 +
</source>
 
<br />
 
<br />
 +
 +
 +
 
<br />
 
<br />
Graphics programs have to be run from Idle to work correctly, and need the graphics.py library distributed by Zelle, the author of our textbook.
+
 
 +
 
 +
<br />
 +
<center>[[Image:ballWithGreenAndMagentaRects.png|300px]]</center>
 +
<br />
 +
<br />
 +
<br />
 +
 
 +
=Using Boolean Functions=
 +
<br />
 +
==isInside()==
 +
<br />
 +
* Add the code of the function '''isInside()''', shown below, to your last program, above the main() function.
 +
<br />
 +
::<source lang="python">
 +
 
 +
# ifInside: returns true of the coordinates of a point defined by
 +
# its coordinates ballX and ballY, are inside the rectangle defined by a top
 +
# left point of coordinates obsX1, obsY1, and a bottom-right point
 +
# with coordinates obsX2, obsY2.  Returns false if the point is outside
 +
# the rectangle.
 +
def isInside( ballX, ballY, obsX1, obsY1, obsX2, obsY2 ):
 +
    if obsX1 < ballX < obsX2 and obsY1 < ballY < obsY2:
 +
        return True
 +
    else:
 +
        return False
 +
 
 +
 
 +
</source>
 +
<br />
 +
* Modify the code inside the '''while''' loop in your main function, so that it uses the '''isInside()''' function to detect contact with Obstacle1 and with Obstacle2.
 +
:Here's what your code should look like (you will have to pass the appropriate parameters to the function):
 +
<br />
 +
::<source lang="python">
 +
        # if the center of the ball is inside the first obstacle, stop
 +
        # the ball.
 +
        if  isInside(  ...  ) == True:
 +
            dx = 0
 +
            dy = 0
 +
 
 +
        # if the center of the ball is inside the second obstacle, bounce
 +
        # off
 +
        if  isInside(  ...  ) == True:
 +
            dx = -dx
 +
            dy = -dy
 +
 
 +
 
 +
</source>
 +
 
 +
 
 +
<br />
 +
 
 +
=IsLeftSide() Boolean Function=
 +
<br />
 +
* Add a new boolean function to your program called '''isLeftSide()'''.  This function receives 3 parameters, in this order:
 +
<br />
 +
:* an x coordinate
 +
:* a y coordinate
 +
:* the width of the window.
 +
<br />
 +
:and it returns '''true''' if the point (x, y) is on the left side of the window, and '''false''' if the point (x, y) is on the right side of the window.  This function basically compares the x coordinate to the midpoint on the x axis of the window.
 +
<br />
 +
* Use your new function to color the ball rid when it is moving on the left side of the window, and yellow when it is moving on the right side of the window.  Example:
 +
<br />
 +
::<source lang="python">
 +
if isLeftSide(  x,  y, win.getWidth() ) == True:
 +
      circ.setFill( 'red' )
 +
else:
 +
      circ.setFill( 'yellow' )
 +
</source>
 +
<br />
 +
=isUpperHalf Boolean Function=
 +
<br />
 +
* Comment out or remove the previous if statement that changes the color of the ball, so that it won't interfere with the code you are about to write.
 +
* Create a new boolean function called '''isUpperHalf()''', that takes 3 parameters, the first two being the coordinates of a point, the third one the height of the window, and that returns true if the point is in the top half of the screen, an false otherwise.
 +
<br />
 +
* Use your new function to control the color of the ball as it moves around the window.  The ball should be 'blue' when it is in the upper half of the screen, and 'brown' when it is in the lower half.
 +
<br />
 +
<br />
 +
<br />
 +
Demonstrate the correct operations of your programs to your Lab Instructor, and you will be instructed on the process of submitting your lab to Moodle.
 +
<br />
 +
<br />
 +
=getColor() Function=
 +
<br />
 +
* Instead of having two boolean functions that detect if the point of coordinates x and y is in one part of the window or not, we now want to create a function that will receive the x, and y coordinate of the center of the ball, and the width and height of the window, and that will return a string.  The function is called '''getColor()'''.  If the x and y coordinates are inside the top left quarter of the window, it will return the color 'yellow'.  If the x and y coordinates are inside the top right quarter, the function will return 'red'.  For the lower-left quarter, the function will return 'blue'.  And finally, the function will return 'brown'  for the bottom-right quarter.
 +
 
 +
* Here is an example of how the function can be used '''inside''' the while loop:
 +
<br />
 +
::<source lang="python">
 +
# get the x and y of the center of the circle.
 +
x = circ.getCenter().getX()
 +
y = circ.getCenter().getY()
 +
 
 +
# set color of circle according to its position
 +
color = getColor( x, y, win.getWidth(), win.getHeight() )
 +
circ.setFill( color )
 +
</source>
 +
<br />
 +
</showafterdate>
 +
<br />
 +
<br />
 +
<showafterdate after="20150313 11:00" before "20150601 00:00">
 +
=Solution Programs=
 +
<br />
 +
The programs below show the evolution of the initial program through many transformations, solving the various challenges contained in this lab.
 +
<br />
 +
==demo0.py==
 +
<br />
 +
<source lang="python">
 +
 
 +
# Uses graphics.py from Zelle
 +
#
 +
# This program displays the basic elements of a program
 +
#
 +
from graphics import *
 +
 
 +
def main():
 +
    win = GraphWin("Demo #0", 400, 300)
 +
    c = Circle(Point(50,50), 10)
 +
    c.draw(win)
 +
    win.getMouse() # Pause to view result
 +
    win.close()    # Close window when done
 +
 
 +
main()
 +
</source>
 +
<br />
 +
==demo1.py==
 +
<br />
 +
<source lang="python">
 +
 
 +
# Uses graphics.py from Zelle
 +
#
 +
# This program displays the basic elements of a program
 +
#
 +
from graphics import *
 +
 
 +
def main():
 +
    win = GraphWin("Demo #0", 600, 400)
 +
   
 +
    c1 = Circle( Point(50,150), 20 )
 +
    c1.draw( win )
 +
    c2 = Circle( Point( 100, 150 ), 20 )
 +
    c2.draw( win )
 +
 
 +
    r1 = Rectangle( Point( 10, 100 ), Point( 150, 150 ) )
 +
    r1.draw( win )
 +
   
 +
    win.getMouse() # Pause to view result
 +
    win.close()    # Close window when done
 +
 
 +
main()
 +
</source>
 +
<br />
 +
==demo2.py==
 +
<br />
 +
<source lang="python">
 +
# Uses graphics.py from Zelle
 +
#
 +
# This program displays the basic elements of a program
 +
#
 +
from graphics import *
 +
 
 +
def main():
 +
    win = GraphWin( "Lab 7 Demo", 600, 400 )
 +
 
 +
    # create and draw a red circle
 +
    center = Point( 100, 100 )
 +
    circ = Circle( center, 30 )
 +
    circ.setFill( 'red' )
 +
    circ.draw( win )
 +
 
 +
    # add a label inside the circle
 +
    label = Text( center, "red circle" )
 +
    label.draw( win )
 +
 
 +
    # create and draw a rectangle
 +
    rect = Rectangle( Point( 30, 30 ), Point( 70, 70 ) )
 +
    rect.draw( win )
 +
 
 +
   
 +
    win.getMouse() # Pause to view result
 +
    win.close()    # Close window when done
 +
 
 +
main()
 +
</source>
 
<br />
 
<br />
==Download graphics.py==
+
==demo3.py==
 
<br />
 
<br />
 +
<source lang="python">
 +
# Uses graphics.py from Zelle
 +
#
 +
# This program displays the basic elements of a program
 +
#
 +
from graphics import *
 +
 +
def main():
 +
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )
 +
 +
    # create and draw a red circle
 +
    center = Point( 100, 100 )
 +
    circ = Circle( center, 30 )
 +
    circ.setFill( 'red' )
 +
    circ.draw( win )
 +
 +
   
 +
    dx = 5
 +
    dy = 0.25
 +
   
 +
    while win.checkMouse() == None:
 +
        circ.move( dx, dy )
 +
        x = circ.getCenter().getX()
 +
        y = circ.getCenter().getY()
 +
        if ( x > 600 ):
 +
            dx = -dx
 +
        if ( x < 0 ):
 +
            dx = -dx
  
  
First, Login to the Mac with your 111c-xx account, and then follow the steps below, referring to the image above
+
   
  
# Open the '''Finder''' window, then the '''Utilities''' folder, then click on '''X11'''
+
    win.close()   # Close window when done
# This opens the white ''XTerm'' window in the top left.  We won't use it, but it needs to be running for the graphics to work.  You can iconize this ''xterm'' window to clean up your desktop, though.
 
#  Use the same steps ('''Finder''' --> '''Utilities''') and open a '''Terminal''' window.
 
# A new black window opens up.  
 
# In it, type the following commands:<br /><br /><tt>  ssh -Y  111c-xx@beowulf.csc.smith.edu        ''(You may have to type '''yes''' to confirm)''</tt><br /><br /><tt>  getcopy graphics.py</tt><br /><br /><tt>  python graphics.py</tt><br /><br />
 
# If everything goes well, you should see the small gray window with a triangle and a rectangle, with the words ''Centered Text''.
 
  
 +
main()
 +
</source>
 
<br />
 
<br />
 +
==demo4.py==
 
<br />
 
<br />
;Question 8
+
<source lang="python">
: Open Python in interactive mode, and try the various graphics functions, as illustrated in Section 5.3 of Zelle's textbook:
+
# Uses graphics.py from Zelle
+
#
  >>> from graphics import *
+
# This program displays the basic elements of a program
  >>> win = GraphWin( "Lab 5 Demo" )
+
#
  >>> center = Point( 100, 100 )
+
from graphics import *
  >>> circ = Circle( center, 30 )
+
 
  >>> circ.setFill( 'red' )
+
def main():
  >>> circ.draw( win )
+
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )
  >>> label = Text( center, "red circle" )
+
 
  >>> label.draw( win )
+
    # create a green obstacle in the middle of the window
  >>> rect = Rectangle( Point( 30, 30 ), Point( 70, 70 ) )
+
    x1 = 200
  >>> rect.draw( win )
+
    y1 = 200
  >>> win.close()
+
    x2 = 250
 +
    y2 = 250
 +
    obstacle = Rectangle( Point( x1, y1 ), Point( x2, y2 ) )
 +
    obstacle.setFill( "green" )
 +
    obstacle.draw( win )
 +
   
 +
    # create and draw a red circle
 +
    radius = 30
 +
    center = Point( 100, 100 )
 +
    circ = Circle( center, radius )
 +
    circ.setFill( 'red' )
 +
    circ.draw( win )
 +
 
 +
    # define the direction the circle will start moving in.
 +
    # 5 pixels to the right every move, and 0.25 pixels down
 +
    # every move.
 +
    dx = 5
 +
    dy = 2.5
  
:Using this bit of knowledge, could you generate this figure?
+
    # as long as the mouse hasn't been clicked on the window
<center>[[Image:taxiCrude.png]]</center>
+
    # keep on looping.
<bluebox>
+
    while win.checkMouse() == None:
The sections below are optional, and intended for those who are interested in writing graphics programs directly on their laptop computers without being connected to Beowulf.
+
 
</bluebox>
+
        # move the circle in the current direction.
 +
        circ.move( dx, dy )
 +
 
 +
        # get the x and y of the center of the circle.
 +
        x = circ.getCenter().getX()
 +
        y = circ.getCenter().getY()
 +
 
 +
        # if the center of the ball is outside the right or left boundary,
 +
        # reverse the x direction of movement.
 +
        if  x > 600 - radius or  x < radius:
 +
            dx = -dx
 +
        if  y > 400 - radius or y < radius:
 +
            dy = -dy
 +
 
 +
        # if the center of the ball is inside the obstacle, stop
 +
        # the ball.
 +
        if  x1 < x < x2 and y1 < y < y2 :
 +
            dx = 0
 +
            dy = 0
 +
 
 +
   
 +
    # if we're here, it's because the the user clicked on the graphic window.
 +
    # we can close everything and quit.
 +
    win.close()   
 +
 
 +
main()
 +
 
 +
 
 +
 
 +
   
 +
</source>
 +
<br />
 +
==demo5.py==
 +
<br />
 +
<source lang="python">
 +
# Uses graphics.py from Zelle
 +
#
 +
# This program displays the basic elements of a program
 +
#
 +
from graphics import *
 +
 
 +
def main():
 +
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )
 +
 
 +
    # create a green obstacle in the middle of the window
 +
    x1 = 200
 +
    y1 = 200
 +
    x2 = 250
 +
    y2 = 250
 +
    obstacle1 = Rectangle( Point( x1, y1 ), Point( x2, y2 ) )
 +
    obstacle1.setFill( "green" )
 +
    obstacle1.draw( win )
 +
 
 +
    # create another green rectangle on the right of the first one
 +
    x3 = 350
 +
    y3 = 200
 +
    x4 = 400
 +
    y4 = 250
 +
    obstacle2 = Rectangle( Point( x3, y3 ), Point( x4, y4 ) )
 +
    obstacle2.setFill( "magenta" )
 +
    obstacle2.draw( win )
 +
   
 +
    # create and draw a red circle
 +
    radius = 30
 +
    center = Point( 100, 100 )
 +
    circ = Circle( center, radius )
 +
    circ.setFill( 'red' )
 +
    circ.draw( win )
 +
 
 +
    # define the direction the circle will start moving in.
 +
    # 5 pixels to the right every move, and 0.25 pixels down
 +
    # every move.
 +
    dx = 5.1
 +
    dy = 2.51
 +
 
 +
    # as long as the mouse hasn't been clicked on the window
 +
    # keep on looping.
 +
    while win.checkMouse() == None:
 +
 
 +
        # move the circle in the current direction.
 +
        circ.move( dx, dy )
 +
 
 +
        # get the x and y of the center of the circle.
 +
        x = circ.getCenter().getX()
 +
        y = circ.getCenter().getY()
 +
 
 +
        # if the center of the ball is outside the right or left boundary,
 +
        # reverse the x direction of movement.
 +
        if  x > 600 - radius or  x < radius:
 +
            dx = -dx
 +
        if  y > 400 - radius or y < radius:
 +
            dy = -dy
 +
 
 +
        # if the center of the ball is inside the first obstacle, stop
 +
        # the ball.
 +
        if  x1 < x < x2 and y1 < y < y2 :
 +
            dx = 0
 +
            dy = 0
 +
 
 +
        # if the center of the ball is inside the second obstacle, bounce
 +
        # off
 +
        if  x3 < x < x4 and y3 < y < y4 :
 +
            dx = -dx
 +
            dy = -dy
 +
 
 +
   
 +
    # if we're here, it's because the the user clicked on the graphic window.
 +
    # we can close everything and quit.
 +
    win.close()   
 +
 
 +
main()
 +
 
 +
 
 +
 
 +
   
 +
</source>
 
<br />
 
<br />
 +
==demo6.py==
 
<br />
 
<br />
 +
<source lang="python">
 +
# Uses graphics.py from Zelle
 +
#
 +
# This program displays the basic elements of a program
 +
#
 +
from graphics import *
  
==Installing the Graphics Package on your laptop (Optional)==
+
# ifInside: returns true of the coordinates of a point defined by
 +
# its coordinates ballX and ballY, are inside the rectangle defined by a top
 +
# left point of coordinates obsX1, obsY1, and a bottom-right point
 +
# with coordinates obsX2, obsY2.  Returns false if the point is outside
 +
# the rectangle.
 +
def isInside( ballX, ballY, obsX1, obsY1, obsX2, obsY2 ):
 +
    if obsX1 < ballX < obsX2 and obsY1 < ballY < obsY2:
 +
        return True
 +
    else:
 +
        return False
  
Use these directions if  you would like to have python and the graphics library installed on your own computer.
+
   
 +
def main():
 +
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )
  
===Directions for Windows laptops===
+
    # create a green obstacle in the middle of the window
(These directions were inspired by directions posted at the Rose-Hulman Institute of Technology)
+
    x1 = 200
 +
    y1 = 200
 +
    x2 = 250
 +
    y2 = 250
 +
    obstacle1 = Rectangle( Point( x1, y1 ), Point( x2, y2 ) )
 +
    obstacle1.setFill( "green" )
 +
    obstacle1.draw( win )
  
====Python====
+
    # create another green rectangle on the right of the first one
;First, Install Python 2.6 on your machine, if you haven't already done so.
+
    x3 = 350
*Logon as an adminstrator if you have a regular user account and an administrator account for your laptop (most people use the same for both).
+
    y3 = 200
* Download Python (it's free!).  Visit http://www.python.org/download/ and select the Python 2.6.2 Windows installer.
+
    x4 = 400
* Run the installer, installing it in C:\Program Files\Python26\ (vs. the default, which is C:\Python26 ). The other defaults are fine to use.
+
    y4 = 250
* Change the directory that the Python development environment, IDLE, starts in when loading and saving files. (By default it looks for and saves files in the program directory.)
+
    obstacle2 = Rectangle( Point( x3, y3 ), Point( x4, y4 ) )
** Log into your regular user account if it is different from your administrator account.
+
    obstacle2.setFill( "magenta" )
** Click on Start → All Programs → Python 2.6
+
    obstacle2.draw( win )
** '''Right'''-click on IDLE (Python GUI) and choose Properties
+
   
**Change the '''Start in:''' field to point to the place where you want to keep Python program files. A good choice might be '''C:\Documents and Settings\yourname\My Documents\PythonFiles'''. (An easy way to get that path name:  Open My Documents and browse to the folder. Select the pathname in the Address bar; Copy. Go back to the Idle Properties Window, and Paste into the Start In field.) Whatever folder you decide to use, you will need to use Windows Explorer to create it if it does not exist.
+
    # create and draw a red circle
 +
    radius = 30
 +
    center = Point( 100, 100 )
 +
    circ = Circle( center, radius )
 +
    circ.setFill( 'red' )
 +
    circ.draw( win )
 +
 
 +
    # define the direction the circle will start moving in.
 +
    # 5 pixels to the right every move, and 0.25 pixels down
 +
    # every move.
 +
    dx = 5.111
 +
    dy = -2.51
 +
 
 +
    # as long as the mouse hasn't been clicked on the window
 +
    # keep on looping.
 +
    while win.checkMouse() == None:
 +
 
 +
        # move the circle in the current direction.
 +
        circ.move( dx, dy )
 +
 
 +
        # get the x and y of the center of the circle.
 +
        x = circ.getCenter().getX()
 +
        y = circ.getCenter().getY()
 +
 
 +
        # if the center of the ball is outside the right or left boundary,
 +
        # reverse the x direction of movement.
 +
        if  x > 600 - radius or  x < radius:
 +
            dx = -dx
 +
        if  y > 400 - radius or y < radius:
 +
            dy = -dy
 +
 
 +
        # if the center of the ball is inside the first obstacle, stop
 +
        # the ball.
 +
        if  isInside( x, y, x1, y1, x2, y2 ):
 +
            dx = 0
 +
            dy = 0
 +
 
 +
        # if the center of the ball is inside the second obstacle, bounce
 +
        # off
 +
        if  isInside( x, y, x3, y3, x4, y4 ):
 +
            dx = -dx
 +
            dy = -dy
 +
 
 +
   
 +
    # if we're here, it's because the the user clicked on the graphic window.
 +
    # we can close everything and quit.
 +
    win.close()   
 +
 
 +
main()
 +
 
 +
 
 +
 
 +
   
 +
</source>
 +
<br />
 +
==demo7.py==
 
<br />
 
<br />
;Then load the Zelle '''Graphics''' library
+
<source lang="python">
* Download this file [http://mcsp.wartburg.edu/zelle/python/python3/ppics2e_code/graphics.py graphics.py].
+
# Uses graphics.py from Zelle
* Save the file graphics.py in the directory '''C:\Program Files\Python26\Lib\site-packages'''
+
#
 +
# This program displays the basic elements of a program
 +
#
 +
from graphics import *
 +
 
 +
# ifInside: returns true of the coordinates of a point defined by
 +
# its coordinates ballX and ballY, are inside the rectangle defined by a top
 +
# left point of coordinates obsX1, obsY1, and a bottom-right point
 +
# with coordinates obsX2, obsY2.  Returns false if the point is outside
 +
# the rectangle.
 +
def isInside( ballX, ballY, obsX1, obsY1, obsX2, obsY2 ):
 +
    if obsX1 < ballX < obsX2 and obsY1 < ballY < obsY2:
 +
        return True
 +
    else:
 +
        return False
 +
 
 +
def isLeftSide( x, y, width ):
 +
    if x < width//2:
 +
        return True
 +
    else:
 +
        return False
 +
   
 +
def main():
 +
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )
 +
 
 +
    # create a green obstacle in the middle of the window
 +
    x1 = 200
 +
    y1 = 200
 +
    x2 = 250
 +
    y2 = 250
 +
    obstacle1 = Rectangle( Point( x1, y1 ), Point( x2, y2 ) )
 +
    obstacle1.setFill( "green" )
 +
    obstacle1.draw( win )
 +
 
 +
    # create another green rectangle on the right of the first one
 +
    x3 = 350
 +
    y3 = 200
 +
    x4 = 400
 +
    y4 = 250
 +
    obstacle2 = Rectangle( Point( x3, y3 ), Point( x4, y4 ) )
 +
    obstacle2.setFill( "magenta" )
 +
    obstacle2.draw( win )
 +
   
 +
    # create and draw a red circle
 +
    radius = 30
 +
    center = Point( 100, 100 )
 +
    circ = Circle( center, radius )
 +
    circ.setFill( 'red' )
 +
    circ.draw( win )
 +
 
 +
    # define the direction the circle will start moving in.
 +
    # 5 pixels to the right every move, and 0.25 pixels down
 +
    # every move.
 +
    dx = 5.111
 +
    dy = -2.51
 +
 
 +
    # as long as the mouse hasn't been clicked on the window
 +
    # keep on looping.
 +
    while win.checkMouse() == None:
  
:::''Potential “gotchas”: (1) That is Lib, not libs, in the path. (2) if you installed Python in a different location than C:\Program Files\Python26, you’ll need to find your Python26\Lib\site-packages folder.''
+
        # move the circle in the current direction.
 +
        circ.move( dx, dy )
  
;To verify your installation:
+
        # get the x and y of the center of the circle.
* Launch '''IDLE''' by clicking Start → All Programs → Python 2.6 → IDLE (Python GUI)
+
        x = circ.getCenter().getX()
* At the prompt type:
+
        y = circ.getCenter().getY()
  
  from graphics import *
+
        # if the center of the ball is outside the right or left boundary,
   
+
        # reverse the x direction of movement.
:if you do not get an error message, then the installation was successful.
+
        if x > 600 - radius or  x < radius:
 +
            dx = -dx
 +
        if  y > 400 - radius or y < radius:
 +
            dy = -dy
  
===Directions for Mac laptops===
+
        # if the center of the ball is inside the first obstacle, stop
 +
        # the ball.
 +
        if  isInside( x, y, x1, y1, x2, y2 ):
 +
            dx = 0
 +
            dy = 0
  
* Use '''Finder''' to create a new folder in your favorite spot.  For example you can create a folder called '''CSC111''' on  your '''Desktop'''.
+
        # if the center of the ball is inside the second obstacle, bounce
* Download this file [http://mcsp.wartburg.edu/zelle/python/python3/ppics2e_code/graphics.py graphics.py], and unzip it. Put grahpics.py in the directory (folder) you created above.
+
        # off
* Open a terminal window, and type the following commands:
+
        if isInside( x, y, x3, y3, x4, y4 ):
 +
            dx = -dx
 +
            dy = -dy
  
  cd
+
        # if the ball is on the left side of the window, its color is
  cd Desktop
+
        # red, else its color is yellow.
  cd CSC111            ''(or whatever directory you decided to create)''
+
        if isLeftSide( x, y, win.getWidth() )==True:
  emacs testgraphics.py
+
            circ.setFill( 'red' )
 +
        else:
 +
            circ.setFill( 'yellow' )
 +
           
 +
   
 +
    # if we're here, it's because the the user clicked on the graphic window.
 +
    # we can close everything and quit.
 +
    win.close()   
  
* create the following python program:
+
main()
 
from graphics import *
 
def main():
 
    test()
 
 
main()
 
 
* Run it!
 
  
  python testgraphics.py
 
  
* You should get this new window on your screen:
+
 
 +
   
 +
</source>
 
<br />
 
<br />
 +
 +
 +
 +
==demo8.py==
 
<br />
 
<br />
 +
<source lang="python">
 +
# Uses graphics.py from Zelle
 +
#
 +
# This program displays the basic elements of a program
 +
#
 +
from graphics import *
 +
 +
# ifInside: returns true of the coordinates of a point defined by
 +
# its coordinates ballX and ballY, are inside the rectangle defined by a top
 +
# left point of coordinates obsX1, obsY1, and a bottom-right point
 +
# with coordinates obsX2, obsY2.  Returns false if the point is outside
 +
# the rectangle.
 +
def isInside( ballX, ballY, obsX1, obsY1, obsX2, obsY2 ):
 +
    if obsX1 < ballX < obsX2 and obsY1 < ballY < obsY2:
 +
        return True
 +
    else:
 +
        return False
 +
 +
def isLeftSide( x, y, width ):
 +
    if x < width//2:
 +
        return True
 +
    else:
 +
        return False
 +
 +
def getColor( x, y, w, h ):
 +
    if x < w/2 and y < h/2:
 +
        return 'yellow'
 +
    elif x < w/2 and y > h/2:
 +
        return 'blue'
 +
    elif x > w/2 and y < h/2:
 +
        return 'red'
 +
    else:
 +
        return 'brown'
 +
       
 +
def main():
 +
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )
  
<center> [[Image:GraphicsTest.png]]</center>
+
    # create a green obstacle in the middle of the window
 +
    x1 = 200
 +
    y1 = 200
 +
    x2 = 250
 +
    y2 = 250
 +
    obstacle1 = Rectangle( Point( x1, y1 ), Point( x2, y2 ) )
 +
    obstacle1.setFill( "green" )
 +
    obstacle1.draw( win )
  
 +
    # create another green rectangle on the right of the first one
 +
    x3 = 350
 +
    y3 = 200
 +
    x4 = 400
 +
    y4 = 250
 +
    obstacle2 = Rectangle( Point( x3, y3 ), Point( x4, y4 ) )
 +
    obstacle2.setFill( "magenta" )
 +
    obstacle2.draw( win )
 +
   
 +
    # create and draw a red circle
 +
    radius = 30
 +
    center = Point( 100, 100 )
 +
    circ = Circle( center, radius )
 +
    circ.setFill( 'red' )
 +
    circ.draw( win )
 +
 +
    # define the direction the circle will start moving in.
 +
    # 5 pixels to the right every move, and 0.25 pixels down
 +
    # every move.
 +
    dx = 5.111
 +
    dy = -2.51
 +
 +
    # as long as the mouse hasn't been clicked on the window
 +
    # keep on looping.
 +
    while win.checkMouse() == None:
 +
 +
        # move the circle in the current direction.
 +
        circ.move( dx, dy )
 +
 +
        # get the x and y of the center of the circle.
 +
        x = circ.getCenter().getX()
 +
        y = circ.getCenter().getY()
 +
 +
        circ.setFill( getColor( x, y, win.getWidth(), win.getHeight() ) )
 +
                 
 +
        # if the center of the ball is outside the right or left boundary,
 +
        # reverse the x direction of movement.
 +
        if  x > 600 - radius or  x < radius:
 +
            dx = -dx
 +
        if  y > 400 - radius or y < radius:
 +
            dy = -dy
 +
 +
        # if the center of the ball is inside the first obstacle, stop
 +
        # the ball.
 +
        if  isInside( x, y, x1, y1, x2, y2 ):
 +
            dx = 0
 +
            dy = 0
 +
 +
        # if the center of the ball is inside the second obstacle, bounce
 +
        # off
 +
        if  isInside( x, y, x3, y3, x4, y4 ):
 +
            dx = -dx
 +
            dy = -dy
 +
 +
        # if the ball is on the left side of the window, its color is
 +
        # red, else its color is yellow.
 +
        """
 +
        if isLeftSide( x, y, win.getWidth() )==True:
 +
            circ.setFill( 'red' )
 +
        else:
 +
            circ.setFill( 'yellow' )
 +
        """
 +
   
 +
    # if we're here, it's because the the user clicked on the graphic window.
 +
    # we can close everything and quit.
 +
    win.close()   
 +
 +
main()
 +
 +
 +
 +
   
 +
</source>
 +
<br />
 +
 +
 +
</showafterdate>
 
<br />
 
<br />
 
<br />
 
<br />
Line 134: Line 1,049:
 
<br />
 
<br />
 
<br />
 
<br />
 +
<br />
 +
 
[[Category:CSC111]][[Category:Labs]][[Category:Python]][[Category:Graphics]]
 
[[Category:CSC111]][[Category:Labs]][[Category:Python]][[Category:Graphics]]

Latest revision as of 21:46, 10 March 2015

--D. Thiebaut (talk) 11:09, 8 March 2015 (EDT)



In this lab you will play with a graphics library. A graphic library typically allows the user to draw simple shapes on the screen. You will also write some boolean functions that will help you control the dynamic movement of objects on the screen. The lab is different from the previous labs, as you must demonstrate that you have finished and implemented the different challenges before being allowed to submit your program on Moodle. When your programs for the challenges work, demonstrate your solutions to the lab instructor (or the TA), who will instruct you about the Moodle submission. You must submit your solution program to Moodle before 3/13 at 11:00 a.m.



TaxiCabCSC111.png


Setup for Graphics


Step 1: Download the graphics.py Library


  • Copy/Paste the code from this page to Idle and save it in the directory where you will save your programs for Week 7, under the name graphics.py.


Step 2: Testing your installation


  • With graphics.py in your Idle window, simply click run to run the library. Normally libraries are not run by themselves, but this library has its own test program to help users verify that the library is working properly.
  • If everything goes well, you should see this simple window appear on your screen:


ZelleGraphics1.png


  • Click a few times on the window and verify that the window responds by changing the color or size of various graphic objects.




Graphics programs have to be run from Idle to work correctly, and need the graphics.py library distributed by Zelle, the author of our textbook.
<showafterdate after="20150311 12:00" before "20150601 00:00">

Step 3: A simple Graphics Program


  • Create a new program and call it lab7.py.
  • Important: save your program in the same directory/folder where you saved the graphics.py library.
  • Copy the code below in it.


# lab7.py
# your name
# draws a circle in a window that is 600x400.

from graphics import *

def main():
    win = GraphWin("My Circle", 600, 400)
    c = Circle(Point(50,50), 10)
    c.draw(win)
    win.getMouse() # Pause to view result
    win.close()    # Close window when done

main()


  • Run the program. Verify that you see a single circle in the graphic window.
  • Click with the mouse on the graphics window to close it.


Step 4: Explanations


  • Observe the program from Step 3 above and recognize the main features:
    1. First we open a new graphic window on our desktop with the win = GraphWin( ... ) statement. 600 and 400 define how wide and high the window will be. "My Circle" is the title that will appear at the top of the window.
    2. Next, we create a circle object with the statement c = Circle( Point(50,50), 10 ). This does not draw the circle. It simply creates one in memory, centered on the point of coordinates 50, 50, with a radius of 10.
    3. Once the circle is created in memory, we make it appear on the graphic window with c.draw( win ).
    4. Finally, we wait for the user to click on the graphic window, and then close the window.


Step 5: Modifications


  • Modify your program, so that it looks like the code shown below:


# lab7.py
# your name
# Uses graphics.py from Zelle
#
# This program displays a red circle, a label
# and a rectangle.
from graphics import *

def main():
    #open the graphic window.
    win = GraphWin( "Lab 7 Demo", 600, 400 )

    # create and draw a red circle
    center = Point( 100, 100 )
    circ = Circle( center, 30 )
    circ.setFill( 'red' )
    circ.draw( win )

    # add a label inside the circle
    label = Text( Point( 100, 100 ), "red circle" )
    label.draw( win )

    # create and draw a rectangle
    rect = Rectangle( Point( 30, 30 ), Point( 70, 70 ) )
    rect.draw( win )

    
    win.getMouse() # Pause to view result
    win.close()    # Close window when done

main()


  • The program uses 2 new objects: a rectangle, defined by its upper-left and bottom-right corners, and a label (text) that simply is a string of characters drawn at a given point on the screen. The string is automatically centered around the given point.
  • Using this new bit of knowledge, can you generate the figure below? Note that the graphics system used here can recognize many different colors, all defined by strings, such as 'red' used above. You can find all the available colors on this page.


TaxiCrude.png



Simple Animation: Moving a Ball on the Graphic Window


  • Create a new program similar to the one covered in Monday's lecture.


# Uses graphics.py from Zelle
#
# This program displays the basic elements of a program
#
from graphics import *

def main():
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )

    # create and draw a red circle
    center = Point( 100, 100 )
    circ = Circle( center, 30 )
    circ.setFill( 'red' )
    circ.draw( win )

    # define the direction the circle will start moving in.
    # 5 pixels to the right every move, and 0.25 pixels down
    # every move.
    dx = 5
    dy = 0.25

    # as long as the mouse hasn't been clicked on the window
    # keep on looping.
    while win.checkMouse() == None:

        # move the circle in the current direction.
        circ.move( dx, dy )

        # get the x and y of the center of the circle.
        x = circ.getCenter().getX()
        y = circ.getCenter().getY()

        # if the center is outside the right or left boundary,
        # reverse the x direction of movement.
        if  x > 600 or x < 0:
            dx = -dx

    
    # if we're here, it's because the the user clicked on the graphic window.
    # we can close everything and quit.
    win.close()    

main()


  • Run the program. Verify that the circle/ball bounces off the left and right boundaries of the window, but disappears down the bottom of the screen. If the ball is moving too fast (it does run at various speeds depending on what computer you're running on), you may want to change the values assigned to dx and dy to these values:


dx = 0.025
dy = 0.025


  • You can stop the program by clicking on the graphic window a couple of times.



Challenge 1

QuestionMark1.jpg


  • Modify your program so that it makes the ball bounce off the bottom and top boundaries of the window.







Challenge 2

QuestionMark2.jpg


  • Modify your program so that the ball bounces when its side (and not its center) touches the "walls" of the graphics window.









Adding an Obstacle


  • Add a rectangle in the middle of the graphic window. You should declare it at the beginning of your main() function, as illustrated here:


def main():
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )

    # create a green obstacle in the middle of the window
    x1 = 200
    y1 = 200
    x2 = 250
    y2 = 250 
    obstacle1 = Rectangle( Point( x1, y1 ), Point( x2, y2 ) )
    obstacle1.setFill( "green" )
    obstacle1.draw( win )

    # the remaining part of your code follows below...



Challenge 3

QuestionMark3.jpg


  • Make your ball stop when its center enters the green rectangle. The image below illustrates this situation.


BallStoppedOnGreenRect.png



  • Hints: to make an object stop, you can simply set its displacement to 0, so that the while-loop makes it move by 0 pixels every loop.



Challenge 4

QuestionMark4.jpg


  • Modify your program one more time, and this time the ball will bounce off the obstacle. When you detect that the center of the ball is inside the green rectangle, change dx and dy to their opposite. Note that this will make the ball bounce back on the same path it came from. It is quite challenging to make the ball bounce in a realistic way, and you are welcome to try to make it happen, but it's trickier. Bouncing off in the opposite direction is fine for this lab!


if  ... :
    dx = -dx
    dy = -dy







Adding a Second Obstacle


  • Add a second rectangle in the graphic window. Make it magenta in color. You should declare it at the beginning of your main() function, as illustrated here:


def main():
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )

    # create a green obstacle in the middle of the window
    x1 = 200
    y1 = 200
    x2 = 250
    y2 = 250 
    obstacle1 = Rectangle( Point( x1, y1 ), Point( x2, y2 ) )
    obstacle1.setFill( "green" )
    obstacle1.draw( win )

    # create another green rectangle on the right of the first one
    x3 = 350
    y3 = 200
    x4 = 400
    y4 = 250 
    obstacle2 = Rectangle( Point( x3, y3 ), Point( x4, y4 ) )
    obstacle2.setFill( "magenta" )
    obstacle2.draw( win )


    # the remaining part of your code follows below...


  • Feel freel to position it at a different location than the one used above.


Challenge 5

QuestionMark5.jpg


  • Make your ball stop when its center is fully inside the first green obstacle, and bounce off the magenta obstacle. For this challenge, simply make the ball bounce off the second obstacle when its center enters the obstacle.
  • If you find that the ball never gets to hit both boxes, you may want to change the initial direction and add decimal digits to the dx and dy to create an angle that yields a path that eventually will hit the obstacles. For example:


    dx = 5.111
    dy = -2.51






BallWithGreenAndMagentaRects.png




Using Boolean Functions


isInside()


  • Add the code of the function isInside(), shown below, to your last program, above the main() function.


# ifInside: returns true of the coordinates of a point defined by 
# its coordinates ballX and ballY, are inside the rectangle defined by a top
# left point of coordinates obsX1, obsY1, and a bottom-right point
# with coordinates obsX2, obsY2.   Returns false if the point is outside
# the rectangle.
def isInside( ballX, ballY, obsX1, obsY1, obsX2, obsY2 ):
    if obsX1 < ballX < obsX2 and obsY1 < ballY < obsY2:
        return True
    else:
        return False


  • Modify the code inside the while loop in your main function, so that it uses the isInside() function to detect contact with Obstacle1 and with Obstacle2.
Here's what your code should look like (you will have to pass the appropriate parameters to the function):


        # if the center of the ball is inside the first obstacle, stop
        # the ball.
        if  isInside(  ...  ) == True:
            dx = 0
            dy = 0

        # if the center of the ball is inside the second obstacle, bounce
        # off
        if  isInside(  ...  ) == True:
            dx = -dx
            dy = -dy



IsLeftSide() Boolean Function


  • Add a new boolean function to your program called isLeftSide(). This function receives 3 parameters, in this order:


  • an x coordinate
  • a y coordinate
  • the width of the window.


and it returns true if the point (x, y) is on the left side of the window, and false if the point (x, y) is on the right side of the window. This function basically compares the x coordinate to the midpoint on the x axis of the window.


  • Use your new function to color the ball rid when it is moving on the left side of the window, and yellow when it is moving on the right side of the window. Example:


if isLeftSide(  x,  y, win.getWidth() ) == True:
      circ.setFill( 'red' )
else:
      circ.setFill( 'yellow' )


isUpperHalf Boolean Function


  • Comment out or remove the previous if statement that changes the color of the ball, so that it won't interfere with the code you are about to write.
  • Create a new boolean function called isUpperHalf(), that takes 3 parameters, the first two being the coordinates of a point, the third one the height of the window, and that returns true if the point is in the top half of the screen, an false otherwise.


  • Use your new function to control the color of the ball as it moves around the window. The ball should be 'blue' when it is in the upper half of the screen, and 'brown' when it is in the lower half.




Demonstrate the correct operations of your programs to your Lab Instructor, and you will be instructed on the process of submitting your lab to Moodle.

getColor() Function


  • Instead of having two boolean functions that detect if the point of coordinates x and y is in one part of the window or not, we now want to create a function that will receive the x, and y coordinate of the center of the ball, and the width and height of the window, and that will return a string. The function is called getColor(). If the x and y coordinates are inside the top left quarter of the window, it will return the color 'yellow'. If the x and y coordinates are inside the top right quarter, the function will return 'red'. For the lower-left quarter, the function will return 'blue'. And finally, the function will return 'brown' for the bottom-right quarter.
  • Here is an example of how the function can be used inside the while loop:


# get the x and y of the center of the circle.
x = circ.getCenter().getX()
y = circ.getCenter().getY()

# set color of circle according to its position
color = getColor( x, y, win.getWidth(), win.getHeight() )
circ.setFill( color )


</showafterdate>

<showafterdate after="20150313 11:00" before "20150601 00:00">

Solution Programs


The programs below show the evolution of the initial program through many transformations, solving the various challenges contained in this lab.

demo0.py


# Uses graphics.py from Zelle
#
# This program displays the basic elements of a program
#
from graphics import *

def main():
    win = GraphWin("Demo #0", 400, 300)
    c = Circle(Point(50,50), 10)
    c.draw(win)
    win.getMouse() # Pause to view result
    win.close()    # Close window when done

main()


demo1.py


# Uses graphics.py from Zelle
#
# This program displays the basic elements of a program
#
from graphics import *

def main():
    win = GraphWin("Demo #0", 600, 400)
    
    c1 = Circle( Point(50,150), 20 )
    c1.draw( win )
    c2 = Circle( Point( 100, 150 ), 20 )
    c2.draw( win )

    r1 = Rectangle( Point( 10, 100 ), Point( 150, 150 ) )
    r1.draw( win )
    
    win.getMouse() # Pause to view result
    win.close()    # Close window when done

main()


demo2.py


# Uses graphics.py from Zelle
#
# This program displays the basic elements of a program
#
from graphics import *

def main():
    win = GraphWin( "Lab 7 Demo", 600, 400 )

    # create and draw a red circle
    center = Point( 100, 100 )
    circ = Circle( center, 30 )
    circ.setFill( 'red' )
    circ.draw( win )

    # add a label inside the circle
    label = Text( center, "red circle" )
    label.draw( win )

    # create and draw a rectangle
    rect = Rectangle( Point( 30, 30 ), Point( 70, 70 ) )
    rect.draw( win )

    
    win.getMouse() # Pause to view result
    win.close()    # Close window when done

main()


demo3.py


# Uses graphics.py from Zelle
#
# This program displays the basic elements of a program
#
from graphics import *

def main():
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )

    # create and draw a red circle
    center = Point( 100, 100 )
    circ = Circle( center, 30 )
    circ.setFill( 'red' )
    circ.draw( win )

    
    dx = 5
    dy = 0.25
    
    while win.checkMouse() == None:
        circ.move( dx, dy )
        x = circ.getCenter().getX()
        y = circ.getCenter().getY()
        if ( x > 600 ):
            dx = -dx
        if ( x < 0 ):
            dx = -dx


    

    win.close()    # Close window when done

main()


demo4.py


# Uses graphics.py from Zelle
#
# This program displays the basic elements of a program
#
from graphics import *

def main():
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )

    # create a green obstacle in the middle of the window
    x1 = 200
    y1 = 200
    x2 = 250
    y2 = 250 
    obstacle = Rectangle( Point( x1, y1 ), Point( x2, y2 ) )
    obstacle.setFill( "green" )
    obstacle.draw( win )
    
    # create and draw a red circle
    radius = 30
    center = Point( 100, 100 )
    circ = Circle( center, radius )
    circ.setFill( 'red' )
    circ.draw( win )

    # define the direction the circle will start moving in.
    # 5 pixels to the right every move, and 0.25 pixels down
    # every move.
    dx = 5
    dy = 2.5

    # as long as the mouse hasn't been clicked on the window
    # keep on looping.
    while win.checkMouse() == None:

        # move the circle in the current direction.
        circ.move( dx, dy )

        # get the x and y of the center of the circle.
        x = circ.getCenter().getX()
        y = circ.getCenter().getY()

        # if the center of the ball is outside the right or left boundary,
        # reverse the x direction of movement.
        if  x > 600 - radius or  x < radius: 
            dx = -dx
        if  y > 400 - radius or y < radius:
            dy = -dy

        # if the center of the ball is inside the obstacle, stop
        # the ball.
        if  x1 < x < x2 and y1 < y < y2 :
            dx = 0
            dy = 0

    
    # if we're here, it's because the the user clicked on the graphic window.
    # we can close everything and quit.
    win.close()    

main()


demo5.py


# Uses graphics.py from Zelle
#
# This program displays the basic elements of a program
#
from graphics import *

def main():
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )

    # create a green obstacle in the middle of the window
    x1 = 200
    y1 = 200
    x2 = 250
    y2 = 250 
    obstacle1 = Rectangle( Point( x1, y1 ), Point( x2, y2 ) )
    obstacle1.setFill( "green" )
    obstacle1.draw( win )

    # create another green rectangle on the right of the first one
    x3 = 350
    y3 = 200
    x4 = 400
    y4 = 250 
    obstacle2 = Rectangle( Point( x3, y3 ), Point( x4, y4 ) )
    obstacle2.setFill( "magenta" )
    obstacle2.draw( win )
    
    # create and draw a red circle
    radius = 30
    center = Point( 100, 100 )
    circ = Circle( center, radius )
    circ.setFill( 'red' )
    circ.draw( win )

    # define the direction the circle will start moving in.
    # 5 pixels to the right every move, and 0.25 pixels down
    # every move.
    dx = 5.1
    dy = 2.51

    # as long as the mouse hasn't been clicked on the window
    # keep on looping.
    while win.checkMouse() == None:

        # move the circle in the current direction.
        circ.move( dx, dy )

        # get the x and y of the center of the circle.
        x = circ.getCenter().getX()
        y = circ.getCenter().getY()

        # if the center of the ball is outside the right or left boundary,
        # reverse the x direction of movement.
        if  x > 600 - radius or  x < radius: 
            dx = -dx
        if  y > 400 - radius or y < radius:
            dy = -dy

        # if the center of the ball is inside the first obstacle, stop
        # the ball.
        if  x1 < x < x2 and y1 < y < y2 :
            dx = 0
            dy = 0

        # if the center of the ball is inside the second obstacle, bounce
        # off
        if  x3 < x < x4 and y3 < y < y4 :
            dx = -dx
            dy = -dy

    
    # if we're here, it's because the the user clicked on the graphic window.
    # we can close everything and quit.
    win.close()    

main()


demo6.py


# Uses graphics.py from Zelle
#
# This program displays the basic elements of a program
#
from graphics import *

# ifInside: returns true of the coordinates of a point defined by 
# its coordinates ballX and ballY, are inside the rectangle defined by a top
# left point of coordinates obsX1, obsY1, and a bottom-right point
# with coordinates obsX2, obsY2.   Returns false if the point is outside
# the rectangle.
def isInside( ballX, ballY, obsX1, obsY1, obsX2, obsY2 ):
    if obsX1 < ballX < obsX2 and obsY1 < ballY < obsY2:
        return True
    else:
        return False

    
def main():
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )

    # create a green obstacle in the middle of the window
    x1 = 200
    y1 = 200
    x2 = 250
    y2 = 250 
    obstacle1 = Rectangle( Point( x1, y1 ), Point( x2, y2 ) )
    obstacle1.setFill( "green" )
    obstacle1.draw( win )

    # create another green rectangle on the right of the first one
    x3 = 350
    y3 = 200
    x4 = 400
    y4 = 250 
    obstacle2 = Rectangle( Point( x3, y3 ), Point( x4, y4 ) )
    obstacle2.setFill( "magenta" )
    obstacle2.draw( win )
    
    # create and draw a red circle
    radius = 30
    center = Point( 100, 100 )
    circ = Circle( center, radius )
    circ.setFill( 'red' )
    circ.draw( win )

    # define the direction the circle will start moving in.
    # 5 pixels to the right every move, and 0.25 pixels down
    # every move.
    dx = 5.111
    dy = -2.51

    # as long as the mouse hasn't been clicked on the window
    # keep on looping.
    while win.checkMouse() == None:

        # move the circle in the current direction.
        circ.move( dx, dy )

        # get the x and y of the center of the circle.
        x = circ.getCenter().getX()
        y = circ.getCenter().getY()

        # if the center of the ball is outside the right or left boundary,
        # reverse the x direction of movement.
        if  x > 600 - radius or  x < radius: 
            dx = -dx
        if  y > 400 - radius or y < radius:
            dy = -dy

        # if the center of the ball is inside the first obstacle, stop
        # the ball.
        if  isInside( x, y, x1, y1, x2, y2 ):
            dx = 0
            dy = 0

        # if the center of the ball is inside the second obstacle, bounce
        # off
        if  isInside( x, y, x3, y3, x4, y4 ):
            dx = -dx
            dy = -dy

    
    # if we're here, it's because the the user clicked on the graphic window.
    # we can close everything and quit.
    win.close()    

main()


demo7.py


# Uses graphics.py from Zelle
#
# This program displays the basic elements of a program
#
from graphics import *

# ifInside: returns true of the coordinates of a point defined by 
# its coordinates ballX and ballY, are inside the rectangle defined by a top
# left point of coordinates obsX1, obsY1, and a bottom-right point
# with coordinates obsX2, obsY2.   Returns false if the point is outside
# the rectangle.
def isInside( ballX, ballY, obsX1, obsY1, obsX2, obsY2 ):
    if obsX1 < ballX < obsX2 and obsY1 < ballY < obsY2:
        return True
    else:
        return False

def isLeftSide( x, y, width ):
    if x < width//2:
        return True
    else:
        return False
    
def main():
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )

    # create a green obstacle in the middle of the window
    x1 = 200
    y1 = 200
    x2 = 250
    y2 = 250 
    obstacle1 = Rectangle( Point( x1, y1 ), Point( x2, y2 ) )
    obstacle1.setFill( "green" )
    obstacle1.draw( win )

    # create another green rectangle on the right of the first one
    x3 = 350
    y3 = 200
    x4 = 400
    y4 = 250 
    obstacle2 = Rectangle( Point( x3, y3 ), Point( x4, y4 ) )
    obstacle2.setFill( "magenta" )
    obstacle2.draw( win )
    
    # create and draw a red circle
    radius = 30
    center = Point( 100, 100 )
    circ = Circle( center, radius )
    circ.setFill( 'red' )
    circ.draw( win )

    # define the direction the circle will start moving in.
    # 5 pixels to the right every move, and 0.25 pixels down
    # every move.
    dx = 5.111
    dy = -2.51

    # as long as the mouse hasn't been clicked on the window
    # keep on looping.
    while win.checkMouse() == None:

        # move the circle in the current direction.
        circ.move( dx, dy )

        # get the x and y of the center of the circle.
        x = circ.getCenter().getX()
        y = circ.getCenter().getY()

        # if the center of the ball is outside the right or left boundary,
        # reverse the x direction of movement.
        if  x > 600 - radius or  x < radius: 
            dx = -dx
        if  y > 400 - radius or y < radius:
            dy = -dy

        # if the center of the ball is inside the first obstacle, stop
        # the ball.
        if  isInside( x, y, x1, y1, x2, y2 ):
            dx = 0
            dy = 0

        # if the center of the ball is inside the second obstacle, bounce
        # off
        if  isInside( x, y, x3, y3, x4, y4 ):
            dx = -dx
            dy = -dy

        # if the ball is on the left side of the window, its color is
        # red, else its color is yellow.
        if isLeftSide( x, y, win.getWidth() )==True:
            circ.setFill( 'red' )
        else:
            circ.setFill( 'yellow' )
            
    
    # if we're here, it's because the the user clicked on the graphic window.
    # we can close everything and quit.
    win.close()    

main()



demo8.py


# Uses graphics.py from Zelle
#
# This program displays the basic elements of a program
#
from graphics import *

# ifInside: returns true of the coordinates of a point defined by 
# its coordinates ballX and ballY, are inside the rectangle defined by a top
# left point of coordinates obsX1, obsY1, and a bottom-right point
# with coordinates obsX2, obsY2.   Returns false if the point is outside
# the rectangle.
def isInside( ballX, ballY, obsX1, obsY1, obsX2, obsY2 ):
    if obsX1 < ballX < obsX2 and obsY1 < ballY < obsY2:
        return True
    else:
        return False

def isLeftSide( x, y, width ):
    if x < width//2:
        return True
    else:
        return False

def getColor( x, y, w, h ):
    if x < w/2 and y < h/2:
        return 'yellow'
    elif x < w/2 and y > h/2:
        return 'blue'
    elif x > w/2 and y < h/2:
        return 'red'
    else:
        return 'brown'
        
def main():
    win = GraphWin( "Lab 7 Moving ball", 600, 400 )

    # create a green obstacle in the middle of the window
    x1 = 200
    y1 = 200
    x2 = 250
    y2 = 250 
    obstacle1 = Rectangle( Point( x1, y1 ), Point( x2, y2 ) )
    obstacle1.setFill( "green" )
    obstacle1.draw( win )

    # create another green rectangle on the right of the first one
    x3 = 350
    y3 = 200
    x4 = 400
    y4 = 250 
    obstacle2 = Rectangle( Point( x3, y3 ), Point( x4, y4 ) )
    obstacle2.setFill( "magenta" )
    obstacle2.draw( win )
    
    # create and draw a red circle
    radius = 30
    center = Point( 100, 100 )
    circ = Circle( center, radius )
    circ.setFill( 'red' )
    circ.draw( win )

    # define the direction the circle will start moving in.
    # 5 pixels to the right every move, and 0.25 pixels down
    # every move.
    dx = 5.111
    dy = -2.51

    # as long as the mouse hasn't been clicked on the window
    # keep on looping.
    while win.checkMouse() == None:

        # move the circle in the current direction.
        circ.move( dx, dy )

        # get the x and y of the center of the circle.
        x = circ.getCenter().getX()
        y = circ.getCenter().getY()

        circ.setFill( getColor( x, y, win.getWidth(), win.getHeight() ) )
                   
        # if the center of the ball is outside the right or left boundary,
        # reverse the x direction of movement.
        if  x > 600 - radius or  x < radius: 
            dx = -dx
        if  y > 400 - radius or y < radius:
            dy = -dy

        # if the center of the ball is inside the first obstacle, stop
        # the ball.
        if  isInside( x, y, x1, y1, x2, y2 ):
            dx = 0
            dy = 0

        # if the center of the ball is inside the second obstacle, bounce
        # off
        if  isInside( x, y, x3, y3, x4, y4 ):
            dx = -dx
            dy = -dy

        # if the ball is on the left side of the window, its color is
        # red, else its color is yellow.
        """
        if isLeftSide( x, y, win.getWidth() )==True:
            circ.setFill( 'red' )
        else:
            circ.setFill( 'yellow' )
        """ 
    
    # if we're here, it's because the the user clicked on the graphic window.
    # we can close everything and quit.
    win.close()    

main()



</showafterdate>