Threading issue with Pygame











up vote
0
down vote

favorite
1












I am developing a small game for learning purposes. I have created a simple animation for the title screen. Since there is also a function for full screen in the code, I wanted to create a title screen that:




  1. Displayed the animation

  2. Turned into full screen when the key was activated

  3. Continued the animation at the point it was before activating full screen


In order to do this, I resorted to threading. However, this is the first time I tried to do any multi-threading, and I don´t know what did I do wrong. The result is an undetermined error.



The code for the title screen is this:



try:
GameAnimation = threading.Thread(target=GameTitleAnimation, (Window, WindowDimensions, FontDictionary, CurrentVersion))
GameAnimation.start()
except:
print "There was an error while loading the screen. Press one key to exit the program."
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
Quit()
if event.type == pygame.KEYDOWN:
if event.key == K_ESCAPE:
Quit()
elif event.key == K_f:
Fullscreen(Window, WindowDimensions)
else:
return


The code for the animation is:



TitleWhite = [255, 255, 255, 0]
Black = BASE_BLACK
TitleLetters = ("R", "O", "G", "U", "E", " ", "H", "U", "N", "T", "E", "R")
Title = FontDictionary["TitleFont"][1].render("ROGUE HUNTER", False, TitleWhite)
TextWidth = Title.get_width()
TextHeight = Title.get_height()
TitleXPosition = (WindowDimensions[0] - TextWidth) / 2
TitleYPosition = (WindowDimensions[1] / 2) - (TextHeight / 2)
for letter in TitleLetters:
if letter == " ":
TitleXPosition += CurrentLetterWidth
else:
while TitleWhite[3] < 100:
TitleWhite[3] += 1
CurrentLetter = FontDictionary["TitleFont"][1].render(letter, False, TitleWhite)
CurrentLetter.set_alpha(TitleWhite[3])
Window.blit(CurrentLetter, (TitleXPosition, TitleYPosition))
time.sleep(0.008)
try:
pygame.display.update()
except Exception:
traceback.print_exception
TitleWhite[3] = 0
CurrentLetterWidth = CurrentLetter.get_width()
TitleXPosition += CurrentLetterWidth
FadeInSurface = pygame.Surface((WindowDimensions[0], WindowDimensions[1]))
FadeInSurface.fill(TitleWhite)
OpacityRounds = 1
while TitleWhite[3] < 100.0:
TitleWhite[3] = 1.1 ** OpacityRounds
FadeInSurface.set_alpha(TitleWhite[3])
Window.blit(FadeInSurface, (0, 0))
OpacityRounds += 1
pygame.display.update()
time.sleep (0.015)
time.sleep(0.7)
TitleXPosition = (WindowDimensions[0] - TextWidth) / 2
Version = FontDictionary["BodyFont"][1].render(CURRENT_VERSION, False, TitleWhite)
VersionHeight = Version.get_height()
VersionWidth = Version.get_width()
VersionXPosition = (WindowDimensions[0] - VersionWidth) / 2
VersionYPosition = TitleYPosition + TextHeight
while True:
pygame.draw.rect(Window, Black, (0, 0, WindowDimensions[0], WindowDimensions[1]), 0)
Window.blit(Title, (TitleXPosition, TitleYPosition))
Window.blit(Version, (VersionXPosition, VersionYPosition))
pygame.display.update()


I'd be very grateful if anyone could help me with this. I am going crazy.










share|improve this question
























  • General comment: Your code would be much easier for everyone to read and understand if you would read and start following the guideline in the PEP 8 - Style Guide for Python Code.
    – martineau
    Nov 8 at 16:23












  • What does "The result is an undetermined error" mean—something (or perhaps nothing) happens, right? What exactly occurs when you try to run your code?
    – martineau
    Nov 8 at 16:31










  • Please don't post only code snippets, provide a minimal, complete (runnable) and verifiable example instead that we can copy, paste and test without modifications. -- Also, you usually don't have to use multithreading in pygame. If you explain your goals and problems more thoroughly, we can probably provide alternative solutions.
    – skrx
    Nov 8 at 17:33















up vote
0
down vote

favorite
1












I am developing a small game for learning purposes. I have created a simple animation for the title screen. Since there is also a function for full screen in the code, I wanted to create a title screen that:




  1. Displayed the animation

  2. Turned into full screen when the key was activated

  3. Continued the animation at the point it was before activating full screen


In order to do this, I resorted to threading. However, this is the first time I tried to do any multi-threading, and I don´t know what did I do wrong. The result is an undetermined error.



