使用Python开发经典俄罗斯方块游戏

发布于:2025-05-16 ⋅ 阅读:(11) ⋅ 点赞:(0)

使用Python开发经典俄罗斯方块游戏

在这篇教程中,我们将学习如何使用Python和Pygame库开发一个经典的俄罗斯方块游戏。这个项目将帮助你理解游戏开发的基本概念,包括图形界面、用户输入处理、碰撞检测等重要内容。
在这里插入图片描述
在这里插入图片描述

项目概述

我们将实现以下功能:

  1. 创建游戏主窗口和网格系统
  2. 实现不同形状的方块(Tetromino)
  3. 添加方块旋转和移动功能
  4. 实现行消除机制
  5. 添加分数系统
  6. 实现游戏结束判定

所需知识

  • Python基础编程
  • Pygame库的基本使用
  • 面向对象编程概念
  • 基本的游戏开发原理

完整代码实现

import pygame
import random

# 初始化Pygame
pygame.init()

# 颜色定义
COLORS = [
    (0, 0, 0),        # 黑色(背景)
    (120, 37, 179),   # 紫色
    (100, 179, 179),  # 青色
    (80, 34, 22),     # 褐色
    (80, 134, 22),    # 绿色
    (180, 34, 22),    # 红色
    (180, 34, 122),   # 粉色
]

# 方块形状定义
SHAPES = [
    [[1, 5, 9, 13], [4, 5, 6, 7]],  # I
    [[1, 2, 5, 9], [0, 4, 5, 6], [1, 5, 9, 8], [4, 5, 6, 10]],  # J
    [[1, 2, 6, 10], [5, 6, 7, 9], [2, 6, 10, 11], [3, 5, 6, 7]],  # L
    [[1, 2, 5, 6]],  # O
    [[5, 6, 8, 9], [1, 5, 6, 10]],  # S
    [[1, 4, 5, 6], [1, 4, 5, 9], [4, 5, 6, 9], [1, 5, 6, 9]],  # T
    [[4, 5, 9, 10], [2, 6, 5, 9]]  # Z
]

class Tetris:
    def __init__(self, height, width):
        self.height = height
        self.width = width
        self.field = []
        self.score = 0
        self.state = "start"
        self.figure = None
        self.x = 0
        self.y = 0
        
        self.init_field()
        
    def init_field(self):
        self.field = []
        for i in range(self.height):
            new_line = []
            for j in range(self.width):
                new_line.append(0)
            self.field.append(new_line)
            
    def new_figure(self):
        self.figure = Figure(3, 0)
        
    def intersects(self):
        intersection = False
        for i in range(4):
            for j in range(4):
                if i * 4 + j in self.figure.image():
                    if (i + self.figure.y > self.height - 1 or
                        j + self.figure.x > self.width - 1 or
                        j + self.figure.x < 0 or
                        self.field[i + self.figure.y][j + self.figure.x] > 0):
                        intersection = True
        return intersection
        
    def freeze(self):
        for i in range(4):
            for j in range(4):
                if i * 4 + j in self.figure.image():
                    self.field[i + self.figure.y][j + self.figure.x] = self.figure.color
        self.break_lines()
        self.new_figure()
        if self.intersects():
            self.state = "gameover"
            
    def break_lines(self):
        lines = 0
        for i in range(1, self.height):
            zeros = 0
            for j in range(self.width):
                if self.field[i][j] == 0:
                    zeros += 1
            if zeros == 0:
                lines += 1
                for i1 in range(i, 1, -1):
                    for j in range(self.width):
                        self.field[i1][j] = self.field[i1-1][j]
        self.score += lines ** 2
        
    def go_space(self):
        while not self.intersects():
            self.figure.y += 1
        self.figure.y -= 1
        self.freeze()
        
    def go_down(self):
        self.figure.y += 1
        if self.intersects():
            self.figure.y -= 1
            self.freeze()
            
    def go_side(self, dx):
        old_x = self.figure.x
        self.figure.x += dx
        if self.intersects():
            self.figure.x = old_x
            
    def rotate(self):
        old_rotation = self.figure.rotation
        self.figure.rotate()
        if self.intersects():
            self.figure.rotation = old_rotation

class Figure:
    def __init__(self, x, y):
        self.x = x
        self.y = y
        self.type = random.randint(0, len(SHAPES) - 1)
        self.color = random.randint(1, len(COLORS) - 1)
        self.rotation = 0
        
    def image(self):
        return SHAPES[self.type][self.rotation]
    
    def rotate(self):
        self.rotation = (self.rotation + 1) % len(SHAPES[self.type])

