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
remove the line
self.ball2 = canvas.create_oval(self.x1, self.y1, self.x2, self.y2, fill="red")
remove the complete move_ball2 function
Change
ball2.move_ball2(x0,y0)
to
ball2.move_ball(x0,y0)
and it will work as expected.
Related Topics
Control the Size Textarea Widget Look in Django Admin
Python How to Parse CSS File as Key Value
How to Highlight Searched Queries in Result Page of Django Template
Using Beautiful Soup to Convert CSS Attributes to Individual HTML Attributes
Find in Files Using Ruby or Python
Aes Python Encryption and Ruby Encryption - Different Behaviour
How to Import a JSON from a File on Cloud Storage to Bigquery
R Markdown: How to Make Rstudio Display Python Plots Inline Instead of in New Window
How to Add Sum to Zero Constraint to Glm in Python
Integration Testing for a Web App
How to Write a Perl, Python, or Ruby Program to Change the Memory of Another Process on Windows
Convert Backward Slash to Forward Slash in Python
R's Which() and Which.Min() Equivalent in Python
Django: Redirect to Previous Page After Login
Detect & Record Audio in Python