如何用Python编写俄罗斯方块Tetris游戏?

news2024/11/19 4:44:10

在本文中,我们将用Python代码构建一个令人惊叹的项目:俄罗斯方块游戏。在这个项目中,我们将使用pygame库来构建游戏。要创建此项目,请确保您的系统中安装了最新版本的Python。让我们开始吧!

Pygame是一组跨平台的Python模块,用于创建视频游戏。它由设计用于Python编程语言的计算机图形和声音库组成。Pygame适合创建客户端应用程序,这些应用程序可能被封装在独立的可执行文件中。要学习pygame,需要具备Python的基本知识。

要安装pygame,请在终端中执行以下代码:

pip install pygame

我们已经完成了项目的先决条件。让我们来看看这个项目中的一些重要功能。

这种update_graphics方法用于设计游戏界面,并在游戏执行过程中进行必要的更新。该函数设置背景颜色和要显示的文本,并设置边框和宽度。它显示当前分数和时间。它绘制一个小屏幕来显示下一个块。为块设置瓷砖,每行20个瓷砖/平方,即19条水平线,每列10个瓷砖/广场,即9条垂直线。

draw_small_screen方法用于设计在游戏执行期间显示下一个块的相同屏幕界面。它设置背景、边框和文本,并显示下一个块。

manage_events函数用于在游戏执行期间处理块。

Python中俄罗斯方块游戏的完整代码:

我们可以在Pygame的帮助下用Python构建俄罗斯方块游戏,因为它有很多功能。现在,让我们从实现部分开始。在注释的帮助下,您可以逐行理解代码。

现在创建两个python文件,并将它们保存为util.py和tetris.py:

util.py文件:

#Import libraries
import pygame
import sys
import random
import time

# Define important global variables
pygame.init()
clock = pygame.time.Clock()

best_score = 0
longest_time = 0

width = 700
height = 750
DISPLAY_SCREEN = pygame.display.set_mode((width, height))
pygame.display.set_caption(" Tetris")

off_set_x = 10
off_set_y = 80
playing_field_width = 330  #330 / 10 = 33 width per tile
playing_field_height = 660  #600 / 20 = 33 height per tile
tile_length = 33 # tile is a square

#colors
blue = (0, 0, 255)
white = (255, 255, 255) 
black = (0, 0, 0)
gray = (95, 95, 96) 
orange  = (249, 87, 0)  
cobalt_blue = (3, 65, 174)
green_apple  = (114, 203, 59)
cyber_yellow= (255, 213, 0)
beer = (255, 151, 28)
ryb_red = (255, 50, 19)
purple = (128, 0, 128)

# colors of Tetris blocks
block_colors = (cobalt_blue, blue, green_apple, purple, cyber_yellow, beer, ryb_red)
# shapes of Tetris blocks
shapes = ("i_block", "l_block", "j_block", "o_block", "s_block", "t_block", "z_block")
directions = ("vertical_1", "vertical_2", "horizontal_1", "horizontal_2")

background_img = pygame.image.load("resources/images/background_img.jpg")      
instructions_img = pygame.image.load("resources/images/instructions_img.jpg")  
icon_img = pygame.image.load("resources/images/icon.png")
pygame.display.set_icon(icon_img)

class Button:
    def __init__(self, button_color, button_hover_over_color, x, y, width, height, text_size,  text_color, text_hover_over_color = None, text_str=""):
        self.button_color = button_color
        self.button_hover_over_color = button_hover_over_color
        self.x = x
        self.y = y
        self.width = width
        self.height = height
        self.text_size = text_size
        self.text_color = text_color

        if text_hover_over_color:
            self.text_hover_over_color = text_hover_over_color
        else:
            self.text_hover_over_color =  text_color
 
        self.text_str = text_str


    def blit(self, display_screen, outline_color=None):
        if outline_color: 
            pygame.draw.rect(display_screen, outline_color, (self.x-3, self.y-3, self.width+6, self.height+6))
        
        pygame.draw.rect(display_screen, self.button_color, (self.x, self.y, self.width, self.height))

        if self.text_str != "": 
            font = pygame.font.Font("freesansbold.ttf", self.text_size)
            text = font.render(self.text_str, True, self.text_color)
            # to center the text in the middle of the button based on the size of the button
            text_position = (self.x + (self.width/2 - text.get_width()/2), self.y + (self.height/2 - text.get_height()/2))
            display_screen.blit(text, text_position)


    def is_hovered_over(self, mouse_position):
        if self.x < mouse_position[0] < self.x+self.width and self.y < mouse_position[1] < self.y+self.height:
            return True
        return False


    def blit_hovered_over(self, display_screen):
        pygame.draw.rect(display_screen, self.button_hover_over_color, (self.x, self.y, self.width, self.height))

        if self.text_str != "":
            font = pygame.font.Font("freesansbold.ttf", self.text_size)
            text = font.render(self.text_str, True, self.text_hover_over_color)
            # to center the text in the middle of the button based on the size of the button
            text_position = (self.x + (self.width/2 - text.get_width()/2), self.y + (self.height/2 - text.get_height()/2))
            display_screen.blit(text, text_position)


    def is_clicked(self, mouse_position, event):
        if self.is_hovered_over(mouse_position):
            if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                return True
        return False

class Tile:
    def __init__(self, x, y, color = black):
        self.x = x
        self.y = y
        self.color = color
        self.empty = True


    def draw_tile(self):
        pygame.draw.rect(DISPLAY_SCREEN , self.color, (self.x, self.y, tile_length, tile_length) )


class PlayingField():
    def __init__(self):
        #y coordinate of first row = (80) off_set_y 
        self.tiles = {
            "row1":  {80:  []},
            "row2":  {113: []},
            "row3":  {146: []},
            "row4":  {179: []},
            "row5":  {212: []},
            "row6":  {245: []},
            "row7":  {278: []},
            "row8":  {311: []},
            "row9":  {344: []},
            "row10": {377: []},
            "row11": {410: []},
            "row12": {443: []},
            "row13": {476: []},
            "row14": {509: []},
            "row15": {542: []},
            "row16": {575: []},
            "row17": {608: []},
            "row18": {641: []},
            "row19": {674: []},
            "row20": {707: []},
        }
        self.__init_field()


    def __init_field(self):    
        y = off_set_y
        for i in range(20): #rows
            x = off_set_x
            for j in range(10): #cols
                tile_to_add = Tile(x, y) 
                self.tiles["row"+str(i+1)][y].append(tile_to_add)
                x += tile_length
            y += tile_length
    

    def destory_full_row(self, player):
        times = 0
        y = off_set_y        
        for i in range(20):
            for tile in self.tiles["row"+str(i+1)][y]:
                if tile.empty: break

                elif tile.x == off_set_x+playing_field_width-tile_length:
                    times += 1
                    for j in range(800): #just for flashing the row
                        if j%2 == 0:
                            pygame.draw.rect(DISPLAY_SCREEN , black, (self.tiles["row"+str(i+1)][y][0].x+1, self.tiles["row"+str(i+1)][y][0].y+1, playing_field_width-2, tile_length-2) )
                        else:
                            for tile in self.tiles["row"+str(i+1)][y]:
                                pygame.draw.rect(DISPLAY_SCREEN , tile.color, (tile.x, tile.y, tile_length, tile_length) )
                        pygame.draw.line(DISPLAY_SCREEN , white, (off_set_x, y), (playing_field_width+off_set_x-1, y)) # horizontal line
                        pygame.display.update()

                    # let's destory this full row
                    self.destroy_and_replace(i+1, y)
                    player.score += 10*times

            y += tile_length 


    def destroy_and_replace(self, row_number, row_y):
        for i in range (row_number, 1, -1):
            prev_row_number = i-1
            prev_y = row_y-tile_length
            
            self.tiles["row"+str(i)][row_y].clear() #current_row.clear()
            temp_x = off_set_x
            for j in range(10):
                empty_tile = Tile(temp_x, row_y)
                temp_x += tile_length
                self.tiles["row"+str(i)][row_y].append(empty_tile)
            if prev_y < 80: 
                break

            
            for j in range(10):
                old_tile = self.tiles["row"+str(i)][row_y][j]
                new_tile = self.tiles["row"+str(prev_row_number)][prev_y][j] 
                old_tile.x = new_tile.x
                old_tile.color = new_tile.color 
                old_tile.empty = new_tile.empty

            row_y -= tile_length


