Python小游戏实战:打造高颜值俄罗斯方块小游戏
Python小游戏实战:打造高颜值俄罗斯方块小游戏,俄罗斯方块是一款经典的休闲益智游戏,其核心玩法是通过控制下落的方块,使其在游戏区域内拼接成完整的行并消除,从而获得积分。本次实战将使用 Python 结合 pygame 库,开发一款功能完善、界面美观的俄罗斯方块小游戏
一、前言
Python作为一门简洁、易读、功能强大的编程语言,其基础语法是入门学习的核心。掌握好基础语法,能为后续的编程实践打下坚实的基础。本文将全面讲解Python3的基础语法知识,适合编程初学者系统学习。Python以其简洁优雅的语法和强大的通用性,成为当今最受欢迎的编程语言。本专栏旨在系统性地带你从零基础入门到精通Python核心。无论你是零基础小白还是希望进阶的专业开发者,都将通过清晰的讲解、丰富的实例和实战项目,逐步掌握语法基础、核心数据结构、函数与模块、面向对象编程、文件处理、主流库应用(如数据分析、Web开发、自动化)以及面向对象高级特性,最终具备独立开发能力和解决复杂问题的思维,高效应对数据分析、人工智能、Web应用、自动化脚本等广泛领域的实际需求。
🥇 点击进入Python入门专栏,Python凭借简洁易读的语法,是零基础学习编程的理想选择。本专栏专为初学者设计,系统讲解Python核心基础:变量、数据类型、流程控制、函数、文件操作及常用库入门。通过清晰示例与实用小项目,助你快速掌握编程思维,打下坚实根基,迈出自动化办公、数据分析或Web开发的第一步。
🥇 点击进入Python小游戏实战专栏, 寓教于乐,用Python亲手打造经典小游戏!本专栏通过开发贪吃蛇、飞机大战、猜数字、简易版俄罗斯方块等趣味项目,在实践中掌握Python核心语法、面向对象编程、事件处理、图形界面(如Pygame)等关键技能,将枯燥的代码学习转化为可见的成果,让学习编程充满乐趣与成就感,快速提升实战能力。
🥇 点击进入Python小工具实战专栏,告别重复劳动,用Python打造效率神器!本专栏教你开发文件批量处理、自动邮件通知、简易爬虫、桌面提醒、密码生成器、天气查询等实用小工具。聚焦os、shutil、requests、smtplib、schedule等核心库,通过真实场景案例,快速掌握自动化脚本编写技巧,解放双手,显著提升工作与生活效率,让代码真正服务于你的日常。
🥇 点击进入Python爬虫实战专栏,解锁网络数据宝库!本专栏手把手教你使用Python核心库(如requests、BeautifulSoup、Scrapy)构建高效爬虫。从基础网页解析到动态页面抓取、数据存储(CSV/数据库)、反爬策略应对及IP代理使用,通过实战项目(如电商比价、新闻聚合、图片采集、舆情监控),掌握合法合规获取并利用网络数据的核心技能,让数据成为你的超能力。
🥇 点击进入Python项目实战专栏,告别碎片化学习,挑战真实项目!本专栏精选Web应用开发(Flask/Django)、数据分析可视化、自动化办公系统、简易爬虫框架、API接口开发等综合项目。通过需求分析、架构设计、编码实现、测试部署的全流程,深入掌握工程化开发、代码复用、调试排错与团队协作核心能力,积累高质量作品集,真正具备解决复杂问题的Python实战经验。
✨ 正文开始
我将以Python的pygame库为基础,分步骤教你实现俄罗斯方块小游戏。先介绍开发环境搭建,再依次讲解游戏核心模块、界面绘制、游戏逻辑等,确保每个功能实现都清晰易懂。
Python 实战:打造高颜值俄罗斯方块小游戏
一、项目介绍
俄罗斯方块是一款经典的休闲益智游戏,其核心玩法是通过控制下落的方块,使其在游戏区域内拼接成完整的行并消除,从而获得积分。本次实战将使用 Python 结合 pygame 库,开发一款功能完善、界面美观的俄罗斯方块小游戏,实现如下核心功能:
- 实时显示下一个方块的形状,帮助玩家提前规划布局
- 支持通过键盘按键旋转方块方向,增加游戏策略性
- 实现积分系统,消除行数越多,得分越高
- 提供游戏暂停/继续功能,提升游戏体验
- 包含游戏开始、结束界面,完善游戏流程
二、开发环境准备
2.1 安装必要库
本次开发主要依赖 pygame 库用于游戏窗口创建、图形绘制和事件监听,安装命令如下:
pip install pygame
2.2 环境要求
- Python 版本:3.6 及以上
- 操作系统:Windows、macOS、Linux 均可(pygame 跨平台支持良好)
三、游戏核心模块设计
整个游戏将分为 5 个核心模块,各模块职责如下:
模块名称 | 核心功能 |
---|---|
方块类(Tetromino) | 定义方块的形状、颜色、旋转逻辑 |
游戏区域类(Board) | 管理游戏区域网格、方块放置、行消除判断 |
游戏控制类(Game) | 整合各模块,处理游戏主循环、事件监听 |
界面绘制模块 | 绘制游戏区域、下一个方块预览、积分面板 |
数据管理模块 | 管理游戏分数、等级、游戏状态(开始/暂停/结束) |
四、代码实现步骤
4.1 初始化游戏窗口与基础设置
首先创建游戏主文件 tetris.py
,完成 pygame 初始化、窗口创建及基础参数设置:
import pygame
import random
# 初始化pygame
pygame.init()
# 游戏常量定义
SCREEN_WIDTH = 400 # 窗口宽度
SCREEN_HEIGHT = 600 # 窗口高度
BLOCK_SIZE = 30 # 方块大小(像素)
BOARD_WIDTH = 10 # 游戏区域列数
BOARD_HEIGHT = 20 # 游戏区域行数
# 颜色定义(使用RGB值,打造清新配色)
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (128, 128, 128)
COLORS = [
(0, 255, 255), # 青色
(0, 0, 255), # 蓝色
(255, 165, 0), # 橙色
(255, 255, 0), # 黄色
(0, 255, 0), # 绿色
(128, 0, 128), # 紫色
(255, 0, 0) # 红色
]
# 创建游戏窗口
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Python 俄罗斯方块")
# 设置字体(用于显示分数、文字)
font = pygame.font.Font(None, 36)
small_font = pygame.font.Font(None, 24)
4.2 实现方块类(Tetromino)
方块是游戏的核心元素,需要定义 7 种基础形状(I、O、T、L、J、S、Z),并实现旋转逻辑:
class Tetromino:
# 定义7种方块形状(0表示空白,1表示方块)
SHAPES = [
[[1, 1, 1, 1]], # I型
[[1, 1], [1, 1]], # O型
[[0, 1, 0], [1, 1, 1]], # T型
[[0, 0, 1], [1, 1, 1]], # L型
[[1, 0, 0], [1, 1, 1]], # J型
[[0, 1, 1], [1, 1, 0]], # S型
[[1, 1, 0], [0, 1, 1]] # Z型
]
def __init__(self):
# 随机选择方块形状和颜色
self.shape = random.choice(self.SHAPES)
self.color = random.choice(COLORS)
# 初始位置(居中顶部)
self.x = BOARD_WIDTH // 2 - len(self.shape[0]) // 2
self.y = 0
def rotate(self):
"""旋转方块(矩阵转置)"""
# 矩阵转置实现旋转效果
rotated = list(zip(*self.shape[::-1]))
# 将元组转换为列表
self.shape = [list(row) for row in rotated]
def get_blocks(self):
"""获取方块的所有方块坐标(相对于游戏区域)"""
blocks = []
for y, row in enumerate(self.shape):
for x, cell in enumerate(row):
if cell:
blocks.append((self.x + x, self.y + y))
return blocks
4.3 实现游戏区域类(Board)
游戏区域负责管理方块的放置、行消除、碰撞检测等核心逻辑:
class Board:
def __init__(self):
# 初始化游戏区域网格(BOARD_HEIGHT行,BOARD_WIDTH列,0表示空白)
self.grid = [[0 for _ in range(BOARD_WIDTH)] for _ in range(BOARD_HEIGHT)]
self.score = 0 # 游戏分数
self.level = 1 # 游戏等级
self.lines_cleared = 0 # 已消除行数
def check_collision(self, tetromino, dx=0, dy=0):
"""检测方块移动后的碰撞(边界碰撞或与已放置方块碰撞)"""
for x, y in tetromino.get_blocks():
new_x = x + dx
new_y = y + dy
# 检测边界碰撞
if new_x < 0 or new_x >= BOARD_WIDTH:
return True
if new_y >= BOARD_HEIGHT:
return True
# 检测与已放置方块碰撞(忽略y<0的情况,方块从顶部生成时可能暂时超出区域)
if new_y >= 0 and self.grid[new_y][new_x] != 0:
return True
return False
def lock_tetromino(self, tetromino):
"""将方块锁定到游戏区域(方块无法继续下落时)"""
for x, y in tetromino.get_blocks():
if y >= 0: # 只锁定在游戏区域内的部分
self.grid[y][x] = tetromino.color
# 锁定后检查是否有可消除的行
self.clear_lines()
def clear_lines(self):
"""消除完整的行,并更新分数和等级"""
lines_cleared = 0
new_grid = []
for row in self.grid:
if all(cell != 0 for cell in row):
# 完整行,不加入新网格(即消除)
lines_cleared += 1
else:
new_grid.append(row)
# 在顶部补充空白行(消除行数等于新增空白行数)
for _ in range(lines_cleared):
new_grid.insert(0, [0 for _ in range(BOARD_WIDTH)])
# 更新游戏区域
self.grid = new_grid
# 更新分数(消除1行100分,2行300分,3行500分,4行800分,鼓励消除多行)
score_map = {1: 100, 2: 300, 3: 500, 4: 800}
self.score += score_map.get(lines_cleared, 0) * self.level
# 更新已消除行数和等级(每消除10行升1级)
self.lines_cleared += lines_cleared
self.level = self.lines_cleared // 10 + 1
def is_game_over(self, tetromino):
"""判断游戏是否结束(新生成的方块刚出现就碰撞)"""
return self.check_collision(tetromino)
4.4 实现游戏控制类(Game)
整合各模块,处理游戏主循环、事件监听、游戏状态管理:
class TetrisGame:
def __init__(self):
self.board = Board()
self.current_tetromino = Tetromino() # 当前下落的方块
self.next_tetromino = Tetromino() # 下一个方块(预览)
self.game_over = False # 游戏结束标志
self.paused = False # 游戏暂停标志
self.fall_time = 0 # 方块下落计时
self.fall_speed = 1000 # 方块下落速度(毫秒,值越小越快)
def switch_tetromino(self):
"""切换当前方块和下一个方块(当前方块锁定后)"""
self.current_tetromino = self.next_tetromino
self.next_tetromino = Tetromino()
# 检查游戏是否结束
if self.board.is_game_over(self.current_tetromino):
self.game_over = True
def handle_events(self):
"""处理键盘事件"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False # 退出游戏
if event.type == pygame.KEYDOWN:
if self.game_over:
# 游戏结束时按R键重新开始
if event.key == pygame.K_r:
self.__init__()
else:
# 按P键暂停/继续游戏
if event.key == pygame.K_p:
self.paused = not self.paused
if not self.paused:
# 左移
if event.key == pygame.K_LEFT and not self.board.check_collision(self.current_tetromino, dx=-1):
self.current_tetromino.x -= 1
# 右移
if event.key == pygame.K_RIGHT and not self.board.check_collision(self.current_tetromino, dx=1):
self.current_tetromino.x += 1
# 下移(加速下落)
if event.key == pygame.K_DOWN and not self.board.check_collision(self.current_tetromino, dy=1):
self.current_tetromino.y += 1
self.board.score += 1 # 下移加速得分
# 旋转(上键或空格键)
if event.key in (pygame.K_UP, pygame.K_SPACE):
self.current_tetromino.rotate()
# 如果旋转后碰撞,恢复原状
if self.board.check_collision(self.current_tetromino):
self.current_tetromino.rotate()
self.current_tetromino.rotate()
self.current_tetromino.rotate()
return True
def update(self, delta_time):
"""更新游戏状态(方块自动下落)"""
if not self.game_over and not self.paused:
self.fall_time += delta_time
# 根据等级调整下落速度(等级越高,速度越快)
adjusted_speed = self.fall_speed - (self.board.level - 1) * 50
adjusted_speed = max(adjusted_speed, 200) # 最低速度限制
# 达到下落时间,自动下移
if self.fall_time >= adjusted_speed:
if not self.board.check_collision(self.current_tetromino, dy=1):
self.current_tetromino.y += 1
else:
# 无法下移,锁定当前方块并切换新方块
self.board.lock_tetromino(self.current_tetromino)
self.switch_tetromino()
self.fall_time = 0
def draw(self):
"""绘制游戏界面"""
# 填充背景色
screen.fill(GRAY)
# 绘制游戏区域边框
board_x = (SCREEN_WIDTH - BOARD_WIDTH * BLOCK_SIZE) // 2 # 游戏区域居中
board_y = 50 # 游戏区域顶部距离
pygame.draw.rect(screen, WHITE, (board_x - 2, board_y - 2, BOARD_WIDTH * BLOCK_SIZE + 4, BOARD_HEIGHT * BLOCK_SIZE + 4), 2)
# 绘制游戏区域网格和已放置的方块
for y in range(BOARD_HEIGHT):
for x in range(BOARD_WIDTH):
color = self.board.grid[y][x]
if color != 0:
pygame.draw.rect(
screen,
color,
(board_x + x * BLOCK_SIZE + 1, board_y + y * BLOCK_SIZE + 1, BLOCK_SIZE - 2, BLOCK_SIZE - 2)
)
# 绘制当前下落的方块
for x, y in self.current_tetromino.get_blocks():
if y >= 0: # 只绘制在游戏区域内的部分
pygame.draw.rect(
screen,
self.current_tetromino.color,
(board_x + x * BLOCK_SIZE + 1, board_y + y * BLOCK_SIZE + 1, BLOCK_SIZE - 2, BLOCK_SIZE - 2)
)
# 绘制下一个方块预览面板
next_x = board_x + BOARD_WIDTH * BLOCK_SIZE + 30 # 预览面板在游戏区域右侧
next_y = board_y + 100
# 绘制预览面板边框
pygame.draw.rect(screen, WHITE, (next_x - 2, next_y - 2, 100, 100), 2)
# 绘制"下一个"文字
next_text = small_font.render("下一个", True, WHITE)
screen.blit(next_text, (next_x + 20, next_y - 30))
# 绘制下一个方块
for x, y in self.next_tetromino.get_blocks():
pygame.draw.rect(
screen,
self.next_tetromino.color,
(next_x + (x - 1) * BLOCK_SIZE + 1, next_y + (y) * BLOCK_SIZE + 1, BLOCK_SIZE - 2, BLOCK_SIZE - 2)
)
# 绘制分数、等级信息
score_text = font.render(f"分数: {self.board.score}", True, WHITE)
screen.blit(score_text, (30, 20))
level_text = font.render(f"等级: {self.board.level}", True, WHITE)
screen.blit(level_text, (SCREEN_WIDTH - 150, 20))
# 绘制暂停提示
if self.paused:
pause_text = font.render("暂停 (P键继续)", True, (255, 0, 0))
screen.blit(pause_text, (SCREEN_WIDTH // 2 - 100, SCREEN_HEIGHT // 2))
# 绘制游戏结束提示
if self.game_over:
game_over_text = font.render("游戏结束", True, (255, 0, 0))
restart_text = small_font.render("按R键重新开始", True, WHITE)
screen.blit(game_over_text, (SCREEN_WIDTH // 2 - 70, SCREEN_HEIGHT // 2 - 50))
screen.blit(restart_text, (SCREEN_WIDTH // 2 - 80, SCREEN_HEIGHT // 2))
# 更新显示
pygame.display.flip()
def run(self):
"""游戏主循环"""
clock = pygame.time.Clock()
running = True
while running:
delta_time = clock.tick(60) # 控制帧率为60FPS
running = self.handle_events() # 处理事件
self.update(delta_time) # 更新游戏状态
self.draw() # 绘制界面
pygame.quit()
4.5 完整代码和运行效果
import pygame
import random
import sys
# 初始化pygame
pygame.init()
# 确保中文显示正常
pygame.font.init()
default_font = pygame.font.get_default_font() # 获取系统默认字体
# 游戏常量定义
SCREEN_WIDTH = 500 # 进一步增加窗口宽度
SCREEN_HEIGHT = 680 # 进一步增加窗口高度
BLOCK_SIZE = 28 # 略微减小方块大小,增加显示空间
BOARD_WIDTH = 10 # 游戏区域列数
BOARD_HEIGHT = 20 # 游戏区域行数
# 颜色定义
BLACK = (0, 0, 0)
WHITE = (255, 255, 255)
GRAY = (128, 128, 128)
LIGHT_GRAY = (200, 200, 200)
COLORS = [
(0, 255, 255), # 青色
(0, 0, 255), # 蓝色
(255, 165, 0), # 橙色
(255, 255, 0), # 黄色
(0, 255, 0), # 绿色
(128, 0, 128), # 紫色
(255, 0, 0) # 红色
]
# 创建游戏窗口
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("Python 俄罗斯方块")
# 设置字体(确保中文正常显示)
try:
# 尝试加载中文字体
font = pygame.font.SysFont(["SimHei", "Microsoft YaHei", "SimSun"], 36)
small_font = pygame.font.SysFont(["SimHei", "Microsoft YaHei", "SimSun"], 24)
except:
# 加载失败时使用默认字体
font = pygame.font.Font(default_font, 36)
small_font = pygame.font.Font(default_font, 24)
class Tetromino:
# 定义7种方块形状
SHAPES = [
[[1, 1, 1, 1]], # I型
[[1, 1], [1, 1]], # O型
[[0, 1, 0], [1, 1, 1]], # T型
[[0, 0, 1], [1, 1, 1]], # L型
[[1, 0, 0], [1, 1, 1]], # J型
[[0, 1, 1], [1, 1, 0]], # S型
[[1, 1, 0], [0, 1, 1]] # Z型
]
def __init__(self):
self.shape = random.choice(self.SHAPES)
self.color = random.choice(COLORS)
self.x = BOARD_WIDTH // 2 - len(self.shape[0]) // 2
self.y = 0
def rotate(self):
"""旋转方块(矩阵转置)"""
rotated = list(zip(*self.shape[::-1]))
self.shape = [list(row) for row in rotated]
def get_blocks(self):
"""获取方块的所有方块坐标"""
blocks = []
for y, row in enumerate(self.shape):
for x, cell in enumerate(row):
if cell:
blocks.append((self.x + x, self.y + y))
return blocks
class Board:
def __init__(self):
self.grid = [[0 for _ in range(BOARD_WIDTH)] for _ in range(BOARD_HEIGHT)]
self.score = 0
self.level = 1
self.lines_cleared = 0
def check_collision(self, tetromino, dx=0, dy=0):
"""检测碰撞"""
for x, y in tetromino.get_blocks():
new_x = x + dx
new_y = y + dy
if new_x < 0 or new_x >= BOARD_WIDTH:
return True
if new_y >= BOARD_HEIGHT:
return True
if new_y >= 0 and self.grid[new_y][new_x] != 0:
return True
return False
def lock_tetromino(self, tetromino):
"""锁定方块到游戏区域"""
for x, y in tetromino.get_blocks():
if y >= 0:
self.grid[y][x] = tetromino.color
self.clear_lines()
def clear_lines(self):
"""消除完整行并更新分数"""
lines_cleared = 0
new_grid = []
for row in self.grid:
if all(cell != 0 for cell in row):
lines_cleared += 1
else:
new_grid.append(row)
for _ in range(lines_cleared):
new_grid.insert(0, [0 for _ in range(BOARD_WIDTH)])
self.grid = new_grid
# 分数计算
score_map = {1: 100, 2: 300, 3: 500, 4: 800}
self.score += score_map.get(lines_cleared, 0) * self.level
self.lines_cleared += lines_cleared
self.level = self.lines_cleared // 10 + 1
def is_game_over(self, tetromino):
"""判断游戏是否结束"""
return self.check_collision(tetromino)
class TetrisGame:
def __init__(self):
# 重新初始化游戏状态
self.board = Board()
self.current_tetromino = Tetromino()
self.next_tetromino = Tetromino()
self.game_over = False
self.paused = False
self.fall_time = 0
self.fall_speed = 1000 # 毫秒
self.move_delay = 150 # 按键连续移动的延迟(毫秒)
self.last_move_time = 0 # 上次移动时间
def reset_game(self):
"""重置游戏状态(解决重新开始问题)"""
self.__init__() # 重新初始化所有属性
def switch_tetromino(self):
"""切换到下一个方块"""
self.current_tetromino = self.next_tetromino
self.next_tetromino = Tetromino()
if self.board.is_game_over(self.current_tetromino):
self.game_over = True
def handle_continuous_moves(self, delta_time):
"""处理持续按键的移动"""
if self.game_over or self.paused:
return
self.last_move_time += delta_time
# 只有达到延迟时间才处理连续移动
if self.last_move_time < self.move_delay:
return
keys = pygame.key.get_pressed()
# 左移
if keys[pygame.K_LEFT] and not self.board.check_collision(self.current_tetromino, dx=-1):
self.current_tetromino.x -= 1
self.last_move_time = 0
# 右移
if keys[pygame.K_RIGHT] and not self.board.check_collision(self.current_tetromino, dx=1):
self.current_tetromino.x += 1
self.last_move_time = 0
# 下移(快速下落)
if keys[pygame.K_DOWN] and not self.board.check_collision(self.current_tetromino, dy=1):
self.current_tetromino.y += 1
self.board.score += 1 # 加速下落得分
self.last_move_time = 0
def handle_events(self):
"""处理一次性按键事件"""
for event in pygame.event.get():
if event.type == pygame.QUIT:
return False
if event.type == pygame.KEYDOWN:
# 无论游戏状态如何,R键都可以重新开始
if event.key == pygame.K_r:
self.reset_game()
return True
if self.game_over:
return True
# 暂停/继续游戏
if event.key == pygame.K_p:
self.paused = not self.paused
if not self.paused:
# 旋转(上键或空格键)
if event.key in (pygame.K_UP, pygame.K_SPACE):
self.current_tetromino.rotate()
# 旋转碰撞检测
if self.board.check_collision(self.current_tetromino):
# 恢复原状(旋转3次回到原来的方向)
for _ in range(3):
self.current_tetromino.rotate()
return True
def update(self, delta_time):
"""更新游戏状态"""
if not self.game_over and not self.paused:
# 处理连续按键移动
self.handle_continuous_moves(delta_time)
# 方块自动下落
self.fall_time += delta_time
adjusted_speed = max(self.fall_speed - (self.board.level - 1) * 50, 200)
if self.fall_time >= adjusted_speed:
if not self.board.check_collision(self.current_tetromino, dy=1):
self.current_tetromino.y += 1
else:
self.board.lock_tetromino(self.current_tetromino)
self.switch_tetromino()
self.fall_time = 0
def draw(self):
"""绘制游戏界面"""
screen.fill(GRAY)
# 计算游戏区域位置(左侧放置,留出右侧足够空间)
board_x = 30 # 左侧留出30像素
board_y = 50
# 绘制游戏区域边框
pygame.draw.rect(screen, WHITE,
(board_x - 2, board_y - 2,
BOARD_WIDTH * BLOCK_SIZE + 4,
BOARD_HEIGHT * BLOCK_SIZE + 4), 2)
# 绘制已放置的方块
for y in range(BOARD_HEIGHT):
for x in range(BOARD_WIDTH):
color = self.board.grid[y][x]
if color != 0:
pygame.draw.rect(
screen,
color,
(board_x + x * BLOCK_SIZE + 1,
board_y + y * BLOCK_SIZE + 1,
BLOCK_SIZE - 2, BLOCK_SIZE - 2)
)
# 绘制当前方块
for x, y in self.current_tetromino.get_blocks():
if y >= 0:
pygame.draw.rect(
screen,
self.current_tetromino.color,
(board_x + x * BLOCK_SIZE + 1,
board_y + y * BLOCK_SIZE + 1,
BLOCK_SIZE - 2, BLOCK_SIZE - 2)
)
# 右侧信息面板 - 确保有足够空间
panel_x = board_x + BOARD_WIDTH * BLOCK_SIZE + 40 # 与游戏区分开40像素
panel_y = board_y
# 绘制下一个方块预览
next_title = small_font.render("下一个", True, WHITE)
screen.blit(next_title, (panel_x, panel_y))
# 下一个方块预览区域
preview_area_size = 140
pygame.draw.rect(screen, WHITE,
(panel_x - 2, panel_y + 30 - 2,
preview_area_size, preview_area_size), 2)
# 计算下一个方块的预览位置(居中显示)
next_shape_height = len(self.next_tetromino.shape)
next_shape_width = len(self.next_tetromino.shape[0])
preview_offset_x = (preview_area_size - next_shape_width * BLOCK_SIZE) // 2
preview_offset_y = (preview_area_size - next_shape_height * BLOCK_SIZE) // 2
for x, y in self.next_tetromino.get_blocks():
pygame.draw.rect(
screen,
self.next_tetromino.color,
(panel_x + preview_offset_x + (x - self.next_tetromino.x) * BLOCK_SIZE + 1,
panel_y + 30 + preview_offset_y + (y - self.next_tetromino.y) * BLOCK_SIZE + 1,
BLOCK_SIZE - 2, BLOCK_SIZE - 2)
)
# 绘制分数信息
score_title = small_font.render("分数", True, WHITE)
score_text = font.render(str(self.board.score), True, WHITE)
screen.blit(score_title, (panel_x, panel_y + 200))
screen.blit(score_text, (panel_x, panel_y + 230))
# 绘制等级信息
level_title = small_font.render("等级", True, WHITE)
level_text = font.render(str(self.board.level), True, WHITE)
screen.blit(level_title, (panel_x, panel_y + 280))
screen.blit(level_text, (panel_x, panel_y + 310))
# 绘制已消除行数
lines_title = small_font.render("消除行数", True, WHITE)
lines_text = font.render(str(self.board.lines_cleared), True, WHITE)
screen.blit(lines_title, (panel_x, panel_y + 360))
screen.blit(lines_text, (panel_x, panel_y + 390))
# 绘制操作说明
controls_title = small_font.render("操作说明", True, WHITE)
screen.blit(controls_title, (panel_x, panel_y + 440))
controls = [
"← → 移动",
"↑(空格)旋转",
"↓ 加速下落",
"P 暂停/继续",
"R 重新开始"
]
for i, text in enumerate(controls):
control_text = small_font.render(text, True, LIGHT_GRAY)
screen.blit(control_text, (panel_x, panel_y + 470 + i * 30))
# 绘制暂停提示
if self.paused:
s = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
s.fill((0, 0, 0, 128)) # 半透明黑色遮罩
screen.blit(s, (0, 0))
pause_text = font.render("暂停中", True, (255, 0, 0))
continue_text = small_font.render("按P键继续", True, WHITE)
screen.blit(pause_text, (SCREEN_WIDTH // 2 - pause_text.get_width() // 2,
SCREEN_HEIGHT // 2 - 30))
screen.blit(continue_text, (SCREEN_WIDTH // 2 - continue_text.get_width() // 2,
SCREEN_HEIGHT // 2 + 20))
# 绘制游戏结束提示
if self.game_over:
s = pygame.Surface((SCREEN_WIDTH, SCREEN_HEIGHT), pygame.SRCALPHA)
s.fill((0, 0, 0, 128)) # 半透明黑色遮罩
screen.blit(s, (0, 0))
over_text = font.render("游戏结束", True, (255, 0, 0))
restart_text = small_font.render("按R键重新开始", True, WHITE)
screen.blit(over_text, (SCREEN_WIDTH // 2 - over_text.get_width() // 2,
SCREEN_HEIGHT // 2 - 50))
screen.blit(restart_text, (SCREEN_WIDTH // 2 - restart_text.get_width() // 2,
SCREEN_HEIGHT // 2))
final_score_text = small_font.render(f"最终分数: {self.board.score}", True, WHITE)
screen.blit(final_score_text, (SCREEN_WIDTH // 2 - final_score_text.get_width() // 2,
SCREEN_HEIGHT // 2 + 40))
pygame.display.flip()
def run(self):
"""游戏主循环"""
clock = pygame.time.Clock()
running = True
while running:
delta_time = clock.tick(60) # 60 FPS
running = self.handle_events()
self.update(delta_time)
self.draw()
pygame.quit()
sys.exit()
if __name__ == "__main__":
game = TetrisGame()
game.run()
运行效果:
暂停效果:
4.6 启动游戏
在文件末尾添加游戏启动代码:
if __name__ == "__main__":
game = TetrisGame()
game.run()
五、游戏功能测试与操作说明
5.1 运行游戏
执行 python tetris.py
即可启动游戏,游戏启动后将显示初始界面,包含游戏区域、下一个方块预览、分数和等级信息。
5.2 操作指南
按键 | 功能 |
---|---|
左箭头 | 方块向左移动 |
右箭头 | 方块向右移动 |
下箭头 | 方块加速下落(获得额外分数) |
上箭头/空格键 | 旋转方块 |
P键 | 暂停/继续游戏 |
R键 | 游戏结束后重新开始 |
关闭窗口按钮 | 退出游戏 |
5.3 功能验证
- 下一个方块预览:游戏右侧面板下面是俄罗斯方块游戏的完整代码,整合了之前介绍的所有功能,包括方块旋转、下一个方块预览、积分系统和暂停功能等:
代码说明
这个完整的俄罗斯方块游戏代码包含以下核心组件:
- 常量定义:设置了游戏窗口大小、方块尺寸、颜色方案等基础参数
- Tetromino类:管理方块的形状、颜色和旋转逻辑
- Board类:处理游戏区域的网格管理、碰撞检测、行消除和分数计算
- TetrisGame类:游戏主控制器,负责事件处理、游戏状态更新和界面绘制
如何运行
- 确保已安装pygame库:
pip install pygame
- 将代码保存为
tetris.py
- 运行命令:
python tetris.py
游戏操作简单直观,通过方向键控制方块移动和旋转,P键暂停游戏,游戏结束后按R键重新开始。随着等级提升,方块下落速度会逐渐加快,增加游戏挑战性。
🔥🔥🔥 相关热门书籍推荐:
书名 | 说明 |
---|---|
![]() | 讲解 Python 中贝叶斯建模计算,理论与实践结合,适合数据科学领域学习贝叶斯方法的读者。 🥇 点击购买 |
![]() | 专注 Python 高性能技术,助力高效处理大数据集,提升编码与数据分析效率。 🥇 点击购买 |
![]() | 依托 PyTorch 和 Google Colab,深入深度学习核心,兼具理论与实践,适合学习者进阶。 🥇 点击购买 |
附录:扩展学习资源
- 官方资源:
- Python官网:https://www.python.org
- PyPI:https://pypi.org(查找第三方库)
- 安装包等相关文件(另附带pycharm工具),网盘下载地址:https://pan.quark.cn/s/649af731037c
- 学习资料视频和文档资源,网盘下载地址: https://pan.quark.cn/s/ee16901a8954
- 本专栏特色资源:
- 代码资源仓库:CSDN专属资源在线获取
- 海量Python教程:关注公众号:xcLeigh,获取网盘地址
- 一对一答疑:添加微信与博主在线沟通(
备注“Python专栏”
)
联系博主
xcLeigh 博主,全栈领域优质创作者,博客专家,目前,活跃在CSDN、微信公众号、小红书、知乎、掘金、快手、思否、微博、51CTO、B站、腾讯云开发者社区、阿里云开发者社区等平台,全网拥有几十万的粉丝,全网统一IP为 xcLeigh。希望通过我的分享,让大家能在喜悦的情况下收获到有用的知识。主要分享编程、开发工具、算法、技术学习心得等内容。很多读者评价他的文章简洁易懂,尤其对于一些复杂的技术话题,他能通过通俗的语言来解释,帮助初学者更好地理解。博客通常也会涉及一些实践经验,项目分享以及解决实际开发中遇到的问题。如果你是开发领域的初学者,或者在学习一些新的编程语言或框架,关注他的文章对你有很大帮助。
亲爱的朋友,无论前路如何漫长与崎岖,都请怀揣梦想的火种,因为在生活的广袤星空中,总有一颗属于你的璀璨星辰在熠熠生辉,静候你抵达。
愿你在这纷繁世间,能时常收获微小而确定的幸福,如春日微风轻拂面庞,所有的疲惫与烦恼都能被温柔以待,内心永远充盈着安宁与慰藉。
至此,文章已至尾声,而您的故事仍在续写,不知您对文中所叙有何独特见解?期待您在心中与我对话,开启思想的新交流。
💞 关注博主 🌀 带你实现畅游前后端!
🏰 大屏可视化 🌀 带你体验酷炫大屏!
💯 神秘个人简介 🌀 带你体验不一样得介绍!
🥇 从零到一学习Python 🌀 带你玩转Python技术流!
🏆 前沿应用深度测评 🌀 前沿AI产品热门应用在线等你来发掘!
💦 注:本文撰写于CSDN平台,作者:xcLeigh(所有权归作者所有) ,https://xcleigh.blog.csdn.net/,如果相关下载没有跳转,请查看这个地址,相关链接没有跳转,皆是抄袭本文,转载请备注本文原地址。
📣 亲,码字不易,动动小手,欢迎 点赞 ➕ 收藏,如 🈶 问题请留言(或者关注下方公众号,看见后第一时间回复,还有海量编程资料等你来领!),博主看见后一定及时给您答复 💌💌💌
转载自CSDN-专业IT技术社区
原文链接:https://blog.csdn.net/weixin_43151418/article/details/151932574