login
欢迎访问QkqBeer博客园!

利用pygame实现简单的俄罗斯方块

__author__ = "那位先生Beer"

import pygame
from pygame.locals import QUIT, KEYUP, K_ESCAPE, KEYDOWN
import sys, time, random
SCREEN_WIDTH = 640
SCREEN_HEIGHT = 480
BOARD_WIDTH = 10
BLUE = (0, 0, 125)

S_SHAPE_TEMPLATE = [['.....',  #S形状的模板
                     '.....',
                     '..cc.',
                     '.cc..',
                     '.....'],
                    ['.....',  #S逆时针变化的形状
                     '..c..',
                     '..cc.',
                     '...c.',
                     '.....']]

Z_SHAPE_TEMPLATE = [['.....', #Z形模板
                     '.....',
                     '.cc..',
                     '..cc.',
                     '.....'],
                    ['.....',
                     '..c..',
                     '.cc..',
                     '.c...',
                     '.....']]

I_SHAPE_TEMPLATE = [['..c..', #I型模板
                     '..c..',
                     '..c..',
                     '..c..',
                     '.....'],
                    ['.....',
                     '.....',
                     'cccc.',
                     '.....',
                     '.....']]

O_SHAPE_TEMPLATE = [['.....', #O型模板
                     '.....',
                     '.cc..',
                     '.cc..',
                     '.....']]

J_SHAPE_TEMPLATE = [['.....', #J型模板
                     '.c...',
                     '.ccc.',
                     '.....',
                     '.....'],
                    ['.....',
                     '..cc.',
                     '..c..',
                     '..c..',
                     '.....'],
                    ['.....',
                     '.....',
                     '.ccc.',
                     '...c.',
                     '.....'],
                    ['.....',
                     '..c..',
                     '..c..',
                     '.cc..',
                     '.....']]

L_SHAPE_TEMPLATE = [['.....', #L型模板
                     '...c.',
                     '.ccc.',
                     '.....',
                     '.....'],
                    ['.....',
                     '..c..',
                     '..c..',
                     '..cc.',
                     '.....'],
                    ['.....',
                     '.....',
                     '.ccc.',
                     '.c...',
                     '.....'],
                    ['.....',
                     '.cc..',
                     '..c..',
                     '..c..',
                     '.....']]

T_SHAPE_TEMPLATE = [['.....', #T型模板
                     '..c..',
                     '.ccc.',
                     '.....',
                     '.....'],
                    ['.....',
                     '..c..',
                     '..cc.',
                     '..c..',
                     '.....'],
                    ['.....',
                     '.....',
                     '.ccc.',
                     '..c..',
                     '.....'],
                    ['.....',
                     '..c..',
                     '.cc..',
                     '..c..',
                     '.....']]

def available_tetris_pieces():
    PIECES = {'S': S_SHAPE_TEMPLATE, #PIECES是一个字典,它储存了所有不同的模板(列表)。每个模板都拥有一个形状所有可能的旋转(列表)。
              'Z': Z_SHAPE_TEMPLATE,
              'J': J_SHAPE_TEMPLATE,
              'L': L_SHAPE_TEMPLATE,
              'I': I_SHAPE_TEMPLATE,
              'O': O_SHAPE_TEMPLATE,
              'T': T_SHAPE_TEMPLATE}
    return PIECES

def run_tetris_game():
    score = 0
    pygame.init()
    windows_size = (SCREEN_WIDTH, SCREEN_HEIGHT)
    screen = pygame.display.set_mode(windows_size)
    pygame.display.set_caption("MyTetris")
    game_matrix = create_game_matrix()
    piece = create_piece()
    last_time_piece_move = time.time()
    while True:
        screen.fill((0, 0, 0))

        if (time.time() - last_time_piece_move > 0.3):
            piece['row'] += 1
            last_time_piece_move = time.time()
        draw_moving_piece( screen, piece )

        pygame.draw.rect(
            screen,
            BLUE,
            [100, 50, 10 * 20 + 10, 20 * 20 + 10], 5)
        draw_broard( screen, game_matrix )

        listen_to_user_input(game_matrix, piece)

        if(not isVaildPosition(game_matrix, piece, adjRow = 1)):
            game_matrix = update_game_matrix(game_matrix, piece)
            lines_removed = remove_completed_line(game_matrix)
            score += lines_removed
            piece = create_piece()
        draw_score(screen, score)
        pygame.display.update()
        for event in pygame.event.get(QUIT):
            pygame.quit()
            sys.exit()
