'''
Show a ball bouncing off the sides of the window.
User always has mouse control over the direction and speed of the ball.
'''
from graphics import *
import time, random
def bounceInBox(shape, dx, dy, xLow, xHigh, yLow, yHigh, win):
''' Animate a shape moving in jumps (dx, dy), bouncing when
its center reaches the low and high x and y coordinates.
The animation stops when the mouse is clicked, and the
last mouse click is returned.'''
delay = .001
win.clearLastMouse() #NEW
pt = None #NEW
while pt == None: #NEW
shape.move(dx, dy)
center = shape.getCenter()
x = center.getX()
y = center.getY()
isInside = True #NEW
if x < xLow or x > xHigh:
dx = -dx
isInside = False #NEW
if y < yLow or y > yHigh:
dy = -dy
isInside = False #NEW
time.sleep(delay)
if isInside: # NEW don't mess with dx, dy when outside
pt = win.getLastMouse() #NEW
return pt #NEW
def moveInBox(shape, stopHeight, xLow, xHigh, yLow, yHigh, win): #NEW
'''Shape bounces in win so its center stays within the low and high
x and y coordinates, and changes direction based on mouse clicks,
terminating when there is a click above stopHeight.'''
scale = 0.01
pt = shape.getCenter() # starts motionless
while pt.getY() < stopHeight:
(dx, dy) = getShift(shape.getCenter(), pt)
pt = bounceInBox(shape, dx*scale, dy*scale,
xLow, xHigh, yLow, yHigh, win)
def makeDisk(center, radius, win):
'''Return a red disk that is drawn in win with given center and radius.'''
disk = Circle(center, radius)
disk.setOutline("red")
disk.setFill("red")
disk.draw(win)
return disk
def getShift(point1, point2):
'''Returns a tuple (dx, dy) which is the shift from point1 to point2.'''
dx = point2.getX() - point1.getX()
dy = point2.getY() - point1.getY()
return (dx, dy)
def bounceBall():
'''Make a ball bounce around the screen, and react to mouse clicks.'''
winWidth = 290
winHeight = 290
win = GraphWin('Ball Bounce 3', winWidth, winHeight)
win.setCoords(0,0,winWidth, winHeight)
#NEW to mark and label the area where a click stops the program
lineHeight = winHeight - 40
textHeight = winHeight - 20
Line(Point(0, lineHeight), Point(winWidth, lineHeight)).draw(win)
prompt = 'Click above the line to stop\nor below to move toward the click.'
Text(Point(winWidth/2, textHeight), prompt).draw(win)
radius = 10
xLow = radius # center is separated from the wall by the radius at a bounce
xHigh = winWidth - radius
yLow = radius
yHigh = lineHeight - radius #NEW lower top to bouncing limits
center = Point(winWidth/2, lineHeight/2)
ball = makeDisk(center, radius, win)
moveInBox(ball, lineHeight, xLow, xHigh, yLow, yHigh, win) #NEW
win.close()
bounceBall()