Tkinter Canvas实现角色触碰窗口墙体结束游戏方法
Tkinter 黑方块碰边框结束游戏实现方法
全程不用复杂概念,照着改几处地方就能实现效果,逻辑非常好懂:
核心原理(大白话版)
你可以把Canvas画布当成一个封闭房间,窗口边框就是房间的四堵墙:
- 房间左上角的固定坐标是
(0, 0) - 房间右墙的位置 = 画布当前的宽度
- 房间下墙的位置 = 画布当前的高度
每次方块移动完,查一下方块四个边的位置,只要任何一个边碰到/超出墙的位置,就直接停止游戏、关闭窗口。
具体修改点说明
- 先修正原代码画方块的参数错误:
create_rectangle的参数顺序固定为(左边x坐标, 上边y坐标, 右边x坐标, 下边y坐标),原代码写反了后两个数值,方块显示会异常,改成(25,25,40,40)就是正常的15像素大小的黑块。 - 在
movement移动方法里,每次移动完方块,立刻获取方块当前坐标、画布实时宽高。 - 加4个简单的碰边判断,只要满足任意一个碰边条件,就停止循环移动,弹出游戏结束提示后关闭窗口。
修改后可直接运行的完整代码
# 导入模块 from tkinter import * from tkinter import messagebox # Tkinter自带的弹窗组件,用来显示游戏结束提示,不用额外安装 # 玩家类 class Player: def __init__(self, master=None): self.master = master self.x = 0 # 控制x方向移动速度 self.y = 0 # 控制y方向移动速度 self.canvas = Canvas(master, bg="white") # 给画布加白色背景,视觉更清晰 # 修正原矩形坐标顺序错误 self.rectangle = self.canvas.create_rectangle(25, 25, 40, 40, fill="black") self.canvas.pack(fill=BOTH, expand=True) # 让画布铺满整个窗口,避免画布尺寸和窗口不匹配 self.is_game_over = False # 游戏状态标记,记录是否已经碰墙结束 self.movement() # 启动移动循环 def movement(self): # 游戏已经结束的话直接返回,不再执行移动逻辑 if self.is_game_over: return # 按当前速度移动方块 self.canvas.move(self.rectangle, self.x, self.y) # ===== 新增的碰边框检测逻辑,不到10行代码 ===== # 获取方块当前四个边的坐标,返回格式为[左x, 上y, 右x, 下y] rect_left, rect_top, rect_right, rect_bottom = self.canvas.coords(self.rectangle) # 获取画布实时宽高(因为窗口可拉伸,每次检测都拿最新值避免bug) canvas_width = self.canvas.winfo_width() canvas_height = self.canvas.winfo_height() # 四个碰边条件,满足任意一个就算游戏失败 if rect_left <= 0 or rect_top <= 0 or rect_right >= canvas_width or rect_bottom >= canvas_height: self.is_game_over = True messagebox.showinfo(title="游戏结束", message="你撞到边框了!") self.master.destroy() # 关闭游戏窗口 return # ============================================= # 没碰墙就继续循环,100毫秒后执行下一次移动 self.canvas.after(100, self.movement) # 方向控制方法 def left(self): self.x = -5 self.y = 0 def right(self): self.x = 5 self.y = 0 def down(self): self.x = 0 self.y = 5 def up(self): self.x = 0 self.y = -5 # 主窗口初始化 print("玩法说明\n尽量不要让黑色方块碰到窗口边框。") master = Tk() master.title("Easy Game") master.geometry("300x300") # 原窗口高度75过窄,调整为300方便操作,可自行修改尺寸 master.resizable(True, True) engine = Player(master) # 绑定方向键事件 master.bind("<KeyPress-Left>", lambda e: engine.left()) master.bind("<KeyPress-Right>", lambda e: engine.right()) master.bind("<KeyPress-Up>", lambda e: engine.up()) master.bind("<KeyPress-Down>", lambda e: engine.down()) # 启动主循环 mainloop()
补充说明(不用死记,了解即可)
- 每次移动都重新获取画布宽高,是因为你开启了窗口可拉伸设置,如果玩家拖动窗口边缘改大小,边框位置会变化,实时取值不会出现检测不准的问题。
coords()是Canvas自带的内置方法,不管图形移动到什么位置,都能准确返回当前坐标,不需要你自己手动计算位置。- 加
is_game_over状态标记,是为了防止碰墙后移动逻辑还在后台运行触发报错。
感谢您的进一步讲解。
内容的提问来源于stack exchange,提问作者Jessica Young
相关产品推荐
相关产品推荐