The code for the title screen is this:



try:
GameAnimation = threading.Thread(target=GameTitleAnimation, (Window, WindowDimensions, FontDictionary, CurrentVersion))
GameAnimation.start()
except:
print "There was an error while loading the screen. Press one key to exit the program."
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
Quit()
if event.type == pygame.KEYDOWN:
if event.key == K_ESCAPE:
Quit()
elif event.key == K_f:
Fullscreen(Window, WindowDimensions)
else:
return


The code for the animation is:



TitleWhite = [255, 255, 255, 0]
Black = BASE_BLACK
TitleLetters = ("R", "O", "G", "U", "E", " ", "H", "U", "N", "T", "E", "R")
Title = FontDictionary["TitleFont"][1].render("ROGUE HUNTER", False, TitleWhite)
TextWidth = Title.get_width()
TextHeight = Title.get_height()
TitleXPosition = (WindowDimensions[0] - TextWidth) / 2
TitleYPosition = (WindowDimensions[1] / 2) - (TextHeight / 2)
for letter in TitleLetters:
if letter == " ":
TitleXPosition += CurrentLetterWidth
else:
while TitleWhite[3] < 100:
TitleWhite[3] += 1
CurrentLetter = FontDictionary["TitleFont"][1].render(letter, False, TitleWhite)
CurrentLetter.set_alpha(TitleWhite[3])
Window.blit(CurrentLetter, (TitleXPosition, TitleYPosition))
time.sleep(0.008)
try:
pygame.display.update()
except Exception:
traceback.print_exception
TitleWhite[3] = 0
CurrentLetterWidth = CurrentLetter.get_width()
TitleXPosition += CurrentLetterWidth
FadeInSurface = pygame.Surface((WindowDimensions[0], WindowDimensions[1]))
FadeInSurface.fill(TitleWhite)
OpacityRounds = 1
while TitleWhite[3] < 100.0:
TitleWhite[3] = 1.1 ** OpacityRounds
FadeInSurface.set_alpha(TitleWhite[3])
Window.blit(FadeInSurface, (0, 0))
OpacityRounds += 1
pygame.display.update()
time.sleep (0.015)
time.sleep(0.7)
TitleXPosition = (WindowDimensions[0] - TextWidth) / 2
Version = FontDictionary["BodyFont"][1].render(CURRENT_VERSION, False, TitleWhite)
VersionHeight = Version.get_height()
VersionWidth = Version.get_width()
VersionXPosition = (WindowDimensions[0] - VersionWidth) / 2
VersionYPosition = TitleYPosition + TextHeight
while True:
pygame.draw.rect(Window, Black, (0, 0, WindowDimensions[0], WindowDimensions[1]), 0)
Window.blit(Title, (TitleXPosition, TitleYPosition))
Window.blit(Version, (VersionXPosition, VersionYPosition))
pygame.display.update()


I'd be very grateful if anyone could help me with this. I am going crazy.










share|improve this question
























  • General comment: Your code would be much easier for everyone to read and understand if you would read and start following the guideline in the PEP 8 - Style Guide for Python Code.
    – martineau
    Nov 8 at 16:23












  • What does "The result is an undetermined error" mean—something (or perhaps nothing) happens, right? What exactly occurs when you try to run your code?
    – martineau
    Nov 8 at 16:31










  • Please don't post only code snippets, provide a minimal, complete (runnable) and verifiable example instead that we can copy, paste and test without modifications. -- Also, you usually don't have to use multithreading in pygame. If you explain your goals and problems more thoroughly, we can probably provide alternative solutions.
    – skrx
    Nov 8 at 17:33













up vote
0
down vote

favorite
1









up vote
0
down vote

favorite
1






1





I am developing a small game for learning purposes. I have created a simple animation for the title screen. Since there is also a function for full screen in the code, I wanted to create a title screen that:




  1. Displayed the animation

  2. Turned into full screen when the key was activated

  3. Continued the animation at the point it was before activating full screen


In order to do this, I resorted to threading. However, this is the first time I tried to do any multi-threading, and I don´t know what did I do wrong. The result is an undetermined error.



The code for the title screen is this:



try:
GameAnimation = threading.Thread(target=GameTitleAnimation, (Window, WindowDimensions, FontDictionary, CurrentVersion))
GameAnimation.start()
except:
print "There was an error while loading the screen. Press one key to exit the program."
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
Quit()
if event.type == pygame.KEYDOWN:
if event.key == K_ESCAPE:
Quit()
elif event.key == K_f:
Fullscreen(Window, WindowDimensions)
else:
return


