Tkinter矩形碰撞检测问题:移动红矩形时黑矩形未触发删除
Tkinter矩形碰撞检测修复方案
我正在做课程作业,用Tkinter写对象碰撞检测(不能用Pygame)。创建了红、黑两个矩形,移动红矩形时,希望两者重叠就删除黑矩形,但实际重叠时黑矩形没被删除,求修复方法。
原代码
import tkinter as tk from tkinter import * window = Tk() window.geometry("1366x768") canvas = tk.Canvas(window, width = 1300, height = 700) rec1 = canvas.create_rectangle(100, 100, 150, 150, fill = "black") #black rectangle mover = canvas.create_rectangle(400, 400, 450, 450, fill = "red", outline = "red") #red moving rectangle canvas.pack() def left(event): x = -10 y = 0 canvas.move(mover, x, y) def right(event): x = 10 y = 0 canvas.move(mover, x, y) def up (event): x = 0 y = -10 canvas.move(mover, x, y) def down(event): x = 0 y = 10 canvas.move(mover, x, y) window.bind("<Left>", left) window.bind("<Right>", right) window.bind("<Up>", up ) window.bind("<Down>", down) a = canvas.bbox(1) # coordinates of the black rectangle b = canvas.bbox(2) # coordinates of the red, moving rectangle if b[0] in range(a[0],a[2]) or b[2] in range(a[0],a[2]) and b[1] in range(a[1],a[3]) or b[3] in range(a[1],a[3]): canvas.delete(rec1) #if they overlap, then delete the static black rectangle window.mainloop()
问题根源
- 碰撞检测仅执行一次:碰撞判断代码只在程序启动时运行了一次,此时两个矩形不重叠,后续移动红矩形时不会再触发检测,因此不会删除黑矩形。
- 碰撞逻辑错误:
- 使用
range(a[0],a[2])判断坐标区间存在缺陷,range仅处理整数,且逻辑上不符合矩形重叠的判断逻辑。 - 逻辑运算符优先级混乱,
and优先级高于or,导致判断条件不符合实际重叠场景。
- 使用
- 依赖创建顺序获取边界:用
canvas.bbox(1)和bbox(2)依赖矩形创建顺序,直接使用变量rec1和mover更可靠。
修复步骤
- 将碰撞检测嵌入移动函数:每次移动红矩形后立即执行碰撞检测。
- 修正碰撞判断逻辑:矩形重叠的正确判断是:红矩形左边界 < 黑矩形右边界,且红矩形右边界 > 黑矩形左边界;同时红矩形上边界 < 黑矩形下边界,且红矩形下边界 > 黑矩形上边界。
- 通过变量获取边界:直接用
canvas.bbox(rec1)和canvas.bbox(mover)获取两个矩形的坐标。
修复后的完整代码
import tkinter as tk from tkinter import * window = Tk() window.geometry("1366x768") canvas = tk.Canvas(window, width = 1300, height = 700) rec1 = canvas.create_rectangle(100, 100, 150, 150, fill = "black") # 黑色矩形 mover = canvas.create_rectangle(400, 400, 450, 450, fill = "red", outline = "red") # 可移动红色矩形 canvas.pack() def check_collision(): # 获取矩形边界坐标,格式为(left, top, right, bottom) black_bbox = canvas.bbox(rec1) red_bbox = canvas.bbox(mover) if black_bbox and red_bbox: # 确保两个矩形都存在 # 判断x轴和y轴是否同时存在重叠区域 overlap_x = red_bbox[0] < black_bbox[2] and red_bbox[2] > black_bbox[0] overlap_y = red_bbox[1] < black_bbox[3] and red_bbox[3] > black_bbox[1] if overlap_x and overlap_y: canvas.delete(rec1) def left(event): x = -10 y = 0 canvas.move(mover, x, y) check_collision() # 移动后触发碰撞检测 def right(event): x = 10 y = 0 canvas.move(mover, x, y) check_collision() def up (event): x = 0 y = -10 canvas.move(mover, x, y) check_collision() def down(event): x = 0 y = 10 canvas.move(mover, x, y) check_collision() window.bind("<Left>", left) window.bind("<Right>", right) window.bind("<Up>", up ) window.bind("<Down>", down) window.mainloop()
额外说明
- 新增
check_collision函数统一处理碰撞检测,避免重复代码,提升可读性。 - 添加
if black_bbox and red_bbox判断,防止黑矩形被删除后调用canvas.bbox(rec1)返回None引发报错。
内容的提问来源于stack exchange,提问作者sm2002
相关产品推荐
相关产品推荐

