Struggling with multiple programming languages? No worries. OurCode Converter has got you covered. Give it a go!
Tetris is a classic puzzle game where the objective is to arrange falling geometric pieces, called tetrominoes, to fill horizontal lines without leaving gaps. When a line is completely filled, it is cleared, and the player earns points. The game becomes progressively more challenging as the tetrominoes fall faster, making it harder to arrange them in time.
In this tutorial, we will walk you through the process of creating a simple Tetris game step by step usingPyGame. We will cover the following topics:
By the end of this tutorial, you will have a fully functional Tetris game that you can play and customize. This project will also help you understand the basics of game development with Python and Pygame and serve as a foundation for creating other types of games. Here's how it'll look like:

Table of content:
Tetromino andTetris Classes to Manage Game LogicOnce you have Python installed, open your terminal or command prompt and enter the following command to install the Pygame library:
$ pip install pygameNow that our development environment is ready, let's start by creating the game window and defining the tetromino shapes.
First, we need to import the necessary modules for our Tetris game. Add the following lines to your Python script:
import sysimport pygameimport randomTo use the Pygame library, we need to initialize it. Add the following line after the import statements:
pygame.init()Next, we need to define some constants for our game, such as screen dimensions, grid size, colors, and the shapes of the tetrominoes. Add the following lines to your script:
# Screen dimensionsWIDTH, HEIGHT = 800, 600GRID_SIZE = 25# ColorsWHITE = (255, 255, 255)BLACK = (0, 0, 0)RED = (255, 0, 0)BLUE = (0, 0, 255)GREEN = (0, 255, 0)COLORS = [RED, BLUE, GREEN]# Tetromino shapesSHAPES = [ [ ['.....', '.....', '.....', 'OOOO.', '.....'], ['.....', '..O..', '..O..', '..O..', '..O..'] ], [ ['.....', '.....', '..O..', '.OOO.', '.....'], ['.....', '..O..', '.OO..', '..O..', '.....'], ['.....', '.....', '.OOO.', '..O..', '.....'], ['.....', '..O..', '..OO.', '..O..', '.....'] ], [ [ '.....', '.....', '..OO.', '.OO..', '.....'], ['.....', '.....', '.OO..', '..OO.', '.....'], ['.....', '.O...', '.OO..', '..O..', '.....'], ['.....', '..O..', '.OO..', '.O...', '.....'] ], [ ['.....', '..O..', '..O.', '..OO.', '.....'], ['.....', '...O.', '.OOO.', '.....', '.....'], ['.....', '.OO..', '..O..', '..O..', '.....'], ['.....', '.....', '.OOO.', '.O...', '.....'] ],]Here, we define the width and height of the game window, the grid size for the tetrominoes, and the colors we will use for the game (white, black, and red). TheSHAPES list contains the tetromino shapes represented as strings, you're free to add/edit as you wish. You can also play around with the colors and grid size.
Tetromino andTetris Classes to Manage Game LogicNow that we have our game window and tetromino shapes defined, let's create two classes to manage the game logic: the Tetromino class and the Tetris class.
Tetromino ClassTheTetromino class will represent a single tetromino piece, with properties for its position,shape,color, androtation. Add the following code to your script:
class Tetromino: def __init__(self, x, y, shape): self.x = x self.y = y self.shape = shape self.color = random.choice(COLORS) # You can choose different colors for each shape self.rotation = 0Tetris ClassTheTetris class will handle the main game logic. It will have methods for creating a new piece, checking if a move is valid, clearing lines, locking a piece, updating the game state, and drawing the game. Add the following code to your script:
class Tetris: def __init__(self, width, height): self.width = width self.height = height self.grid = [[0 for _ in range(width)] for _ in range(height)] self.current_piece = self.new_piece() self.game_over = False self.score = 0 # Add score attributeLet's make a method for making a newTetromino piece:
def new_piece(self): # Choose a random shape shape = random.choice(SHAPES) # Return a new Tetromino object return Tetromino(self.width // 2, 0, shape)Next, thevalid_move() method checks whether a piece can move to the given position:
def valid_move(self, piece, x, y, rotation): """Check if the piece can move to the given position""" for i, row in enumerate(piece.shape[(piece.rotation + rotation) % len(piece.shape)]): for j, cell in enumerate(row): try: if cell == 'O' and (self.grid[piece.y + i + y][piece.x + j + x] != 0): return False except IndexError: return False return TrueTheclear_lines() method clears the lines that are full and returns the number of cleared lines so we can calculate the score later:
def clear_lines(self): """Clear the lines that are full and return the number of cleared lines""" lines_cleared = 0 for i, row in enumerate(self.grid[:-1]): if all(cell != 0 for cell in row): lines_cleared += 1 del self.grid[i] self.grid.insert(0, [0 for _ in range(self.width)]) return lines_clearedNow the method for locking the pieces:
def lock_piece(self, piece): """Lock the piece in place and create a new piece""" for i, row in enumerate(piece.shape[piece.rotation % len(piece.shape)]): for j, cell in enumerate(row): if cell == 'O': self.grid[piece.y + i][piece.x + j] = piece.color # Clear the lines and update the score lines_cleared = self.clear_lines() self.score += lines_cleared * 100 # Update the score based on the number of cleared lines # Create a new piece self.current_piece = self.new_piece() # Check if the game is over if not self.valid_move(self.current_piece, 0, 0, 0): self.game_over = True return lines_clearedTheupdate() function to move the tetromino one cell down:
def update(self): """Move the tetromino down one cell""" if not self.game_over: if self.valid_move(self.current_piece, 0, 1, 0): self.current_piece.y += 1 else: self.lock_piece(self.current_piece)Finally, we make the method for drawing the game grid and the current piece:
def draw(self, screen): """Draw the grid and the current piece""" for y, row in enumerate(self.grid): for x, cell in enumerate(row): if cell: pygame.draw.rect(screen, cell, (x * GRID_SIZE, y * GRID_SIZE, GRID_SIZE - 1, GRID_SIZE - 1)) if self.current_piece: for i, row in enumerate(self.current_piece.shape[self.current_piece.rotation % len(self.current_piece.shape)]): for j, cell in enumerate(row): if cell == 'O': pygame.draw.rect(screen, self.current_piece.color, ((self.current_piece.x + j) * GRID_SIZE, (self.current_piece.y + i) * GRID_SIZE, GRID_SIZE - 1, GRID_SIZE - 1))Now that we've made theTetris class, let's make two helper functions that draw text, one for the score, and another for the "Game Over!":
def draw_score(screen, score, x, y): """Draw the score on the screen""" font = pygame.font.Font(None, 36) text = font.render(f"Score: {score}", True, WHITE) screen.blit(text, (x, y)) def draw_game_over(screen, x, y): """Draw the game over text on the screen""" font = pygame.font.Font(None, 48) text = font.render("Game Over", True, RED) screen.blit(text, (x, y))These functions take four arguments (three in the case ofdraw_game_over()):
screen: the Pygame surface to draw on.score: the current game score.x: the x-coordinate of the position where the score will be displayed.y: the y-coordinate of the position where the score will be displayed.The functions create a font object usingpygame.font.Font(None, 36), render the score text with thefont.render() method, and then usescreen.blit() to display the text on the screen.
Before running the loop, we start by initializing Pygame, creating the clock object, and creating the game screen and the game, theTetris object:
def main(): # Initialize pygame screen = pygame.display.set_mode((WIDTH, HEIGHT)) pygame.display.set_caption('Tetris') # Create a clock object clock = pygame.time.Clock() # Create a Tetris object game = Tetris(WIDTH // GRID_SIZE, HEIGHT // GRID_SIZE) fall_time = 0 fall_speed = 50 # You can adjust this value to change the falling speed, it's in millisecondsYou can adjust thefall_speed to lower it (make it faster), or increase it to make it slower.
Here's the game loop:
while True: # Fill the screen with black screen.fill(BLACK) for event in pygame.event.get(): # Check for the QUIT event if event.type == pygame.QUIT: pygame.quit() sys.exit() # Check for the KEYDOWN event if event.type == pygame.KEYDOWN: if event.key == pygame.K_LEFT: if game.valid_move(game.current_piece, -1, 0, 0): game.current_piece.x -= 1 # Move the piece to the left if event.key == pygame.K_RIGHT: if game.valid_move(game.current_piece, 1, 0, 0): game.current_piece.x += 1 # Move the piece to the right if event.key == pygame.K_DOWN: if game.valid_move(game.current_piece, 0, 1, 0): game.current_piece.y += 1 # Move the piece down if event.key == pygame.K_UP: if game.valid_move(game.current_piece, 0, 0, 1): game.current_piece.rotation += 1 # Rotate the piece if event.key == pygame.K_SPACE: while game.valid_move(game.current_piece, 0, 1, 0): game.current_piece.y += 1 # Move the piece down until it hits the bottom game.lock_piece(game.current_piece) # Lock the piece in place # Get the number of milliseconds since the last frame delta_time = clock.get_rawtime() # Add the delta time to the fall time fall_time += delta_time if fall_time >= fall_speed: # Move the piece down game.update() # Reset the fall time fall_time = 0 # Draw the score on the screen draw_score(screen, game.score, 10, 10) # Draw the grid and the current piece game.draw(screen) if game.game_over: # Draw the "Game Over" message draw_game_over(screen, WIDTH // 2 - 100, HEIGHT // 2 - 30) # Draw the "Game Over" message # You can add a "Press any key to restart" message here # Check for the KEYDOWN event if event.type == pygame.KEYDOWN: # Create a new Tetris object game = Tetris(WIDTH // GRID_SIZE, HEIGHT // GRID_SIZE) # Update the display pygame.display.flip() # Set the framerate clock.tick(60)The main game loop is awhile loop that continuously executes the following steps:
That's it! This simple implementation of a Tetris game should now be functional. You can run the script to play the game and make any desired customizations to the gameplay, graphics, or controls.
You can getthe complete code here.
Here are some related games built with Python:
Happy coding ♥
Found the article interesting? You'll love ourPython Code Generator! Give AI a chance to do the heavy lifting for you. Check it out!
View Full Code Transform My CodeGot a coding query or need some guidance before you comment? Check out thisPython Code Assistant for expert advice and handy tips. It's like having a coding tutor right in your fingertips!
