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

Python turtle Tron游戏光轨碰撞检测实现咨询

实现方案

你原本的4个while循环独立存储坐标的方案无法正常运行:while True属于阻塞逻辑,会直接卡死turtle的事件主循环,程序启动后会直接无响应;拆分x、y坐标单独存储也没有必要,直接存储(x坐标, y坐标)格式的元组,读写效率更高。

不建议使用颜色检测实现碰撞判定:Python turtle没有原生提供高性能的屏幕像素取色接口,依赖底层tkinter抓屏取色的方案运行效率低、跨平台兼容问题多,稳定性远不如坐标点匹配方案。

正确实现逻辑如下:

  • 初始化两个列表,分别存储红、蓝玩家光轮摩托驶过的所有轨迹坐标
  • 每次游戏循环内,玩家完成移动后,将当前坐标追加到对应玩家的轨迹列表中;开局前5个坐标点跳过碰撞检测,避免误判玩家撞到自身出发位置
  • 碰撞检测环节新增轨迹碰撞判断:将红方当前坐标与蓝方历史轨迹点逐一比对,距离小于容差则判定红方撞线,蓝方获胜;反之判定蓝方撞线,红方获胜
  • 修复原有代码的已知问题:修正collisions()函数永远返回False的bug、修正换行符错写为/n的问题、碰撞触发后直接终止游戏循环,避免程序继续运行。
修改后完整代码
import turtle
import math
import time

width = 800
height = 600
game_running = True

def TronGame():
    global blue_direction, red_direction
    blue_direction = 'right'
    red_direction = 'left'

    # 蓝方移动控制
    def blue_up():  
        global blue_direction
        if blue_direction != 'down':
            blue_direction = 'up'
        
    def blue_down():
        global blue_direction
        if blue_direction != 'up':
            blue_direction = 'down'
        
    def blue_left():
        global blue_direction
        if blue_direction != 'right':
            blue_direction = 'left'
        
    def blue_right():
        global blue_direction
        if blue_direction != 'left':
            blue_direction = 'right'

    # 红方移动控制
    def red_up():   
        global red_direction
        if red_direction != 'down':
            red_direction = 'up'
        
    def red_down():
        global red_direction
        if red_direction != 'up':
            red_direction = 'down'
        
    def red_left():
        global red_direction
        if red_direction != 'right':
            red_direction = 'left'
        
    def red_right():
        global red_direction
        if red_direction != 'left':
            red_direction = 'right'

    # 玩家移动逻辑
    def move_player(player, direction):
        if direction == 'up':
            player.setheading(90)
            player.forward(5)
        elif direction == 'down':
            player.setheading(270)
            player.forward(5)
        elif direction == 'left':
            player.setheading(180)
            player.forward(5)
        elif direction == 'right':
            player.setheading(0)
            player.forward(5)

    # 游戏结束提示
    def game_over(message):
        global game_running
        game_running = False
        TurtleCrash = turtle.Turtle(visible=False)
        TurtleCrash.color("white")
        style = ('Arial', 25, 'italic')
        TurtleCrash.write(f"{message}\nGame over!", font=style, align='center')

    # 碰撞检测
    def collisions(blue_trail, red_trail):  
        x_blue, y_blue = blue_player.xcor(), blue_player.ycor() 
        x_red, y_red  = red_player.xcor(), red_player.ycor()
        
        # 两车直接相撞
        if(math.isclose(x_blue, x_red, abs_tol=5.0) and
            math.isclose(y_blue, y_red, abs_tol=5.0)):
            game_over("Red and Blue Crashed!")
            return True
        
        # 边界碰撞
        if x_blue > width/2 or x_blue < -width/2 or y_blue > height/2 or y_blue < -height/2:
            game_over("Blue went out of bounds.\nRed wins!")
            return True
        if x_red > width/2 or x_red < -width/2 or y_red > height/2 or y_red < -height/2:
            game_over("Red went out of bounds.\nBlue wins!")
            return True
        
        # 轨迹碰撞 跳过前5个点避免开局误判
        for (tx, ty) in red_trail[5:]:
            if math.isclose(x_blue, tx, abs_tol=3.0) and math.isclose(y_blue, ty, abs_tol=3.0):
                game_over("Blue hit Red's trail.\nRed wins!")
                return True
        for (tx, ty) in blue_trail[5:]:
            if math.isclose(x_red, tx, abs_tol=3.0) and math.isclose(y_red, ty, abs_tol=3.0):
                game_over("Red hit Blue's trail.\nBlue wins!")
                return True

        return False

    def MainTron():
        global screen
        global blue_player
        global red_player
    
        screen = turtle.Screen()
        screen.setup(width, height)
        screen.bgcolor('black')
        # 有自定义素材时取消下面三行注释即可
        # screen.bgpic('TronBg.png')
        # screen.addshape('BlueBike.gif')
        # screen.addshape('RedBike.gif')

        blue_player = turtle.Turtle()
        # 无自定义素材时默认使用蓝色方块
        blue_player.shape('square')
        blue_player.color("blue")
        # blue_player.shape('BlueBike.gif')
        blue_player.pencolor("blue")
        blue_player.pensize(3)
        blue_player.pu()
        blue_player.goto(-1*(width)/3, height/8)
        blue_player.pd()

        red_player = turtle.Turtle()
        # 无自定义素材时默认使用红色方块
        red_player.shape('square')
        red_player.color("red")
        # red_player.shape('RedBike.gif')
        red_player.pencolor("red")
        red_player.pensize(3)
        red_player.pu()
        red_player.goto(width/3, height/8)
        red_player.pd()

        # 初始化轨迹存储列表
        blue_trail = []
        red_trail = []

        # 开局倒计时
        for x in range(5):
            count_turtle = turtle.Turtle(visible=False)
            count_turtle.color("white")
            style = ('Arial', 25, 'italic')
            count_turtle.write(5-x, font=style, align='center') 
            time.sleep(1)
            count_turtle.undo()
    
        screen.listen()
        # 红方键位WASD
        screen.onkey(red_up, "w")
        screen.onkey(red_down, "s")
        screen.onkey(red_left, "a")
        screen.onkey(red_right, "d")
        # 蓝方键位方向键
        screen.onkey(blue_up, "Up")
        screen.onkey(blue_down, "Down")
        screen.onkey(blue_left, "Left")
        screen.onkey(blue_right, "Right")

        def gameloop():
            if not game_running:
                return
            move_player(red_player, red_direction)
            move_player(blue_player, blue_direction)
            # 记录当前坐标到轨迹列表
            red_trail.append((red_player.xcor(), red_player.ycor()))
            blue_trail.append((blue_player.xcor(), blue_player.ycor()))
            # 碰撞检测 触发则结束游戏
            if collisions(blue_trail, red_trail): 
                return
            # 约60帧刷新率
            screen.ontimer(gameloop, 16)
        
        screen.ontimer(gameloop, 250)
    
        gameloop()
        screen.mainloop()

    MainTron()

TronGame()

代码额外做了优化:增加方向反向锁,避免玩家按反方向键直接掉头撞到自己的轨迹;没有自定义gif素材时默认用彩色方块代替,可直接运行测试。

内容的提问来源于stack exchange,提问作者Ian

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 14:39:54