2013-03-29 2 views
3

Я пишу простую текстовую приключенческую игру на Python. Я хотел бы, чтобы определенные процессы происходили периодически, независимо от того, что делает пользователь, примерно каждые 2 минуты. Например: Имейте NPC перемещаться по комнатам, есть люди, голодные и жаждущие, люди заживают, и во время боя, битва продолжается. Прямо сейчас, я использую 'raw_input' для получения команд от пользователя, но это существенно приостанавливает код. Как я могу продолжить игру, даже если пользователь просто сидит там и ничего не вводит?Кодирование временных функций в текстовой игре с использованием Python

+0

Похоже, вам понадобятся по крайней мере два потока - один для IO, а другой для действий в реальном времени. –

+0

Что-то происходит «асинхронно» (может случиться, что в ожидании ввода пользователем), или это просто изменения, которые могут произойти, и единственная возможность засвидетельствовать их - это ввести новую команду? –

+0

Да, Валид, я думаю, что все. Хотя я не знаю, как это сделать ... Да и Брайану. Я бы предпочел, чтобы все продолжалось, даже если пользователь ничего не вводил. – user2218093

ответ

0

Ответ: не пишите в реальном времени для консоли! Если вы хотите сделать это на основе текста, вы можете переключиться на Tkinter. Это позволит вам делать это отдельно - а также отображать текст во время этих периодических событий, и использовать простой вызов .after() для их выполнения.

0
  1. Образец времени после каждого ввода (до вас, нужно ли это делать только для успешных команд или необязательно включать недопустимые).

  2. Сравните это время с предыдущим образцом и разделите его на некоторый интервал тиков.

  3. Итерации по списку видов деятельности, которые происходят за отметку (for npc in npcs: npc.move_to_adjacent_posn(), например).

1

Я думаю, что обычно в этой ситуации у вас не было бы фонового процесса или потока, выполняющего вычисления. Вместо этого, когда пользователь вводит какой-либо ответ, выполняйте временную дельта и основываясь на прошедшем времени между входами, подсчитайте, сколько игрок исцелил бы и какие были бы события битвы и т. Д. То есть, если вам не нужны обновления консоли пока игра ждет ответа пользователя.

Edit: или попробовать что-то вроде этого:

import time 
import sys 

win32 = True 
try: 
    from msvcrt import kbhit, getch 
    print "[+] Running on windows, using msvcrt." 
except ImportError: 
    print "[+] Not running on windows, attempting unix-like." 
    win32 = False 

    import termios, fcntl, sys, os 
    import select 
    fd = sys.stdin.fileno() 

    oldterm = termios.tcgetattr(fd) 
    newattr = termios.tcgetattr(fd) 
    newattr[3] = newattr[3] & ~termios.ICANON & ~termios.ECHO 
    termios.tcsetattr(fd, termios.TCSANOW, newattr) 

    oldflags = fcntl.fcntl(fd, fcntl.F_GETFL) 
    fcntl.fcntl(fd, fcntl.F_SETFL, oldflags | os.O_NONBLOCK) 


POLLTIME = 5 
done = False 
command = "" 
while not done: 

    sys.stdout.write("\r") 
    print("Something happened (polling)%s" % (" " * command.__len__())) 
    sys.stdout.write("Enter command: %s" % command) 
    sys.stdout.flush() 

    t = time.time() 
    if win32: 
     while time.time() - t < POLLTIME: 
      if kbhit(): 
       c = getch() 
       if ord(c) < 127 and ord(c) > 31: 
        command += c 
        message = "\rEnter command: " + command 
        sys.stdout.write("\r%s" % message) 
       if "\r" == c: 
        if "quit\r" == command: 
         done = True 
         break 
        sys.stdout.write("\rThe command was: %s\n" % command) 
        command = "" 
        sys.stdout.write("\rEnter command: %s \b" %command) 
       elif "\b" == c: 
        command = command[:-1] 
        sys.stdout.write("\rEnter command: %s \b" %command) 
       sys.stdout.flush() 
    else: 
     while time.time() - t < POLLTIME: 
      try: 
       c = '\0'     
       if sys.stdin in select.select([sys.stdin], [], [], 0)[0]: 
        c = sys.stdin.readline(1) 
        if ord(c) < 127 and ord(c) > 31: 
         command += c 
         message = "\rEnter command: " + command 
         sys.stdout.write("\r%s" % message) 
       if c == "\n": 
        if "quit" == command: 
         done = True 
         break 
        print("\rThe command was: %s" % command) 
        command = "" 
        message = "\rEnter command: " + command 
        sys.stdout.write("\r%s" % message) 
       if 127 == ord(c): 
        command = command[:-1] 
        sys.stdout.write("\rEnter command: %s \b" % command) 
       sys.stdout.flush() 

      except IOError: 
        pass 
+0

Я бы предпочел, чтобы консоль _does_ обновлялась, ожидая ответа пользователя. В противном случае возникнет большое количество событий. Скажите, что пользователь встает и обедает, а затем возвращается через 30 минут. Как только они вступят в команду, будет спешка вещей, которые произошли за 30 минут. Кроме того, я хотел бы, чтобы пользователь знал, что они могут умереть, если они покинут игру без присмотра. – user2218093

+0

См. Мое редактирование выше – Alden

+0

Я хотел бы проверить этот код, но когда я запускаю на своей машине, он не распознает msvcrt. Я запускаю python 3.3 на Mac. Что мне нужно сделать, чтобы сделать эту работу? – user2218093

0

Есть способы, чтобы читать ввод данных пользователя без остановки код. Он называется «асинхронный ввод-вывод» или «неблокирующий ввод-вывод». Один из способов сделать это - создать отдельный поток для прослушивания запросов пользователя и поставить их в очередь для обработки внутри игрового цикла.

Этот вопрос и его ответы объяснить, как это сделать без блокировки ввода/вывода в Python: Non-blocking read on a subprocess.PIPE in python

0

Я не знаю, как вы можете сделать это без использования отдельного потока (и это легко использовать отдельный нить).

Но моя точка здесь будет выглядеть: как ваша текстовая функция - это приложение на основе событий/команд? то есть состояние клиента не изменится, если от пользователя нет никакой дополнительной команды/события? Не уверен, что вы пытаетесь контролировать с помощью функции времени, но если ваше приложение уже не основано на событиях, т.е. агрегирует состояние из набора событий, которые пользователь выполняет/отправляет, тогда вы можете захотеть сделать ваше приложение событием , вы можете избавиться от функции времени. надеюсь, что помощь.

Смежные вопросы