class Block:
    def __init__(self, shape:str, color = black):
        self.shape = shape
        self.color = color

        self.direction = directions[0] #vertical_1

        #                         tile1                                                        , tile2            , tile3            , tile4
        self.tiles = [ Tile(off_set_x+playing_field_width/2-tile_length, off_set_y, self.color), Tile(0, 0, color), Tile(0, 0, color), Tile(0, 0, color)]
        
        self.__init_shape() 
        for tile in self.tiles:
            tile.empty = False


    def __init_shape(self):
        if self.shape == "i_block":
            self.tiles[1] = Tile(self.tiles[0].x, self.tiles[0].y-tile_length, self.color)
            self.tiles[2] = Tile(self.tiles[0].x, self.tiles[1].y-tile_length, self.color)
            self.tiles[3] = Tile(self.tiles[0].x, self.tiles[2].y-tile_length, self.color)
        elif self.shape == "l_block":
            self.tiles[1] = Tile(self.tiles[0].x+tile_length, self.tiles[0].y, self.color)
            self.tiles[2] = Tile(self.tiles[0].x-tile_length, self.tiles[0].y, self.color)
            self.tiles[3] = Tile(self.tiles[2].x, self.tiles[2].y-tile_length, self.color)
        elif self.shape == "j_block":
            self.tiles[1] = Tile(self.tiles[0].x+tile_length, self.tiles[0].y, self.color)
            self.tiles[2] = Tile(self.tiles[0].x-tile_length, self.tiles[0].y, self.color)
            self.tiles[3] = Tile(self.tiles[1].x, self.tiles[1].y-tile_length, self.color)
        elif self.shape == "o_block":
            self.tiles[1] = Tile(self.tiles[0].x+tile_length,  self.tiles[0].y, self.color)
            self.tiles[2] = Tile(self.tiles[0].x, self.tiles[0].y-tile_length, self.color)
            self.tiles[3] = Tile(self.tiles[1].x, self.tiles[1].y-tile_length, self.color)
        elif self.shape == "s_block":
            self.tiles[1] = Tile(self.tiles[0].x-tile_length, self.tiles[0].y, self.color)
            self.tiles[2] = Tile(self.tiles[0].x, self.tiles[0].y-tile_length, self.color)
            self.tiles[3] = Tile(self.tiles[2].x+tile_length, self.tiles[2].y, self.color)
        elif self.shape == "t_block":
            self.tiles[1] = Tile(self.tiles[0].x+tile_length,  self.tiles[0].y, self.color)
            self.tiles[2] = Tile(self.tiles[0].x-tile_length, self.tiles[0].y, self.color)
            self.tiles[3] = Tile(self.tiles[0].x, self.tiles[0].y-tile_length, self.color)
        elif self.shape == "z_block":
            self.tiles[1] = Tile(self.tiles[0].x+tile_length,  self.tiles[0].y, self.color)
            self.tiles[2] = Tile(self.tiles[0].x, self.tiles[0].y-tile_length, self.color)
            self.tiles[3] = Tile(self.tiles[2].x-tile_length, self.tiles[2].y, self.color)
        else:
            print("Error: wrong block name.")
            pygame.quit()
            sys.exit()

    
    def complete_block(self):
        self.__init_shape()


    def can_fall(self, next_block, playing_field, player):
        from tetris import manage_events, update_graphics
        manage_events(self, next_block, playing_field, player)
        #check borders
        for block_tile in self.tiles:
            if block_tile.y >= playing_field_height+off_set_y-tile_length:
                return False  

        #check already existed tiles
        for block_tile in self.tiles:
            y = off_set_y
            for i in range(20):
                for tile in playing_field.tiles["row"+str(i+1)][y]:
                    if not tile.empty and block_tile.y+tile_length == tile.y and block_tile.x == tile.x: 
                        return False  
                y += tile_length
    
        return True


    def block_is_falling(self, next_block, playing_field, player, faster=None):
        from tetris import manage_events, update_graphics
        manage_events(self,next_block, playing_field, player)

        if self.can_fall(next_block, playing_field, player):
            for tile in self.tiles:
                tile.y += tile_length

            manage_events(self, next_block, playing_field, player)             
            update_graphics(self, next_block, playing_field, player)
            if faster:                
                clock.tick(40)
                self.block_is_falling( next_block, playing_field, player)
            else:                
                clock.tick(5)
            manage_events(self, next_block, playing_field, player)             
            update_graphics(self, next_block, playing_field, player)


    def get_new_block(self, next_block, playing_field, player):
        if self.can_fall(next_block, playing_field, player): return (self, next_block, False)
        
        #if the block has falled completely
        for block_tile in self.tiles: 
            found = False 
            y = off_set_y
            for i in range(20):
                if not found:
                    for j in range(10):
                        if block_tile.x == playing_field.tiles["row"+str(i+1)][y][j].x and block_tile.y == playing_field.tiles["row"+str(i+1)][y][j].y:
                            playing_field.tiles["row"+str(i+1)][y][j].color = block_tile.color
                            playing_field.tiles["row"+str(i+1)][y][j].empty = False
                            found = True
                            break
                    y += tile_length
                else:
                    break
        
        new_block = next_block

        next_rand_index1 = random.randint(0, 6)
        next_rand_index2 = random.randint(0, 6)
        new_next_block = Block(shapes[next_rand_index1], block_colors[next_rand_index2])

        clock.tick(2)
        return (new_block, new_next_block, True)


    def move_left(self, playing_field):
        if self.can_move_left(playing_field):
            for tile in self.tiles:
                tile.x -= tile_length


    def move_right(self, playing_field):
        if self.can_move_right(playing_field):
            for tile in self.tiles:
                tile.x += tile_length


    def can_move_left(self, playing_field):
        # whether inside the playing field or not
        for tile in self.tiles:
            if tile.x <= off_set_x:
                return False
        # whether adjacent field_tiles are occupied or not
        for block_tile in self.tiles:
            y = off_set_y
            for i in range(20):
                for tile in playing_field.tiles["row"+str(i+1)][y]:
                    if not tile.empty and block_tile.x-tile_length == tile.x and block_tile.y  == tile.y:
                        return False  
                y += tile_length
        return True
        

    def can_move_right(self, playing_field):
        # whether inside the playing field or not
        for tile in self.tiles:
            if tile.x + tile_length >= off_set_x+playing_field_width:
                return False
        # whether adjacent field_tiles are occupied or not
        for block_tile in self.tiles:
            y = off_set_y
            for i in range(20):
                for tile in playing_field.tiles["row"+str(i+1)][y]:
                    if not tile.empty and block_tile.x+tile_length == tile.x and block_tile.y  == tile.y:
                        return False  
                y += tile_length
        return True


    def rotate(self, next_block, playing_field, player):
        from tetris import manage_events, update_graphics
        manage_events(self, next_block, playing_field, player)

        if self.shape == "i_block":
            self.rotate_i_block(playing_field)
        elif self.shape == "l_block":
            self.rotate_l_block(playing_field)
        elif self.shape == "j_block":
            self.rotate_j_block(playing_field)
        elif self.shape == "o_block":
            return
            #no rotation for o_block.
        elif self.shape == "s_block":
            self.rotate_s_block(playing_field)
        elif self.shape == "t_block":
            self.rotate_t_block(playing_field)
        elif self.shape == "z_block":
            self.rotate_z_block(playing_field)
        else:
            print("Error: wrong block name.")
            pygame.quit()
            sys.exit()
        manage_events(self, next_block, playing_field, player)
        update_graphics(self, next_block, playing_field, player)


    def rotate_i_block(self, playing_field): #done
        temp_rotated_i = Block("i_block", self.color)
        temp_rotated_i.tiles = self.tiles.copy()
        
        if self.direction == directions[0] or self.direction == directions[1]:
            # ----
            temp_rotated_i.tiles[0] = Tile(temp_rotated_i.tiles[1].x, temp_rotated_i.tiles[0].y, temp_rotated_i.color) 
            temp_rotated_i.tiles[1] = Tile(temp_rotated_i.tiles[0].x-tile_length, temp_rotated_i.tiles[0].y, temp_rotated_i.color)
            temp_rotated_i.tiles[2] = Tile(temp_rotated_i.tiles[0].x+tile_length, temp_rotated_i.tiles[0].y, temp_rotated_i.color)
            temp_rotated_i.tiles[3] = Tile(temp_rotated_i.tiles[2].x+tile_length, temp_rotated_i.tiles[0].y, temp_rotated_i.color)
            temp_rotated_i.direction = directions[2] # "horizontal_1"
        elif self.direction == directions[2] or self.direction == directions[3]:
            # |
            # |
            # |
            # |
            temp_rotated_i.tiles[1] = Tile(temp_rotated_i.tiles[0].x, temp_rotated_i.tiles[0].y-tile_length, temp_rotated_i.color)
            temp_rotated_i.tiles[2] = Tile(temp_rotated_i.tiles[1].x, temp_rotated_i.tiles[1].y-tile_length, temp_rotated_i.color)
            temp_rotated_i.tiles[3] = Tile(temp_rotated_i.tiles[2].x, temp_rotated_i.tiles[2].y-tile_length, temp_rotated_i.color)
            temp_rotated_i.direction = directions[0] #"vertical_1"

        for block_tile in temp_rotated_i.tiles:
            if block_tile.x <= off_set_x or block_tile.x >= playing_field_width:
                return 
            y = off_set_y
            for i in range(20):
                for tile in playing_field.tiles["row"+str(i+1)][y]:
                    if not tile.empty and block_tile.x == tile.x and block_tile.y  == tile.y:
                        return
                y += tile_length

        self.direction = temp_rotated_i.direction
        self.tiles = temp_rotated_i.tiles


    def rotate_l_block(self, playing_field): #done
        temp_rotated_l = Block("l_block", self.color)
        temp_rotated_l.tiles = self.tiles.copy()
        
        if self.direction == directions[0]:
            # after rotating, the block should look like this ↓
            #  _
            # |
            # |
            # |
            temp_rotated_l.tiles[0] = Tile(temp_rotated_l.tiles[0].x, temp_rotated_l.tiles[0].y, temp_rotated_l.color)
            temp_rotated_l.tiles[1] = Tile(temp_rotated_l.tiles[0].x, temp_rotated_l.tiles[0].y-tile_length, temp_rotated_l.color)
            temp_rotated_l.tiles[2] = Tile(temp_rotated_l.tiles[1].x, temp_rotated_l.tiles[1].y-tile_length, temp_rotated_l.color)
            temp_rotated_l.tiles[3] = Tile(temp_rotated_l.tiles[2].x+tile_length, temp_rotated_l.tiles[2].y, temp_rotated_l.color)
            temp_rotated_l.direction = directions[2] # "horizontal_1"
        elif self.direction == directions[2]:
            # after rotating, the block should look like this ↓
            # ---
            #   |
            temp_rotated_l.tiles[0] = Tile(temp_rotated_l.tiles[3].x, temp_rotated_l.tiles[0].y, temp_rotated_l.color)
            temp_rotated_l.tiles[1] = Tile(temp_rotated_l.tiles[0].x, temp_rotated_l.tiles[0].y-tile_length, temp_rotated_l.color)
            temp_rotated_l.tiles[2] = Tile(temp_rotated_l.tiles[1].x-tile_length, temp_rotated_l.tiles[1].y, temp_rotated_l.color)
            temp_rotated_l.tiles[3] = Tile(temp_rotated_l.tiles[2].x-tile_length, temp_rotated_l.tiles[2].y, temp_rotated_l.color)
            temp_rotated_l.direction = directions[1] #"vertical_2"
        elif self.direction == directions[1]: 
            # after rotating, the block should look like this ↓
            #  |
            #  |
            # _|
            temp_rotated_l.tiles[0] = Tile(temp_rotated_l.tiles[3].x, temp_rotated_l.tiles[0].y, temp_rotated_l.color)
            temp_rotated_l.tiles[1] = Tile(temp_rotated_l.tiles[0].x+tile_length, temp_rotated_l.tiles[0].y, temp_rotated_l.color)
            temp_rotated_l.tiles[2] = Tile(temp_rotated_l.tiles[1].x, temp_rotated_l.tiles[1].y-tile_length, temp_rotated_l.color)
            temp_rotated_l.tiles[3] = Tile(temp_rotated_l.tiles[2].x, temp_rotated_l.tiles[2].y-tile_length, temp_rotated_l.color)
            temp_rotated_l.direction = directions[3] #"horizontal_2"
        elif self.direction == directions[3]: 
            # after rotating, the block should look like this ↓
            # |
            # ---
            temp_rotated_l.tiles[0] = Tile(temp_rotated_l.tiles[1].x, temp_rotated_l.tiles[0].y, temp_rotated_l.color)
            temp_rotated_l.tiles[1] = Tile(temp_rotated_l.tiles[0].x+tile_length, temp_rotated_l.tiles[0].y, temp_rotated_l.color)
            temp_rotated_l.tiles[2] = Tile(temp_rotated_l.tiles[0].x-tile_length, temp_rotated_l.tiles[1].y, temp_rotated_l.color)
            temp_rotated_l.tiles[3] = Tile(temp_rotated_l.tiles[2].x, temp_rotated_l.tiles[2].y-tile_length, temp_rotated_l.color) 
            temp_rotated_l.direction = directions[0] #"vertical_1"

        for block_tile in temp_rotated_l.tiles:
            if block_tile.x <= off_set_x or block_tile.x >= playing_field_width:
                return 
            y = off_set_y
            for i in range(20):
                for tile in playing_field.tiles["row"+str(i+1)][y]:
                    if not tile.empty and block_tile.x == tile.x and block_tile.y  == tile.y:
                        return
                y += tile_length

        self.direction = temp_rotated_l.direction
        self.tiles = temp_rotated_l.tiles
        

    def rotate_j_block(self, playing_field): #done
        temp_rotated_j = Block("j_block", self.color)
        temp_rotated_j.tiles = self.tiles.copy()
        
        if self.direction == directions[0]: 
            temp_rotated_j.tiles[0] = Tile(temp_rotated_j.tiles[1].x, temp_rotated_j.tiles[0].y, temp_rotated_j.color)
            temp_rotated_j.tiles[1] = Tile(temp_rotated_j.tiles[0].x-tile_length, temp_rotated_j.tiles[0].y, temp_rotated_j.color)
            temp_rotated_j.tiles[2] = Tile(temp_rotated_j.tiles[1].x, temp_rotated_j.tiles[1].y-tile_length, temp_rotated_j.color)
            temp_rotated_j.tiles[3] = Tile(temp_rotated_j.tiles[2].x, temp_rotated_j.tiles[2].y-tile_length, temp_rotated_j.color)
            temp_rotated_j.direction = directions[2] # "horizontal_1"
        elif self.direction == directions[2]:
            temp_rotated_j.tiles[0] = Tile(temp_rotated_j.tiles[1].x-tile_length, temp_rotated_j.tiles[0].y, temp_rotated_j.color)
            temp_rotated_j.tiles[1] = Tile(temp_rotated_j.tiles[0].x, temp_rotated_j.tiles[0].y-tile_length, temp_rotated_j.color)
            temp_rotated_j.tiles[2] = Tile(temp_rotated_j.tiles[1].x+tile_length, temp_rotated_j.tiles[1].y, temp_rotated_j.color)
            temp_rotated_j.tiles[3] = Tile(temp_rotated_j.tiles[2].x+tile_length, temp_rotated_j.tiles[2].y, temp_rotated_j.color)
            temp_rotated_j.direction = directions[1] #"vertical_2"
        elif self.direction == directions[1]: 
            temp_rotated_j.tiles[0] = Tile(temp_rotated_j.tiles[2].x, temp_rotated_j.tiles[0].y, temp_rotated_j.color)
            temp_rotated_j.tiles[1] = Tile(temp_rotated_j.tiles[0].x, temp_rotated_j.tiles[0].y-tile_length, temp_rotated_j.color)
            temp_rotated_j.tiles[2] = Tile(temp_rotated_j.tiles[1].x, temp_rotated_j.tiles[1].y-tile_length, temp_rotated_j.color)
            temp_rotated_j.tiles[3] = Tile(temp_rotated_j.tiles[2].x-tile_length, temp_rotated_j.tiles[2].y, temp_rotated_j.color)
            temp_rotated_j.direction = directions[3] #"horizontal_2"
        elif self.direction == directions[3]: #back to normal:
            temp_rotated_j.tiles[0] = Tile(temp_rotated_j.tiles[0].x, temp_rotated_j.tiles[0].y, temp_rotated_j.color)
            temp_rotated_j.tiles[1] = Tile(temp_rotated_j.tiles[0].x+tile_length, temp_rotated_j.tiles[0].y, temp_rotated_j.color)
            temp_rotated_j.tiles[2] = Tile(temp_rotated_j.tiles[0].x-tile_length, temp_rotated_j.tiles[0].y, temp_rotated_j.color)
            temp_rotated_j.tiles[3] = Tile(temp_rotated_j.tiles[1].x, temp_rotated_j.tiles[1].y-tile_length, temp_rotated_j.color) 
            temp_rotated_j.direction = directions[0] #"vertical_1"

        for block_tile in temp_rotated_j.tiles:
            if block_tile.x <= off_set_x or block_tile.x >= playing_field_width:
                return 
            y = off_set_y
            for i in range(20):
                for tile in playing_field.tiles["row"+str(i+1)][y]:
                    if not tile.empty and block_tile.x == tile.x and block_tile.y  == tile.y:
                        return 
                y += tile_length

        self.direction = temp_rotated_j.direction
        self.tiles = temp_rotated_j.tiles


    def rotate_s_block(self, playing_field): #done
        temp_rotated_s = Block("s_block", self.color)
        temp_rotated_s.tiles = self.tiles.copy()
        
        if self.direction == directions[0] or self.direction == directions[1]:
            temp_rotated_s.tiles[0] = Tile(temp_rotated_s.tiles[3].x, temp_rotated_s.tiles[0].y, temp_rotated_s.color)
            temp_rotated_s.tiles[1] = Tile(temp_rotated_s.tiles[0].x, temp_rotated_s.tiles[0].y-tile_length, temp_rotated_s.color)
            temp_rotated_s.tiles[2] = Tile(temp_rotated_s.tiles[1].x-tile_length, temp_rotated_s.tiles[1].y, temp_rotated_s.color)
            temp_rotated_s.tiles[3] = Tile(temp_rotated_s.tiles[2].x, temp_rotated_s.tiles[2].y-tile_length, temp_rotated_s.color)
            temp_rotated_s.direction = directions[2] # "horizontal_1"
        elif self.direction == directions[2] or self.direction == directions[3]
            temp_rotated_s.tiles[0] = Tile(temp_rotated_s.tiles[2].x, temp_rotated_s.tiles[0].y, temp_rotated_s.color)
            temp_rotated_s.tiles[1] = Tile(temp_rotated_s.tiles[0].x-tile_length, temp_rotated_s.tiles[0].y, temp_rotated_s.color)
            temp_rotated_s.tiles[2] = Tile(temp_rotated_s.tiles[0].x, temp_rotated_s.tiles[0].y-tile_length, temp_rotated_s.color)
            temp_rotated_s.tiles[3] = Tile(temp_rotated_s.tiles[2].x+tile_length, temp_rotated_s.tiles[2].y, temp_rotated_s.color)
            temp_rotated_s.direction = directions[0] #"vertical_1"

        for block_tile in temp_rotated_s.tiles:
            if block_tile.x <= off_set_x or block_tile.x >= playing_field_width:
                return 
            y = off_set_y
            for i in range(20):
                for tile in playing_field.tiles["row"+str(i+1)][y]:
                    if not tile.empty and block_tile.x == tile.x and block_tile.y  == tile.y:
                        return
                y += tile_length

        self.direction = temp_rotated_s.direction
        self.tiles = temp_rotated_s.tiles   


    def rotate_t_block(self, playing_field): #done
        temp_rotated_t = Block("j_block", self.color)
        temp_rotated_t.tiles = self.tiles.copy()
        
        if self.direction == directions[0]: 
            temp_rotated_t.tiles[0] = Tile(temp_rotated_t.tiles[0].x, temp_rotated_t.tiles[0].y, temp_rotated_t.color)
            temp_rotated_t.tiles[1] = Tile(temp_rotated_t.tiles[0].x, temp_rotated_t.tiles[0].y-tile_length, temp_rotated_t.color)
            temp_rotated_t.tiles[2] = Tile(temp_rotated_t.tiles[1].x, temp_rotated_t.tiles[1].y-tile_length, temp_rotated_t.color)
            temp_rotated_t.tiles[3] = Tile(temp_rotated_t.tiles[1].x+tile_length, temp_rotated_t.tiles[1].y, temp_rotated_t.color)
            temp_rotated_t.direction = directions[2] # "horizontal_1"
        elif self.direction == directions[2]:
            temp_rotated_t.tiles[0] = Tile(temp_rotated_t.tiles[0].x, temp_rotated_t.tiles[0].y, temp_rotated_t.color)
            temp_rotated_t.tiles[1] = Tile(temp_rotated_t.tiles[0].x, temp_rotated_t.tiles[0].y-tile_length, temp_rotated_t.color)
            temp_rotated_t.tiles[2] = Tile(temp_rotated_t.tiles[1].x-tile_length, temp_rotated_t.tiles[1].y, temp_rotated_t.color)
            temp_rotated_t.tiles[3] = Tile(temp_rotated_t.tiles[1].x+tile_length, temp_rotated_t.tiles[2].y, temp_rotated_t.color)
            temp_rotated_t.direction = directions[1] #"vertical_2"
        elif self.direction == directions[1]:
            temp_rotated_t.tiles[0] = Tile(temp_rotated_t.tiles[0].x, temp_rotated_t.tiles[0].y, temp_rotated_t.color)
            temp_rotated_t.tiles[1] = Tile(temp_rotated_t.tiles[0].x, temp_rotated_t.tiles[0].y-tile_length, temp_rotated_t.color)
            temp_rotated_t.tiles[2] = Tile(temp_rotated_t.tiles[1].x, temp_rotated_t.tiles[1].y-tile_length, temp_rotated_t.color)
            temp_rotated_t.tiles[3] = Tile(temp_rotated_t.tiles[1].x-tile_length, temp_rotated_t.tiles[1].y, temp_rotated_t.color)
            temp_rotated_t.direction = directions[3] #"horizontal_2"
        elif self.direction == directions[3]: #back to normal:
            temp_rotated_t.tiles[0] = Tile(temp_rotated_t.tiles[0].x, temp_rotated_t.tiles[0].y, temp_rotated_t.color)
            temp_rotated_t.tiles[1] = Tile(temp_rotated_t.tiles[0].x+tile_length, temp_rotated_t.tiles[0].y, temp_rotated_t.color)
            temp_rotated_t.tiles[2] = Tile(temp_rotated_t.tiles[0].x-tile_length, temp_rotated_t.tiles[0].y, temp_rotated_t.color)
            temp_rotated_t.tiles[3] = Tile(temp_rotated_t.tiles[0].x, temp_rotated_t.tiles[0].y-tile_length, temp_rotated_t.color) 
            temp_rotated_t.direction = directions[0] #"vertical_1"

        for block_tile in temp_rotated_t.tiles:
            if block_tile.x <= off_set_x or block_tile.x >= playing_field_width:
                return 
            y = off_set_y
            for i in range(20):
                for tile in playing_field.tiles["row"+str(i+1)][y]:
                    if not tile.empty and block_tile.x == tile.x and block_tile.y  == tile.y:
                        return
                y += tile_length

        self.direction = temp_rotated_t.direction
        self.tiles = temp_rotated_t.tiles


    def rotate_z_block(self, playing_field): #done
        temp_rotated_z = Block("z_block", self.color)
        temp_rotated_z.tiles = self.tiles.copy()
        
        if self.direction == directions[0] or self.direction == directions[1]:

            temp_rotated_z.tiles[0] = Tile(temp_rotated_z.tiles[3].x, temp_rotated_z.tiles[0].y, temp_rotated_z.color)
            temp_rotated_z.tiles[1] = Tile(temp_rotated_z.tiles[0].x, temp_rotated_z.tiles[0].y-tile_length, temp_rotated_z.color)
            temp_rotated_z.tiles[2] = Tile(temp_rotated_z.tiles[1].x+tile_length, temp_rotated_z.tiles[1].y, temp_rotated_z.color)
            temp_rotated_z.tiles[3] = Tile(temp_rotated_z.tiles[2].x, temp_rotated_z.tiles[2].y-tile_length, temp_rotated_z.color)
            temp_rotated_z.direction = directions[2] # "horizontal_1"
        elif self.direction == directions[2] or self.direction == directions[3]:
            temp_rotated_z.tiles[0] = Tile(temp_rotated_z.tiles[3].x, temp_rotated_z.tiles[0].y, temp_rotated_z.color)
            temp_rotated_z.tiles[1] = Tile(temp_rotated_z.tiles[0].x+tile_length, temp_rotated_z.tiles[0].y, temp_rotated_z.color)
            temp_rotated_z.tiles[2] = Tile(temp_rotated_z.tiles[0].x, temp_rotated_z.tiles[0].y-tile_length, temp_rotated_z.color)
            temp_rotated_z.tiles[3] = Tile(temp_rotated_z.tiles[2].x-tile_length, temp_rotated_z.tiles[2].y, temp_rotated_z.color)
            temp_rotated_z.direction = directions[0] #"vertical_1"

        for block_tile in temp_rotated_z.tiles:
            if block_tile.x <= off_set_x or block_tile.x >= playing_field_width:
                return 
            y = off_set_y
            for i in range(20):
                for tile in playing_field.tiles["row"+str(i+1)][y]:
                    if not tile.empty and block_tile.x == tile.x and block_tile.y  == tile.y:
                        return
                y += tile_length

        self.direction = temp_rotated_z.direction
        self.tiles = temp_rotated_z.tiles      

    def fall_completely(self, next_block, playing_field, player):
        from tetris import update_graphics

        fall= True
        while fall:
            for block_tile in self.tiles:
                if block_tile.y >= playing_field_height+off_set_y-tile_length:
                    fall = False  
                    break 

            #check already existed tiles
            for block_tile in self.tiles:
                y = off_set_y
                for i in range(20):
                    for tile in playing_field.tiles["row"+str(i+1)][y]:
                        if not tile.empty and block_tile.y+tile_length == tile.y and block_tile.x == tile.x: 
                            fall = False   
                            break
                    y += tile_length
            
            if not fall:
                break
            
            for tile in self.tiles:
                tile.y += tile_length
            
            update_graphics(self, next_block, playing_field, player)
            clock.get_rawtime()
            clock.tick(50)
            

