While循环问题-Python
我已经用Python创建了一个简单的基于文本的游戏,并将其与libPd(纯数据包装器)结合使用。所有的游戏代码都是在音频实现之前编写的,并按预期工作;类似地,libPd脚本本身也可以完美地独立工作。然而,要让他们在一起玩得开心是很棘手的 我想这与while循环和我对它们的使用有关 下面是游戏代码的摘录-While循环问题-Python,python,while-loop,structure,break,Python,While Loop,Structure,Break,我已经用Python创建了一个简单的基于文本的游戏,并将其与libPd(纯数据包装器)结合使用。所有的游戏代码都是在音频实现之前编写的,并按预期工作;类似地,libPd脚本本身也可以完美地独立工作。然而,要让他们在一起玩得开心是很棘手的 我想这与while循环和我对它们的使用有关 下面是游戏代码的摘录- while True: command = raw_input().lower() if command == "commands": print '"loo
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部分缩进整个游戏代码,但这导致音频仅在键入命令后播放,在返回打印消息后停止
如何将这两者结合起来,使音乐保持不变,同时播放器可以自由地运行其余的命令/游戏?您的问题是,您必须坐在那里等待
原始输入()
返回,但与此同时,您必须在音频消息进入队列后立即处理它们。你怎么能同时做这两件事呢
首先,您现在使用的是事件循环样式 如果您可以编写一个等待输入消息或音频消息的函数,则可以围绕等待该函数的循环重写程序。一般来说,这很难做到。(GUI框架和网络服务器框架可能会有所帮助,但对于文本游戏来说,两者都有点愚蠢。) 您可以通过对每一行只等待一小段时间来伪造它,例如,在
sys.stdin
上使用select.select
并短暂超时。但这是一个很大的工作,很难用这样的设计来平衡响应能力和性能
或者,您可以使用线程。下面是它的外观:
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()
<>如果你想做干净的关机,而不是让音乐线程在你退出时做的任何事情中胡杀,那就有点复杂了……但不是那么多。基本上,使用
条件
,事件
,队列
,或者只使用一个布尔变量和一个锁
,您可以轻松构建一种从主线程向背景音乐线程发送信号的方法。如果为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"
更多信息,请查看该文档-它非常全面。要运行该程序,请执行以下操作:
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
听起来您可能正在寻找多个线程。一个是让游戏循环,另一个是播放音乐。我建议你看看线程的概念。您的音频需要在不同于游戏代码的线程中运行。看看Python,谢谢你花时间帮我。我尝试了线程解决方案,因为你张贴它,但它是一个没有去的音频输出方面。我错过了一些简单的东西吗?有一声咔嗒声,好像它只是短暂地初始化了一下,但之后什么也没有。在我发布这个问题之前,我在尝试将这两种代码结合起来时得到了类似的结果。@CapricornOne:在没有看到其余代码的情况下,很难确定…但我怀疑您试图在音乐线程和主线程中的其他代码之间共享一些变量,可能
选择器是一个共享全局变量,或者可能ch.get_queue()
正在使用列表而不是队列.queue
,或者可能在另一个线程尝试播放时试图清除排队的缓冲区,或者…?通常,对于两个线程使用的任何对象,您也必须共享锁,然后用mylock:
在修改或访问对象的每行、块或代码周围编写。像Queue
和Lock
这样的自同步类型,以及像int
和tuple
这样的不可变类型,都不需要这个,但其他类型通常都需要。我原以为“选择器”是问题所在,但我不确定。据我所知,这两个线程也不应该有任何交叉。如果您想查看我在此处添加的完整代码,请尝试将inbuf
、ch
、声音
、和示例
变量全部移动到播放音乐
函数的顶部,以及文件顶部的内容(BUFFERSIZE=4096
通过patch=libpd\u open\u patch
)。这样可以确保您不会从主线程接触libpd或pygame。