异步获取用户输入并传递给python中的Event循环

时间:2012-06-08 00:54:45

标签: python input event-loop mud

我正在构建一个单人游戏MUD,它基本上是一个基于文本的战斗游戏。它没有联网。

我不明白如何收集用户命令并将它们异步传递到我的事件循环中。当游戏事件发生时,玩家需要能够随时输入命令。因此,使用raw_input暂停该过程将不起作用。我想我需要做一些像select.select和使用线程的事情。

在下面的示例中,我有一个userInputListener()的模型函数,我喜欢接收命令,如果有输入,则将它们附加到命令Que。

如果有一个事件循环,例如:

from threading import Timer
import time

#Main game loop, runs and outputs continuously
def gameLoop(tickrate):

    #Asynchronously get some user input and add it to a command que 
    commandQue.append(userInputListener())
    curCommand = commandQue(0)
    commandQue.pop(0)

    #Evaluate input of current command with regular expressions
    if re.match('move *', curCommand):
        movePlayer(curCommand)
    elif re.match('attack *', curCommand):
        attackMonster(curCommand)
    elif re.match('quit', curCommand):
        runGame.stop()
    #... etc    

    #Run various game functions...
    doStuff()

    #All Done with loop, sleep
    time.sleep(tickrate)

#Thread that runs the game loop
runGame = Timer(0.1, gameLoop(1))
runGame.start()

如何在那里获取用户输入?

或者更简单地说,任何人都可以向我展示存储用户输入的任何示例,而另一个循环同时运行吗?如果我们可以做到这一点,我可以弄清楚剩下的。

2 个答案:

答案 0 :(得分:2)

你确实需要两个线程。一个是关注主游戏循环和一个处理用户输入。这两个人将通过Queue进行沟通。

您可以让主进程启动游戏循环线程,然后让用户从用户处获取一行文本并将其“放入”队列(即runGame.start()之后)。这可以很简单:

while not gameFinished:
    myQueue.put(raw_input()). 

游戏循环线程将简单地“对齐”队列中的一行文本,操作员并执行它。

Python有一个可以使用的线程安全的queue implementation(包括一个非常基本的多线程用法示例,您可以将其用作指南)。

还有一个简单的命令行交互模块(cmd modulehere用于实用的概述),这对于这种项目也可能有用。

答案 1 :(得分:1)

我做了一个pygame hanoi-visualiser,它以异步方式读取输入here

重要的是:

#creates an input buffer for stdin 
bufferLock=threading.Lock()
inputBuffer=[]

class StdinParser(threading.Thread):
    def __init__(self):
        threading.Thread.__init__(self)
    def run(self):
        global inputBuffer
        running = True
        while running:
            try:
                instruction=raw_input()
                bufferLock.acquire()
                if inputBuffer == False:
                    running = False
                else:
                    inputBuffer.insert(0,instruction)
                bufferLock.release()
            except EOFError:
                running = False
        pyglet.app.exit()

def check_for_input(dt):
    bufferLock.acquire()
    if len(inputBuffer)>0:
        instruction = inputBuffer.pop()
        parseLine(instruction,board)
    bufferLock.release()