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

如何修复Pygame(Python)中窗口左上角闪烁的方块问题?

问题解决:下落方块卡在左上角闪烁

问题根源

你的代码存在两个关键错误,直接导致方块异常卡顿:

  1. 障碍物销毁条件错误:Obstacle类的update方法中,判断方块是否超出屏幕的逻辑用了SCREEN_WIDTH(宽度),但方块是垂直下落,应该判断是否超出屏幕底部的SCREEN_HEIGHT(高度)。这个错误让本该被销毁的方块一直留在精灵组中,后续位置计算出现异常,表现为卡在左上角闪烁。
  2. 初始化位置语义错误:虽然当前OBSTACLE_WIDTH和OBSTACLE_HEIGHT数值相同,但初始化self.y时用-OBSTACLE_HEIGHT更贴合垂直方向的逻辑,避免后续修改尺寸时出现隐性问题。

修正后的完整代码

import pygame, sys
import random

# Initialize Pygame
pygame.init()

# 屏幕尺寸设置
SCREEN_WIDTH = 1920
SCREEN_HEIGHT = 1080
FPS = 60

# 创建游戏窗口
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption('Dodge')

# 时钟初始化
clock = pygame.time.Clock()


class Player(pygame.sprite.Sprite):
    def __init__(self):
        super(Player, self).__init__()
        self.surf = pygame.image.load('graphics\\player.png')
        self.rect = self.surf.get_rect()

        self.x = SCREEN_WIDTH / 2
        self.y = SCREEN_HEIGHT / 10 * 9
        self.rect.center = (self.x, self.y)

        self.max_speed = 15
        self.velX = 0
        self.velY = 0

        self.acceleration = 0.7
        self.friction = 0.9

    def update(self):
        keys = pygame.key.get_pressed()

        if keys[pygame.K_a]:
            if self.velX > -self.max_speed:
                self.velX -= self.acceleration
        if keys[pygame.K_d]:
            if self.velX < self.max_speed:
                self.velX += self.acceleration
        if keys[pygame.K_w]:
            if self.velY > -self.max_speed:
                self.velY -= self.acceleration
        if keys[pygame.K_s]:
            if self.velY < self.max_speed:
                self.velY += self.acceleration

        self.x += self.velX
        self.y += self.velY

        self.velX *= self.friction
        self.velY *= self.friction

        self.rect.center = (self.x, self.y)
        if self.rect.left < 0:
            self.rect.left = 0
        if self.rect.right > SCREEN_WIDTH:
            self.rect.right = SCREEN_WIDTH
        if self.rect.top <= 0:
            self.rect.top = 0
        if self.rect.bottom >= SCREEN_HEIGHT:
            self.rect.bottom = SCREEN_HEIGHT


class Obstacle(pygame.sprite.Sprite):
    def __init__(self):
        super(Obstacle, self).__init__()

        OBSTACLE_WIDTH = 64
        OBSTACLE_HEIGHT = 64
        
        self.surf = pygame.Surface((OBSTACLE_WIDTH, OBSTACLE_HEIGHT))
        self.surf.fill('white')
        self.rect = self.surf.get_rect()

        self.x = random.randint(5, SCREEN_WIDTH - OBSTACLE_WIDTH - 5)
        self.y = -OBSTACLE_HEIGHT  # 修正垂直方向初始化语义

        self.velY = random.randint(15, 20)

    def update(self):
        self.y += self.velY
        self.rect.topleft = (self.x, self.y)
        # 修正销毁条件:判断是否超出屏幕底部
        if self.rect.top > SCREEN_HEIGHT + 5:
            self.kill()


ADD_OBSTACLE = pygame.USEREVENT + 1
pygame.time.set_timer(ADD_OBSTACLE, 250)

# 玩家实例
player = Player()

# 障碍物精灵组
obstacles = pygame.sprite.Group()

# 游戏主循环
run = True
while run:
    # 事件处理
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            run = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_ESCAPE:
                run = False
        elif event.type == ADD_OBSTACLE:
            new_obstacle = Obstacle()
            obstacles.add(new_obstacle)
 
    # 清空屏幕
    screen.fill((0, 0, 0))

    # 绘制玩家和障碍物
    screen.blit(player.surf, player.rect)
    for obs in obstacles:
        screen.blit(obs.surf, obs.rect)

    # 碰撞检测
    if pygame.sprite.spritecollideany(player, obstacles):
        player.kill()
        run = False

    # 更新角色状态
    player.update()
    obstacles.update()

    # 更新显示
    pygame.display.flip()
    clock.tick(FPS)

# 退出游戏
pygame.quit()
sys.exit()

额外优化建议

  • 将OBSTACLE_WIDTH和OBSTACLE_HEIGHT设为全局常量,方便后续统一调整尺寸。
  • 玩家移动逻辑可以直接操作rect属性,无需单独维护x、y变量,减少坐标同步出错的可能。

内容的提问来源于stack exchange,提问作者rukenup

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 19:10:32