Tkinter Canvas Handling of racket and ball collisions
In the execution result of the above program, the ball touches the racket basically to penetrate through, this section will explain the handling of collision. First you can add passing the Racket class to the Ball class as shown below.
class Ball:
def __init__(self, canvas, color, winW, winH, racket):
self.canvas = canvas
self.racket = racket
Of course, the call method needs to be modified when creating the Ball class object in the main program as follows.
racket = Racket(canvas, 'purple') # Define purple racket
ball = Ball(canvas, 'yellow', winW, winH, racket) # Define the ball object
In the Ball class, we need to add a method to see if the ball touches the racket, and if so, let the ball bounce up the path.
if self.hitRacket(ballPos) == True: # Detects if the racket is hit
self.y = -step
In the Ball class ballMove () method above the need to add the following hitRacket () method to detect whether the ball collision racket, if the collision will return True, otherwise return False.
def hitRacket(self,ballPos):
racketPos = self.canvas.coords(self.racket.id)
if ballPos[2] >= racketPos[0] and ballPos[0] <= racketPos[2]:
if ballPos[3] >= racketPos[1] and ballPos[3] <= racketPos[3]:
return True
return False
The above detection of whether the ball has hit the racket must meet the following two conditions.
(1) The right x-coordinate of the ball, ballPos[2], is greater than the left x-coordinate of the racket, racketPos[0], while the left x-coordinate of the ball, ballPos[0], is less than the right x-coordinate of the racket, racketPos[2].
(2) The y-coordinate ballPos[3] below the ball is greater than the y-coordinate racketPos[1] above the racket, and must be less than the y-coordinate racketPos[3] below the racket. The reader may wonder why the detection does not just touch the top of the racket, mainly because the ball does not move 1 pixel at a time, if it moves 3 pixels, it will probably skip the top of the racket.
Below is an illustration of the possible ways the ball can move.
Example#1
当球碰撞到球拍时会反弹。下面是完整的Ball类设计。
from tkinter import *
from random import *
import time
class Ball:#class Ball():#It is the same when written like this
def __init__(self,canvas,color,winW,winH,racket):
self.canvas = canvas
self.canvas = canvas
self.id = canvas.create_oval(0, 0, 20, 20, fill=color) # create ball object
self.canvas.move(self.id,winW/2,winH/2) # set the initial position of the ball
startPos = [-4, -3, -2, -1, 1, 2, 3, 4] # random number of initial x-axis movements of the ball
shuffle(startPos) # upset the ordering
self.x = startPos[0] # initial horizontal movement of the ball in units
self.y = step # vertical movement units
def hitRacket(self,ballPos):
racketPos = self.canvas.coords(self.racket.id)
if ballPos[2] >= racketPos[0] and ballPos[0] <= racketPos[2]:
if ballPos[3] >= racketPos[1] and ballPos[3] <= racketPos[3]:
return True
return False
def ballMove(self):
self.canvas.move(self.id, self.x, self.y) # step is a positive value to move down
ballPos = self.canvas.coords(self.id)
if ballPos[0] <= 0: # detect if the ball is over the left side of the canvas
self.x = step
if ballPos[1] <= 0: # detect if the ball is over the top of the canvas
self.y = step
if ballPos[2] >= winW: # detect if the ball goes over the right side of the canvas
self.x = -step
if ballPos[3] >= winH: # detect if the ball is over the bottom of the canvas
self.y = -step
if self.hitRacket(ballPos): # detect if the ball hits the racket
self.y = -step
class Racket():
def __init__(self, canvas, color):
self.canvas = canvas
self.id = canvas.create_rectangle(0,0,100,15,fill=color) # Racket Object
self.canvas.move(self.id, 270, 400)
self.x = 0
self.canvas.bind_all('<KeyPress-Right>',self.moveRight) # Bind Press and hold the right button ##########################
self.canvas.bind_all('<KeyPress-Left>',self.moveLeft) # Bind Press and hold the left button
def racketMove(self):
self.canvas.move(self.id,self.x,0)
pos = self.canvas.coords(self.id)
# self.x = 0
if pos[0] <= 0:
self.x = 0
elif pos[2] >= winW:
self.x = 0
def moveLeft(self,event):
print("Press the left button")
self.x = -3
def moveRight(self,event):
print("Press the right button")
self.x = 3
winW = 640 # Defines the width of the canvas
winH = 480 # Defines the height of the canvas
step = 3 # Define the speed as a displacement step
speed = 0.03 # Set the speed of movement
tk = Tk()
tk.title("Bouncing Ball apidemos") # Game window title
tk.wm_attributes('-topmost',1) # Make sure the game window is at the top of the screen
canvas = Canvas(tk,width=winW, height=winH) # Create a canvas
canvas.pack()
tk.update()
# The order in which the following two lines of code are executed determines which object is obscured when the two overlap
racket = Racket(canvas,'purple') # Define purple racket
ball = Ball(canvas,'yellow',winW,winH,racket) # Defines the ball object
while True:
ball.ballMove()
racket.racketMove()
tk.update()
time.sleep(speed) # Can control the speed of movement
# tk.mainloop()
Output: