Pygame重力下物体穿屏修复及单/双击跳跃功能实现
修复方案
针对你遇到的两个问题,直接做以下逻辑调整即可:
- 边界/地面穿模修复:把原有的移动前速度反弹逻辑,改成移动后位置钳制+碰撞速度清零:每次移动完玩家矩形后,直接把超出屏幕/地面的坐标拉回合法范围,同时把对应方向的速度清零,避免重力持续累加把速度堆得太大穿模;补上你之前写了但没调用的地面碰撞检测逻辑,给水平移动加摩擦力,避免左右移动速度无限增长。
- 单击/双击跳跃实现:删掉原有的“按住上键持续向上飞”的逻辑,改成监听跳跃键的单次按下事件,记录两次按跳跃键的时间间隔,间隔小于300毫秒判定为双击,触发2倍高度的跳跃;单次按键触发普通高度跳跃,且只有站在地面时才能触发跳跃,避免空中乱跳。
修改后完整代码
import pygame canvas_width = 1000 canvas_height = 500 pygame.init() screen = pygame.display.set_mode([canvas_width,canvas_height]) screen_rect = screen.get_rect() clock = pygame.time.Clock() red = (255,0,0) blue = (0,0,255) green = (0,255,0) white = (255,255,255) black = (0,0,0) class Ground: def __init__ (self,position,size,color): self.xPos = position[0] self.yPos = position[1] self.width = size[0] self.height = size[1] self.color = color self.rect = pygame.rect.Rect(position,size) class Ball: def __init__(self,position,size,color): self.xPos = position[0] self.yPos = position[1] self.width = size[0] self.height = size[1] self.color = color self.speed = [0, 0] self.rect = pygame.rect.Rect(position,size) # 跳跃相关参数 self.on_ground = False self.last_jump_time = 0 self.normal_jump_power = -12 # 普通跳跃向上速度,pygame坐标向下为正所以用负数 self.double_jump_power = -18 # 双倍跳跃向上速度 self.double_click_threshold = 300 # 双击判定间隔,单位毫秒 # 移动参数 self.move_acc = 0.5 self.friction = 0.9 self.max_horizontal_speed = 6 self.gravity_acc = 0.5 def move (self, ground): self.keymove() self.gravity() self.rect.move_ip(self.speed) # 地面碰撞检测 self.touchRect(ground) # 边界约束,移动完直接钳制位置 self.check_boundary(ground) pygame.draw.rect(screen, self.color,self.rect) def touchRect(self, ground): self.on_ground = False if self.rect.colliderect(ground.rect): # 碰到地面就把垂直速度清零,位置拉到地面上方 self.speed[1] = 0 self.rect.bottom = ground.rect.top self.on_ground = True def gravity(self): # 不在地面的时候才加重力 if not self.on_ground: self.speed[1] += self.gravity_acc def check_boundary(self, ground): # 左右边界约束 if self.rect.left < 0: self.rect.left = 0 self.speed[0] = 0 if self.rect.right > canvas_width: self.rect.right = canvas_width self.speed[0] = 0 # 上边界约束 if self.rect.top < 0: self.rect.top = 0 self.speed[1] = 0 # 下边界(地面)约束兜底 if self.rect.bottom > ground.rect.top: self.rect.bottom = ground.rect.top self.speed[1] = 0 self.on_ground = True def keymove(self): key = pygame.key.get_pressed() # 左右移动 if key[pygame.K_LEFT]: self.speed[0] -= self.move_acc if key[pygame.K_RIGHT]: self.speed[0] += self.move_acc # 加摩擦力,避免速度无限增长 self.speed[0] *= self.friction # 限制最大水平速度 if self.speed[0] > self.max_horizontal_speed: self.speed[0] = self.max_horizontal_speed if self.speed[0] < -self.max_horizontal_speed: self.speed[0] = -self.max_horizontal_speed def jump(self): if not self.on_ground: return current_time = pygame.time.get_ticks() # 判断是不是双击 if current_time - self.last_jump_time < self.double_click_threshold: self.speed[1] = self.double_jump_power else: self.speed[1] = self.normal_jump_power self.last_jump_time = current_time ball = Ball ([500,250],[30,30],blue) ground = Ground ([0,470],[1000,30],green) Game = True while Game: for event in pygame.event.get(): if event.type == pygame.QUIT: Game = False # 监听跳跃键按下 if event.type == pygame.KEYDOWN: if event.key == pygame.K_UP: ball.jump() screen.fill(black) ball.move(ground) pygame.draw.rect(screen, ground.color, ground.rect) pygame.display.update() clock.tick(60) pygame.quit()
使用说明
- 运行后按左右键控制角色移动,按一下上键触发普通跳跃,快速连按两下上键触发更高的双倍跳跃
- 角色不会再穿出屏幕左右/上边界,也不会掉到地面下方
- 水平移动加了摩擦力,松开按键后角色会慢慢停下,不会一直加速滑走
- 如果觉得跳跃高度、移动速度、重力大小不符合预期,直接修改Ball类初始化里对应参数的数值即可。
内容的提问来源于stack exchange,提问作者Kayaan
相关产品推荐
相关产品推荐

