Instead of making arbitrary vars to manage the state, you can use variables that get created anyway and hold more meaning than your arbitrary ones. Let's consider something. Right now as your code stands it is very small, but is it going to stay that way? What will dir
mean to you in 1000 lines ... 5000 lines? Is it a direction? Which direction? Is it a directory? Which directory? What if you need your move
code to absolutely stop when you press "a", as opposed to enacting one last lingering process? Your dir
var can't manage that.
Another thing to consider is your bind_all
. Is that really necessary? Do you really want to add an event listener to every last child of root? As it stands currently, all that is necessary is to force the focus back to the root and only use 1 event listener. That could break for you in the future, but it doesn't have to.
Moving your ball 1 pixel at a time is not smart. Doing so forces you to rely on how fast you can call the move function again for speed. This will be different from one computer to the next and your game will never run reliably. Your player should have a move speed and that speed should become smaller or greater to compensate for the current frames-per-second. This way, the game always runs at the exact same speed, no-matter-what. It will just appear more choppy as the fps drops, but appearance or not the actual distance traveled of everything is identical. If everything remains identical regardless of performance, then everything also remains predictable. Imagine a multiplayer game played between 2 people, one running at 60 fps and the other at 30. How could you be sure of anything if everything moves half as much for the second person?
import tkinter as tk
root = tk.Tk()
canvas = tk.Canvas(root, width=500, height=400, bd=0, highlightthickness=0)
canvas.pack()
circle = canvas.create_oval(50, 50, 80, 80, fill="yellow")
update_id = None
def update():
global update_id
canvas.move(circle, 0, 5)
#this id gets created whether you use it or not ... so use it.
update_id = root.after(1000//60, update)
root.bind("a", lambda e:root.after_cancel(update_id))
root.focus_force()
update()
root.mainloop()