我在Python中创建了一个简单的基于文本的游戏,我将它与libPd(Pure Data的包装器)结合使用。所有游戏代码都是在音频实现之前编写的,并按预期工作;类似地,libPd脚本本身也可以完美地工作。然而,让他们一起玩得很好是证明是棘手的。
我认为这与while循环和我对它们的使用有关。
以下是游戏代码的摘录 -
while True:
command = raw_input().lower()
if command == "commands":
print '"look around"'
print '"explore"'
print '"inventory"'
print '"examine"'
print '"take"'
print '"combine"'
print '"quit"'
elif command == "look" or command == "look around":
char.look()
...等... ...等等...
虽然libPd脚本本身如下 -
while True:
if not ch.get_queue():
for x in range(BUFFERSIZE):
if x % BLOCKSIZE == 0:
outbuf = m.process(inbuf)
samples[selector][x][0] = outbuf[(x % BLOCKSIZE) * 2]
samples[selector][x][1] = outbuf[(x % BLOCKSIZE) * 2 + 1]
ch.queue(sounds[selector])
selector = int(not selector)
libpd_release()
我最初尝试在libPd部分缩进整个游戏代码,但这导致音频仅在键入命令后播放,一旦返回打印消息就停止。
我如何将两者结合起来,以便音乐不变,同时玩家可以自由地运行其余的命令/游戏?
答案 0 :(得分:1)
你的问题是你必须坐在那里等待raw_input()
返回,但同时你必须在他们进来后继续处理音频消息。你怎么能在同时?
首先,你今天使用的是事件循环风格。
如果您可以编写一个等待输入或音频消息的函数,以先到者为准,您可以围绕等待该函数的循环重写您的程序。一般来说这很难做到。 (GUI框架和网络服务器框架可以提供帮助,但对于您的文本游戏来说可能有点愚蠢。)
您可以通过仅等待每一行的短时间来伪造它,例如,在select.select
上使用短暂超时的sys.stdin
。但这需要做很多工作,并且很难通过这样的设计来平衡响应性和性能。
或者,您可以使用线程。这就是它的样子:
def play_music():
while True:
if not ch.get_queue():
for x in range(BUFFERSIZE):
if x % BLOCKSIZE == 0:
outbuf = m.process(inbuf)
samples[selector][x][0] = outbuf[(x % BLOCKSIZE) * 2]
samples[selector][x][1] = outbuf[(x % BLOCKSIZE) * 2 + 1]
ch.queue(sounds[selector])
selector = int(not selector)
libpd_release()
play_music_thread = threading.Thread(target=play_music)
play_music_thread.daemon = True
play_music_thread.start()
while True:
command = raw_input().lower()
if command == "commands":
print '"look around"'
print '"explore"'
print '"inventory"'
print '"examine"'
print '"take"'
print '"combine"'
print '"quit"'
elif command == "look" or command == "look around":
char.look()
如果您希望能够进行干净关闭,而不是仅仅在您退出时将音乐线程置于其正在执行的任务中间,那么它会更复杂......但不是那么多。基本上,使用Condition
,Event
,Queue
或只是一个布尔变量和一个Lock
,您可以轻松地构建一种从主要信号中发出背景音乐线程信号的方法线程。
答案 1 :(得分:1)
代码中的while True:
循环是“阻塞”,这意味着当该循环运行时,没有其他循环在同一个线程上运行。运行多个线程的一个简单示例是:
import threading
import time
class MyGame(object):
def __init__(self):
# an "event" is used to tell the threads when to stop
# this is "thread safe", meaning it can be used by a number
# of different threads without causing problems
self.stop_event = threading.Event()
# create and start a thread to run your sound
self.sound_thread = threading.Thread(target=self.sound, args=[self.stop_event])
print "Starting sound thread"
self.sound_thread.start()
# create and start a thread to run your game
self.game_thread = threading.Thread(target=self.game, args=[self.stop_event])
print "Starting game thread"
self.game_thread.start()
def sound(self, stop_event):
print "Entering sound thread"
while not stop_event.is_set():
# put the bit that used to be in the While True loop in here
time.sleep(0.5)
print "Exiting sound thread"
def game(self, stop_event):
print "Entering game thread"
while not stop_event.is_set():
# put the bit that used to be in the While True loop in here
time.sleep(0.5)
print "Exiting game thread"
def stop(self):
"""Used to stop the threads from running"""
print "Stopping threads"
self.stop_event.set()
self.sound_thread.join()
print "Sound thread stopped"
self.game_thread.join()
print "Game thread stopped"
查看Python Threading documentation了解更多信息 - 非常详尽。要运行该程序,您可以执行以下操作:
game = MyGame()
time.sleep(2)
game.stop()
在您的控制台中,您会看到类似
的内容>>> Starting sound thread
>>> Entering sound thread
>>> Starting game thread
>>> Entering game thread
>>> Stopping threads
>>> Exiting sound thread
>>> Sound thread stopped
>>> Exiting game thread
>>> Game thread stopped