Захватите пользовательский ввод асинхронно и перейдите в цикл событий в python

Я создаю однопользовательскую MUD, которая представляет собой текстовую боевую игру. Он не сетевой.

Я не понимаю, как собирать пользовательские команды и асинхронно передавать их в мой цикл обработки событий. Игрок должен иметь возможность вводить команды в любое время, когда запускаются игровые события. Поэтому приостановка процесса с помощью raw_input не сработает. Я думаю, мне нужно сделать что-то вроде select.select и использовать потоки.

В приведенном ниже примере у меня есть функция макета userInputListener(), в которой мне нравится получать команды и добавлять их в очередь команд, если есть ввод.

Если есть цикл событий, например:

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()

Как я могу получить мой пользовательский ввод там?

Или, проще говоря, может ли кто-нибудь показать мне какой-либо пример сохранения пользовательского ввода, когда в то же время выполняется другой цикл? Я могу выяснить остальное, если мы сможем зайти так далеко.


person msystems    schedule 08.06.2012    source источник
comment
Можно ли использовать Twisted?   -  person sarnold    schedule 08.06.2012
comment
Вместо того, чтобы создавать свои собственные, вы можете попробовать использовать PyGame или curses для обработки вашего ввода.   -  person Andrew Gorcester    schedule 08.06.2012
comment
Разве MUD не означает многопользовательское подземелье? В любом случае, я согласен с @AndrewGorcester, вероятно, было бы проще не изобретать велосипед.   -  person Joel Cornett    schedule 08.06.2012


Ответы (2)


Вам действительно понадобятся две нити. Один связан с основным игровым циклом, а другой — с пользовательским вводом. Эти двое будут общаться через Queue.

Вы можете запустить основной процесс в потоке игрового цикла, а затем получить строку текста от пользователя и «поместить» ее в очередь (т.е. выполнить runGame.start()). Это может быть так же просто, как:

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

Поток игрового цикла будет просто «получать» строку текста из очереди, интерпретировать и выполнять ее.

Python имеет многопоточную реализацию очереди, которую вы можете использовать (включая очень простой пример для многопоточное использование, которое вы можете использовать в качестве руководства).

Существует также простой модуль интерпретатора командной строки (модуль cmd и здесь для хорошего практического обзора), который также может быть полезен для такого рода проектов.

person A_A    schedule 08.06.2012

Я сделал pygame hanoi-visualizer, который асинхронно считывает ввод здесь

Важные строки:

#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()
person Kenkron    schedule 02.07.2015