from tkinter import *
from random import randint

#Return random color #RRGGBB
def getRandomColor():
    color = '#'
    for j in range(6):
        color+= toHexChar(randint(0, 15))
    return color

#Convert an integer to a single hex digit in a character
def toHexChar(hexValue):
    if 0 <= hexValue <= 9:
        return chr(hexValue+ord('0'))
        return chr(hexValue - 10 + ord('A'))

#Define ball class
class Ball:
    def __init__(self):
        self.x = 0
        self.y = 0
        self.dx = 2
        self.dy = 2
        self.radius = 9
        self.color = getRandomColor()

class BounceBalls():
    def __init__(self):
        self.ballList = []
        window = Tk()
        window.title("Bouncing Balls")
        self.width = 350
        self.height = 150
        self.canvas = Canvas(window, bg = "white", width = self.width, height = self.height)

        frame = Frame(window)

        buttonStop = Button(frame, text = "Stop", command = self.stop)
        buttonStop.pack(side = LEFT)

        buttonFaster = Button(frame, text = "Faster", command = self.increaseBallSpeed)
        buttonFaster.pack(side = LEFT)

        buttonSlower = Button(frame, text = "Slower", command = self.decreaseBallSpeed)
        buttonSlower.pack(side = LEFT)

        buttonResume = Button(frame, text = "Resume", command = self.resume)
        buttonResume.pack(side = LEFT)

        buttonAdd = Button(frame, text = "Add", command = self.add)
        buttonAdd.pack(side = LEFT)

        buttonRemove = Button(frame, text = "Remove", command = self.remove)
        buttonRemove.pack(side = LEFT)

        self.sleepTime = 50
        self.isStopped = False

    def stop(self): #Stop animation
        self.isStopped = True

    def resume(self): #Resume animation
        self.isStopped = False

    def add(self): #Add a new ball

    def remove(self): #Remove the last ball

    def animate(self): #Animate ball movements
        while not self.isStopped:
            for ball in self.ballList:

    def increaseBallSpeed(self):
        if self.sleepTime <= 10:
            self.sleepTime = 10

    def decreaseBallSpeed(self):

    def redisplayBall(self, ball):
        if ball.x > self.width or ball.x < 0:
            ball.dx = -ball.dx
        if ball.y > self.height or ball.y < 0:
            ball.dy = -ball.dy

        ball.x += ball.dx
        ball.y += ball.dy
        self.canvas.create_oval(ball.x - ball.radius, ball.y - ball.radius,
                                ball.x + ball.radius, ball.y + ball.radius,
                                fill = ball.color, tags = "ball")


I'm copying this program from my book and I've added a few things of my own such as the remove, slower, faster and stop methods. I'm having issues understanding the redisplayBall method, quite a lot of code in there to process and I'm not entirely sure I understand it.

I'm trying to think of how I can expand on this program, perhaps add some collision detection logic or allow the balls the be controlled when you click and drag them. Not sure how to go about this though. Would someone mind explaining to me why the balls travel through each other and how I might approach solving this problem? Thanks.

P.S I'm really really bad at math.

Did you ever tried to run the example from the book and saw if it worked?

Of course it works. It's Python 3.x so make sure you're using the correct IDE.

Hmmm, when I copy the code from here and paste it into my IDE, the indenatation disappears... not very helpful for people who want to copy and paste the code from the forum into their IDE.

Is the code not working guys?

You need to double click on the code field which will highlight the code. Now you can copy and paste it to an IDE editor.

The code works. Initially you may want to tell the user to click add. Once you have more than 2 balls collision response will be a code nightmare.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.