10

我正在构建一个单人 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()

我如何在那里获得我的用户输入?

或者更简单地说,任何人都可以向我展示在另一个循环同时运行时存储用户输入的任何示例吗?如果我们能走到那一步,我可以弄清楚其余的。

4

2 回答 2

3

你确实需要两个线程。一个负责主游戏循环,另一个负责处理用户输入。两者将通过Queue进行通信。

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

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

游戏循环线程将简单地从队列中“获取”一行文本,插入并执行它。

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

还有一个简单的命令行 interperter 模块(cmd 模块这里有一个很好的实用概述),它也可能对这类项目有用。

于 2012-06-08T01:56:24.243 回答
2

我制作了一个 pygame hanoi-visualiser,它在这里异步读取输入

重要的几行是:

#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()
于 2015-07-02T15:19:31.383 回答