title: PyGame multithreading display.update is not smooth
body: <p>I am making a game with python and pygame, and since my game involves very many sprites, I decided to use a separate thread for every enemy\character, which runs a method <code>_mainloop</code>. I am just getting started with this, and i ran into a problem. I am making a basic class that draws a stickman, and has the ability so far to maove on X coordinates. it runs almost perfectly, but the problem is I think that since the stickman is being drawn in the class's <code>_mainloop</code> method, and the display is being updated in the main event handling loop, which makes the stickman look a lot thicker at times, which is kind of weird. I dont want to update the display in <code>_mainloop</code>, because there would be about FPS * enemies + players on screen, which could work out to about 500 <code>pygame.display.updates</code> per second, which is a little overkill. If anyone knows of any better way to do this, can you tell me? please?<br>
  iv'e read these:<br>
  <a href="https://stackoverflow.com/questions/15755500/pygame-multithreading">Pygame Multithreading</a><br>
  <a href="https://stackoverflow.com/questions/7141665/multithreading-with-pygame">Multithreading with Pygame</a><br>
  these arent really related to my question. I couldn't really find anything on it.<br>
  Here is my code:  </p>
  
  <pre><code>from random import randint
  import threading
  
  from pygame.locals import *
  import pygame as pg
  
  FPS = 60
  CLOCK = pg.time.Clock()
  COLOURS = {
      'beige': (232, 202, 145),
      'green': (0, 128, 0),
      'blue': (0, 0, 128),
      'red': (128, 0, 0),
      'dark red': (255, 0, 0),
      'dark blue': (0, 0, 255),
      'dark green': (0, 255, 0),
      'black': (0, 0, 0),
      'aqua': (0, 255, 255),
      'white': (255, 255, 255),
      'teal': (0, 128, 128),
      'purple': (128, 128, 0),
      'dark purple': (255, 255, 0),
      'yellow': (255, 255, 0),
      'silver': (192, 192, 192),
      'gold': (192, 192, 96),
      'gray': (211, 211, 211),
  }
  
  class CharacterImage:
      """
      this is a sprite that at this point, should really
      just be able to move around.
      """
  
      # lots of methods and properties and stuff
      ...
  
      def build_image(self, surface):
          """
          constructs and draws the stickman to the 
          screen.
          """
          # really big function
          ...
  
      def move_to(self, pos: 'x', surface, pixels=1):
          """
          moves the character image by pixels
          towards the destination.
          INCOMPLETE: only X coordinates are supported
          """
  
          current = self.topleft[0]
          direction = 'b' if pos &lt; current else 'f'
          current_pos = current - pixels if direction == 'b' else current + pixels
          self.update_coords((current_pos, self.topleft[1]))
          self.build_image(surface)
          return current_pos
  
      def start_thread(self, pos, surface, pixels=1):
          a = threading.Thread(target=lambda: self._mainloop(pos, surface, pixels), daemon=True)
          self.mainthread = a
          a.start()
  
      def _mainloop(self, pos, surface, pixels, *args, **kwargs):
          new_pos = pos
          while self.topleft != new_pos:
              new_pos = self.move_to(pos, surface, pixels, *args, **kwargs)
              CLOCK.tick(FPS)
  
  
  class WeaponDummy:
      ... # random code
  
  
  def main():
      a = pg.display.set_mode((800, 400))
      testsurf = pg.surface.Surface((2, 2))
      testsurf.fill(COLOURS['green'])
      s = CharacterImage('test', WeaponDummy(testsurf), (10, 300))
      d = CharacterImage('test', WeaponDummy(testsurf), (10, 320))
      s.build_image(a)
      d.build_image(a)
      d.start_thread(880, a)
      s.start_thread(880, a)
  
      while True:
  
          for i in pg.event.get():
              if i.type == QUIT:
                  pg.quit()
                  raise Exception
  
          pg.display.update()
          a.fill(COLOURS['black'])
  
          print('updated')
          CLOCK.tick(FPS)
  
  if __name__ == '__main__':
      main()
  </code></pre>
  
  <p>if you want the full code, that can be run, you can get it <a href="https://1drv.ms/u/s!AvWzFxb0hDBNgv8pR44dBaxe-xCC4A" rel="nofollow noreferrer">here</a>  </p>
  
  <p>any help would be appreciated. thank you so much!  </p>