Let’s make Tetris with Python and a little help of Chatcpt

As many knows the entrance of chatgpt in the World has made people pleasently (most of all) surprised by all the things you can ask to it. And this tool could also change the way we code. Let’s see what chatgpt is.

What is ChatGPT

ChatGPT (pronounced “chat-gept”) is a language model developed by OpenAI that is trained to generate human-like text. It can be used to create chatbots that can carry on natural-sounding conversations with users, as well as to perform a wide range of other language-based tasks. ChatGPT is based on the GPT-3 language model and has been specifically trained on large amounts of chat data to improve its ability to generate relevant and appropriate responses in a conversational context.

Now we want to see if we are able to create a Tetris game with the help of chatgpt. We don’t want to have the whole game made by chatgpt in one shot, because we want to understand how the game is done and we want also guide the ai of this bot to create the game the way we want, personalising it. So we want to use it as a tool, not as a substitute of a coder. We want to use it to make the boring stuff instead of making it by ourself so that we don’t get bored and we save time in those boring things that are the initial stuff you need to do for any program and also to see how the ai “thinks” to see if the methods of the ai are better and also to learn new stuffs. Let’s go.

We are going to use the pygame module, of course.

Pygame

Pygame is a set of Python modules designed for writing video games. It is built on top of the SDL (Simple DirectMedia Layer) library, which is a cross-platform development library designed to provide low-level access to audio, keyboard, mouse, joystick, and graphics hardware via OpenGL and Direct3D.

Pygame provides a set of Python classes for handling common game development tasks, such as creating a game window, rendering graphics, handling user input, and playing sounds and music. It also includes a variety of utility modules for loading images, playing sounds, and parsing game controller input.

One of the benefits of using Pygame is that it is easy to get started and create simple games quickly. It is also well-documented and has a large community of users, making it a good choice for beginners and experienced game developers alike.

Overall, Pygame is a powerful tool for creating games in Python, and is well-suited for a wide range of game development projects. Whether you are a beginner looking to learn game development, or an experienced developer looking for a quick and easy way to create games in Python, Pygame is worth considering.

Let’s start

I asked chatgpt to: “make a classic setup to make a tetris game in python

To make a classic Tetris game in Python, you will need to follow these steps:

  1. Import the necessary modules: You will need to import the pygame module to handle the game graphics and user input, as well as any other modules you may need for your game, such as random for generating random shapes.
  2. Initialize Pygame: Call the pygame.init() function to initialize Pygame.
  3. Set up the game window: Use the pygame.display.set_caption() function to set the title of the game window, and use the pygame.display.set_mode() function to set the size of the window.
  4. Create a game clock: Use the pygame.time.Clock() function to create a clock object that will be used to control the frame rate of the game.
  5. Define game constants: Define constants for the dimensions of the game board and the size of the Tetris blocks.
  6. Define the Tetris shapes: Create a list of lists representing the different Tetris shapes, with each inner list representing a rotation of the shape.
  7. Create the game board: Create a two-dimensional list to represent the game board, initialized with all zeros.
  8. Define the game loop: Create a main game loop that will handle user input, update the game state, and draw the game to the screen.
  9. Handle user input: Use the pygame.event.get() function to get a list of user input events, and use the pygame.key.get_pressed() function to check for key presses.
  10. Update the game state: Update the position and rotation of the current Tetris shape based on user input. Check for completed rows and remove them from the game board.
  11. Draw the game to the screen: Use the pygame.draw.rect() function to draw the Tetris shapes and the game board to the screen.
  12. Display the game: Use the pygame.display.update() function to update the game window with the new game state.
  13. Advance the game clock: Use the tick() method of the clock object to pause the game loop for the appropriate amount of time to maintain the desired frame rate.

This is just a basic outline of the steps involved in creating a Tetris game in Python. There are many additional details and considerations that you will need to take into account, such as handling the end of the game, keeping track of the player’s score, and so on.

Now let’s see if chatgpt gives some code example to start with and if it works.

I had to add this variables, because they were not defined

current_shape = shapes[0]
current_x = 10
current_y = 0

So the code (with the variables above) was this

import pygame
import random

# Initialize Pygame
pygame.init()

# Set up the game window
screen = pygame.display.set_mode((400, 600))
pygame.display.set_caption("Tetris")

# Create a game clock
clock = pygame.time.Clock()

# Define game constants
board_width = 10
board_height = 20
block_size = 20