class Player:
    def __init__(self, start_time):
        self.start_time = start_time

        self.time_since_start = 0
        self.score = 0 

tetris.py文件:

#import libraries
import pygame
from util import *

def update_graphics(block, next_block, playing_field, player):
    
    #Sets black background and text
    DISPLAY_SCREEN.blit(background_img, (0, 0))
    pygame.draw.rect(DISPLAY_SCREEN , black, (off_set_x, off_set_y, playing_field_width, playing_field_height) )
    font = pygame.font.SysFont("comicsansms", 48)
    rendered_text = font.render("Tetris", 1, orange)
    DISPLAY_SCREEN.blit(rendered_text, (width/2-80, 10))

    #Displays Current score and time
    player.time_since_start = pygame.time.get_ticks() - player.start_time
    font = pygame.font.SysFont("comicsansms", 20)
    rendered_text_time =  font.render("Time: " + str(player.time_since_start), 1, orange)
    DISPLAY_SCREEN.blit(rendered_text_time, (playing_field_width+tile_length*2, playing_field_height-80))  
    rendered_text_score = font.render("Score: " + str(player.score), 1, orange)
    DISPLAY_SCREEN.blit(rendered_text_score, (playing_field_width+tile_length*2, playing_field_height-50))
    
    #Draw the small screen for the next block
    draw_small_screen(next_block)

    #Set tiles
    y = off_set_y
    for i in range(20):
        for tile in playing_field.tiles["row"+str(i+1)][y]:
            tile.draw_tile()
        y += tile_length

    #Blocks while falling
    for tile in block.tiles:
        if tile.y >= off_set_y:
            tile.draw_tile()

    #Sets borders
    pygame.draw.line(DISPLAY_SCREEN , blue, (off_set_x-2, off_set_y-3), (playing_field_width+off_set_x+1, off_set_y-3), 4) # horizontal line top
    pygame.draw.line(DISPLAY_SCREEN , blue, (off_set_x-2, off_set_y+playing_field_height+1), (playing_field_width+off_set_x+1, off_set_y+playing_field_height+1), 4) # horizontal line bottom
    pygame.draw.line(DISPLAY_SCREEN , blue, (off_set_x-3, off_set_y-3), (off_set_x-3, off_set_y+playing_field_height+1), 4) # vertical line left
    pygame.draw.line(DISPLAY_SCREEN , blue, (playing_field_width+off_set_x+1, off_set_y-3), (playing_field_width+off_set_x+1, off_set_y+playing_field_height+1), 4) # vertical line right

    #Sets Grid
    current_y_horizontal_lines = off_set_y
    current_x_vertical_lines = off_set_x
    for i in range(19): 
        current_y_horizontal_lines += 33
        pygame.draw.line(DISPLAY_SCREEN , white, (off_set_x, current_y_horizontal_lines), (playing_field_width+off_set_x-1, current_y_horizontal_lines)) # horizontal line top
    for j in range(9): 
        current_x_vertical_lines += 33        
        pygame.draw.line(DISPLAY_SCREEN , white, (current_x_vertical_lines-1, off_set_y), (current_x_vertical_lines-1, playing_field_height+off_set_y)) # horizontal line top

    pygame.display.update()

