You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Tkinter Canvas实现角色触碰窗口墙体结束游戏方法

Tkinter 黑方块碰边框结束游戏实现方法

全程不用复杂概念,照着改几处地方就能实现效果,逻辑非常好懂:

核心原理(大白话版)

你可以把Canvas画布当成一个封闭房间,窗口边框就是房间的四堵墙:

  • 房间左上角的固定坐标是(0, 0)
  • 房间右墙的位置 = 画布当前的宽度
  • 房间下墙的位置 = 画布当前的高度
    每次方块移动完,查一下方块四个边的位置,只要任何一个边碰到/超出墙的位置,就直接停止游戏、关闭窗口。

具体修改点说明

  1. 先修正原代码画方块的参数错误:create_rectangle的参数顺序固定为(左边x坐标, 上边y坐标, 右边x坐标, 下边y坐标),原代码写反了后两个数值,方块显示会异常,改成(25,25,40,40)就是正常的15像素大小的黑块。
  2. 在movement移动方法里,每次移动完方块,立刻获取方块当前坐标、画布实时宽高。
  3. 加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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 07:45:35