# Define the Tetris shapes
shapes = [
    [[1, 1, 1],
     [0, 1, 0]],
    
    [[0, 2, 2],
     [2, 2, 0]],
     
    [[3, 3, 0],
     [0, 3, 3]],
     
    [[4, 0, 0],
     [4, 4, 4]],
     
    [[0, 0, 5],
     [5, 5, 5]],
     
    [[6, 6, 6, 6]],
     
    [[7, 7],
     [7, 7]]
]
current_shape = shapes[0]
current_x = 10
current_y = 0
# Create the game board
board = [[0 for _ in range(board_width)] for _ in range(board_height)]

# Define the game loop
running = True
while running:
    # Handle user input
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                # Move the current Tetris shape to the left
                pass
            elif event.key == pygame.K_RIGHT:
                # Move the current Tetris shape to the right
                pass
            elif event.key == pygame.K_UP:
                # Rotate the current Tetris shape
                pass
            elif event.key == pygame.K_DOWN:
                # Move the current Tetris shape down faster
                pass
    
    # Update the game state
    # Check for completed rows and remove them
    # Update the position and rotation of the current Tetris shape
    
    # Draw the game to the screen
    screen.fill((0, 0, 0))  # Clear the screen
    for y in range(board_height):
        for x in range(board_width):
            if board[y][x] > 0:
                # Draw a block on the board
                pygame.draw.rect(screen, (255, 255, 255), (x * block_size, y * block_size, block_size, block_size))
    
    # Draw the current Tetris shape
    for y in range(len(current_shape)):
        for x in range(len(current_shape[y])):
            if current_shape[y][x] > 0:
                # Draw a block for the current shape
                pygame.draw.rect(screen, (255, 255, 255), (current_x + x * block_size, current_y + y * block_size, block_size, block_size))
    
    # Display the game
    pygame.display.update()

pygame.quit()

If you run the script you will get this

You can see the piece up there, but it does not move. Let ask the ai to move it.

At this point the ai is not giving the complete working code for this, so we will try to approach with a different plan.

Let’s divide the code into it’s part, so that we understand well what is going on in the code:

The initial stuffs: screen, clock etc.

import pygame
import random

# Initialize Pygame
pygame.init()

# Set up the game window
screen = pygame.display.set_mode((400, 600))
pygame.display.set_caption("Tetris")

# Create a game clock
clock = pygame.time.Clock()

# Define game constants
board_width = 10
board_height = 20
block_size = 20
move_delay = 500  # Delay between shape moves (in milliseconds)

The blocks (or Tetris shapes)

# Define the Tetris shapes
shapes = [
    [[1, 1, 1],
     [0, 1, 0]],
    
    [[0, 2, 2],
     [2, 2, 0]],
     
    [[3, 3, 0],
     [0, 3, 3]],
     
    [[4, 0, 0],
     [4, 4, 4]],
     
    [[0, 0, 5],
     [5, 5, 5]],
     
    [[6, 6, 6, 6]],
     
    [[7, 7],
     [7, 7]]
]

Let’s choose the initial block and the initial position of the tetris shape

# Create the game board
board = [[0 for _ in range(board_width)] for _ in range(board_height)]

# Generate a new Tetris shape
current_shape = random.choice(shapes)
current_x = board_width // 2 - len(current_shape[0]) // 2
current_y = 0
current_rotation = 0

The while loops (it is not wright yet)

# Define the game loop
running = True
last_move_time = pygame.time.get_ticks()
while running:
    # Handle user input
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                # Move the current Tetris shape to the left
                current_x -= 1
            elif event.key == pygame.K_RIGHT:
                # Move the current Tetris shape to the right
                current_x += 1
            elif event.key == pygame.K_UP:
                # Rotate the current Tetris shape
                current_rotation = (current_rotation + 1) % len(current_shape)
                current_shape = shapes[current_shape][current_rotation]
            elif event.key == pygame.K_DOWN:
                # Move the current Tetris shape down faster
                current_y += 1
    
    # Update the game state
    current_time = pygame.time.get_ticks()
    if current_time - last_move_time > move_delay:
        # Move the current Tetris shape down
        current_y += 1
        last_move_time = current_time
    
    # Check if the current Tetris shape has collided with something
    shape_collided = False
    for y in range(len(current_shape)):
        for x in range(len(current_shape[y])):
            if current_shape[y][x] > 0:
                # Check if the block is outside the game board
                if current_x + x < 0 or current_x + x >= board_width or current_y + y >= board_height:
                    shape_collided = True
                    break
                # Check if the block is colliding with another block on the game board
                elif board[current_y + y][current_x + x] > 0:
                    shape_collided = True
                    break
        if shape_collided:
            break

    if shape_collided:
        # The shape has collided with something, so do something (e.g. add it to the board, generate a new shape)
        pass