def draw_small_screen(next_block):
    
    #Sets background
    pygame.draw.rect(DISPLAY_SCREEN , black, (playing_field_width+tile_length*2, height/2-20, 6*tile_length, 6*tile_length) )
    
    #Sets borders
    pygame.draw.line(DISPLAY_SCREEN , blue, (playing_field_width+tile_length*2-2, height/2-20-2), ((6*tile_length)+(playing_field_width+tile_length*2), (height/2-20-2)), 3) # horizontal line top
    pygame.draw.line(DISPLAY_SCREEN , blue, (playing_field_width+tile_length*2-2, height/2-20+(6*tile_length)), ((6*tile_length)+(playing_field_width+tile_length*2), height/2-20+(6*tile_length)), 3) # horizontal line bottom
    pygame.draw.line(DISPLAY_SCREEN , blue, (playing_field_width+tile_length*2-2, height/2-20-2), (playing_field_width+tile_length*2-2, height/2-20+(6*tile_length)), 3) # vertical line left
    pygame.draw.line(DISPLAY_SCREEN , blue, ((6*tile_length)+(playing_field_width+tile_length*2), height/2-20-2), ((6*tile_length)+(playing_field_width+tile_length*2), height/2-20+(6*tile_length)), 3) # vertical line right
    
    #Sets text
    font = pygame.font.SysFont("comicsansms", 30)
    rendered_text = font.render("Next Block", 1, orange)
    DISPLAY_SCREEN.blit(rendered_text, (playing_field_width+tile_length*2,  height/2-70))
    
    #Displays next block
    temp_block = Block(next_block.shape, next_block.color)  
    temp_block.tiles = [Tile(playing_field_width+tile_length*2+2*tile_length, height/2-20+4*tile_length, next_block.color), Tile(0, 0, next_block.color), Tile(0, 0, next_block.color), Tile(0, 0, next_block.color)]
    temp_block.complete_block()

    for tile in temp_block.tiles:
        tile.draw_tile()

