Multithreading With Pygame, Program Crashing
Solution 1:
Threading causes many problems and a general rule of thumb is to avoid them if they aren't necessary. They make your program non-deterministic, harder to debug, harder to test, harder to maintain and slower (most of the time). In your program, there are no reasons to use threads. Instead, you should do things sequentially. Pygame will implicitly create threads whenever necessary (for example when dealing with pygame.mixer
)
Why it doesn't work, is because pygame expects all event handling to happen in the thread that set the video mode (pygame is using SDL2, hence that link). You cannot handle them in another thread, and as you don't handle them (correctly), the operating system will think your program has crashed.
I made an example to show one way you could do the animation. The concept is that you tell pygame that after a certain amount of time, you want an event to be posted. When that event appears in your event loop, you do something.
In your case, you tell pygame to post DRAW_TEXT_EVENT
after 500 ms. When this event appears in your event loop, you first tell pygame to don't post DRAW_TEXT_EVENT
anymore, but to post CLEAR_TEXT_EVENT
after 1000ms. Then you draw the text.
After 1000ms, the CLEAR_TEXT_EVENT
will appear in your event loop. Now you do basically the same thing, but disable CLEAR_TEXT_EVENT
and tell pygame to post DRAW_TEXT_EVENT
after 500ms.
I haven't changed much in your code. I added 2 definitions for the events at the top. I've removed your functions loop
and animateTitle
, and put them into the game loop. Lastly, I've added the game loop in the main
function.
import pygame
from pygame.localsimport *
# Events that we're going to post.
DRAW_TEXT_EVENT = pygame.USEREVENT + 1
CLEAR_TEXT_EVENT = pygame.USEREVENT + 2defencadre(screen):
pygame.draw.line(screen, (250, 250, 250), (230, 140), (520, 140), 3)
pygame.draw.line(screen, (250, 250, 250), (230, 190), (520, 190), 3)
pygame.draw.line(screen, (250, 250, 250), (230, 140), (230, 190), 3)
pygame.draw.line(screen, (250, 250, 250), (520, 140), (520, 190), 3)
definitRoad(screen):
pygame.draw.line(screen, (250, 250, 250), (30, 0), (30, 500))
pygame.draw.line(screen, (250, 250, 250), (100, 0), (100, 500))
pygame.draw.line(screen, (250, 250, 250), (650, 0), (650, 500))
pygame.draw.line(screen, (250, 250, 250), (720, 0), (720, 500))
drawLines(screen)
defdrawLines(screen):
i = 0while i <= 49:
pygame.draw.line(screen, (250, 250, 250), (65, i * 10), (65, (i + 1) * 10))
pygame.draw.line(screen, (250, 250, 250), (685, i * 10), (685, (i + 1) * 10))
i = i + 3definitText(screen, text1):
text1pos = text1.get_rect()
text1pos.x = 235
text1pos.y = 150
screen.blit(text1, text1pos)
font1 = pygame.font.Font(None, 30)
text1 = font1.render("PLAY", 1, (10, 10, 10))
text1pos = text1.get_rect()
text1pos.x = 210
text1pos.y = 310
screen.blit(text1, text1pos)
font1 = pygame.font.Font(None, 30)
text1 = font1.render("QUIT", 1, (10, 10, 10))
text1pos = text1.get_rect()
text1pos.x = 490
text1pos.y = 310
screen.blit(text1, text1pos)
defanimateRoad(screen): # not done
pygame.draw.line(screen, (130, 130, 130), (65, 0), (65, 500))
pygame.draw.line(screen, (130, 130, 130), (685, 0), (685, 500))
defmain():
pygame.init()
screen = pygame.display.set_mode((750, 500))
pygame.display.set_caption('Infinite circle run')
background = pygame.Surface(screen.get_size())
background = background.convert()
background.fill((130, 130, 130))
screen.blit(background, (0, 0))
encadre(screen)
initRoad(screen)
surface1 = pygame.Rect(193, 290, 85, 50)
button1 = pygame.draw.rect(screen, (0, 0, 240), surface1)
surface2 = pygame.Rect(472, 290, 85, 50)
button2 = pygame.draw.rect(screen, (240, 0, 0), surface2)
font1 = pygame.font.Font(None, 50)
text1 = font1.render("Infinite circle run", 1, (0, 240, 0))
initText(screen, text1)
pygame.display.flip()
pygame.time.set_timer(DRAW_TEXT_EVENT, 500)
text1pos = text1.get_rect()
# GAME LOOPwhileTrue:
for event in pygame.event.get():
if event.type == QUIT:
returnelif event.type == pygame.MOUSEBUTTONDOWN:
if surface1.topleft[0] <= pygame.mouse.get_pos()[0] <= surface1.topright[0]:
if surface1.topleft[1] <= pygame.mouse.get_pos()[1] <= surface1.bottomleft[1]:
print('play')
elif surface2.topleft[0] <= pygame.mouse.get_pos()[0] <= surface2.topright[0]:
if surface2.topleft[1] <= pygame.mouse.get_pos()[1] <= surface2.bottomleft[1]:
returnelif event.type == DRAW_TEXT_EVENT:
pygame.draw.rect(screen, (130, 130, 130), (235, 150, 283, 35))
pygame.time.set_timer(DRAW_TEXT_EVENT, 0) # Disable the event.
pygame.time.set_timer(CLEAR_TEXT_EVENT, 1000) # Post event after 1000ms.elif event.type == CLEAR_TEXT_EVENT:
text1pos.x = 235
text1pos.y = 150
screen.blit(text1, text1pos)
pygame.time.set_timer(CLEAR_TEXT_EVENT, 0) # Disable the event.
pygame.time.set_timer(DRAW_TEXT_EVENT, 500) # Post event after 500ms.# Only call once each frame!
pygame.display.flip()
if __name__ == '__main__':
main()
Post a Comment for "Multithreading With Pygame, Program Crashing"