Pygame开发俄罗斯方块:方块无法显示问题求助
俄罗斯方块方块不显示问题修复
核心问题分析
- 方块生成逻辑错误:
create_piece和rotate函数中使用row.split()处理形状字符串是错误操作。形状的每一行是连续字符(如'..00..'),无空格分隔,split()会返回空列表,导致遍历不到任何字符,最终生成的Sprite组为空,自然看不到方块。 - 底部碰撞检测缺失:仅检测了与静止方块的碰撞,未判断方块是否到达游戏区域底部,方块会直接下落出屏幕。
- Sprite引用失效:旋转方块后,旧的Sprite列表未更新,导致后续碰撞检测失效。
修复后的完整代码
import pygame import random ####### SETTINGS ######## FPS = 60 SCREEN_WIDTH = 500 BOARD_WIDTH = 300 BOARD_HEIGHT = 600 TILE_SIZE = [30, 30] S = [['.....', '......', '..00..', '.00...', '.....'], ['.....', '..0..', '..00.', '...0.', '.....']] Z = [['.....', '.....', '.00..', '..00.', '.....'], ['.....', '..0..', '.00..', '.0...', '.....']] I = [['..0..', '..0..', '..0..', '..0..', '.....'], ['.....', '0000.', '.....', '.....', '.....']] O = [['.....', '.....', '.00..', '.00..', '.....']] J = [['.....', '.0...', '.000.', '.....', '.....'], ['.....', '..00.', '..0..', '..0..', '.....'], ['.....', '.....', '.000.', '...0.', '.....'], ['.....', '..0..', '..0..', '.00..', '.....']] L = [['.....', '...0.', '.000.', '.....', '.....'], ['.....', '..0..', '..0..', '..00.', '.....'], ['.....', '.....', '.000.', '.0...', '.....'], ['.....', '.00..', '..0..', '..0..', '.....']] T = [['.....', '..0..', '.000.', '.....', '.....'], ['.....', '..0..', '..00.', '..0..', '.....'], ['.....', '.....', '.000.', '..0..', '.....'], ['.....', '..0..', '.00..', '..0..', '.....']] shapes = [S, Z, I, O, J, L, T] shape_colors = [(0, 255, 0), (255, 0, 0), (0, 255, 255), (255, 255, 0), (255, 165, 0), (0, 0, 255), (128, 0, 128)] class Block(pygame.sprite.Sprite): def __init__(self, color, x, y, rotation): pygame.sprite.Sprite.__init__(self) self.image = pygame.Surface(TILE_SIZE) self.image.fill(color) self.rect = self.image.get_rect() # 初始位置偏移到游戏区域上方居中 self.rect.topleft = ( (BOARD_WIDTH // 2 - 2*TILE_SIZE[0]) + x * TILE_SIZE[0], y * TILE_SIZE[1] ) self.rotation = rotation def update(self): self.rect.y += TILE_SIZE[1] def rotate(self): self.rotation += 1 def createBoard(): board = pygame.Surface((BOARD_WIDTH, BOARD_HEIGHT)) board.fill((255, 255, 255)) return board def create_piece(): rotation = 0 shape = random.choice(shapes) shape_rot = shape[rotation] shape_index = shapes.index(shape) color = shape_colors[shape_index] final_shape = pygame.sprite.Group() # 直接遍历字符串的每个字符,不要用split() for y, row in enumerate(shape_rot): for x, char in enumerate(row): if char == "0": final_shape.add(Block(color, x, y, rotation)) return final_shape, shape_index def rotate(shape_index, rotation): # 处理旋转索引越界 rotation %= len(shapes[shape_index]) new_shape = shapes[shape_index][rotation] color = shape_colors[shape_index] final_shape = pygame.sprite.Group() for y, row in enumerate(new_shape): for x, char in enumerate(row): if char == '0': # 保持旋转后位置居中,基于原形状中心偏移 final_shape.add(Block(color, x, y, rotation)) return final_shape def mainGame(): pygame.init() screen = pygame.display.set_mode((SCREEN_WIDTH, BOARD_HEIGHT)) pygame.display.set_caption("Tetris") clock = pygame.time.Clock() running = True falling = False rotation = 0 not_falling = pygame.sprite.Group() shape = None shape_index = None board = createBoard() while running: screen.fill((0,0,0)) screen.blit(board, (0, 0)) for event in pygame.event.get(): if event.type == pygame.QUIT: running = False if event.type == pygame.KEYDOWN: if event.key == pygame.K_SPACE and shape_index is not None: rotation += 1 shape = rotate(shape_index, rotation) if event.key == pygame.K_LEFT and shape is not None: # 左移,先检测碰撞 for block in shape: block.rect.x -= TILE_SIZE[0] if pygame.sprite.groupcollide(shape, not_falling, False, False) or any(block.rect.x < 0 for block in shape): for block in shape: block.rect.x += TILE_SIZE[0] if event.key == pygame.K_RIGHT and shape is not None: # 右移,检测碰撞 for block in shape: block.rect.x += TILE_SIZE[0] if pygame.sprite.groupcollide(shape, not_falling, False, False) or any(block.rect.x + TILE_SIZE[0] > BOARD_WIDTH for block in shape): for block in shape: block.rect.x -= TILE_SIZE[0] if event.key == pygame.K_DOWN and shape is not None: # 快速下落 shape.update() if not falling: shape_var = create_piece() shape_index = shape_var[1] shape = shape_var[0] falling = True if shape is not None: # 检测是否到底部或碰撞静止方块 hit_bottom = any(block.rect.y + TILE_SIZE[1] > BOARD_HEIGHT for block in shape) collision = pygame.sprite.groupcollide(shape, not_falling, False, False) if hit_bottom or collision: not_falling.add(shape) falling = False else: shape.update() shape.draw(board) not_falling.draw(board) pygame.display.flip() clock.tick(FPS) if __name__ == '__main__': mainGame()
关键修复点说明
- 修正方块生成逻辑:将
row.split()改为直接遍历字符串字符,确保正确识别形状中的0并生成Block。 - 添加底部碰撞检测:主循环中检查方块是否到达游戏区域底部,结合静止方块碰撞判断是否停止下落。
- 移除无效引用:直接使用
shape组进行碰撞检测和绘制,避免旧Sprite列表引用失效。 - 优化初始位置:将方块初始位置设置为游戏区域上方居中,避免生成在屏幕外。
- 补充移动逻辑:实现左右移动的碰撞检测,防止方块移出游戏区域或与静止方块重叠。
内容的提问来源于stack exchange,提问作者Colin Smith
相关产品推荐
相关产品推荐