def is_game_over(playing_field, player): 
    y = off_set_y
    for i in range(20):
        for tile in playing_field.tiles["row"+str(i+1)][y]:
            if not tile.empty and tile.y <= off_set_y: 
                temp_y = off_set_y
                for j in range(20):
                    for tile in playing_field.tiles["row"+str(j+1)][temp_y]:
                        tile.draw_tile()
                    temp_y += tile_length

                font = pygame.font.SysFont("comicsansms", 48)
                rendered_text = font.render("GAME OVER", 1, white)
                DISPLAY_SCREEN.blit(rendered_text, (off_set_x+20, playing_field_height/2))
                pygame.display.update()

                time.sleep(2)   
                introduction(player)
        y += tile_length

def start_game():    
    global best_score
    global longest_time

    rand_index = random.randint(0, 6)
    block = Block(shapes[rand_index], block_colors[rand_index])

    next_rand_index = random.randint(0, 6)
    next_block = Block(shapes[next_rand_index], block_colors[next_rand_index]) 

    playing_field = PlayingField()
    start_time = pygame.time.get_ticks()
    player = Player(start_time)

    while True:
        update_graphics(block, next_block, playing_field, player)

        (block, next_block, is_new) = block.get_new_block(next_block, playing_field, player)
        if is_new:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()
            pygame.event.clear()

        manage_events(block, next_block, playing_field, player)
        update_graphics(block, next_block, playing_field, player)

        block.block_is_falling(next_block, playing_field, player)
        update_graphics(block, next_block, playing_field, player)
        
        playing_field.destory_full_row(player)
        update_graphics(block, next_block, playing_field, player)

        if player.score > best_score:
            best_score = player.score
        if player.time_since_start > longest_time:
            longest_time = player.time_since_start

        is_game_over(playing_field, player)
        update_graphics(block, next_block, playing_field, player)

        pygame.display.update()
        clock.tick(60)


