Moving Balls in Tkinter Canvas

Generating Multiple Moving Objects In The Tkinter Canvas

Here is an OOP approach that creates a collection of Ball objects, keeps track of them on the canvas, and updates them at each turn.

import tkinter as tk      # for python 2, replace with import Tkinter as tk
import random

class Ball:

def __init__(self):
self.xpos = random.randint(0, 254)
self.ypos = random.randint(0, 310)
self.xspeed = random.randint(1, 5)
self.yspeed = random.randint(1, 5)

class MyCanvas(tk.Canvas):

def __init__(self, master):

super().__init__(master, width=254, height=310, bg="snow2", bd=0, highlightthickness=0, relief="ridge")
self.pack()

self.balls = [] # keeps track of Ball objects
self.bs = [] # keeps track of Ball objects representation on the Canvas
for _ in range(25):
ball = Ball()
self.balls.append(ball)
self.bs.append(self.create_oval(ball.xpos - 10, ball.ypos - 10, ball.xpos + 10, ball.ypos + 10, fill="saddle brown"))
self.run()

def run(self):
for b, ball in zip(self.bs, self.balls):
self.move(b, ball.xspeed, ball.yspeed)
pos = self.coords(b)
if pos[3] >= 310 or pos[1] <= 0:
ball.yspeed = - ball.yspeed
if pos[2] >= 254 or pos[0] <= 0:
ball.xspeed = - ball.xspeed
self.after(10, self.run)

if __name__ == '__main__':

shop_window = tk.Tk()
shop_window.geometry("254x310")
c = MyCanvas(shop_window)

shop_window.mainloop()

tkinter bouncing ball

I made some modifications in you code. Problem was in speed definition, in you code speed is changed globally 2 times instead of each time for each ball.
Here you go:

from tkinter import *
import time

root = Tk()

def balls():
# define speed for each ball
green_x_speed, green_y_speed = [5,3]
red_x_speed, red_y_speed = [5,3]

canvas = Canvas(root, width=800, height=800, bg="grey")
root.title("collision detection")
canvas.grid()

green_ball = canvas.create_oval(20, 20, 30, 10, fill="green")
red_ball = canvas.create_oval(780, 780, 790, 790, fill="red")

while True:
# green ball
canvas.move(green_ball, green_x_speed, green_y_speed)
green_coordinates = canvas.coords(green_ball)
if green_coordinates[3] >= 800 or green_coordinates[1] <= 0:
green_y_speed = -green_y_speed
if green_coordinates[2] >= 800 or green_coordinates[0] <= 0:
green_x_speed = -green_x_speed

# red ball
canvas.move(red_ball, red_x_speed, red_y_speed)
red_coordinates = canvas.coords(red_ball)
if red_coordinates[3] >= 800 or red_coordinates[1] <= 0:
red_y_speed = -red_y_speed
if red_coordinates[2] >= 800 or red_coordinates[0] <= 0:
red_x_speed = -red_x_speed

time.sleep(0.01)
root.update()

balls()
root.mainloop()

Tkinter moving balls program creating 4 balls instead of 2

The problem is that you changed the class Ball in addition to adding a second ball. The idea of object oriented programming (i.e. in simple words classes in python) is to create a class, here Ball, that defines how ONE generic ball works. You can from this class create as many objects (here ball1, ball2, etc.) as you want.

In your code you just have to

  1. remove the line

    self.ball2 = canvas.create_oval(self.x1, self.y1, self.x2, self.y2, fill="red")

  2. remove the complete move_ball2 function

  3. Change

ball2.move_ball2(x0,y0)

to

ball2.move_ball(x0,y0)

and it will work as expected.



Related Topics



Leave a reply



Submit