Python Help with Pygame and Multiprocessing
I'm using pygame to blit an image to screen, while it does the mainloop. I'm using multiprocessing for threads, but there seems to be a problem. Please don't chew me out over the weird wannabe xml comments, as I'm fairly new at this.
Here's my code.
#Import libraries
import pygame
import os, sys
import multiprocessing as threading
import time
from pygame.locals import *
pygame.init()
screen = pygame.display.set_mode((1400,900), FULLSCREEN)
class loader:
def sound(name):
load = os.path.join("data", name)
sound = pygame.mixer.Sound(load)
return sound
def song(name):
load = os.path.join('data', name)
song = pygame.mixer.Sound(load)
return song
def picture(name):
load = os.path.join("data", name)
image = pygame.image.load(load)
image = image.convert()
return image
def movie(name):
load = os.path.join("data", name + ".mp开发者_开发技巧g")
movie = pygame.movie.Movie(name)
return movie
class data():
class movies():
#Turns out it's not supported D:
pass
class songs():
theme = loader.song("theme.ogg")
class sounds():
fctune = loader.sound("fctune.wav")
class pictures():
fc = loader.picture("fc_opaque.tga")
#------------------------Logics-------------------------
def showlogo():
screen.blit(data.pictures.fc, (0,0))
data.sounds.fctune.play()
time.sleep(30)
def startloops():
logo = threading.Process(target=showlogo, args=())
gameloop = threading.Process(target=mainloop, args=())
logo.start()
logo.join(None)
gameloop.start()
gameloop.join(None)
def mainloop():
while 1:
clock.tick(30)
pygame.display.flip()
for event in pygame.event.get():
if event.type == QUIT:
return
elif event.type == KEYDOWN and event.key == K_ESCAPE:
sys.exit(1)
elif event.type == MOUSEBUTTONDOWN:
pass
elif event.type is MOUSEBUTTONUP:
pass
#End of looper.
#-----------------------/Logics-------------------------
#----------------------Globals--------------------------
clock = pygame.time.Clock()
#----------------------/Globals-------------------------
if __name__ == "__main__": startloops()
What it does is it creates 2 pygame windows.. (one is supposed to show up when you call
screen = pygame.display.set_mode((1400,900), FULLSCREEN)
So apparently it's calling that twice. Hmm, multiprocessing seems to be the culprit. Can anyone help out?
Here's what I believe is happening. Basically, the multiprocessing
module works by sending copies of everything that the target
needs to a brand new interpreter; that's how it skirts the GIL. But that means that side-effects (changes to global vars, changes to objects passed in but not returned) don't get propagated as expected. Here's a simple example:
>>> import multiprocessing
>>> d = {'a':5, 'b':6}
>>> def alter_d():
... d['a'] = 7
... print d
...
>>> p = multiprocessing(target=alter_d)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'module' object is not callable
>>> p = multiprocessing.Process(target=alter_d)
>>> p.start()
>>> {'a': 7, 'b': 6}
>>> d
{'a': 5, 'b': 6}
So as you can see, the version of d
that has been passed to the new process has been altered. But the local version of d
remains the same.
Now I don't know anything about the internals of pygame. But my guess is that when you create a new process using logo = threading.Process(target=showlogo, args=())
, it makes a copy of screen
. Then, either when that copy is made, or when screen.blit(data.pictures.fc, (0,0))
is called inside the new process, a whole new screen gets generated.
Fortunately, the way you're using multiprocessing right now is completely pointless. join
just halts the main process and waits for the subprocess to finish -- there's no concurrency whatsoever. Furthermore, I'd bet money that pygame provides whatever threading functionality you actually need -- I doubt you need multiprocessing at all. I'd suggest that you ditch it.
精彩评论