def manage_events(block, next_block, playing_field, player):
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()
        
        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                #move the block to the left
                block.move_left(playing_field)
            elif event.key == pygame.K_RIGHT:
                #move the block to the right
                block.move_right(playing_field)
            elif event.key == pygame.K_UP:
                # rotate block
                block.rotate(next_block, playing_field, player)
            if event.key == pygame.K_SPACE:
                # let the block fall completely
                block.fall_completely(next_block, playing_field, player)
            if event.key == pygame.K_DOWN:
                # let the block fall down faster
                block.block_is_falling(next_block, playing_field, player, "faster")

    update_graphics(block, next_block, playing_field, player)


def introduction(player = None):
    button_width = 300
    button_height = 90
    
    #start_x_button = width/2-button_width/2
    play_button = Button(blue, orange, -400, height/2, button_width, button_height, 32, black, white, "PLAY")
    instructions_button = Button(blue, orange, width+150, height/2+button_height+10, button_width,button_height, 32, black, white, "INSTRUCTIONS")
    quit_button = Button(blue, orange, -400, height/2+button_height*2+20, button_width,button_height, 32, black, white, "QUIT")
    
    font = pygame.font.SysFont("comicsansms", 48)
    rendered_text = font.render("Tetris", 1, black)
    rendered_text_y = height

    #To draw the Tetris text in an animated way
    while rendered_text_y > 10: 
        DISPLAY_SCREEN.blit(background_img, (0, 0))

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()

        rendered_text_y -= 1.5
        DISPLAY_SCREEN.blit(rendered_text, (width/2-80, rendered_text_y))
        pygame.display.update()

    #To draw the score and time texts in an animated way
    if player:
        font_small = pygame.font.SysFont("comicsansms", 30)
        rendered_current_score = font_small.render("Current Score: " + str(player.score), 1, orange)
        rendered_best_score = font_small.render("Best Score: " + str(best_score), 1, orange)
        rendered_current_time = font_small.render("Current Time: " + str(player.time_since_start), 1, orange)
        rendered_longest_time = font_small.render("Longest Time: " + str(longest_time), 1, orange)

        rendered_current_score_y = height
        rendered_best_score_y = height+40
        rendered_current_time_y = height+80
        rendered_longest_time_y = height+120

        while rendered_current_score_y > 150: 
            DISPLAY_SCREEN.blit(background_img, (0, 0))
            DISPLAY_SCREEN.blit(rendered_text, (width/2-80, rendered_text_y))

            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    pygame.quit()
                    sys.exit()

            rendered_current_score_y -= 1.5
            rendered_best_score_y -= 1.5
            rendered_current_time_y -= 1.5
            rendered_longest_time_y -= 1.5

            DISPLAY_SCREEN.blit(rendered_current_score, (off_set_x, rendered_current_score_y))
            DISPLAY_SCREEN.blit(rendered_best_score, (off_set_x+45, rendered_best_score_y))
            DISPLAY_SCREEN.blit(rendered_current_time, (off_set_x+15, rendered_current_time_y))
            DISPLAY_SCREEN.blit(rendered_longest_time, (off_set_x+15, rendered_longest_time_y))

            pygame.display.update()

    #To draw the buttons in an animated way
    while play_button.x < width/2-button_width/2 or instructions_button.x > width/2-button_width/2:
        DISPLAY_SCREEN.blit(background_img, (0, 0))
        DISPLAY_SCREEN.blit(rendered_text, (width/2-80, rendered_text_y))
        if player:
            DISPLAY_SCREEN.blit(rendered_current_score, (off_set_x, rendered_current_score_y))
            DISPLAY_SCREEN.blit(rendered_best_score, (off_set_x+45, rendered_best_score_y))
            DISPLAY_SCREEN.blit(rendered_current_time, (off_set_x+15, rendered_current_time_y))
            DISPLAY_SCREEN.blit(rendered_longest_time, (off_set_x+15, rendered_longest_time_y))

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
        
        if play_button.x < width/2-button_width/2:
            play_button.x += 3
            quit_button.x += 3
        if instructions_button.x > width/2-button_width/2 :    
            instructions_button.x -= 3

        play_button.blit(DISPLAY_SCREEN)
        instructions_button.blit(DISPLAY_SCREEN)
        quit_button.blit(DISPLAY_SCREEN)
        pygame.display.update()

    run = True
    while run:
        DISPLAY_SCREEN.blit(background_img, (0, 0))
        DISPLAY_SCREEN.blit(rendered_text, (width/2-80, rendered_text_y))
        if player:
            DISPLAY_SCREEN.blit(rendered_current_score, (off_set_x, rendered_current_score_y))
            DISPLAY_SCREEN.blit(rendered_best_score, (off_set_x+45, rendered_best_score_y))
            DISPLAY_SCREEN.blit(rendered_current_time, (off_set_x+15, rendered_current_time_y))
            DISPLAY_SCREEN.blit(rendered_longest_time, (off_set_x+15, rendered_longest_time_y))

        # Get the position of the mouse
        mouse_position = pygame.mouse.get_pos() 
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if play_button.is_clicked(mouse_position, event):
                    start_game()
                    run = False
                elif instructions_button.is_clicked(mouse_position, event):
                    instructions(player)
                    run = False
                elif quit_button.is_clicked(mouse_position, event):
                    pygame.quit()
                    sys.exit()
        
        if play_button.is_hovered_over(mouse_position):
            play_button.blit_hovered_over(DISPLAY_SCREEN)
        else:
            play_button.blit(DISPLAY_SCREEN, gray)
        if instructions_button.is_hovered_over(mouse_position):
            instructions_button.blit_hovered_over(DISPLAY_SCREEN)
        else:
            instructions_button.blit(DISPLAY_SCREEN, gray)
        if quit_button.is_hovered_over(mouse_position):
            quit_button.blit_hovered_over(DISPLAY_SCREEN)
        else:
            quit_button.blit(DISPLAY_SCREEN, gray)

        clock.tick(60)
        pygame.display.update()


