1

我在 Python 中创建了一个简单的基于文本的游戏,我将它与 libPd(纯数据包装器)结合使用。所有游戏代码都是在音频实现之前编写的,并按预期工作;同样,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 部分中缩进整个游戏代码,但这导致音频仅在键入命令后播放,一旦返回打印消息就停止。

我如何将两者结合起来,以使音乐保持不变,而玩家可以自由地运行其余的命令/游戏?

4

2 回答 2

1

您的问题是您必须坐在那里等待raw_input()返回,但同时您必须继续处理队列中的音频消息,一旦它们进入。您如何同时做这两个?


首先,有您今天使用的事件循环样式。

如果您可以编写一个等待输入或音频消息的函数,无论哪个先出现,您都可以围绕等待该函数的循环重写您的程序。这一般很难做到。(GUI 框架和网络服务器框架可以提供帮助,但对于您的文本游戏来说,两者都有些愚蠢。)

您可以通过只为每行等待很短的时间来伪造它,例如,通过使用select.selectonsys.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()

如果您希望能够彻底关闭,而不是在您退出时让音乐线程在它正在做的任何事情中被杀死,它有点复杂......但不是那么多。基本上,使用 a ConditionEventQueue或只是一个布尔变量和 a Lock,您可以轻松地构建一种从主线程向背景音乐线程发出信号的方法。

于 2013-07-12T20:34:28.957 回答
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 文档以获取更多信息——它非常详尽。要运行该程序,您需要执行以下操作:

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
于 2013-07-12T20:40:00.003 回答