[超简单] 在Ubuntu上使用Python和Pygame开发俄罗斯方块游戏

一、环境准备

1. 安装Python 3

Ubuntu系统通常预装了Python。如果没有,可以通过以下命令安装:

sudo apt-get update sudo apt-get install python3 python3-pip

2. 安装Pygame库

Pygame是Python的一个跨平台的游戏开发库,适合用于开发2D游戏。

使用pip安装Pygame:

pip3 install pygame

验证安装是否成功:

python3 -c "import pygame; print(pygame.ver)"

如果没有报错,且打印出版本信息,说明Pygame安装成功。

二、创建项目

1. 创建项目目录

在主目录下创建一个名为tetris_game的项目文件夹:

mkdir ~/tetris_game cd ~/tetris_game

2. 创建Python脚本文件

创建主程序文件:

touch tetris.py

3. 打开Python脚本文件

gedit tetris.py

三、编写代码

tetris.py中,粘贴Python代码:

import pygame
import sys
import random

# 初始化Pygame
pygame.init()

# 设置窗口大小
screen_width = 400
screen_height = 500

# 创建游戏窗口
screen = pygame.display.set_mode((screen_width, screen_height))
pygame.display.set_caption('俄罗斯方块')

# 设置时钟
clock = pygame.time.Clock()

# 定义游戏网格大小
grid_width = 10
grid_height = 20
block_size = 20

# 定义颜色
colors = [
    (0, 0, 0),      # 黑色
    (255, 0, 0),    # 红色
    (0, 255, 0),    # 绿色
    (0, 0, 255),    # 蓝色
    (255, 255, 0),  # 黄色
    (255, 165, 0),  # 橙色
    (128, 0, 128),  # 紫色
    (0, 255, 255)   # 青色
]

# 创建游戏网格
grid = [[0 for x in range(grid_width)] for y in range(grid_height)]

# 形状定义
shapes = [
    [['.....',
      '.....',
      '..00.',
      '.00..',
      '.....'],
     ['.....',
      '..0..',
      '..00.',
      '...0.',
      '.....']],
    [['.....',
      '.....',
      '.00..',
      '..00.',
      '.....'],
     ['.....',
      '..0..',
      '.00..',
      '.0...',
      '.....']],
    [['..0..',
      '..0..',
      '..0..',
      '..0..',
      '.....'],
     ['.....',
      '0000.',
      '.....',
      '.....',
      '.....']],
    [['.....',
      '.....',
      '.00..',
      '.00..',
      '.....']],
    [['.....',
      '..0..',
      '.000.',
      '.....',
      '.....'],
     ['.....',
      '..0..',
      '..00.',
      '..0..',
      '.....'],
     ['.....',
      '.....',
      '.000.',
      '..0..',
      '.....'],
     ['.....',
      '..0..',
      '.00..',
      '..0..',
      '.....']],
    [['.....',
      '.0...',
      '.000.',
      '.....',
      '.....'],
     ['.....',
      '..00.',
      '..0..',
      '..0..',
      '.....'],
     ['.....',
      '.....',
      '.000.',
      '...0.',
      '.....'],
     ['.....',
      '..0..',
      '..0..',
      '.00..',
      '.....']],
    [['.....',
      '...0.',
      '.000.',
      '.....',
      '.....'],
     ['.....',
      '..0..',
      '..0..',
      '..00.',
      '.....'],
     ['.....',
      '.....',
      '.000.',
      '.0...',
      '.....'],
     ['.....',
      '.00..',
      '..0..',
      '..0..',
      '.....']]
]

# 形状对应的颜色(从1开始,0为黑色)
shape_colors = [1, 2, 3, 4, 5, 6, 7]

# 分数
score = 0

class Piece(object):
    def __init__(self, x, y, shape):
        self.x = x  # x位置(网格坐标)
        self.y = y  # y位置(网格坐标)
        self.shape = shape
        self.color = random.choice(shape_colors)
        self.rotation = 0  # 当前旋转状态

def create_grid(locked_positions={}):
    grid = [[0 for _ in range(grid_width)] for _ in range(grid_height)]
    for y in range(grid_height):
        for x in range(grid_width):
            if (x, y) in locked_positions:
                c = locked_positions[(x, y)]
                grid[y][x] = c
    return grid

def convert_shape_format(shape):
    positions = []
    format = shape.shape[shape.rotation % len(shape.shape)]

    for i, line in enumerate(format):
        row = list(line)
        for j, column in enumerate(row):
            if column == '0':
                positions.append((shape.x + j - 2, shape.y + i - 4))

    return positions

def valid_space(shape, grid):
    accepted_positions = [[(x, y) for x in range(grid_width) if grid[y][x] == 0] for y in range(grid_height)]
    accepted_positions = [x for sub in accepted_positions for x in sub]

    formatted = convert_shape_format(shape)

    for pos in formatted:
        if pos not in accepted_positions:
            if pos[1] > -1:
                return False
    return True

def check_lost(positions):
    for pos in positions:
        x, y = pos
        if y < 1:
            return True
    return False

def get_shape():
    return Piece(5, 0, random.choice(shapes))

def draw_text_middle(text, size, color, surface):
    font = pygame.font.SysFont('comicsans', size)
    label = font.render(text, 1, color)

    surface.blit(label, (screen_width / 2 - label.get_width() / 2, screen_height / 2 - label.get_height() / 2))