def instructions(player = None):
    button_width = 150
    button_height = 60

    play_button = Button(blue, orange, width-150-10, height-80, button_width, button_height, 32, black, white, "PLAY >>")
    back_button = Button(blue, orange, 10, height-80, button_width, button_height, 32, black, white, "<< BACK")

    run = True
    while run:
        DISPLAY_SCREEN.blit(instructions_img, (0, 0))
        font = pygame.font.SysFont("comicsansms", 48)
        rendered_text = font.render("Tetris", 1, orange)
        DISPLAY_SCREEN.blit(rendered_text, (width/2-80, 10))

        # Get the position of the mouse
        mouse_position = pygame.mouse.get_pos() 
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                sys.exit()
            if event.type == pygame.MOUSEBUTTONDOWN:
                if play_button.is_clicked(mouse_position, event):
                    start_game()
                    run = False
                elif back_button.is_clicked(mouse_position, event):
                    introduction(player)
                    run = False

        instructions_label = "Instructions" 
        font = pygame.font.SysFont("comicsansms", 40)
        rendered_text = font.render(instructions_label, 1, orange)
        DISPLAY_SCREEN.blit(rendered_text, (width/2 - rendered_text.get_width()/2, 100))
    
         
        instructions1 = "   Move Right:                      right arrow >"  
        instructions2 = "   Move   Left:                     left    arrow <" 
        instructions3 = "          Rotate:                      up      arrow ^" 
        instructions4 = "   Soft  Drop:                      down   arrow" 
        instructions5 = "   Hard  Drop:                      space"

        font = pygame.font.SysFont("comicsansms", 20)
        rendered_text1 = font.render(instructions1, 1, orange)
        rendered_text2 = font.render(instructions2, 1, orange)
        rendered_text3 = font.render(instructions3, 1, orange)
        rendered_text4 = font.render(instructions4, 1, orange)
        rendered_text5 = font.render(instructions5, 1, orange)

        DISPLAY_SCREEN.blit(rendered_text1, (20, 200))
        DISPLAY_SCREEN.blit(rendered_text2, (20, 240))
        DISPLAY_SCREEN.blit(rendered_text3, (20, 280))
        DISPLAY_SCREEN.blit(rendered_text4, (20, 320))
        DISPLAY_SCREEN.blit(rendered_text5, (20, 360))

        if play_button.is_hovered_over(mouse_position):
            play_button.blit_hovered_over(DISPLAY_SCREEN)
        else:
            play_button.blit(DISPLAY_SCREEN, gray)
        if back_button.is_hovered_over(mouse_position):
            back_button.blit_hovered_over(DISPLAY_SCREEN)
        else:
            back_button.blit(DISPLAY_SCREEN, gray)
        
        clock.tick(60)
        pygame.display.update()

if __name__ == "__main__":
    introduction()
    

Python俄罗斯方块Tetris源文件本站下载:
https://download.csdn.net/download/mufenglaoshi/88612722

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1298391.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mysql研学-认识与安装

一 数据库 1 Java的数据存储技术 ① 变量:一个数据存储空间的表示 ② 数组:存储一组相同数据类型的"容器" ③ 集合:存储一组任意引用数据类型的"容器" ④ 配置文件: .properties:基于Properties集合存储(Map集合的具体实例) .xml文件:基于标签存储数据…

centos7 安装 mysql8 详细步骤记录

下载 mysql 8 更新系统&#xff1a; sudo yum update 添加 MySQL Yum存储库&#xff1a; sudo rpm -Uvh https://repo.mysql.com/mysql80-community-release-el7-3.noarch.rpm 安装 MySQL 8&#xff1a; sudo yum install mysql-server 重置密码 查看初始密码&#xff1…

