Henry Pham
Henry Pham

Reputation: 1

How to make objects bounce off each other in canvas

I was trying to make the balls in my program bouncing from each other, but it didn't work and most of the time it just get glitched. Here is the source code of my main:

from tkinter import *
from Ball import *
import time
HEIGHT = 500
WIDTH = 500
window = Tk()


canvas = Canvas(window,height=HEIGHT,width = WIDTH)
canvas.pack()
basket_ball = Ball(canvas,0,0,100,1,1,"orange")
soccer_ball = Ball(canvas,399,399,499,1,1,"black")

while True:
    basket_ball_coords = canvas.coords(basket_ball.image)
    soccer_ball_coords = canvas.coords(soccer_ball.image)
    basket_ball.move()
    soccer_ball.move()
    print (basket_ball_coords)
    print (soccer_ball_coords)
    if basket_ball_coords[2] == soccer_ball_coords[0] and ((soccer_ball_coords[3] - basket_ball_coords[3])<= 100 and (soccer_ball_coords[3] - basket_ball_coords[3])> -101):
        basket_ball.xVelo = -basket_ball.xVelo
        soccer_ball.xVelo = -soccer_ball.xVelo
    if basket_ball_coords[3] == soccer_ball_coords[1] and ((soccer_ball_coords[2]- basket_ball_coords[2]<=100)and (soccer_ball_coords[2] - basket_ball_coords[2])> -101):
        basket_ball.yVelo = -basket_ball.yVelo
        soccer_ball.yVelo = -soccer_ball.yVelo
    if basket_ball_coords[0] == soccer_ball_coords[2] and ((soccer_ball_coords[3] - basket_ball_coords[3]) <= 100 and (soccer_ball_coords[3] - basket_ball_coords[3]) > -101):
        basket_ball.xVelo = -basket_ball.xVelo
        soccer_ball.xVelo = -soccer_ball.xVelo
    if basket_ball_coords[1] == soccer_ball_coords[3] and ((soccer_ball_coords[2]- basket_ball_coords[2]<=100)and (soccer_ball_coords[2] - basket_ball_coords[2])> -101):
        basket_ball.yVelo = -basket_ball.yVelo
        soccer_ball.yVelo = -soccer_ball.yVelo
    window.update()
    time.sleep(0.01)


window.mainloop()

Here is the Ball class I used to create Ball objects

class Ball:
    def __init__ (self,canvas,x,y,diameter,xVelo,yVelo,color):
        self.canvas = canvas
        self.image = canvas.create_oval(x,y,diameter,diameter,fill=color)
        self.xVelo = xVelo
        self.yVelo = yVelo
    def move(self):
        coordinates = self.canvas.coords(self.image)
        if (coordinates[2] >= self.canvas.winfo_width() or coordinates[0] < 0):
            self.xVelo = -self.xVelo
        if (coordinates[3] >= self.canvas.winfo_height() or coordinates[1] < 0):
            self.yVelo = -self.yVelo
        self.canvas.move(self.image,self.xVelo,self.yVelo)

Upvotes: 0

Views: 686

Answers (1)

dirck
dirck

Reputation: 868

The balls "bounce" if the distance between the centers of the balls is less than the sum of their radiuses.

The Pythagorean theorem says the Distance is the square root of the sum of the squares of the x and y deltas.

Assuming:

  • x and y passed are upper left corner (?)
  • self.radius = diameter/2
  • self.center_x = x + self.radius
  • self.center_y = y + self.radius

add to Class Ball:

def intersects_ball(self, other):
    xdelta = self.center_x - other.center_x
    ydelta = self.center_y - other.center_y
    distance = math.sqrt(xdelta*xdelta + ydelta*ydelta)
    return distance < (self.radius + other.radius)

Edited to add:

What happens to the balls when they collide depends on each ball's velocity vector and mass, and presumably the offset angle of collision...

Here are a couple of online examples with source that work:

Upvotes: 2

Related Questions