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.
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.
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