如何修复Flappy Bird克隆游戏中的碰撞检测代码?
Flappy Bird碰撞检测问题修复方案
核心问题分析
碰撞检测失效的核心原因:
- 碰撞逻辑依赖静态的
pipe_1/pipe_2列表,完全没用到实际在屏幕上移动的pipes1/pipes2中的管道对象 - 小鸟位置管理混乱:
bird[1]未同步实际显示的y_pos,导致碰撞检测用了错误的Y坐标 - 碰撞判定的半径值完全不符合图形实际尺寸
- 管道初始化和移动逻辑存在错误(比如
pipes2错误添加pipe1、管道移动速度设置异常)
修复后的完整代码
import turtle as t import random # 屏幕设置 wn = t.Screen() wn.setup(width=600, height=800) # 明确窗口尺寸,替代模糊的screensize wn.title("Flappy Bird") wn.bgcolor("light blue") wn.tracer(0) # 手动控制刷新,提升游戏流畅度 # 小鸟配置 bird_radius = 15 # 对应shapesize(1,1)的实际碰撞半径 b = t.Turtle() b.penup() b.shape("circle") b.shapesize(1, 1) b.color("yellow") b.goto(-200, 0) bird_y_vel = 0 gravity = -0.5 flap_force = 8 # 管道配置 pipe_width = 100 # shapesize(5,5)对应实际宽度:5*20=100 pipe_height = 400 # shapesize(20,5)对应实际高度:20*20=400 pipes1 = [] # 上管道列表 pipes2 = [] # 下管道列表 def flap(): global bird_y_vel bird_y_vel = flap_force wn.onkeypress(flap, "Up") wn.listen() # 创建管道的工具函数 def create_pipe(is_top): pipe = t.Turtle() pipe.penup() pipe.shape('square') pipe.shapesize(20, 5) pipe.color('green') pipe.dx = -2 # 统一管道移动速度 x_pos = 300 if is_top: y_pos = random.randint(100, 300) else: y_pos = random.randint(-300, -100) pipe.goto(x_pos, y_pos) return pipe # 生成初始管道 pipes1.append(create_pipe(True)) pipes2.append(create_pipe(False)) # 碰撞检测函数(矩形碰撞判定,适配管道形状) def check_collision(bird, pipe): bird_x, bird_y = bird.pos() pipe_x, pipe_y = pipe.pos() # 计算碰撞边界 bird_left = bird_x - bird_radius bird_right = bird_x + bird_radius bird_top = bird_y + bird_radius bird_bottom = bird_y - bird_radius pipe_left = pipe_x - pipe_width/2 pipe_right = pipe_x + pipe_width/2 pipe_top = pipe_y + pipe_height/2 pipe_bottom = pipe_y - pipe_height/2 # 判断是否发生碰撞 return (bird_right > pipe_left and bird_left < pipe_right) and (bird_top > pipe_bottom and bird_bottom < pipe_top) # 主游戏循环 while True: # 小鸟移动逻辑 bird_y_vel += gravity b.sety(b.ycor() + bird_y_vel) # 上管道处理 for pipe in pipes1: pipe.setx(pipe.xcor() + pipe.dx) # 管道移出屏幕则替换 if pipe.xcor() < -400: pipes1.remove(pipe) pipes1.append(create_pipe(True)) # 碰撞检测 if check_collision(b, pipe): print("碰撞!游戏结束") wn.bye() exit() # 下管道处理 for pipe in pipes2: pipe.setx(pipe.xcor() + pipe.dx) if pipe.xcor() < -400: pipes2.remove(pipe) pipes2.append(create_pipe(False)) # 碰撞检测 if check_collision(b, pipe): print("碰撞!游戏结束") wn.bye() exit() # 屏幕边界碰撞检测 if b.ycor() > 380 or b.ycor() < -380: print("撞边界!游戏结束") wn.bye() exit() wn.update() wn.mainloop()
关键修改说明
- 移除冗余的静态列表,直接通过Turtle对象的
pos()获取实时位置 - 用矩形碰撞判定替代圆形判定,适配管道的矩形形状
- 修复管道初始化错误,分离上下管道生成逻辑
- 统一管道移动速度,修正原代码中速度异常的问题
- 添加屏幕边界碰撞检测,完善游戏逻辑
- 启用手动刷新机制,提升游戏运行流畅度
内容的提问来源于stack exchange,提问作者dborders643
相关产品推荐
相关产品推荐