三种入耳检测光感芯片驱动开发比较

三种入耳检测光感芯片驱动开发比较 是否需要申请加入数字音频系统研究开发交流答疑群(课题组)&#xff1f;可加我微信hezkz17, 本群提供音频技术答疑服务&#xff0c;群赠送语音信号处理降噪算法&#xff0c;蓝牙耳机音频&#xff0c;DSP音频项目核心开发资料, 重要的寄存器…

应用层之应用层的网络应用模型————C/S和P2P、域名解析系统DNS、文件传输协议FTP

学习的最大理由是想摆脱平庸&#xff0c;早一天就多一份人生的精彩&#xff1b;迟一天就多一天平庸的困扰。各位小伙伴&#xff0c;如果您&#xff1a; 想系统/深入学习某技术知识点… 一个人摸索学习很难坚持&#xff0c;想组团高效学习… 想写博客但无从下手&#xff0c;急需…

Ubuntu上svn基本使用(gitee提交下载)

目录 环境准备 1. 获取代码到本地 直接获取 获取代码时加入用户名密码 指定版本更新 2. 提交代码 3. 展示代码列表 4. 添加代码文件(目录) 5. 删除gitee仓库中的文件 参考文档链接 环境准备 当前操作系统为Ubuntu22.04LTS gitee 创建仓库时 需要打开svn的支持 sudo…

54.grpc实现文件上传和下载

文章目录 一&#xff1a;简介1. 什么是grpc2. 为什么我们要用grpc 二&#xff1a;grpc的hello world1、 定义hello.proto文件2、生成xxx_grpc.pb.go文件3、生成xxx.pb.go结构体文件4、编写服务代码service.go5、编写客户端代码client.go 三、服务端流式传输&#xff1a;文件下载…

短视频无人实景直播源码技术开发=抖去推saas直播源码

开发无人直播源码技术需要具备一定的编程和网络知识。以下是一些基本的步骤和资源&#xff0c;帮助你进行无人直播源码的开发搭建&#xff1a; 1. 选择编程语言和开发环境&#xff1a;根据你的个人喜好和技术熟练程度&#xff0c;可以选择一些流行的编程语言&#xff0c;如Pyth…

根据应聘者的姓名和所学专业判断是否需要这样的程序设计人员

一、程序分析 导入Scanner函数&#xff0c;分别输入应聘者的姓名和应聘者所学的程序设计语言。 二、具体代码 import java.util.Scanner; public class Recruitment {public static void main(String[] args){try (Scanner scan new Scanner(System.in)) {System.out.prin…

【Vue】设置路由默认跳转指定页面

目录 设置路由默认跳转 上一篇&#xff1a; 登录注册界面制作 https://blog.csdn.net/m0_67930426/article/details/134895214?spm1001.2014.3001.5502 以这篇文章为例 首先我们要了解一下vue项目的router包的作用 上一篇文章里&#xff0c;创建了登录注册页面 如果我们…

SpringSecurity6 | 自定义登录页面

✅作者简介&#xff1a;大家好&#xff0c;我是Leo&#xff0c;热爱Java后端开发者&#xff0c;一个想要与大家共同进步的男人&#x1f609;&#x1f609; &#x1f34e;个人主页&#xff1a;Leo的博客 &#x1f49e;当前专栏&#xff1a; Java从入门到精通 ✨特色专栏&#xf…

Qt开发 之 Qt5各版本情况分析

文章目录 1、简介2、Qt5 版本归纳3、下载地址3.1、典型版本3.1.1、Qt5.0.03.1.2、Qt5.9.93.1.3、Qt5.12.12 3.2、当前Qt5最新版本 1、简介 Qt6 出生刚刚好一年的时间&#xff0c;已经出到6.6版本&#xff0c;带来了许多的新特性和改进。今天刚刚好抽空总结下陪伴 我工作这么长…

【K8S in Action】副本机制与控制器:部署托管的Pod

通过控制器来运行托管的 pod&#xff0c;Pod失败的时候自动重新启动它们。 1. 保持pod健康 从外部检查应用程序的运行状况: HTTPGET探针对容器的 IP 地址TCP套接字探针尝试与容器指定端口建立TCP连接Exec探针在容器内执行任意命令&#xff0c;并检查命令的退出状态码。如果状…

智能优化算法应用:基于人工兔算法无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于人工兔算法无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于人工兔算法无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.人工兔算法4.实验参数设定5.算法结果6.参考文献7.…

初出茅庐的小李博客之TobudOS移植到EVB_AIoT开发板

本博客参考教程&#xff1a; https://atomgit.com/OpenAtomFoundation/TobudOS/blob/master/doc/TobudOS_EVB_AIoT_STM32_Guide.md 介绍一下EVB_AIoT开发板 这个开发板是由TobudOS开源社区联合意法半导体、南京厚德物联网设计的一款高性能IoT开发平台&#xff0c;主控芯片是S…

学校安全检查系统

校园面积大、安全盲区多对学校安全管理带来诸多挑战&#xff1b;传统依靠人工纸质巡检记录存在漏检、管理难、联动差等诸多问题和缺点&#xff0c;巡检过程中很容易遗漏安全隐患的存续&#xff0c;从而导致安全事故的发生。 通过凡尔码平台模块化搭建学校安全管理系统&#xf…

【Bootloader学习理解----跳转优化异常】

笔者接着来介绍一下Bootloader的跳转代码以及优化 1、跳转代码理解 跳转代码可能要涉及到芯片架构的知识,要跳转到对应的位置&#xff0c;还要设置相关的SP 堆栈指针&#xff0c;具体可以参考笔者这篇文章BootLoader的理解与实现。 STM32的跳转代码如下所示&#xff1a; u32 …

多张二维码能一次解码处理吗?3个步骤就能完成

二维码是现在生活中很常见的内容承载方式&#xff0c;但是有时候我们需要将二维码内容转换成文本或者链接来使用&#xff0c;那么如何处理能够将二维码分解处理呢&#xff1f;想要将多张二维码图片分解处理&#xff0c;那么为了提高效率可以用二维码解码器的批量解码功能来处理…

【词云图】从excel和从txt文件,绘制以句子、词为单位的词云图

从excel和从txt文件&#xff0c;绘制以句子、词为单位的词云图 写在最前面数据说明&结论 从txt文件&#xff0c;绘制以句子、词为单位的词云图自我介绍 从excel&#xff0c;绘制以句子、词为单位的词云图读取excel绘制以句子、词为单位的词云图文章标题 写在最前面 经常绘…

TSINGSEE青犀AI视频识别技术渣土车识别智能监管方案

随着城市化进程的不断推进&#xff0c;渣土车在建筑垃圾的运输中发挥着越来越重要的作用。未密闭化运输、车容不洁挂土、违规抛洒滴漏是目前渣土运输过程中最常见的违规行为。传统的渣土车运输管理方式存在着很多问题&#xff0c;导致渣土车在运输过程出现的不规范行为得到有效…

vue3实现2d楼宇模型

需求背景解决效果视频效果2dFloor.vue 需求背景 需要实线一个2d楼宇模型&#xff0c;并按照租户温度渲染颜色 解决效果 视频效果 2dFloor.vue <!--/*** author: liuk* date: 2023/12/06* describe: 2d楼宇模型* CSDN:https://blog.csdn.net/hr_beginner?typeblog*/--&g…