How do I blit text from an if statement in pygame?

Viewed 377

I have been working on this dice game for my first project and I got everything up and running I just can't figure out how to display (blit) the results on the window. Everything should be formatted correctly but I get an error that says argument 1 must be pygame.Surface, not pygame.Rect. How can I display who won correctly?

Here is my code for reference...

import pygame
import random
import os
import os.path

WIDTH = 750
HEIGHT = 750
FPS = 60
QUARTER_WIDTH = WIDTH // 4
MIDDLE_HEIGHT = HEIGHT // 2
white = (255, 255, 255)

pygame.init()
pygame.font.init()
window = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Dice Game")

# Fonts and Text
title_font = pygame.font.SysFont("comicsans", 70)
title_label = title_font.render("Would You like to roll? Y/N", 1, (255, 255, 255))
result_font = pygame.font.Font("freesansbold.ttf", 32)

# Load images
dice1 = pygame.image.load(os.path.join("assets", "dice_1.png"))
dice2 = pygame.image.load(os.path.join("assets", "dice_2.png"))
dice3 = pygame.image.load(os.path.join("assets", "dice_3.png"))
dice4 = pygame.image.load(os.path.join("assets", "dice_4.png"))
dice5 = pygame.image.load(os.path.join("assets", "dice_5.png"))
dice6 = pygame.image.load(os.path.join("assets", "dice_6.png"))

# Indexed list to reference all the faces
all_dice = [None, dice1, dice2, dice3, dice4, dice5, dice6]
pygame.display.set_icon(dice6)

# Game Background
background = pygame.transform.scale(pygame.image.load(os.path.join("assets", "dice_board.png")), (WIDTH, HEIGHT))


### Function to perform the random parts of the game
def rollDice():
    """ Generate the two random numbers, one for the Player and Opponent """
    player_roll = random.randint(1, 6)
    opponent_roll = random.randint(1, 6)

    return player_roll, opponent_roll


### Main Loop
clock = pygame.time.Clock()
running = True
player_face = None  # No dice before first roll
player_roll = 0
opponent_face = None  # No dice before first roll
player_roll = 0
result = None
textRect1 = None

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_y:
                player_roll, opponent_roll = rollDice()
                player_face = all_dice[player_roll]
                opponent_face = all_dice[opponent_roll]

                # Debug prints

                text1 = result_font.render(f'opponent won. They rolled a {opponent_roll}', 1, white)
                text2 = result_font.render(f'You win! They rolled a {opponent_roll}', 1, white)
                text3 = result_font.render('Tied!', 1, white)
                textRect1 = text1.get_rect()

                if opponent_roll > player_roll:
                    result = window.blit(text1, (WIDTH, MIDDLE_HEIGHT))
                    print(f"opponent won. They rolled a {opponent_roll}")
                elif opponent_roll < player_roll:
                    result = window.blit(text2, (WIDTH, MIDDLE_HEIGHT))
                    print(f"You win! They rolled a {opponent_roll}")
                elif opponent_roll == player_roll:
                    result = window.blit(text3, (WIDTH, MIDDLE_HEIGHT))
                    print("tied!")

    # Repaint the screen

    window.blit(background, (0, 0))
    window.blit(title_label, (WIDTH // 2 - title_label.get_width() // 2, 250))
    # Where I'm trying to blit the result text
    if (result != None) and (textRect1 != None):
        window.blit(result, textRect1)
    # Paint the dice faces
    if (player_face != None):
        window.blit(player_face, (QUARTER_WIDTH, MIDDLE_HEIGHT))
    if (opponent_face != None):
        window.blit(opponent_face, (3 * QUARTER_WIDTH, MIDDLE_HEIGHT))

    # flush display changes
    pygame.display.flip()

    # Constrain FPS
    clock.tick(FPS)

pygame.quit()
3 Answers

What you actually do is to blit the result text once in the event loop. pygame.Surface.blit returns a pygame.Rect object, with the affected area. This rectangle is assigned to result. The issue is caused, because you try to blit result.

You have to assign the rendered text (pygame.Surface) to the variable result.
Furthermore, if the position of the text is (WIDTH, MIDDLE_HEIGHT) then the text will be blit out of the window. Likely you want to use the position (QUARTER_WIDTH, MIDDLE_HEIGHT):

while running:
    # [...]

    for event in pygame.event.get():
        # [...]

        elif event.type == pygame.KEYDOWN:
            if event.key == pygame.K_y:
                # [...]

                textRect1 = text1.get_rect(topleft = (QUARTER_WIDTH, MIDDLE_HEIGHT))
                
                if opponent_roll > player_roll:
                    result = text1
                    print(f"opponent won. They rolled a {opponent_roll}")
                
                elif opponent_roll < player_roll:
                    result = text2
                    print(f"You win! They rolled a {opponent_roll}")
                
                elif opponent_roll == player_roll:
                    result = text3
                    print("tied!") 

You can do that using the blit function from pygames. By creating the variable text, you can also choose the font of the text.

len_of_snake = 5
font = pygame.font.Font('Roboto-Italic.ttf', 32)
text = font.render(f'AI: {len_of_snake}', True, (0, 0, 0))
window.blit(text, [0, 0])

Here's my take even though the other answers were good.

When I changed

# Where I'm trying to blit the result text
if (result != None):
    window.blit(result, (QUARTER_WIDTH, MIDDLE_HEIGHT))

and

 if opponent_roll > player_roll:
                result =  result_font.render(f'opponent won. They rolled a {opponent_roll}', 1, white)
                print(f"opponent won. They rolled a {opponent_roll}")
            elif opponent_roll < player_roll:
                result = result_font.render(f'You win! They rolled a {opponent_roll}', 1, white)
                print(f"You win! They rolled a {opponent_roll}")
            elif opponent_roll == player_roll:
                result = result_font.render('Tied!', 1, white)
                print("tied!")

and

            if event.key == pygame.K_y:
                window.fill((0,0,0))  # Read the text under here for clarification 
                player_roll, opponent_roll = rollDice()

It worked for me after I changed it and I had to comment out all the external .png files. Normally I use a redraw window function that draws the background and then text and then images because once and object is blit to the screen it cannot be unblit and you need to redraw the entire screen.

Related