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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 02:15:39