Tkinter Canvas 球拍与球碰撞的处理

Tkinter Canvas 球拍与球碰撞的处理

在上述程序的执行结果中,球碰到球拍基本上是可以穿透过去,本节将讲解碰撞的处理。首先可以增加将Racket类传给Ball类,如下所示。

class Ball:
    def __init__(self, canvas, color, winW, winH, racket):
        self.canvas = canvas
        self.racket = racket

当然在主程序中建立Ball类对象时需修改调用方法如下。

racket = Racket(canvas, 'purple')                   # 定义紫色球拍
ball = Ball(canvas, 'yellow', winW, winH, racket)   # 定义球对象

在Ball类中需增加是否球碰到球拍的方法,如果碰到就让球沿路径往上反弹。

if self.hitRacket(ballPos) == True:                 # 侦测是否撞到球拍
    self.y = -step

在Ball类的ballMove( )方法上方需增加下列hitRacket( )方法,检测球是否碰撞球拍,如果碰撞了会传回True,否则传回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

上述侦测是否球撞到球拍必须符合以下两个条件。

(1)球的右侧x轴坐标ballPos[2]大于球拍左侧x坐标racketPos[0],同时球的左侧x坐标ballPos[0]小于球拍右侧x坐标racketPos[2]。

image-20220915154259295

(2)球的下方y坐标ballPos[3]大于球拍上方的y坐标racketPos[1],同时必须小于球拍下方的y坐标racketPos[3]。读者可能奇怪为何不是侦测碰到球拍上方即可,主要是球不是一次移动1像素,如果移动3像素,很可能会跳过球拍上方。

image-20220915154321553

下面是球的可能移动方式图示。

image-20220915154347523

示例1

当球碰撞到球拍时会反弹。下面是完整的Ball类设计。

from tkinter import * 
from random import * 
import time 

class Ball:#class Ball():#这样写是一样的
    def __init__(self,canvas,color,winW,winH,racket):
        self.canvas = canvas
        self.racket = racket
        self.id = canvas.create_oval(0, 0, 20, 20, fill=color) # 建立球对象
        self.canvas.move(self.id,winW/2,winH/2)   # 设置球最初位置
        startPos = [-4, -3, -2, -1, 1, 2, 3, 4]   # 球最初x轴位移的随机数
        shuffle(startPos)                         # 打乱排序
        self.x = startPos[0]                      # 球最初水平移动单位
        self.y = step                             # 垂直移动单位
    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是正值表示往下移动
        ballPos = self.canvas.coords(self.id)
        if ballPos[0] <= 0:          # 侦测球是否超过画布左方
            self.x = step       
        if ballPos[1] <= 0:          # 侦测球是否超过画布上方
            self.y = step
        if ballPos[2] >= winW:       # 侦测球是否超过画布右方
            self.x = -step           
        if ballPos[3] >= winH:       # 侦测球是否超过画布下方
            self.y = -step
        if self.hitRacket(ballPos):  # 侦测是否撞到球拍
            self.y = -step

class Racket():
    def __init__(self, canvas, color):
        self.canvas = canvas
        self.id = canvas.create_rectangle(0,0,100,15,fill=color)  # 球拍对象
        self.canvas.move(self.id, 270, 400)
        self.x = 0
        self.canvas.bind_all('<KeyPress-Right>',self.moveRight)   # 绑定按住右键 ##########################
        self.canvas.bind_all('<KeyPress-Left>',self.moveLeft)     # 绑定按住左键
    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      # 定义画布宽度
winH = 480      # 定义画布高度
step = 3        # 定义速度可想成位移步长
speed = 0.03    # 设置移动速度

tk = Tk()
tk.title("Bouncing Ball apidemos")                    # 游戏窗口标题
tk.wm_attributes('-topmost',1)               # 确保游戏窗口在屏幕最上层
canvas = Canvas(tk,width=winW, height=winH)  # 建立画布
canvas.pack()
tk.update()   

# 以下两行代码执行顺序决定了两者重合时哪一个对象被遮挡
racket = Racket(canvas,'purple')        # 定义紫色球拍
ball = Ball(canvas,'yellow',winW,winH,racket)  # 定义球对象

while True:
    ball.ballMove()
    racket.racketMove()
    tk.update()
    time.sleep(speed)   # 可以控制移动速度

# tk.mainloop()

输出:

image-20220915154457228

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程