Creating an Arkanoid-like game in Python using ChatGPT

How to utilize ChatGPT to develop a game in Python

ChatGPT is a truly amazing tool.

I believe it has the potential to change our world and improve our productivity by 10x.

It complements Google search in a way like no other tool before.

I have decided to try it out over the weekend and develop a simple Python game using it.

In this short article I will show you how you can use Chat GPT to create a simple version of Arkanoid game in Python.

The results are astonishing and this is what I managed to achieve within a couple of hours and no knowledge of pygame at all.

The way it leads you through a design is just unbelievable.

Check out the end result below:

                                
import pygame

def create_paddle(window_size, paddle_width=150, paddle_height=20, paddle_color=(255, 255, 255)):
    """Create a paddle object and return it.

    Keyword arguments:
    window_size -- a tuple containing the width and height of the window
    paddle_width -- the width of the paddle (default 150)
    paddle_height -- the height of the paddle (default 20)
    paddle_color -- the color of the paddle (default white)
    """
    paddle_x = (window_size[0] - paddle_width) // 2
    paddle_y = window_size[1] - paddle_height - 10
    return pygame.Rect(paddle_x, paddle_y, paddle_width, paddle_height)

def create_ball(window_size, ball_radius=10, ball_color=(255, 255, 255), ball_initial_position=(400, 300)):
    """Create a ball object and return it.

    Keyword arguments:
    window_size -- a tuple containing the width and height of the window
    ball_radius -- the radius of the ball (default 10)
    ball_color -- the color of the ball (default white)
    ball_initial_position -- a tuple containing the initial x and y coordinates of the ball (default (400, 300))
    """
    x, y = ball_initial_position
    ball = pygame.draw.circle(screen, ball_color, (x, y), ball_radius)
    return ball, ball_radius


def create_bricks(window_size, brick_size, brick_color, num_rows, num_columns):
    """Create a grid of bricks and return a list of brick rectangles.

    Keyword arguments:
    window_size -- a tuple containing the width and height of the window
    brick_size -- a tuple containing the width and height of each brick
    brick_color -- the color of the bricks
    num_rows -- the number of rows of bricks
    num_columns -- the number of columns of bricks
    """
    bricks = []
    brick_width, brick_height = brick_size
    for i in range(num_rows):
        for j in range(num_columns):
            brick_x = j * (brick_width + 5) + 10
            brick_y = i * (brick_height + 5) + 60
            brick = pygame.Rect(brick_x, brick_y, brick_width, brick_height)
            bricks.append(brick)
            pygame.draw.rect(screen, brick_color, brick)
    return bricks


def move_paddle(paddle, velocity, window_size):
    """Move the paddle by the specified velocity.

    Keyword arguments:
    paddle -- the paddle to move
    velocity -- the velocity of the paddle
    window_size -- a tuple containing the width and height of the window
    """
    paddle.move_ip(velocity, 0)
    if paddle.left < 0:
        paddle.left = 0
    elif paddle.right > window_size[0]:
        paddle.right = window_size[0]

