Grab user input asynchronously and pass to an Event loop in python

我们两清 提交于 2019-11-28 03:25:30

问题


I am building a single player MUD, which is basically a text-based combat game. It is not networked.

I don't understand how to gather user commands and pass them into my event loop asynchronously. The player needs to be able to enter commands at any time as game events are firing. So pausing the process by using raw_input won't work. I think I need to do something like select.select and use threads.

In the example below, I have a mockup function of userInputListener() which is where I like to receive commands, and append them to the command Que if there is input.

If have an event loop such as:

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

How do I get my user input in there?

Or more simply, can anyone show me any example of storing user input while another loop is running at the same time? I can figure out the rest if we can get that far.


回答1:


You will indeed need two threads. One to be concerned with the main game loop and one to handle user input. The two would be communicating through a Queue.

You can have your main process start the game loop thread and then have it obtaining a line of text from the user and "puting" it to the queue (i.e following runGame.start()). This can be as simple as:

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

The game loop thread will simply be "geting" a line of text from the queue, interpert and execute it.

Python has a thread-safe queue implementation which you can use (including a very basic example for multi-threaded usage that you can use as a guide).

There's also a simple command line interperter module (the cmd module and here for a good practical overview) which might also be useful for this kind of project.




回答2:


I made a pygame hanoi-visualiser that reads input asynchronously here

The important lines are:

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


来源:https://stackoverflow.com/questions/10941851/grab-user-input-asynchronously-and-pass-to-an-event-loop-in-python

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!