pygame.quit()
E:\tetris ai>py -3.10 tetris02.py                                                                                                   
pygame 2.1.2 (SDL 2.0.18, Python 3.10.7)                                                                                            
Hello from the pygame community. https://www.pygame.org/contribute.html                                                             
Traceback (most recent call last):                                                                                                  
  File "E:\tetris ai\tetris02.py", line 70, in <module>                                                                             
    current_shape = shapes[current_shape][current_rotation]                                                                         
TypeError: list indices must be integers or slices, not list  

We get this error when we run the script

The errors appears when I press the keys to move the shapes. Nothing appears on the screen.

Ok, I made some changes by myself, figuring out what whas missing. I had to make the shape visible on the screen and so I did this:

import pygame
import random

# Initialize Pygame ================================ INIT
pygame.init()
# Set up the game window
screen = pygame.display.set_mode((400, 600))
pygame.display.set_caption("Tetris")
# Create a game clock
clock = pygame.time.Clock()

# Define game constants
board_width = 10
board_height = 20
block_size = 20
move_delay = 500  # Delay between shape moves (in milliseconds)



# Define the Tetris shapes ======================= SHAPES
shapes = [
    [[1, 1, 1],
     [0, 1, 0]],
    
    [[0, 2, 2],
     [2, 2, 0]],
     
    [[3, 3, 0],
     [0, 3, 3]],
     
    [[4, 0, 0],
     [4, 4, 4]],
     
    [[0, 0, 5],
     [5, 5, 5]],
     
    [[6, 6, 6, 6]],
     
    [[7, 7],
     [7, 7]]
]


# Create the game board
board = [[0 for _ in range(board_width)] for _ in range(board_height)]

# Generate a new Tetris shape
current_shape = random.choice(shapes)
current_x = board_width // 2 - len(current_shape[0]) // 2
current_y = 0
current_rotation = 0


# Define the game loop
running = True
last_move_time = pygame.time.get_ticks()
while running:
    # Handle user input
    screen.fill(0)
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            running = False
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                # Move the current Tetris shape to the left
                current_x -= block_size
            elif event.key == pygame.K_RIGHT:
                # Move the current Tetris shape to the right
                current_x += block_size
            elif event.key == pygame.K_UP:                        # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
                # Rotate the current Tetris shape
                current_rotation = (current_rotation + block_size) % len(current_shape)
                current_shape = shapes[current_shape][current_rotation]
            elif event.key == pygame.K_DOWN:
                # Move the current Tetris shape down faster
                current_y += block_size
    
    # Update the game state
    current_time = pygame.time.get_ticks()
    if current_time - last_move_time > move_delay:
        # Move the current Tetris shape down
        current_y += block_size
        last_move_time = current_time
    
    # Check if the current Tetris shape has collided with something
    shape_collided = False
    for y in range(len(current_shape)):
        for x in range(len(current_shape[y])):
            if current_shape[y][x] > 0:
                # Check if the block is outside the game board
                if current_x + x < 0 or current_x + x >= board_width or current_y + y >= board_height:
                    shape_collided = True
                    break
                # Check if the block is colliding with another block on the game board
                elif board[current_y + y][current_x + x] > 0:
                    shape_collided = True
                    break
        if shape_collided:
            break

    if shape_collided:
        # The shape has collided with something, so do something (e.g. add it to the board, generate a new shape)
        pass

    for yn, line in enumerate(current_shape):
        for xn, square in enumerate(line):
            if square != 0:
                pygame.draw.rect(screen,
                    (255,255,255),
                    pygame.Rect(
                        current_x+xn*block_size,
                        current_y+yn*block_size,
                        block_size,
                        block_size))
    pygame.display.update()
    clock.tick(60)

pygame.quit()

I added a line to clear the screen on the top of the while loop.

The shape comes down and I can also move it but now we need to check when it reaches the ground with a collition function.

Ok, see you in the next part.


Subscribe to the newsletter for updates
Tkinter templates
Avatar My youtube channel

Twitter: @pythonprogrammi - python_pygame

Videos

Speech recognition game

Pygame's Platform Game

Other Pygame's posts

Published by pythonprogramming

Started with basic on the spectrum, loved javascript in the 90ies and python in the 2000, now I am back with python, still making some javascript stuff when needed.