0
votes

I'm trying to build a game in Pygame where if a player moves onto a red square, the player loses. When this happens, I want to display a picture of an explosion where the player lost until the user presses any key on the keyboard. When the user presses a key, I'll call the function new_game() to start a new game. The issue is that my code seems to skip over the line where I blit the explosion, and instead just starts a new game right away.

I've tried using something like this, but I'm not sure what to put in the while loop (I want it to wait until there is a keypress):

while event != KEYDOWN:
   # Not sure what to put here

If I put time.sleep() in the while loop, the whole program seems to freeze and no image is blitted.

Here's me loading the image into Pygame:

explosionpic = pygame.image.load('C:/Users/rohan/Desktop/explosion.png')

And here's where I call it/determine if a player has lost (program seems to skip over the screen.blit line because I don't even see the image at all):

if get_color(p1.x + p1_velocity_x, p1.y + p1_velocity_y) == red:  # If player lands on a red box
    screen.blit(explosionpic, (p1.x, p1.y))
    # Bunch of other code goes here, like changing the score, etc.
    new_game()

It's supposed to display the image, then when the user presses a key, call the new_game() function.

I'd appreciate any help.

2
in "bunch of other code" you should have a call to pygame.display.update() and some way to delay the call to new_game() until the key is pressed. Do you have it? If so, please add it to the question - Valentino

2 Answers

2
votes

The simplest solution which comes to my mind is to write a small independent function which delay the execution of the code. Something like:

def wait_for_key_press():
    wait = True
    while wait:
        for event in pygame.event.get():
            if event.type == KEYDOWN:
                wait = False
                break

This function will halt the execution until a KEYDOWN signal is catch by the event system.

So your code would be:

if get_color(p1.x + p1_velocity_x, p1.y + p1_velocity_y) == red:  # If player lands on a red box
    screen.blit(explosionpic, (p1.x, p1.y))
    pygame.display.update() #needed to show the effect of the blit
    # Bunch of other code goes here, like changing the score, etc.
    wait_for_key_press()
    new_game()
1
votes

Add a state to the game, which indicates if the game is running, the explsoion happens or a ne game has to be started. Define the states RUN, EXPLODE and NEWGAME. Initialize the state game_state:

RUN = 1
EXPLODE = 2
NEWGAME = 3

game_state = RUN

If the explosion happens, the set the state EXPLODE

if get_color(p1.x + p1_velocity_x, p1.y + p1_velocity_y) == red:  # If player lands on a red box
    game_state = EXPLODE

When a key is pressed then switch to the state NEWGAME:

if game_state == EXPLODE and event.type == pygame.KEYDOWN:
    game_state = NEWGAME

When newgame() was executed, then set game_state = RUN:

newgame()
game_state = RUN

Implement a separated case in the main loop for each state of the game. With this solution not any "sleep" is needed:

e.g.

ENDGAME = 0
RUN = 1
EXPLODE = 2
NEWGAME = 3

game_state = RUN
while game_state != ENDGAME:

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            game_state = ENDGAME

        if game_state == EXPLODE and event.type == pygame.KEYDOWN:
            game_state = NEWGAME


    if game_state == RUN:
        # [...]

        if get_color(p1.x + p1_velocity_x, p1.y + p1_velocity_y) == red:  # If player lands on a red box
            game_state = EXPLODE

        # [...]

    elif game_state == EXPLODE:
        screen.blit(explosionpic, (p1.x, p1.y))

    elif game_state == NEWGAME:
        newgame()
        game_state = RUN

    pygame.display.flip()