'''
Show a ball bouncing off the sides of the window.
'''
from graphics import *
import time, random, math
RADIUS = 10
MYHITS=0
THEIRHITS=0
WIN = None
WINX=300
WINY=WINX + 100 # must be > WINX
MSG = None
HOMERECT = None
def bounceInBox(ball1, dx1, dy1, xLow, xHigh, yLow, yHigh):
''' Animate a shape moving in jumps (dx, dy), bouncing when
its center reaches the low and high x and y coordinates.
'''
global HOMERECT, MYHITS, THEIRHITS
delay = .03
for i in range(6000):
ball1.move(dx1, dy1)
center1 = ball1.getCenter()
x1 = center1.getX()
y1 = center1.getY()
if x1 < xLow or x1 > xHigh:
dx1 = -dx1
if y1 < yLow:
dy1 = -dy1
elif y1 > yHigh: # the invaders got you
THEIRHITS+=1
printscore()
return
p = WIN.checkMouse()
if p != None and isInside(p, HOMERECT):
l = Line(p, Point(p.getX(), xLow))
l.setFill("black")
l.draw(WIN)
time.sleep(delay)
l.undraw()
if isBelow(p, center1, RADIUS): # you got the invader
ball1.undraw()
MYHITS +=1
printscore()
return
time.sleep(delay) # end of loop
def isInside(point, rect):
'''Return True if the point is inside the Rectangle rect.'''
pt1 = rect.getP1()
pt2 = rect.getP2()
return isBetween(point.getX(), pt1.getX(), pt2.getX()) and \
isBetween(point.getY(), pt1.getY(), pt2.getY())
def isBetween(x, end1, end2):
'''Return True if x is between the ends or equal to either.
The ends do not need to be in increasing order.'''
return end1 <= x <= end2 or end2 <= x <= end1
def isBelow(p1,p2,r):
''' true if p2 is below p1, with a horizontal error of at most r '''
x1 = p1.getX()
y1 = p2.getX()
if abs(x1-y1) < r: return True
return False
def getRandomPoint(xLow, xHigh, yLow, yHigh):
'''Return a random Point with coordinates in the range specified.'''
x = random.randrange(xLow, xHigh+1)
y = random.randrange(yLow, yHigh+1)
return Point(x, y)
def makeDisk(center, radius, color):
'''return a red disk that is drawn in win with given center and radius.'''
disk = Circle(center, radius)
disk.setOutline(color)
disk.setFill(color)
disk.draw(WIN)
return disk
def printscore():
''' prints the score, hopefully within WIN. Why is MSG global here? '''
global MSG
if type(MSG) == Text: MSG.undraw()
MSG = Text(Point(WINX/2, WINX+75), 'your hits: {} attacker hits: {}'.format(MYHITS, THEIRHITS))
MSG.draw(WIN)
# bounceBall() is set up for two balls, but just one is used initially
def bounceBall(dx1, dy1):
global WIN, HOMERECT
'''Make a ball bounce around the screen, initially moving by (dx, dy)
at each jump.'''
#pld win.yUp()
xLow = RADIUS # center is separated from the wall by the radius at a bounce
xHigh = WIN.getWidth() - RADIUS
yLow = RADIUS
yHigh = WIN.getHeight() - RADIUS - 100
lineofdeath = Line(Point(0,WINX), Point(WINX,WINX))
lineofdeath.draw(WIN)
center1 = getRandomPoint(xLow, xHigh, yLow, yHigh)
center1 = Point(xLow, yLow)
ball1 = makeDisk(center1, RADIUS, "red")
HOMERECT = Rectangle(Point(0,WINX), Point(WINX, WINX+50))
HOMERECT.setOutline("green")
HOMERECT.setFill("green")
HOMERECT.draw(WIN)
bounceInBox(ball1, dx1, dy1, xLow, xHigh, yLow, yHigh)
#pld win.close()
#bounceBall(5, 0.5)
def play():
global WIN
WIN = GraphWin('Invaders', WINX, WINY)
for i in range(10):
bounceBall(5, 0.5)
play()