def game_over_message(screen, font, score):
    """Display a game over message on the screen.

    Keyword arguments:
    screen -- the pygame screen object
    font -- the pygame font object
    score -- the current score
    """
    game_over_text = font.render("Game Over! Score: " + str(score), True, (255, 255, 255))
    game_over_rect = game_over_text.get_rect()
    game_over_rect.center = (screen.get_width() // 2, screen.get_height() // 2)
    screen.blit(game_over_text, game_over_rect)

def game_over(screen, font):
    """Display a "Game Over!" message and wait for the user to press the R key to restart the game.

    Keyword arguments:
    screen -- the screen to draw the message on
    font -- the font to use for the message
    """
    # Redraw the screen
    screen.fill((0, 0, 0))
    # Render the game over text
    game_over_message(screen, font, score)
    pygame.display.flip()
    # Wait for the user to press the R key
    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT or ((event.type == pygame.KEYDOWN) and (event.key == pygame.K_ESCAPE)):
                pygame.quit()
            if event.type == pygame.KEYDOWN and event.key == pygame.K_r:
                return

def reset_game(window_size):
    """Reset the ball, ball velocity, paddle, and bricks to their initial positions.

    Keyword arguments:
    window_size -- the size of the window

    Returns:
    A tuple containing the reset values of ball, ball_velocity, paddle, bricks, and ball_radius.
    """
    ball, ball_radius = create_ball(window_size)
    ball_velocity = [4, -4]
    paddle = create_paddle(window_size)
    bricks = create_bricks(window_size, (75, 25), (255, 255, 255), 5, 10)
    return ball, ball_velocity, paddle, bricks, ball_radius


# Initialize pygame
pygame.init()

# Set the window size
window_size = (800, 600)

# Create the window
screen = pygame.display.set_mode(window_size)

# Set the title of the window
pygame.display.set_caption("Arkanoid")

# Initialize the font module
pygame.font.init()

# Set the font and font size
font = pygame.font.Font(None, 36)

# Initialize the score
score = 0

# Create the game objects
paddle = create_paddle(window_size)
# Create the ball
ball, ball_radius = create_ball(window_size)
brick_color = (255, 255, 255)
bricks = create_bricks(window_size, (75, 25), brick_color, 5, 10)

# Set the initial velocity of the ball
ball_velocity = [4, 4]

# Run the game loop
clock = pygame.time.Clock()
is_reset = False
paddle_velocity = 0
while True:
    is_reset = False
    # Handle events
    for event in pygame.event.get():
        if event.type == pygame.QUIT or ((event.type == pygame.KEYDOWN) and (event.key == pygame.K_ESCAPE)):
            pygame.quit()
        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_LEFT:
                paddle_velocity = -10
            elif event.key == pygame.K_RIGHT:
                paddle_velocity = 10
        elif event.type == pygame.KEYUP:
            if event.key in (pygame.K_LEFT, pygame.K_RIGHT):
                paddle_velocity = 0

    # Update the position of the paddle
    move_paddle(paddle, paddle_velocity, window_size)

    # Update the ball's position
    ball.x += ball_velocity[0]
    ball.y += ball_velocity[1]

    # Check for collisions with the paddle, walls, and bricks
    if ball.colliderect(paddle):
        ball_velocity[1] = -abs(ball_velocity[1])
    elif ball.left < 0 or ball.right > window_size[0]:
        ball_velocity[0] = -ball_velocity[0]
    elif ball.top < 0:
        ball_velocity[1] = abs(ball_velocity[1])
    elif ball.bottom > window_size[1]:
        game_over(screen, font)
        ball, ball_velocity, paddle, bricks, ball_radius = reset_game(window_size)
        score = 0
        is_reset = True

    if not is_reset:
        for brick in bricks:
            if ball.colliderect(brick):
                ball_velocity[1] = abs(ball_velocity[1])
                bricks.remove(brick)
                # Update the score (e.g. when a brick is destroyed)
                score += 1
                break

    if not bricks:
        game_over(screen, font)
        ball, ball_velocity, paddle, bricks, ball_radius = reset_game(window_size)
        score = 0

    # Redraw the screen
    screen.fill((0, 0, 0))
    pygame.draw.rect(screen, (255, 255, 255), paddle)
    pygame.draw.circle(screen, (255, 255, 255), (ball.x, ball.y), ball_radius)
    # Redraw the bricks
    for brick in bricks:
        pygame.draw.rect(screen, brick_color, brick)
    # Render the score text
    score_text = font.render(f"Score: {score}", True, (255, 255, 255))
    # Draw the score text on the screen
    screen.blit(score_text, (10, 10))
    pygame.display.flip()
    clock.tick(60)

# Quit pygame
pygame.quit()
                                
                            

And here are a couple of screenshots from the game:

arkanoid2.png

arkanoid1.png

At the end you can see the exact questions I have asked ChatGPT.

It tends to get confused sometimes, but overall if you ask it to correct itself it actually understands the hints that you are giving to it.

I had to google only a few small things like the fact you have to run `pygame.display.flip()` or manually adjust offsets in places that it did not fully understand.

It also suffers from network/performance issues (it sometimes suddenly stops responding mid-sentence), but these will most likely get fixed soon.

To summarize, I can see a future where things like games can be created with both ChatGPT and Stable Diffusion in a way like never before.

This will unblock the creativity in everyone of us and allow us to truly speak things into reality.

arkanoidgpt1.png

arkanoidgpt2.png

arkanoidgpt3.png

arkanoidgpt4.png

arkanoidgpt5.png

arkanoidgpt6.png

arkanoidgpt7.png

arkanoidgpt8.png

arkanoidgpt9.png

arkanoidgpt10.png

arkanoidgpt11.png

arkanoidgpt12.png

arkanoidgpt13.png

arkanoidgpt14.png

arkanoidgpt15.png

arkanoidgpt16.png

arkanoidgpt17.png

arkanoidgpt18.png

arkanoidgpt19.png

arkanoidgpt20.png

arkanoidgpt21.png

arkanoidgpt22.png

arkanoidgpt23.png

arkanoidgpt24.png

arkanoidgpt25.png

arkanoidgpt26.png

arkanoidgpt27.png

arkanoidgpt28.png

arkanoidgpt29.png

arkanoidgpt30.png

arkanoidgpt31.png

arkanoidgpt32.png