CSC111 Homework 6 Solution Programs 2011
--D. Thiebaut 15:33, 7 November 2011 (EST)
Moving Balls
Program 1
Program 2
- This version implements fully elastic collision and respects the laws of physics, even giving the two balls a mass proportional to their radii.
[15:32:56] ~/classes/111/Submitted/2011/hw6/111a-ar$: cat hw6a.py
- hw6a.py
- 111a-ar
- Gavi Levy Haskell
- This program is an adaptation of the hw6a Demo Program.
- Two balls, one turquoise and one blue, bounce off the
- walls, each other, and a white box, and stop if they
- completely enter one of three black boxes, or if the
- program goes through 1000 steps.
- NOTE: The circles bounce "realistically" assuming that:
- The speeds never exceed those which Newton's equations
- work for
- All collisions occur along the x-y axis (not true for
- virtually any collision, but a fair approximation for
- most blows, less good for glancing blows)
- The masses of the circles are relative to each other,
- imagining them to be 2D representations of 3D figures
- (spheres, to be precise)
- The world has no friction, either between objects or
- with the ground
- The collisions are perfectly elastic
from graphics import *
import random
def distance(P1, P2):
"""distance formula """ return (( (P1.getX() - P2.getX())**2 + (P1.getY() - P2.getY())**2)**.5)
def velocity():
"""picks a random velocity between -5 and 5, not 0 """ v = 0 while True: v = random.randrange(-5, 5) if v!=0: return v
def main():
#sets up graphics window w = 600 h = 300 win = GraphWin("111a-ar: Ten to the Fifteenth", w, h) win.setBackground("black")
#picks random radii r1 = random.randrange(10, 20) #radius r2 = random.randrange(10, 20) #radius
#calls velocity for all four velocities of the #circle vx1 = velocity() vy1 = velocity() vx2 = velocity() vy2 = velocity()
#draws circles at random locations c1 = Circle(Point(random.randrange(r1, w//2), random.randrange(r1, h//2 - r1)), r1) c1.setWidth(0) c1.setFill("turquoise") c1.draw(win)
c2 = Circle(Point(random.randrange(r2, w//2), random.randrange(h//2, h - r2)), r2) c2.setWidth(0) c2.setFill("blue") c2.draw(win)
#draws white box rw = Rectangle(Point(400, 200), Point(500, 250)) rw.setWidth(0) rw.setFill("white") rw.draw(win)
#draws three black boxes boxes = [[10, 240, 80, 290], [250, 80, 350, 130], [520, 40, 570, 120]] for i in range(3): a, b, c, d = boxes[i] rb = Rectangle(Point(a,b), Point(c,d)) rb.setOutline("white") rb.setWidth(2) rb.draw(win)
#loop to move circles for i in range(1000): #assigns locations of circles to variables x1 = c1.getCenter().getX() y1 = c1.getCenter().getY() x2 = c2.getCenter().getX() y2 = c2.getCenter().getY()
#variable to allow for turning off inter- #action between circles when in black box n = 0
#traps circles in black boxes for j in range(3): a,b,c,d = boxes[j] #margin for circle 1 xl1 = a + r1 yu1 = b + r1 xr1 = c - r1 yb1 = d - r1 #if circle is inside box if xl1 < x1 < xr1 and yu1 < y1 < yb1: vx1 = 0 #set velocities vy1 = 0 #to zero n = 1 #indicates circle is in box #margin for circle 2 xl2 = a + r2 yu2 = b + r2 xr2 = c - r2 yb2 = d - r2 #if circle is inside box if xl2 < x2 < xr2 and yu2 < y2 < yb2: vx2 = 0 #set velocities vy2 = 0 #to zero n = 1 #indicates circle is in box
#breaks if circles have been trapped if vx1 == 0 and vy1 == 0 and vx2 == 0 and vy2 == 0: break
#lets circles bounce off white box #FIRST CIRCLE lb1 = 400 - r1 #left bound for first circle rb1 = 500 + r1 #right bound ub1 = 200 - r1 #upper bound bb1 = 250 + r1 #lower bound if lb1 < x1 < rb1 and ub1 < y1 < bb1: if 400 > x1: #on left side vx1 = -abs(vx1) #bounce left if 500 < x1: #on right side vx1 = abs(vx1) #bounce right if 200 > y1: #above vy1 = -abs(vy1) #bounce up if 250 < y1: #below vy1 = abs(vy1) #bounce down #SECOND CIRCLE lb2 = 400 - r2 #left bound for second circle rb2 = 500 + r2 #right bound ub2 = 200 - r2 #upper bound bb2 = 250 + r2 #lower bound if lb2 < x2 < rb2 and ub2 < y2 < bb2: if 400 > x2: #on left side vx2 = -abs(vx2) #bounce left if 500 < x2: #on right side vx2 = abs(vx2) #bounce right if 200 > y2: #above vy2 = -abs(vy2) #bounce up if 250 < y2: #below vy2 = abs(vy2) #bounce down
#lets circles bounce off walls (w/o sticking) #circle 1 if x1 < r1 + 5: #left side vx1 = abs(vx1) if x1 > w - r1: #right side vx1 = -abs(vx1) if y1 < r1 + 5: #top vy1 = abs(vy1) if y1 > h - r1: #bottom vy1 = -abs(vy1) #circle 2 if x2 < r2 + 5: #left side vx2 = abs(vx2) if x2 > w - r2: #right side vx2 = -abs(vx2) if y2 < r2 + 5: #top vy2 = abs(vy2) if y2 > h - r2: #bottom vy2 = -abs(vy2)
#lets circles bounce off each other #distance between circles dc = distance(c1.getCenter(), c2.getCenter()) if dc <= (r1 + r2) and n == 0: #"masses" of circles (relative, 3D) m1 = r1*r1*r1 m2 = r2*r2*r2 #elastic collisions a1 = (vx1*(m1 - m2) + 2*m2*vx2)/(m1 + m2) a2 = (vx2*(m2 - m1) + 2*m1*vx1)/(m1 + m2) b1 = (vy1*(m1 - m2) + 2*m2*vy2)/(m1 + m2) b2 = (vy2*(m2 - m1) + 2*m1*vy1)/(m1 + m2)
vx1 = a1 vx2 = a2 vy1 = b1 vy2 = b2
#moves circles c1.move(vx1, vy1) c2.move(vx2, vy2)
text = Text(Point(w//2, h//2), "Click to quit") text.setFill("white") text.draw(win) win.getMouse() win.close()
main() [xgridmac] [15:33:04] ~/classes/111/Submitted/2011/hw6/111a-ar$: