# L-15 MCS 507 Mon 26 Sep 2011 : basic GUI for billiard ball

from Tkinter import *
import random,math

class BilliardBall():
   """
   GUI to simulate billiard ball movement.
   """
   def __init__(self,wdw,dimension,increment,delay):
      "determines the layout of the GUI"
      wdw.title('a pool table')
      self.dim = dimension # dimension of the canvas
      self.inc = increment
      self.dly = delay
      self.go = False # state of animation
      # initial coordinates of the ball
      self.x = random.randint(10,self.dim-10)
      self.y = random.randint(10,self.dim-10)
      self.c = Canvas(wdw,width=self.dim,\
        height=self.dim,bg ='green')
      self.c.grid(row=0,column=0,columnspan=2)
      self.b0 = Button(wdw,text='start',\
        command = self.start)
      self.b0.grid(row=1,column=0,sticky=W+E)
      self.b1 = Button(wdw,text='stop',\
        command = self.stop)
      self.b1.grid(row=1,column=1,sticky=W+E)

   def MapToTable(self,p):
      "keeps the ball on the pool table"
      if p < 0:
         (q,r) = divmod(-p,self.dim)
      else:
         (q,r) = divmod(p,self.dim)
      if q % 2 == 1:
         r = self.dim - r
      return r

   def DrawBall(self):
      "draws the ball on the pool table"
      x = self.MapToTable(self.x)
      y = self.MapToTable(self.y)
      self.c.delete('dot')
      self.c.create_oval(x-6,y-6,x+6,y+6,width=1,\
        outline='black',fill='red',tags='dot')

   def animate(self):
      "performs the animation"
      self.DrawBall()
      angle = random.uniform(0,2*math.pi)
      vx = math.cos(angle)
      vy = math.sin(angle)
      while self.go:
         x = self.x; y = self.y
         self.x = x + vx*self.inc
         self.y = y + vy*self.inc
         self.c.after(self.dly)
         self.DrawBall()
         self.c.update()

   def start(self):
      "starts the animation"
      self.go = True
      self.animate()

   def stop(self):
      "stops the animation"
      self.go = False
  
def main():
   top = Tk()
   dimension = 400 # dimension of pool table
   increment = 10  # increment for coordinates
   delay = 60      # how much sleep before update
   show = BilliardBall(top,dimension,increment,delay)
   top.mainloop()

if __name__ == "__main__": main()