def draw_broard(screen, matrix):
    game_matrix_columns = 10
    game_matrix_rows = 20
    for row in range(game_matrix_rows):
        for column in range(game_matrix_columns):
            if matrix[row][column] != '.':
                draw_single_tetris_box(screen, row, column, (255, 255, 255), (217, 222, 226))

def draw_single_tetris_box(screen, matrix_cell_row, matrix_cell_column, color, shadow_color):
    origin_x = 100 + 5 + (matrix_cell_column * 20 + 1)
    origin_y = 50 + 5 + (matrix_cell_row * 20 + 1)
    pygame.draw.rect(screen, shadow_color, [origin_x, origin_y, 20, 20])
    pygame.draw.rect(screen, color, [origin_x, origin_y, 18, 18])

def create_game_matrix():
    game_matrix_columns = 10
    game_matrix_rows = 20
    matrix = []
    for i in range(game_matrix_rows):
        new_row = []
        for j in range(game_matrix_columns):
            new_row.append('.')
        matrix.append(new_row)
    return matrix

def update_game_matrix(matrix, piece):
    for row in range(5):
        for column in range(5):
            if available_tetris_pieces()[piece["shape"]][piece["rotation"]][row][column] != '.':
                matrix[piece["row"] + row][piece["column"] + column] = 'c'
    return matrix

def create_piece():
    piece = {}
    random_shape = random.choice(list(available_tetris_pieces().keys()))
    piece["shape"] = random_shape
    piece["rotation"] = 0
    piece["column"] = 2
    piece["row"] = 0
    return piece

def draw_moving_piece(screen, piece):
    white_color = (255, 255, 255)
    gray_color = (217, 222, 226)
    shape_to_draw = available_tetris_pieces()[piece["shape"]][piece["rotation"]]
    for row in range(5):
        for column in range(5):
            if shape_to_draw[row][column] != '.':
                draw_single_tetris_box(screen, piece["row"] + row, piece["column"] + column, white_color, gray_color)


def listen_to_user_input(game_matrix, piece):
    for event in pygame.event.get():
        if event.type == KEYDOWN:
            if (event.key == pygame.K_LEFT) and isVaildPosition(game_matrix, piece, adjColumn = -1):
                piece['column'] -= 1
            if (event.key == pygame.K_RIGHT) and isVaildPosition(game_matrix, piece, adjColumn = 1):
                piece['column'] += 1
            if event.key == pygame.K_UP:
                piece['rotation'] = (piece['rotation'] + 1) % len(available_tetris_pieces()[piece['shape']])
                if not isVaildPosition(game_matrix, piece):
                    piece['rotation'] = (piece['rotation'] - 1) % len(available_tetris_pieces()[piece['shape']])
#检查是否为有效位置
def isVaildPosition(game_matrix, piece, adjColumn = 0, adjRow = 0):
    # if not (column >= 0 and column < 10 and row < 20 ):
    #     return False
    # #这里特别巧妙,使用not和返回False,仔细品味一下
    # if game_matrix[row][column] != '.':
    #     return False
    # return True
    piece_shape = available_tetris_pieces()[piece["shape"]][piece["rotation"]]
    for row in range(5):
            for column in range(5):
                if piece_shape[row][column] == ".":
                    continue
                if not isOnBoard(piece["row"] + row + adjRow, piece["column"] + column + adjColumn):
                    return False
                if game_matrix[piece["row"] + row + adjRow][piece["column"] + column + adjColumn] != '.':
                    return False
    return True
def isOnBoard(row, column):
    if column >= 0 and column < 10 and row < 20:
        return True
    return False

def is_line_complete(game_matrix, row):
    for column in range(10):
        if game_matrix[row][column] == '.':
            return False
    return True
def remove_completed_line(game_matrix):
    num_lines_remove = 0
    for row in range(20):
        if is_line_complete(game_matrix, row):
            for row_to_move_down in range(row, 0, -1):
                for column in range(10):
                    game_matrix[row_to_move_down ][column] = game_matrix[row_to_move_down - 1][column]
            for x in range(10):
                game_matrix[0][x] = '.'
            num_lines_remove += 1
    return num_lines_remove

def draw_score(screen, score):
    font = pygame.font.Font("freesansbold.ttf", 18)
    scoreSurf = font.render('Score : %s'%score, True, (255, 255, 255))
    screen.blit(scoreSurf, (640 - 150, 20))

run_tetris_game()

https://www.bilibili.com/video/av54227194?t=1858 大家可以去看看这个视频连接,一步一步去实现这些小功能。有利于新手可以从零开始,培养一种解决问题的思路。

posted @ 2020-03-20 13:55  BeerQkq  阅读(365)  评论(0)    收藏  举报