SquintyEyesMcgee
SquintyEyesMcgee

Reputation: 21

why does the while loop keep making the game crash in pygame?

the code works just fine until I add the while true: also for some reason, the sleep function makes the entire code wait. however, I want only the parts after sleep() to wait

import pygame, sys
pygame.init()
from time import sleep

screen = pygame.display.set_mode((500,400))

PINK = (255,192,203)
WHITE = (255,255,255)


screen.fill(PINK)
pygame.display.update()


font = pygame.font.SysFont("comicsansms", 72)


text = font.render("loading", True, WHITE)
textrect = text.get_rect()
textrect.center = (225,40)
screen.blit(text,textrect)


while True:
    pygame.event.get()    sleep(1)
    text = font.render(".", True, WHITE)
    textrect = text.get_rect()
    textrect.center = (350,40)
    screen.blit(text,textrect)
    sleep(0.5)
    text = font.render(".", True, WHITE)
    textrect = text.get_rect()
    textrect.center = (370,40)
    screen.blit(text,textrect)
    sleep(0.5)
    text = font.render(".", True, WHITE)
    textrect = text.get_rect()
    textrect.center = (390,40)
    screen.blit(text,textrect)
    sleep(0.5)

Upvotes: 2

Views: 274

Answers (4)

Ryan's World
Ryan's World

Reputation: 64

I would use this for your while loop:

import pygame,sys

while True:
    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            pygame.quit()
            sys.exit()

    screen.fill((red,green,blue)) # Max RGB value is 0-255
    # then the rest of your code
    # after the rest of your code add this at the end of it
    pygame.display.update()

Upvotes: 0

Teerth Sonawani
Teerth Sonawani

Reputation: 11

Mr.squinty! i think the issue is in the while loop think the issue is because you are defining variables repeatedly you should define the variables out of the loop and then blit them in the loop!

Upvotes: -1

Vedant36
Vedant36

Reputation: 328

You can see that in your program, no call is being made to the event queue. In the pygame documentation for pygame.event.pump(), it says

"If you fail to make a call to the event queue for too long, the system may decide your program has locked up."

This causes the program to seem to be unresponsive. To solve this call the function pygame.event.pump() after pygame.init() so that the events are internally handeled

import pygame, sys
pygame.init()
pygame.event.pump()
from time import sleep

screen = pygame.display.set_mode((500,400))
PINK = (255,192,203)
WHITE = (255,255,255)
screen.fill(PINK)
pygame.display.update()


font = pygame.font.SysFont("comicsansms", 72)
text = font.render("loading", True, WHITE)
textrect = text.get_rect()
textrect.center = (225,40)
screen.blit(text,textrect)


while True:
    sleep(1)
    text = font.render(".", True, WHITE)
    textrect = text.get_rect()
    textrect.center = (350,40)
    screen.blit(text,textrect)
    sleep(0.5)
    text = font.render(".", True, WHITE)
    textrect = text.get_rect()
    textrect.center = (370,40)
    screen.blit(text,textrect)
    sleep(0.5)
    text = font.render(".", True, WHITE)
    textrect = text.get_rect()
    textrect.center = (390,40)
    screen.blit(text,textrect)
    sleep(0.5)

Upvotes: 0

Kingsley
Kingsley

Reputation: 14906

[...] The sleep function makes the entire code wait

Yes! It does. The entire thread anyway. PyGame uses an "event model" to work with the user-interface. Your code above "fights" against this, but while you might see the updates on-screen, essentially the application has "locked up" (is non-responsive) as far as your operating environment it concerned. Your OS thinks this because your program is not accepting events.

A PyGame application should process the events in the event-queue (even if it does nothing except exit). So instead of implementing times with time.sleep(), it's much better to use the real-time clock provided by pygame.time.get_ticks(). This function returns the time as the number of milliseconds since your program started. Your program needs multiple things to happen at certain times. These can be created at the beginning (time=0), with a time in the future. If the clock says this time has passed, then do the things.

One way to implement this is to create a simple structure to hold your text items, and the time they need to be drawn in the future:

### Structure to hold some text to draw
### after a certain number of seconds have passed
class TimedText:
    def __init__( self, text, position, at, colour=WHITE ):
        self.text     = text
        self.position = position,
        self.at_time  = at * 1000    # convert to milliseconds
        self.colour   = colour

Create these items before your main loop starts:

### Make some timed-text structures/objects
timed_texts = []
timed_texts.append( TimedText( "loading", (225,40), 0.0 ) )
timed_texts.append( TimedText( ".",       (350,40), 0.5 ) )
timed_texts.append( TimedText( ".",       (370,40), 1.0 ) )
timed_texts.append( TimedText( ".",       (390,40), 1.5 ) )

Then in your main loop, look through each of the items, drawing the texts that need to be draw - but according to the clock.

# Loop through each timed-text structure
#     Check if enough time has elapsed, and if-so, draw the text:
for tt in timed_texts:
    if ( time_now >= tt.at_time ):   # has enough time elapsed
        text = font.render( tt.text, True, tt.colour )
        textrect = text.get_rect()
        textrect.center = tt.position
        screen.blit( text, textrect )

This allows your code to process the events, and still have timed text-animation.

Reference code:

import pygame

# Window size
WINDOW_WIDTH    = 500
WINDOW_HEIGHT   = 400
WINDOW_SURFACE  = pygame.HWSURFACE|pygame.DOUBLEBUF|pygame.RESIZABLE

PINK  = (255,192,203)
WHITE = (255,255,255)

### initialisation
pygame.init()
pygame.mixer.init()
screen = pygame.display.set_mode( ( WINDOW_WIDTH, WINDOW_HEIGHT ), WINDOW_SURFACE )
pygame.display.set_caption("Going Dotty...")


### Structure to hold some text to draw
### after a certain number of seconds have passed
class TimedText:
    def __init__( self, text, position, at, colour=WHITE ):
        self.text     = text
        self.position = position,
        self.at_time  = at * 1000    # convert to milliseconds
        self.colour   = colour


### Make some timed-text structures/objects
font = pygame.font.SysFont("comicsansms", 72)
timed_texts = []
timed_texts.append( TimedText( "loading", (225,40), 0 ) )
timed_texts.append( TimedText( ".",       (350,40), 0.5 ) )
timed_texts.append( TimedText( ".",       (370,40), 1.0 ) )
timed_texts.append( TimedText( ".",       (390,40), 1.5 ) )

### Main Loop
clock = pygame.time.Clock()
done = False
while not done:

    # Handle user-input
    for event in pygame.event.get():
        if ( event.type == pygame.QUIT ):
            done = True
        elif ( event.type == pygame.MOUSEBUTTONUP ):
            # On mouse-click
            pass
        elif ( event.type == pygame.KEYUP ):
            # On key-release
            #keys = pygame.key.get_pressed()
            pass

    # Update the window, but not more than 60fps
    screen.fill( PINK )

    time_now = pygame.time.get_ticks()

    # Loop through each timed-text structure
    #     Check if enough time has elapsed, and if-so, draw the text:
    for tt in timed_texts:
        if ( time_now >= tt.at_time ):   # has enough time elapsed
            text = font.render( tt.text, True, tt.colour )
            textrect = text.get_rect()
            textrect.center = tt.position
            screen.blit( text, textrect )

    pygame.display.flip()
    clock.tick_busy_loop(60)


pygame.quit()

Upvotes: 4

Related Questions