目录
成品展示
模块划分
初始化模块
Pygame 初始化
常量定义
窗口创建
方块管理模块
方块形状定义
方块生成
方块绘制
碰撞检测
方块合并
游戏逻辑模块
主循环
事件处理
方块下落逻辑
消除满行
得分规则
界面绘制模块
游戏面板绘制
提示窗口绘制
游戏结束界面绘制
完整代码链接
1984 年,苏联工程师阿列克谢・帕基特诺夫在电脑上敲下一串代码,无意间创造出了风靡全球的游戏 —— 俄罗斯方块。这个由 “tetra”(希腊语,意为 “四”)与 “Tennis”(帕基特诺夫喜爱的网球)组合而成的名字,带着数学与运动的奇妙融合,开启了一场跨越时代的方块冒险。
作为童年的回忆,每个游戏少年都希望有一款自己的俄罗斯方块游戏,接下来我们就开始“tetra”的创作之旅。
pygame.init()
调用 pygame.init()
函数初始化 Pygame 库的所有模块。
BLACK
、WHITE
等。WIDTH
和 HEIGHT
定义游戏区域的宽度和高度,PREVIEW_WIDTH
定义提示窗口的宽度。BLOCK_SIZE
定义每个方块的大小。screen = pygame.display.set_mode((WIDTH + PREVIEW_WIDTH, HEIGHT))
pygame.display.set_caption("俄罗斯方块")
SHAPES = [
[[1, 1, 1, 1]],
[[1, 1], [1, 1]],
[[1, 1, 0], [0, 1, 1]],
[[0, 1, 1], [1, 1, 0]],
[[1, 1, 1], [0, 1, 0]],
[[1, 1, 1], [1, 0, 0]],
[[1, 1, 1], [0, 0, 1]]
]
定义了 7 种不同形状的方块。
def new_piece():
shape = random.choice(SHAPES)
color = random.choice(COLORS)
return {
'x': WIDTH // 2 // BLOCK_SIZE - len(shape[0]) // 2,
'y': 0,
'shape': shape,
'color': color
}
随机选择一个方块形状和颜色,生成一个新的方块。
def draw_piece(piece, offset_x=0, offset_y=0):
for y, row in enumerate(piece['shape']):
for x, val in enumerate(row):
if val:
pygame.draw.rect(screen, piece['color'], [
offset_x + (piece['x'] + x) * BLOCK_SIZE,
offset_y + (piece['y'] + y) * BLOCK_SIZE,
BLOCK_SIZE, BLOCK_SIZE
])
pygame.draw.rect(screen, GRAY, [
offset_x + (piece['x'] + x) * BLOCK_SIZE,
offset_y + (piece['y'] + y) * BLOCK_SIZE,
BLOCK_SIZE, BLOCK_SIZE
], 1)
根据方块的位置、形状和颜色,在游戏窗口中绘制方块。
def is_collision(board, piece):
for y, row in enumerate(piece['shape']):
for x, val in enumerate(row):
if val:
new_x = piece['x'] + x
new_y = piece['y'] + y
if new_x < 0 or new_x >= WIDTH // BLOCK_SIZE or new_y >= HEIGHT // BLOCK_SIZE:
return True
if new_y >= 0 and board[new_y][new_x]:
return True
return False
检查方块是否越界或与游戏面板上已有的方块发生碰撞。
def merge(board, piece):
for y, row in enumerate(piece['shape']):
for x, val in enumerate(row):
if val:
board[piece['y'] + y][piece['x'] + x] = piece['color']
return board
将方块合并到游戏面板中。
while running:
# 事件处理
# 方块下落逻辑
# 界面绘制
pygame.display.flip()
for event in pygame.event.get():
if event.type == pygame.QUIT:
running = False
elif event.type == pygame.KEYDOWN and not game_over:
# 处理键盘按键事件
处理游戏中的各种事件,如关闭窗口、键盘按键等。
if not game_over and fall_time / 1000 >= fall_speed:
fall_time = 0
new_piece_data = {
'x': current_piece['x'],
'y': current_piece['y'] + 1,
'shape': current_piece['shape'],
'color': current_piece['color']
}
if not is_collision(board, new_piece_data):
current_piece = new_piece_data
else:
board = merge(board, current_piece)
board, cleared_lines = clear_lines(board)
# 更新得分
current_piece = next_piece
next_piece = new_piece()
if is_collision(board, current_piece):
game_over = True
控制方块自动下落,当方块落地后,合并方块、消除满行并更新得分。
def clear_lines(board):
full_lines = []
for y, row in enumerate(board):
if all(row):
full_lines.append(y)
for line in full_lines:
del board[line]
board = [[0] * (WIDTH // BLOCK_SIZE)] + board
return board, len(full_lines)
检查游戏面板中是否有满行,若有则消除并返回消除的行数。
if cleared_lines == 1:
score += 1
elif cleared_lines == 2:
score += 4
elif cleared_lines == 3:
score += 9
elif cleared_lines == 4:
score += 16
根据消除的行数更新得分,消除 1 行得 1 分,消除 2 行得 4 分,消除 3 行得 9 分,消除 4 行得 16 分。
for y, row in enumerate(board):
for x, val in enumerate(row):
if val:
pygame.draw.rect(screen, val, [
x * BLOCK_SIZE,
y * BLOCK_SIZE,
BLOCK_SIZE, BLOCK_SIZE
])
pygame.draw.rect(screen, GRAY, [
x * BLOCK_SIZE,
y * BLOCK_SIZE,
BLOCK_SIZE, BLOCK_SIZE
], 1)
绘制游戏面板上已有的方块。
game_over_text = font.render("Game Over!", True, RED)
screen.blit(game_over_text, (WIDTH // 2 - game_over_text.get_width() // 2, HEIGHT // 2 - 100))
draw_button("Play Again", ...)
draw_button("Quit", ...)
当游戏结束时,显示游戏结束信息和重新开始、退出游戏的按钮。
https://download.csdn.net/download/huangcheng86/90641302