Adjust the following script to simulate the movement of a billiard ball to work
ID: 3663985 • Letter: A
Question
Adjust the following script to simulate the movement of a billiard ball to work for rectangular pool tables.
from tkinter import Tk, Canvas, Button, W, E
import random
from math import pi, sin, cos
class BilliardBall(object):
"""
GUI to simulate billiard ball movement.
"""
def __init__(self, wdw, dimension, increment, delay):
"""
Determines the layout of the GUI.
wdw : top level widget, the main window,
dimension : determines the size of the canvas,
increment : step size for a billiard move,
delay : time between updates of canvas.
"""
wdw.title('a pool table')
self.dim = dimension # dimension of the canvas
self.inc = increment
self.dly = delay
self.togo = False # state of animation
# initial coordinates of the ball
self.xpt = random.randint(10, self.dim-10)
self.ypt = random.randint(10, self.dim-10)
self.cnv = Canvas(wdw, width=self.dim,
height=self.dim, bg='green')
self.cnv.grid(row=0, column=0, columnspan=2)
self.bt0 = Button(wdw, text='start',
command=self.start)
self.bt0.grid(row=1, column=0, sticky=W+E)
self.bt1 = Button(wdw, text='stop',
command=self.stop)
self.bt1.grid(row=1, column=1, sticky=W+E)
def map2table(self, pnt):
"""
Keeps the ball on the pool table.
"""
if pnt < 0:
(quo, rest) = divmod(-pnt, self.dim)
else:
(quo, rest) = divmod(pnt, self.dim)
if quo % 2 == 1:
rest = self.dim - rest
return rest
def drawball(self):
"""
Draws the ball on the pool table.
"""
xpt = self.map2table(self.xpt)
ypt = self.map2table(self.ypt)
self.cnv.delete('dot')
self.cnv.create_oval(xpt-6, ypt-6, xpt+6, ypt+6,
width=1, outline='black', fill='red', tags='dot')
def animate(self):
"""
Performs the animation.
"""
self.drawball()
angle = random.uniform(0, 2*pi)
vcx = cos(angle)
vsy = sin(angle)
while self.togo:
(xpt, ypt) = (self.xpt, self.ypt)
self.xpt = xpt + vcx*self.inc
self.ypt = ypt + vsy*self.inc
self.cnv.after(self.dly)
self.drawball()
self.cnv.update()
def start(self):
"""
Starts the animation.
"""
self.togo = True
self.animate()
def stop(self):
"""
Stops the animation.
"""
self.togo = False
def main():
"""
Defines the dimensions of the canvas
and launches the main event loop.
"""
top = Tk()
dimension = 400 # dimension of pool table
increment = 10 # increment for coordinates
delay = 60 # how much sleep before update
BilliardBall(top, dimension, increment, delay)
top.mainloop()
if __name__ == "__main__":
main()
Explanation / Answer
from tkinter import Tk, Canvas, Button, W, E
import random
from math import pi, sin, cos
class BilliardBall(object):
"""
GUI to simulate billiard ball movement.
"""
def __init__(self, wdw, dimension, increment, delay):
"""
Determines the layout of the GUI.
wdw : top level widget, the main window,
dimension : determines the size of the canvas,
increment : step size for a billiard move,
delay : time between updates of canvas.
"""
wdw.title('a pool table')
self.dim = dimension # dimension of the canvas
self.inc = increment
self.dly = delay
self.togo = False # state of animation
# initial coordinates of the ball
self.xpt = random.randint(10, self.dim-10)
self.ypt = random.randint(10, self.dim-10)
self.cnv = Canvas(wdw, width=self.dim,
height=self.dim, bg='green')
self.cnv.grid(row=0, column=0, columnspan=2)
self.bt0 = Button(wdw, text='start',
command=self.start)
self.bt0.grid(row=1, column=0, sticky=W+E)
self.bt1 = Button(wdw, text='stop',
command=self.stop)
self.bt1.grid(row=1, column=1, sticky=W+E)
def map2table(self, pnt):
"""
Keeps the ball on the pool table.
"""
if pnt < 0:
(quo, rest) = divmod(-pnt, self.dim)
else:
(quo, rest) = divmod(pnt, self.dim)
if quo % 2 == 1:
rest = self.dim - rest
return rest
def drawball(self):
"""
Draws the ball on the pool table.
"""
xpt = self.map2table(self.xpt)
ypt = self.map2table(self.ypt)
self.cnv.delete('dot')
self.cnv.create_oval(xpt-6, ypt-6, xpt+6, ypt+6,
width=1, outline='black', fill='red', tags='dot')
def animate(self):
"""
Performs the animation.
"""
self.drawball()
angle = random.uniform(0, 2*pi)
vcx = cos(angle)
vsy = sin(angle)
while self.togo:
(xpt, ypt) = (self.xpt, self.ypt)
self.xpt = xpt + vcx*self.inc
self.ypt = ypt + vsy*self.inc
self.cnv.after(self.dly)
self.drawball()
self.cnv.update()
def start(self):
"""
Starts the animation.
"""
self.togo = True
self.animate()
def stop(self):
"""
Stops the animation.
"""
self.togo = False
def main():
"""
Defines the dimensions of the canvas
and launches the main event loop.
"""
top = Tk()
dimension = 400 # dimension of pool table
increment = 10 # increment for coordinates
delay = 60 # how much sleep before update
BilliardBall(top, dimension, increment, delay)
top.mainloop()
if __name__ == "__main__":
main()
Related Questions
drjack9650@gmail.com
Navigate
Integrity-first tutoring: explanations and feedback only — we do not complete graded work. Learn more.