The code for the animation is:



TitleWhite = [255, 255, 255, 0]
Black = BASE_BLACK
TitleLetters = ("R", "O", "G", "U", "E", " ", "H", "U", "N", "T", "E", "R")
Title = FontDictionary["TitleFont"][1].render("ROGUE HUNTER", False, TitleWhite)
TextWidth = Title.get_width()
TextHeight = Title.get_height()
TitleXPosition = (WindowDimensions[0] - TextWidth) / 2
TitleYPosition = (WindowDimensions[1] / 2) - (TextHeight / 2)
for letter in TitleLetters:
if letter == " ":
TitleXPosition += CurrentLetterWidth
else:
while TitleWhite[3] < 100:
TitleWhite[3] += 1
CurrentLetter = FontDictionary["TitleFont"][1].render(letter, False, TitleWhite)
CurrentLetter.set_alpha(TitleWhite[3])
Window.blit(CurrentLetter, (TitleXPosition, TitleYPosition))
time.sleep(0.008)
try:
pygame.display.update()
except Exception:
traceback.print_exception
TitleWhite[3] = 0
CurrentLetterWidth = CurrentLetter.get_width()
TitleXPosition += CurrentLetterWidth
FadeInSurface = pygame.Surface((WindowDimensions[0], WindowDimensions[1]))
FadeInSurface.fill(TitleWhite)
OpacityRounds = 1
while TitleWhite[3] < 100.0:
TitleWhite[3] = 1.1 ** OpacityRounds
FadeInSurface.set_alpha(TitleWhite[3])
Window.blit(FadeInSurface, (0, 0))
OpacityRounds += 1
pygame.display.update()
time.sleep (0.015)
time.sleep(0.7)
TitleXPosition = (WindowDimensions[0] - TextWidth) / 2
Version = FontDictionary["BodyFont"][1].render(CURRENT_VERSION, False, TitleWhite)
VersionHeight = Version.get_height()
VersionWidth = Version.get_width()
VersionXPosition = (WindowDimensions[0] - VersionWidth) / 2
VersionYPosition = TitleYPosition + TextHeight
while True:
pygame.draw.rect(Window, Black, (0, 0, WindowDimensions[0], WindowDimensions[1]), 0)
Window.blit(Title, (TitleXPosition, TitleYPosition))
Window.blit(Version, (VersionXPosition, VersionYPosition))
pygame.display.update()


I'd be very grateful if anyone could help me with this. I am going crazy.










share|improve this question















I am developing a small game for learning purposes. I have created a simple animation for the title screen. Since there is also a function for full screen in the code, I wanted to create a title screen that:




  1. Displayed the animation

  2. Turned into full screen when the key was activated

  3. Continued the animation at the point it was before activating full screen


In order to do this, I resorted to threading. However, this is the first time I tried to do any multi-threading, and I don´t know what did I do wrong. The result is an undetermined error.



The code for the title screen is this:



try:
GameAnimation = threading.Thread(target=GameTitleAnimation, (Window, WindowDimensions, FontDictionary, CurrentVersion))
GameAnimation.start()
except:
print "There was an error while loading the screen. Press one key to exit the program."
while True:
for event in pygame.event.get():
if event.type == pygame.QUIT:
Quit()
if event.type == pygame.KEYDOWN:
if event.key == K_ESCAPE:
Quit()
elif event.key == K_f:
Fullscreen(Window, WindowDimensions)
else:
return


The code for the animation is:



TitleWhite = [255, 255, 255, 0]
Black = BASE_BLACK
TitleLetters = ("R", "O", "G", "U", "E", " ", "H", "U", "N", "T", "E", "R")
Title = FontDictionary["TitleFont"][1].render("ROGUE HUNTER", False, TitleWhite)
TextWidth = Title.get_width()
TextHeight = Title.get_height()
TitleXPosition = (WindowDimensions[0] - TextWidth) / 2
TitleYPosition = (WindowDimensions[1] / 2) - (TextHeight / 2)
for letter in TitleLetters:
if letter == " ":
TitleXPosition += CurrentLetterWidth
else:
while TitleWhite[3] < 100:
TitleWhite[3] += 1
CurrentLetter = FontDictionary["TitleFont"][1].render(letter, False, TitleWhite)
CurrentLetter.set_alpha(TitleWhite[3])
Window.blit(CurrentLetter, (TitleXPosition, TitleYPosition))
time.sleep(0.008)
try:
pygame.display.update()
except Exception:
traceback.print_exception
TitleWhite[3] = 0
CurrentLetterWidth = CurrentLetter.get_width()
TitleXPosition += CurrentLetterWidth
FadeInSurface = pygame.Surface((WindowDimensions[0], WindowDimensions[1]))
FadeInSurface.fill(TitleWhite)
OpacityRounds = 1
while TitleWhite[3] < 100.0:
TitleWhite[3] = 1.1 ** OpacityRounds
FadeInSurface.set_alpha(TitleWhite[3])
Window.blit(FadeInSurface, (0, 0))
OpacityRounds += 1
pygame.display.update()
time.sleep (0.015)
time.sleep(0.7)
TitleXPosition = (WindowDimensions[0] - TextWidth) / 2
Version = FontDictionary["BodyFont"][1].render(CURRENT_VERSION, False, TitleWhite)
VersionHeight = Version.get_height()
VersionWidth = Version.get_width()
VersionXPosition = (WindowDimensions[0] - VersionWidth) / 2
VersionYPosition = TitleYPosition + TextHeight
while True:
pygame.draw.rect(Window, Black, (0, 0, WindowDimensions[0], WindowDimensions[1]), 0)
Window.blit(Title, (TitleXPosition, TitleYPosition))
Window.blit(Version, (VersionXPosition, VersionYPosition))
pygame.display.update()


I'd be very grateful if anyone could help me with this. I am going crazy.







python multithreading pygame python-2.x






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited Nov 8 at 16:19









martineau

65.2k987176




65.2k987176










asked Nov 8 at 16:15









A. Jarreta

32




32












  • General comment: Your code would be much easier for everyone to read and understand if you would read and start following the guideline in the PEP 8 - Style Guide for Python Code.
    – martineau
    Nov 8 at 16:23












  • What does "The result is an undetermined error" mean—something (or perhaps nothing) happens, right? What exactly occurs when you try to run your code?
    – martineau
    Nov 8 at 16:31










  • Please don't post only code snippets, provide a minimal, complete (runnable) and verifiable example instead that we can copy, paste and test without modifications. -- Also, you usually don't have to use multithreading in pygame. If you explain your goals and problems more thoroughly, we can probably provide alternative solutions.
    – skrx
    Nov 8 at 17:33


















  • General comment: Your code would be much easier for everyone to read and understand if you would read and start following the guideline in the PEP 8 - Style Guide for Python Code.
    – martineau
    Nov 8 at 16:23












  • What does "The result is an undetermined error" mean—something (or perhaps nothing) happens, right? What exactly occurs when you try to run your code?
    – martineau
    Nov 8 at 16:31










  • Please don't post only code snippets, provide a minimal, complete (runnable) and verifiable example instead that we can copy, paste and test without modifications. -- Also, you usually don't have to use multithreading in pygame. If you explain your goals and problems more thoroughly, we can probably provide alternative solutions.
    – skrx
    Nov 8 at 17:33
















General comment: Your code would be much easier for everyone to read and understand if you would read and start following the guideline in the PEP 8 - Style Guide for Python Code.
– martineau
Nov 8 at 16:23






General comment: Your code would be much easier for everyone to read and understand if you would read and start following the guideline in the PEP 8 - Style Guide for Python Code.
– martineau
Nov 8 at 16:23














What does "The result is an undetermined error" mean—something (or perhaps nothing) happens, right? What exactly occurs when you try to run your code?
– martineau
Nov 8 at 16:31




What does "The result is an undetermined error" mean—something (or perhaps nothing) happens, right? What exactly occurs when you try to run your code?
– martineau
Nov 8 at 16:31












Please don't post only code snippets, provide a minimal, complete (runnable) and verifiable example instead that we can copy, paste and test without modifications. -- Also, you usually don't have to use multithreading in pygame. If you explain your goals and problems more thoroughly, we can probably provide alternative solutions.
– skrx
Nov 8 at 17:33




Please don't post only code snippets, provide a minimal, complete (runnable) and verifiable example instead that we can copy, paste and test without modifications. -- Also, you usually don't have to use multithreading in pygame. If you explain your goals and problems more thoroughly, we can probably provide alternative solutions.
– skrx
Nov 8 at 17:33












2 Answers
2






active

oldest

votes

















up vote
1
down vote













There's no reason to use threading in your code. It will only make your code harder to read, harder to debug and error prone.



Usually you want to have some kind of state in your game that you use to determinate what should happen in a frame. You can find a class based example here.



Another way to handle this, which is a bit similar to your code, is to use coroutines.



