# Python tkinter bouncing ball animation

In the current code, the animation is very unclear, and not "polished" (it doesn't run smooth).

Can I make the animation smoother? And/or, why it doesn't run smooth?

from tkinter import *
import time

WIDTH = 800
HEIGHT = 500
SIZE = 50
tk = Tk()
canvas = Canvas(tk, width=WIDTH, height=HEIGHT, bg="grey")
canvas.pack()
color = 'black'

class Ball:
def __init__(self):
self.shape = canvas.create_oval(0, 0, SIZE, SIZE, fill=color)
self.speedx = 9 # changed from 3 to 9
self.speedy = 9 # changed from 3 to 9
self.active = True
self.move_active()

def ball_update(self):
canvas.move(self.shape, self.speedx, self.speedy)
pos = canvas.coords(self.shape)
if pos[2] >= WIDTH or pos[0] <= 0:
self.speedx *= -1
if pos[3] >= HEIGHT or pos[1] <= 0:
self.speedy *= -1

def move_active(self):
if self.active:
self.ball_update()
tk.after(40, self.move_active) # changed from 10ms to 30ms

ball = Ball()
tk.mainloop()

• What do you mean "not working as expected"? I provided a working code, and I'm asking for a code review. – sheldonzy Sep 16 '17 at 18:11

Your animation isn't smooth because the ball is jumping 9 pixels for every frame. If you want smooth animation, change your "speed" to a much smaller number.

Animation is a set of trade-offs. The speed is a simple multiplier of how many frames you display each second times how many pixels you move in each frame. As the number of pixels you move goes up, the more jerky the animation will be. Likewise, the more often you update, the faster your animation will go. You need to decide which is more important: smoothness or speed.

• The thing is, when I decrease the speed, and decrease the stop between each update, the animation still doesn't look good. For example, run with speed 2, and update each 10ms and see what happens. – sheldonzy Sep 16 '17 at 18:19
• Those are the only two things you can change to improve the animation in this code. – Bryan Oakley Sep 16 '17 at 18:27

This question was old, but I found it in a search because it was related to an issue I am having. My attempt at fixing this was to try to implement "double-buffering". On my computer, my version of code fixes the clipping that occurs causing 1/4 of the circle to be a square. It's still not as smooth as I'd like though.

from tkinter import *
import time

WIDTH = 800
HEIGHT = 500
SIZE = 50
tk = Tk()
canvas = Canvas(tk, width=WIDTH, height=HEIGHT, bg="blue")
canvas.pack()
color = 'black'

class Ball:
def __init__(self, tag):
self.shape = canvas.create_oval(0, 0, SIZE, SIZE, fill=color, tags=tag)
self.speedx = 9 # changed from 3 to 9
self.speedy = 9 # changed from 3 to 9
self.active = True

def ball_update(self):
canvas.move(self.shape, self.speedx, self.speedy)
pos = canvas.coords(self.shape)
if pos[2] >= WIDTH or pos[0] <= 0:
self.speedx *= -1
if pos[3] >= HEIGHT or pos[1] <= 0:
self.speedy *= -1

global switcher
switcher = True
def cycle():
global switcher
canvas.tag_raise("bg")
if switcher:
ball2.ball_update()
ball2.ball_update()
canvas.tag_raise("ball")
else:
ball.ball_update()
ball.ball_update()
canvas.tag_raise("ball2")