pygame的event.get()中如何正确获取函数返回的碰撞状态?
问题根因
碰撞逻辑不生效是三个硬伤导致的,没有玄学问题:
- 你只在按键按下的瞬间做了一次碰撞检测,按住按键持续移动的过程中,每帧更新坐标前完全没做碰撞校验
- 每帧调用
Extracted_Data算出来的碰撞结果根本没被用到,帧末不管有没有碰撞都会直接执行x += x_speed/y += y_speed位移,角色自然会穿进障碍区 - 碰撞盒计算逻辑错位:玩家碰撞盒用屏幕固定位置减速度计算,没有对齐玩家实际的世界坐标,检测结果本身就有偏差
- 把渲染逻辑和碰撞逻辑混写,全局变量乱传状态,很容易出现状态不同步的问题
修复方案
1. 重构碰撞检测函数
把碰撞检测和渲染拆开,函数只做纯逻辑判断,不要在里面画矩形、不要乱改全局变量,直接返回碰撞结果:
def check_collision(world_x, world_y, offset_x, offset_y): # 计算玩家下一帧位置对应的实际碰撞盒,对齐世界坐标 player_hitbox = pygame.Rect( world_x + (screen_width - png_width/4)/2 + offset_x, world_y + (screen_height - png_height/8)/2 + offset_y, tile_size, 3/4 * tile_size ) # 遍历所有障碍块检测碰撞 for row_index, row in enumerate(data): for col_index, val in enumerate(row): if val == 1025: boundary_rect = pygame.Rect( world_x + col_index * tile_size, world_y + row_index * tile_size, tile_size, tile_size ) if player_hitbox.colliderect(boundary_rect): return True return False
2. 调整主循环执行顺序
把碰撞检测挪到位移执行之前,每帧都做校验,不要只在按键事件里做检测:
- 事件循环只负责更新速度方向,不要在事件分支里直接做碰撞判断
- 分X/Y两个轴单独做碰撞校验,避免斜向移动卡墙、穿模
- 确认碰撞后先把对应方向的速度清零,再执行位移
while not leaved: gameDisplay.fill('white') # 处理输入事件,仅更新速度状态 for event in pygame.event.get(): if event.type == pygame.QUIT: leaved = True if event.type == pygame.KEYDOWN: if event.key == pygame.K_q: Img_Position = Img_Positions.get("left") x_speed = -player_speed if event.key == pygame.K_d: x_speed = player_speed if event.key == pygame.K_z: y_speed = -player_speed if event.key == pygame.K_s: y_speed = player_speed if event.type == pygame.KEYUP: if event.key in (pygame.K_q, pygame.K_d): x_speed = 0 if event.key in (pygame.K_z, pygame.K_s): y_speed = 0 # 位移前先做碰撞校验,分轴检测 if x_speed != 0 and check_collision(x, y, x_speed, 0): x_speed = 0 if y_speed != 0 and check_collision(x, y, 0, y_speed): y_speed = 0 # 校验通过再更新坐标 x += x_speed y += y_speed # 所有逻辑跑完再渲染 Background(x,y) Player(Img_Position) Foreground(x,y) Text() pygame.display.update() clock.tick(FPS) pygame.quit() quit()
优化提示
- 不要把
pygame.draw.rect这类渲染调用写到纯逻辑函数里,碰撞检测直接用pygame.Rect做数学计算即可,不需要真的把形状画到屏幕上,能减少不必要的性能消耗 - 尽量少用全局变量传递状态,函数需要什么参数就传入什么,计算结果直接return,避免多段逻辑修改变量导致的状态不同步问题
- 分轴碰撞检测是2D Tile类游戏的标准实现方案,比整体碰撞检测的卡墙概率低很多
内容的提问来源于stack exchange,提问作者Thomas Perr
相关产品推荐
相关产品推荐