Look at your animation code and instead of calling pygame.display.update(), give the control back to the main loop. The main loop will handle events, frame limiting and drawing, then give control back to the coroutine (which keeps track of it's own state).



Here's a simple hacky example:



import pygame
import pygame.freetype

pygame.init()
size = (640, 480)
screen = pygame.display.set_mode(size)
clock = pygame.time.Clock()

def game_state(surf):
rect = pygame.Rect(200, 200, 32, 32)
while True:
events = yield
pressed = pygame.key.get_pressed()
x = 1 if pressed[pygame.K_RIGHT] else -1 if pressed[pygame.K_LEFT] else 0
rect.move_ip(x*5, 0)
pygame.draw.rect(surf, pygame.Color('dodgerblue'), rect)
yield

def title_state(surf):
text = 'Awesome Game'
colors = [[255, 255, 255, 20] for letter in text]
font = pygame.freetype.SysFont(None, 22)
font.origin = True
while True:
for color in colors:
color[3] += 33
if color[3] > 255: color[3] = 0
x = 200
for (letter, c) in zip(text, colors):
bounds = font.get_rect(letter)
font.render_to(surf, (x, 100), letter, c)
x += bounds.width + 1

font.render_to(surf, (180, 150), 'press [space] to start', pygame.Color('grey'))
events = yield
yield

def main():
title = title_state(screen)
game = game_state(screen)
state = title

while True:
events = pygame.event.get()
for e in events:
if e.type == pygame.QUIT:
return
if e.type == pygame.KEYDOWN:
if e.key == pygame.K_ESCAPE:
return
if e.key == pygame.K_SPACE:
state = game if state == title else title
if e.key == pygame.K_f:
if screen.get_flags() & pygame.FULLSCREEN:
pygame.display.set_mode(size)
else:
pygame.display.set_mode(size, pygame.FULLSCREEN)

screen.fill(pygame.Color('grey12'))
next(state)
state.send(events)
pygame.display.update()
clock.tick(60)

if __name__ == '__main__':
main()


See how the main loop is clean and simple, and all of the game state is handled in the coroutines. The title screen part of the code does not care about fullscreen or not or how to switch to fullscreen, and the main loop does not care of what the title screen coroutine does. And we don't need threading.



enter image description here



In practice it's not that different from the class based example I linked above, but using coroutines makes it easy to implement the title screen animation.



Basically you have an endless loop, you mutate some state (like the color of a letter), and then say "now draw this!" by just calling yield.






share|improve this answer




























    up vote
    0
    down vote













    This is a large chunk of code to debug.



    I'm not familiar with pygame or python threading, but it seems to me that you need to include some debug lines to determine exactly where the error occurs during your game animation thread (if it's even occuring there at all).



    Something like this pattern should help determine the source of the problem:



    import logging

    logging.info("start animation initialization")
    ...
    logging.info("begin animation loop")
    ...
    logging.info("end animation loop")


    https://docs.python.org/2/howto/logging.html






    share|improve this answer





















      Your Answer






      StackExchange.ifUsing("editor", function () {
      StackExchange.using("externalEditor", function () {
      StackExchange.using("snippets", function () {
      StackExchange.snippets.init();
      });
      });
      }, "code-snippets");

      StackExchange.ready(function() {
      var channelOptions = {
      tags: "".split(" "),
      id: "1"
      };
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function() {
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled) {
      StackExchange.using("snippets", function() {
      createEditor();
      });
      }
      else {
      createEditor();
      }
      });

      function createEditor() {
      StackExchange.prepareEditor({
      heartbeatType: 'answer',
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader: {
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      },
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      });


      }
      });














      draft saved

      draft discarded


















      StackExchange.ready(
      function () {
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53211801%2fthreading-issue-with-pygame%23new-answer', 'question_page');
      }
      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      1
      down vote













      There's no reason to use threading in your code. It will only make your code harder to read, harder to debug and error prone.



      Usually you want to have some kind of state in your game that you use to determinate what should happen in a frame. You can find a class based example here.



      Another way to handle this, which is a bit similar to your code, is to use coroutines.



      Look at your animation code and instead of calling pygame.display.update(), give the control back to the main loop. The main loop will handle events, frame limiting and drawing, then give control back to the coroutine (which keeps track of it's own state).



      Here's a simple hacky example:



      import pygame
      import pygame.freetype

      pygame.init()
      size = (640, 480)
      screen = pygame.display.set_mode(size)
      clock = pygame.time.Clock()

      def game_state(surf):
      rect = pygame.Rect(200, 200, 32, 32)
      while True:
      events = yield
      pressed = pygame.key.get_pressed()
      x = 1 if pressed[pygame.K_RIGHT] else -1 if pressed[pygame.K_LEFT] else 0
      rect.move_ip(x*5, 0)
      pygame.draw.rect(surf, pygame.Color('dodgerblue'), rect)
      yield

      def title_state(surf):
      text = 'Awesome Game'
      colors = [[255, 255, 255, 20] for letter in text]
      font = pygame.freetype.SysFont(None, 22)
      font.origin = True
      while True:
      for color in colors:
      color[3] += 33
      if color[3] > 255: color[3] = 0
      x = 200
      for (letter, c) in zip(text, colors):
      bounds = font.get_rect(letter)
      font.render_to(surf, (x, 100), letter, c)
      x += bounds.width + 1

      font.render_to(surf, (180, 150), 'press [space] to start', pygame.Color('grey'))
      events = yield
      yield

      def main():
      title = title_state(screen)
      game = game_state(screen)
      state = title

      while True:
      events = pygame.event.get()
      for e in events:
      if e.type == pygame.QUIT:
      return
      if e.type == pygame.KEYDOWN:
      if e.key == pygame.K_ESCAPE:
      return
      if e.key == pygame.K_SPACE:
      state = game if state == title else title
      if e.key == pygame.K_f:
      if screen.get_flags() & pygame.FULLSCREEN:
      pygame.display.set_mode(size)
      else:
      pygame.display.set_mode(size, pygame.FULLSCREEN)

      screen.fill(pygame.Color('grey12'))
      next(state)
      state.send(events)
      pygame.display.update()
      clock.tick(60)

      if __name__ == '__main__':
      main()


      See how the main loop is clean and simple, and all of the game state is handled in the coroutines. The title screen part of the code does not care about fullscreen or not or how to switch to fullscreen, and the main loop does not care of what the title screen coroutine does. And we don't need threading.



      enter image description here



      In practice it's not that different from the class based example I linked above, but using coroutines makes it easy to implement the title screen animation.



      Basically you have an endless loop, you mutate some state (like the color of a letter), and then say "now draw this!" by just calling yield.






      share|improve this answer

























        up vote
        1
        down vote













        There's no reason to use threading in your code. It will only make your code harder to read, harder to debug and error prone.



        Usually you want to have some kind of state in your game that you use to determinate what should happen in a frame. You can find a class based example here.



        Another way to handle this, which is a bit similar to your code, is to use coroutines.



        Look at your animation code and instead of calling pygame.display.update(), give the control back to the main loop. The main loop will handle events, frame limiting and drawing, then give control back to the coroutine (which keeps track of it's own state).



        Here's a simple hacky example:



        import pygame
        import pygame.freetype

        pygame.init()
        size = (640, 480)
        screen = pygame.display.set_mode(size)
        clock = pygame.time.Clock()

        def game_state(surf):
        rect = pygame.Rect(200, 200, 32, 32)
        while True:
        events = yield
        pressed = pygame.key.get_pressed()
        x = 1 if pressed[pygame.K_RIGHT] else -1 if pressed[pygame.K_LEFT] else 0
        rect.move_ip(x*5, 0)
        pygame.draw.rect(surf, pygame.Color('dodgerblue'), rect)
        yield

        def title_state(surf):
        text = 'Awesome Game'
        colors = [[255, 255, 255, 20] for letter in text]
        font = pygame.freetype.SysFont(None, 22)
        font.origin = True
        while True:
        for color in colors:
        color[3] += 33
        if color[3] > 255: color[3] = 0
        x = 200
        for (letter, c) in zip(text, colors):
        bounds = font.get_rect(letter)
        font.render_to(surf, (x, 100), letter, c)
        x += bounds.width + 1

        font.render_to(surf, (180, 150), 'press [space] to start', pygame.Color('grey'))
        events = yield
        yield

        def main():
        title = title_state(screen)
        game = game_state(screen)
        state = title

        while True:
        events = pygame.event.get()
        for e in events:
        if e.type == pygame.QUIT:
        return
        if e.type == pygame.KEYDOWN:
        if e.key == pygame.K_ESCAPE:
        return
        if e.key == pygame.K_SPACE:
        state = game if state == title else title
        if e.key == pygame.K_f:
        if screen.get_flags() & pygame.FULLSCREEN:
        pygame.display.set_mode(size)
        else:
        pygame.display.set_mode(size, pygame.FULLSCREEN)

        screen.fill(pygame.Color('grey12'))
        next(state)
        state.send(events)
        pygame.display.update()
        clock.tick(60)

        if __name__ == '__main__':
        main()


        See how the main loop is clean and simple, and all of the game state is handled in the coroutines. The title screen part of the code does not care about fullscreen or not or how to switch to fullscreen, and the main loop does not care of what the title screen coroutine does. And we don't need threading.



        enter image description here



        In practice it's not that different from the class based example I linked above, but using coroutines makes it easy to implement the title screen animation.



        Basically you have an endless loop, you mutate some state (like the color of a letter), and then say "now draw this!" by just calling yield.






        share|improve this answer























          up vote
          1
          down vote










          up vote
          1
          down vote









          There's no reason to use threading in your code. It will only make your code harder to read, harder to debug and error prone.



          Usually you want to have some kind of state in your game that you use to determinate what should happen in a frame. You can find a class based example here.



          Another way to handle this, which is a bit similar to your code, is to use coroutines.



          Look at your animation code and instead of calling pygame.display.update(), give the control back to the main loop. The main loop will handle events, frame limiting and drawing, then give control back to the coroutine (which keeps track of it's own state).



          Here's a simple hacky example:



          import pygame
          import pygame.freetype

          pygame.init()
          size = (640, 480)
          screen = pygame.display.set_mode(size)
          clock = pygame.time.Clock()

          def game_state(surf):
          rect = pygame.Rect(200, 200, 32, 32)
          while True:
          events = yield
          pressed = pygame.key.get_pressed()
          x = 1 if pressed[pygame.K_RIGHT] else -1 if pressed[pygame.K_LEFT] else 0
          rect.move_ip(x*5, 0)
          pygame.draw.rect(surf, pygame.Color('dodgerblue'), rect)
          yield

          def title_state(surf):
          text = 'Awesome Game'
          colors = [[255, 255, 255, 20] for letter in text]
          font = pygame.freetype.SysFont(None, 22)
          font.origin = True
          while True:
          for color in colors:
          color[3] += 33
          if color[3] > 255: color[3] = 0
          x = 200
          for (letter, c) in zip(text, colors):
          bounds = font.get_rect(letter)
          font.render_to(surf, (x, 100), letter, c)
          x += bounds.width + 1

          font.render_to(surf, (180, 150), 'press [space] to start', pygame.Color('grey'))
          events = yield
          yield

          def main():
          title = title_state(screen)
          game = game_state(screen)
          state = title

          while True:
          events = pygame.event.get()
          for e in events:
          if e.type == pygame.QUIT:
          return
          if e.type == pygame.KEYDOWN:
          if e.key == pygame.K_ESCAPE:
          return
          if e.key == pygame.K_SPACE:
          state = game if state == title else title
          if e.key == pygame.K_f:
          if screen.get_flags() & pygame.FULLSCREEN:
          pygame.display.set_mode(size)
          else:
          pygame.display.set_mode(size, pygame.FULLSCREEN)

          screen.fill(pygame.Color('grey12'))
          next(state)
          state.send(events)
          pygame.display.update()
          clock.tick(60)

          if __name__ == '__main__':
          main()


          See how the main loop is clean and simple, and all of the game state is handled in the coroutines. The title screen part of the code does not care about fullscreen or not or how to switch to fullscreen, and the main loop does not care of what the title screen coroutine does. And we don't need threading.



          enter image description here



          In practice it's not that different from the class based example I linked above, but using coroutines makes it easy to implement the title screen animation.



          Basically you have an endless loop, you mutate some state (like the color of a letter), and then say "now draw this!" by just calling yield.






          share|improve this answer












          There's no reason to use threading in your code. It will only make your code harder to read, harder to debug and error prone.



          Usually you want to have some kind of state in your game that you use to determinate what should happen in a frame. You can find a class based example here.



          Another way to handle this, which is a bit similar to your code, is to use coroutines.



          Look at your animation code and instead of calling pygame.display.update(), give the control back to the main loop. The main loop will handle events, frame limiting and drawing, then give control back to the coroutine (which keeps track of it's own state).



          Here's a simple hacky example:



          import pygame
          import pygame.freetype

          pygame.init()
          size = (640, 480)
          screen = pygame.display.set_mode(size)
          clock = pygame.time.Clock()

          def game_state(surf):
          rect = pygame.Rect(200, 200, 32, 32)
          while True:
          events = yield
          pressed = pygame.key.get_pressed()
          x = 1 if pressed[pygame.K_RIGHT] else -1 if pressed[pygame.K_LEFT] else 0
          rect.move_ip(x*5, 0)
          pygame.draw.rect(surf, pygame.Color('dodgerblue'), rect)
          yield

          def title_state(surf):
          text = 'Awesome Game'
          colors = [[255, 255, 255, 20] for letter in text]
          font = pygame.freetype.SysFont(None, 22)
          font.origin = True
          while True:
          for color in colors:
          color[3] += 33
          if color[3] > 255: color[3] = 0
          x = 200
          for (letter, c) in zip(text, colors):
          bounds = font.get_rect(letter)
          font.render_to(surf, (x, 100), letter, c)
          x += bounds.width + 1

          font.render_to(surf, (180, 150), 'press [space] to start', pygame.Color('grey'))
          events = yield
          yield

          def main():
          title = title_state(screen)
          game = game_state(screen)
          state = title

          while True:
          events = pygame.event.get()
          for e in events:
          if e.type == pygame.QUIT:
          return
          if e.type == pygame.KEYDOWN:
          if e.key == pygame.K_ESCAPE:
          return
          if e.key == pygame.K_SPACE:
          state = game if state == title else title
          if e.key == pygame.K_f:
          if screen.get_flags() & pygame.FULLSCREEN:
          pygame.display.set_mode(size)
          else:
          pygame.display.set_mode(size, pygame.FULLSCREEN)

          screen.fill(pygame.Color('grey12'))
          next(state)
          state.send(events)
          pygame.display.update()
          clock.tick(60)

          if __name__ == '__main__':
          main()


          See how the main loop is clean and simple, and all of the game state is handled in the coroutines. The title screen part of the code does not care about fullscreen or not or how to switch to fullscreen, and the main loop does not care of what the title screen coroutine does. And we don't need threading.



          enter image description here



          In practice it's not that different from the class based example I linked above, but using coroutines makes it easy to implement the title screen animation.



          Basically you have an endless loop, you mutate some state (like the color of a letter), and then say "now draw this!" by just calling yield.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered Nov 9 at 7:50









          sloth

          72.5k14127167




          72.5k14127167
























              up vote
              0
              down vote













              This is a large chunk of code to debug.



              I'm not familiar with pygame or python threading, but it seems to me that you need to include some debug lines to determine exactly where the error occurs during your game animation thread (if it's even occuring there at all).



              Something like this pattern should help determine the source of the problem:



              import logging

              logging.info("start animation initialization")
              ...
              logging.info("begin animation loop")
              ...
              logging.info("end animation loop")


              https://docs.python.org/2/howto/logging.html






              share|improve this answer

























                up vote
                0
                down vote













                This is a large chunk of code to debug.



                I'm not familiar with pygame or python threading, but it seems to me that you need to include some debug lines to determine exactly where the error occurs during your game animation thread (if it's even occuring there at all).



                Something like this pattern should help determine the source of the problem:



                import logging

                logging.info("start animation initialization")
                ...
                logging.info("begin animation loop")
                ...
                logging.info("end animation loop")


                https://docs.python.org/2/howto/logging.html






                share|improve this answer























                  up vote
                  0
                  down vote










                  up vote
                  0
                  down vote









                  This is a large chunk of code to debug.



                  I'm not familiar with pygame or python threading, but it seems to me that you need to include some debug lines to determine exactly where the error occurs during your game animation thread (if it's even occuring there at all).



                  Something like this pattern should help determine the source of the problem:



                  import logging

                  logging.info("start animation initialization")
                  ...
                  logging.info("begin animation loop")
                  ...
                  logging.info("end animation loop")


                  https://docs.python.org/2/howto/logging.html






                  share|improve this answer












                  This is a large chunk of code to debug.



                  I'm not familiar with pygame or python threading, but it seems to me that you need to include some debug lines to determine exactly where the error occurs during your game animation thread (if it's even occuring there at all).



                  Something like this pattern should help determine the source of the problem:



                  import logging

                  logging.info("start animation initialization")
                  ...
                  logging.info("begin animation loop")
                  ...
                  logging.info("end animation loop")


                  https://docs.python.org/2/howto/logging.html







                  share|improve this answer












                  share|improve this answer



                  share|improve this answer










                  answered Nov 8 at 16:32









                  Curt Toppin

                  1413




                  1413






























                      draft saved

                      draft discarded




















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.





                      Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


                      Please pay close attention to the following guidance:


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid



                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.


                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function () {
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53211801%2fthreading-issue-with-pygame%23new-answer', 'question_page');
                      }
                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      這個網誌中的熱門文章

                      Academy of Television Arts & Sciences

                      L'Équipe

                      1995 France bombings