def draw_grid(surface):
    for y in range(grid_height):
        pygame.draw.line(surface, (128, 128, 128), (0, y*block_size), (grid_width*block_size, y*block_size))
    for x in range(grid_width):
        pygame.draw.line(surface, (128, 128, 128), (x*block_size, 0), (x*block_size, grid_height*block_size))

def clear_rows(grid, locked):
    global score
    inc = 0
    for i in range(len(grid)-1, -1, -1):
        row = grid[i]
        if 0 not in row:
            inc += 1
            ind = i
            for j in range(len(row)):
                try:
                    del locked[(j, i)]
                except:
                    continue
    if inc > 0:
        score += inc * 10  # 每消除一行加10分
        for key in sorted(list(locked), key=lambda x: x[1])[::-1]:
            x, y = key
            if y < ind:
                newKey = (x, y + inc)
                locked[newKey] = locked.pop(key)

def draw_next_shape(shape, surface):
    font = pygame.font.SysFont('comicsans', 30)
    label = font.render('下一个方块:', 1, (255, 255, 255))

    start_x = screen_width - 150
    start_y = 50

    format = shape.shape[shape.rotation % len(shape.shape)]

    for i, line in enumerate(format):
        row = list(line)
        for j, column in enumerate(row):
            if column == '0':
                pygame.draw.rect(surface, colors[shape.color], (start_x + j*block_size, start_y + i*block_size, block_size, block_size), 0)

    surface.blit(label, (start_x, start_y - 30))

def draw_window(surface, grid, score=0, next_piece=None):
    surface.fill((0, 0, 0))  # 清空屏幕

    # 绘制当前得分
    font = pygame.font.SysFont('comicsans', 30)
    label = font.render('得分: ' + str(score), 1, (255, 255, 255))
    surface.blit(label, (screen_width - label.get_width() - 10, 10))

    for y in range(grid_height):
        for x in range(grid_width):
            pygame.draw.rect(surface, colors[grid[y][x]], (x*block_size, y*block_size, block_size, block_size), 0)

    # 绘制网格线
    draw_grid(surface)

    # 绘制下一个方块
    if next_piece:
        draw_next_shape(next_piece, surface)

def main():
    global grid, score

    locked_positions = {}
    grid = create_grid(locked_positions)

    change_piece = False
    run = True
    current_piece = get_shape()
    next_piece = get_shape()
    fall_time = 0

    while run:
        fall_speed = 0.27

        grid = create_grid(locked_positions)
        fall_time += clock.get_rawtime()
        clock.tick()

        # 让方块下降
        if fall_time / 1000 > fall_speed:
            fall_time = 0
            current_piece.y += 1
            if not(valid_space(current_piece, grid)) and current_piece.y > 0:
                current_piece.y -= 1
                change_piece = True

        # 处理事件
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False
                pygame.display.quit()
                sys.exit()

            if event.type == pygame.KEYDOWN:
                if event.key == pygame.K_LEFT:
                    current_piece.x -= 1
                    if not valid_space(current_piece, grid):
                        current_piece.x += 1
                elif event.key == pygame.K_RIGHT:
                    current_piece.x += 1
                    if not valid_space(current_piece, grid):
                        current_piece.x -= 1
                elif event.key == pygame.K_DOWN:
                    current_piece.y += 1
                    if not valid_space(current_piece, grid):
                        current_piece.y -= 1
                elif event.key == pygame.K_UP:
                    current_piece.rotation = (current_piece.rotation + 1) % len(current_piece.shape)
                    if not valid_space(current_piece, grid):
                        current_piece.rotation = (current_piece.rotation - 1) % len(current_piece.shape)

        shape_pos = convert_shape_format(current_piece)

        # 将方块添加到网格
        for pos in shape_pos:
            x, y = pos
            if y > -1:
                grid[y][x] = current_piece.color

        # 如果方块落地,生成新方块
        if change_piece:
            for pos in shape_pos:
                locked_positions[(pos[0], pos[1])] = current_piece.color
            current_piece = next_piece
            next_piece = get_shape()
            change_piece = False

            clear_rows(grid, locked_positions)

            if check_lost(locked_positions):
                run = False

        draw_window(screen, grid, score, next_piece)
        pygame.display.update()

    # 游戏结束画面
    screen.fill((0, 0, 0))
    font = pygame.font.SysFont('comicsans', 60)
    label = font.render('游戏结束', 1, (255, 255, 255))
    score_label = font.render('得分: ' + str(score), 1, (255, 255, 255))
    screen.blit(label, (screen_width / 2 - label.get_width() / 2, screen_height / 2 - label.get_height()))
    screen.blit(score_label, (screen_width / 2 - score_label.get_width() / 2, screen_height / 2))
    pygame.display.update()
    pygame.time.delay(3000)
    pygame.quit()
    sys.exit()

if __name__ == '__main__':
    main()

四、运行游戏

保存tetris.py文件,然后在终端中运行:

python3 tetris.py

可以看到一个游戏窗口,方块会自动下落,您可以使用键盘方向键进行控制:

  • 左键:向左移动方块
  • 右键:向右移动方块
  • 下键:加速方块下落
  • 上键:旋转方块

当方块堆积到顶部时,游戏会结束,并显示最终得分。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值