# 游戏参数设置
GAME_HEIGHT = 20
GAME_WIDTH = 10
TILE_SIZE = 30
GAME_RES = GAME_WIDTH * TILE_SIZE, GAME_HEIGHT * TILE_SIZE
FPS = 60

# 初始化游戏窗口
pygame.init()
screen = pygame.display.set_mode(GAME_RES)
pygame.display.set_caption("俄罗斯方块")
clock = pygame.time.Clock()

# 创建游戏对象
game = Tetris(GAME_HEIGHT, GAME_WIDTH)
counter = 0
pressing_down = False

while True:
    if game.figure is None:
        game.new_figure()
    counter += 1
    if counter > 100000:
        counter = 0

    if counter % (FPS // (game.score + 1) // 2 + 1) == 0 or pressing_down:
        if game.state == "start":
            game.go_down()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            exit()
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_UP:
                game.rotate()
            if event.key == pygame.K_DOWN:
                pressing_down = True
            if event.key == pygame.K_LEFT:
                game.go_side(-1)
            if event.key == pygame.K_RIGHT:
                game.go_side(1)
            if event.key == pygame.K_SPACE:
                game.go_space()
            if event.key == pygame.K_ESCAPE:
                pygame.quit()
                exit()
        if event.type == pygame.KEYUP:
            if event.key == pygame.K_DOWN:
                pressing_down = False

    screen.fill((0, 0, 0))

    for i in range(game.height):
        for j in range(game.width):
            if game.field[i][j] > 0:
                pygame.draw.rect(screen, COLORS[game.field[i][j]],
                               [j * TILE_SIZE, i * TILE_SIZE, TILE_SIZE - 1, TILE_SIZE - 1])

    if game.figure is not None:
        for i in range(4):
            for j in range(4):
                if i * 4 + j in game.figure.image():
                    pygame.draw.rect(screen, COLORS[game.figure.color],
                                   [(j + game.figure.x) * TILE_SIZE,
                                    (i + game.figure.y) * TILE_SIZE,
                                    TILE_SIZE - 1, TILE_SIZE - 1])

    pygame.display.flip()
    clock.tick(FPS)

代码详解

1. 基础设置和常量定义

import pygame
import random

# 颜色定义
COLORS = [
    (0, 0, 0),        # 黑色(背景)
    (120, 37, 179),   # 紫色
    # ... 其他颜色
]

# 方块形状定义
SHAPES = [
    [[1, 5, 9, 13], [4, 5, 6, 7]],  # I形
    # ... 其他形状
]

这部分代码定义了:

  • 游戏使用的颜色列表
  • 七种不同的俄罗斯方块形状
  • 每种形状的旋转状态

2. Tetris类

Tetris类是游戏的核心,包含了以下主要功能:

  • 游戏场地初始化
  • 方块生成和移动
  • 碰撞检测
  • 消行处理
  • 游戏状态管理

3. Figure类

Figure类负责管理方块对象,包括:

  • 方块的位置
  • 方块的类型和颜色
  • 方块的旋转状态

4. 游戏主循环

主循环处理:

  • 用户输入
  • 游戏状态更新
  • 画面渲染

游戏功能

  1. 基本操作

    • 左右方向键:移动方块
    • 上方向键:旋转方块
    • 下方向键:加速下落
    • 空格键:直接落到底部
  2. 计分系统

    • 同时消除的行数越多,得分越高
    • 分数影响方块下落速度
  3. 游戏结束条件

    • 新方块无法放置时游戏结束

运行效果

运行代码后,你将看到:

  1. 一个黑色背景的游戏窗口
  2. 不同颜色的方块随机出现
  3. 方块可以移动和旋转
  4. 完整的行会被消除
  5. 游戏分数实时更新

扩展优化建议

你可以通过以下方式改进这个游戏:

  1. 界面优化

    • 添加开始菜单
    • 显示下一个方块预览
    • 添加分数显示界面
    • 添加游戏结束画面
  2. 功能增强

    • 添加音效
    • 实现方块阴影提示
    • 添加暂停功能
    • 实现存档功能
  3. 游戏性提升

    • 添加难度级别
    • 实现连击奖励机制
    • 添加特殊方块效果

注意事项

  1. 运行前确保已安装Python和Pygame库
  2. 可以通过pip安装Pygame:
    pip install pygame
    
  3. 游戏参数(如窗口大小、速度等)可以根据需要调整
  4. 建议在开发时多添加注释,便于后续维护

网站公告

今日签到

点亮在社区的每一天
去签到