Pygame平台游戏Sprite渲染异常:闪烁且无法正常移动求助
Pygame平台游戏:精灵闪烁+移动异常修复
开发的平台游戏需求:左键点击生成平台,右键点击生成方块,左右方向键控制方块移动,但目前存在精灵闪烁、方块无法正常移动/下落的问题。
原代码:
import pygame class Square(pygame.sprite.Sprite): def __init__(self, x, y, width, height): super().__init__(sprites) self.image = pygame.Surface((width, height), pygame.SRCALPHA, 32) self.rect = pygame.Rect(x, y, width, height) pygame.draw.rect(screen, pygame.Color('blue'), pygame.Rect(x, y, width, height)) def new_rect(self, x, y, width, height): self.rect = pygame.Rect(x, y, width, height) pygame.draw.rect(screen, pygame.Color('blue'), pygame.Rect(x, y, width, height)) def fall(self): if not pygame.sprite.spritecollideany(self, platforms): self.rect = self.rect.move(0, 1) def move(self, direction): if direction == 'left': self.rect = self.rect.move(-10, 0) elif direction == 'right': self.rect = self.rect.move(10, 0) class Platform(pygame.sprite.Sprite): def __init__(self, x, y, width, height): super().__init__(sprites) self.add(platforms) self.image = pygame.Surface((width, height), pygame.SRCALPHA, 32) self.rect = pygame.Rect(x, y, width, height) pygame.draw.rect(screen, pygame.Color('gray'), pygame.Rect(x, y, width, height)) sprites = pygame.sprite.Group() platforms = pygame.sprite.Group() screen = pygame.display.set_mode((500, 500)) CUBEFALL = pygame.USEREVENT + 1 running = True while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1: Platform(event.pos[0], event.pos[1], 50, 10) elif event.button == 3: cube = Square(event.pos[0], event.pos[1], 20, 20) pygame.time.set_timer(CUBEFALL, 20) if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: cube.move('left') elif event.key == pygame.K_RIGHT: cube.move('right') if event.type == CUBEFALL: screen.fill(pygame.Color('black')) cube.fall() sprites.draw(screen) pygame.display.flip() pygame.quit()
问题根源及修复步骤
错误的绘制逻辑:直接在screen上绘制精灵图形,而非绘制到精灵自身的
image表面,导致sprites.draw()无法正确渲染精灵,引发闪烁。- 修正:在
Square和Platform的__init__中,把图形绘制到self.image上,比如:# Square类__init__里替换原draw语句 pygame.draw.rect(self.image, pygame.Color('blue'), self.image.get_rect()) # Platform类__init__里替换原draw语句 pygame.draw.rect(self.image, pygame.Color('gray'), self.image.get_rect())
- 修正:在
混乱的帧刷新流程:
screen.fill()、sprites.draw()放在事件循环内部,导致部分帧没有完整刷新,出现闪烁。- 修正:把屏幕填充、精灵绘制、显示刷新统一放到事件循环外部,保证每一帧都完整执行,同时添加帧率控制避免运行过快。
不完整的碰撞检测:左右移动时未检测碰撞,会导致方块穿过平台;下落逻辑仅检测一次,可能出现方块卡进平台的情况。
- 修正
move方法,添加碰撞后位置回退逻辑;修正fall方法,处理垂直碰撞后的位置对齐。
- 修正
变量未初始化:右键点击生成方块前按方向键,会因
cube未定义报错,提前初始化cube = None并在按键时判断。
修复后完整代码
import pygame class Square(pygame.sprite.Sprite): def __init__(self, x, y, width, height): super().__init__(sprites) self.image = pygame.Surface((width, height), pygame.SRCALPHA, 32) self.rect = pygame.Rect(x, y, width, height) # 绘制到自身image表面 pygame.draw.rect(self.image, pygame.Color('blue'), self.image.get_rect()) def fall(self): self.rect.y += 1 hit = pygame.sprite.spritecollideany(self, platforms) if hit: self.rect.bottom = hit.rect.top def move(self, direction): dx = -10 if direction == 'left' else 10 self.rect.x += dx hit = pygame.sprite.spritecollideany(self, platforms) if hit: if direction == 'left': self.rect.left = hit.rect.right else: self.rect.right = hit.rect.left class Platform(pygame.sprite.Sprite): def __init__(self, x, y, width, height): super().__init__(sprites) self.add(platforms) self.image = pygame.Surface((width, height), pygame.SRCALPHA, 32) self.rect = pygame.Rect(x, y, width, height) # 绘制到自身image表面 pygame.draw.rect(self.image, pygame.Color('gray'), self.image.get_rect()) sprites = pygame.sprite.Group() platforms = pygame.sprite.Group() screen = pygame.display.set_mode((500, 500)) clock = pygame.time.Clock() running = True cube = None while running: for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.MOUSEBUTTONDOWN: if event.button == 1: Platform(event.pos[0], event.pos[1], 50, 10) elif event.button == 3: cube = Square(event.pos[0], event.pos[1], 20, 20) if event.type == pygame.KEYDOWN: if cube: if event.key == pygame.K_LEFT: cube.move('left') elif event.key == pygame.K_RIGHT: cube.move('right') # 统一帧刷新 screen.fill(pygame.Color('black')) if cube: cube.fall() sprites.draw(screen) pygame.display.flip() clock.tick(60) pygame.quit()
内容的提问来源于stack exchange,提问作者zer
相关产品推荐
相关产品推荐

