How to run pygame in background from ipython / python interpreter?

190 views Asked by At

I would like to setup a pygame app from ipython in a background thread.

I already tried to import pygame from this thread before importing it anywhere else.

The problem is that when I launch my main loop inside this thread, soon, it gets frozen until I press enter in the interpreter.

How could I always keep it running ?

Note : that when starting a dummy thread that just print stuffs, it doesn't get blocked, so I think it's more related to pygame than to ipython or python interpreter. The same behaviour appears in IPython and regular python interpreter

1

There are 1 answers

0
Nathan Tibbetts On

I just built an example of this for my own project!

I'm not sure what caused yours to freeze, though I know for mine the OS kept trying to force it to close until I started actually processing the events from the event queue - apparently when the queue filled up the OS thought my thread was broken.

Here's the basic idea below, though you can find my slightly more detailed example, with more comments and with example instances to use, Here on GitHub.

import threading
import pygame


class ThreadedRenderer(threading.Thread):

    def __init__(self, instances=[], size=(128, 128), fps=30, event_functions={}):

        threading.Thread.__init__(self) # Run the Thread parent init

        # Set up program structure
        self.instances = instances
        self.fps = fps
        self.events = event_functions
        self.running = True

        # Set up Pygame
        pygame.init()
        self.screen = pygame.display.set_mode(size)
        self.clock = pygame.time.Clock()

        # Start the thread, which starts the loop
        self.start()

    def _step(self):
        """ Update the program objects, called each frame."""
        for inst in self.instances:
            inst.update()

    def _draw(self):
        """ Redraw the screen, called each frame."""
        self.screen.fill((0, 0, 0))
        for inst in self.instances:
            inst.draw(self.screen)
        pygame.display.flip()

    def run(self):
        """ The function that is Threaded. DO NOT call this function."""
        while self.running is True:
            self.clock.tick(self.fps)
            for event in pygame.event.get():
                if event.type in self.events:
                    self.events[event.type](event)
                elif event.type == pygame.QUIT: # May be overridden
                    self.running = False
            self._step()
            self._draw()
        # Below will be executed whenever the thread quits gracefully or kill is called
        pygame.quit()
        ThreadedRenderer.instantiated = False

    def kill(self):
        self.running = False