Pygame角色移动碰撞问题求助:触碰方块时停止不穿透
问题:Pygame角色触碰方块时停止移动,避免穿透效果
我是Python和Pygame新手,希望实现角色触碰"Block"方块时停止移动,避免穿透效果。目前的角色移动代码如下:
def Player_Movement(): global x_plr, y_plr, X_vel, Y_vel, Main_Player keys = pygame.key.get_pressed() speed = 5 if X_vel > 0: X_vel -= 1 if X_vel < 0: X_vel += 1 if Y_vel > 0: Y_vel -= 1 if Y_vel < 0: Y_vel += 1 if keys[pygame.K_d]: X_vel = speed if keys[pygame.K_a]: X_vel = -speed if keys[pygame.K_w]: Y_vel = -speed if keys[pygame.K_s]: Y_vel = speed if Main_Player.colliderect(Block): Main_Player = pygame.draw.rect(win, playercolor, (x_plr, y_plr, size, size)) X_vel += abs(X_vel) print(X_vel) x_plr += X_vel if Main_Player.colliderect(Block): Main_Player = pygame.draw.rect(win, playercolor, (x_plr, y_plr, size, size)) Y_vel += abs(Y_vel) print(Y_vel) y_plr += Y_vel
为方便排查,附上完整代码:
import pygame pygame.init() clock = pygame.time.Clock() winWidth = 1100 winHeight = 700 win = pygame.display.set_mode((winWidth, winHeight)) pygame.display.set_caption('my caption') # variables x_plr = 200 y_plr = 100 X_vel = 0 Y_vel = 0 size = 25 playercolor = (255, 70, 70) Main_Player = pygame.draw.rect(win, playercolor, (x_plr, y_plr, size, size)) Block = pygame.draw.rect(win, (230, 230, 230), (500, 100, 50, 50)) def Displaying(): global Main_Player, Block Main_Player = pygame.draw.rect(win, playercolor, (x_plr, y_plr, size, size)) Block = pygame.draw.rect(win, (230, 230, 230), (350, 100, 300, 50)) def Player_Movement(): global x_plr, y_plr, X_vel, Y_vel, Main_Player keys = pygame.key.get_pressed() speed = 5 if X_vel > 0: X_vel -= 1 if X_vel < 0: X_vel += 1 if Y_vel > 0: Y_vel -= 1 if Y_vel < 0: Y_vel += 1 if keys[pygame.K_d]: X_vel = speed if keys[pygame.K_a]: X_vel = -speed if keys[pygame.K_w]: Y_vel = -speed if keys[pygame.K_s]: Y_vel = speed if Main_Player.colliderect(Block): Main_Player = pygame.draw.rect(win, playercolor, (x_plr, y_plr, size, size)) X_vel += abs(X_vel) print(X_vel) x_plr += X_vel if Main_Player.colliderect(Block): Main_Player = pygame.draw.rect(win, playercolor, (x_plr, y_plr, size, size)) Y_vel += abs(Y_vel) print(Y_vel) y_plr += Y_vel while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() win.fill((50,50,50)) Player_Movement() Displaying() pygame.display.update() pygame.display.update(Main_Player) clock.tick(60)
解决方案
问题分析
原代码存在几个核心问题:
- 碰撞检测时机错误:移动前检测碰撞时角色位置未更新,移动后检测时角色已穿透方块,无法有效阻止穿透。
- 碰撞处理逻辑错误:直接修改速度的方式无法精准控制角色位置,反而会导致速度异常。
- 矩形对象管理混乱:依赖绘制函数返回的矩形对象进行碰撞检测,位置同步容易出错。
修改后的完整代码
import pygame pygame.init() clock = pygame.time.Clock() winWidth = 1100 winHeight = 700 win = pygame.display.set_mode((winWidth, winHeight)) pygame.display.set_caption('my caption') # 变量定义 x_plr = 200 y_plr = 100 X_vel = 0 Y_vel = 0 size = 25 playercolor = (255, 70, 70) # 直接创建碰撞用的矩形对象,脱离绘制逻辑 Main_Player = pygame.Rect(x_plr, y_plr, size, size) Block = pygame.Rect(350, 100, 300, 50) def Displaying(): # 仅负责绘制,不修改矩形位置数据 pygame.draw.rect(win, playercolor, Main_Player) pygame.draw.rect(win, (230, 230, 230), Block) def Player_Movement(): global x_plr, y_plr, X_vel, Y_vel, Main_Player keys = pygame.key.get_pressed() speed = 5 # 保留原有的摩擦力逻辑 if X_vel > 0: X_vel -= 1 if X_vel < 0: X_vel += 1 if Y_vel > 0: Y_vel -= 1 if Y_vel < 0: Y_vel += 1 # 按键控制速度 if keys[pygame.K_d]: X_vel = speed if keys[pygame.K_a]: X_vel = -speed if keys[pygame.K_w]: Y_vel = -speed if keys[pygame.K_s]: Y_vel = speed # 分方向处理移动与碰撞:先X轴,再Y轴 # X方向移动与碰撞检测 Main_Player.x += X_vel if Main_Player.colliderect(Block): # 碰撞后回退到刚好接触的位置 if X_vel > 0: Main_Player.right = Block.left else: Main_Player.left = Block.right X_vel = 0 # 重置X方向速度,避免持续移动 # Y方向移动与碰撞检测 Main_Player.y += Y_vel if Main_Player.colliderect(Block): # 碰撞后回退到刚好接触的位置 if Y_vel > 0: Main_Player.bottom = Block.top else: Main_Player.top = Block.bottom Y_vel = 0 # 重置Y方向速度 # 更新全局坐标变量(供其他逻辑使用) x_plr = Main_Player.x y_plr = Main_Player.y while True: for event in pygame.event.get(): if event.type == pygame.QUIT: pygame.quit() win.fill((50,50,50)) Player_Movement() Displaying() pygame.display.update() clock.tick(60)
关键修改说明
- 独立碰撞矩形:用
pygame.Rect直接创建角色和方块的碰撞区域,不再依赖绘制函数返回的对象,确保位置数据准确。 - 分方向碰撞处理:先处理X轴移动与碰撞,再处理Y轴,避免多方向碰撞时的逻辑冲突。
- 精准位置回退:碰撞时将角色位置调整到与方块刚好接触的状态,同时重置对应方向的速度,彻底阻止穿透。
- 职责分离:
Displaying函数仅负责绘制,不再修改矩形位置,代码逻辑更清晰。
内容的提问来源于stack exchange,提问作者Xseis
相关产品推荐
相关产品推荐

