2012-06-08 8 views
6

Я создаю однопользовательскую MUD, которая в основном представляет собой текстовую боевую игру. Он не подключен к сети.Асинхронно вставляйте пользовательский ввод и переходите в цикл событий в python

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

В приведенном ниже примере у меня есть функция mockup 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() 

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

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

+0

Is [Twisted] (http://twistedmatrix.com/) вариант? – sarnold

+2

Вместо того, чтобы кататься самостоятельно, вы можете попробовать использовать PyGame или проклятия для обработки ввода. –

+0

Не подходит ли MUD для многопользовательской подземелья? Я согласен с @AndrewGorcester в любом случае, вероятно, было бы легче избежать повторного использования колеса. –

ответ

2

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

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

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

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

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

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

1

Я сделал Pygame Ханоя-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()