Попытка быстрее визуализировать ASCII-арт в python

Я пытаюсь создать текстовую игру с открытым миром на питоне.

world = [["=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","=","="],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
     [" "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "," "],
    ]

for i in world:
    for j in i:
        print(j, end="")
    print("")

Этот код успешно печатает карту мира, хотя и несколько медленно. Есть ли способ улучшить производительность? В конце концов, я хотел бы иметь огромную карту, на которой игрок может двигаться, взаимодействовать с врагами, NPC и т. д. Можно ли как-то ускорить рендеринг, чтобы он стал лучше, чем 0,1 FPS?

Я на Python 3.7 IDLE.

Спасибо!


person woodchuck321    schedule 27.11.2018    source источник


Ответы (3)


String уже являются итераторами только для чтения в python. Итак, вы можете сделать что-то вроде

world = [
    "  X  ",
    " XXX ",
    " X   ",
    ]
for row in world:
    print(row)

Но вы действительно должны попытаться свести к минимуму еще больше вызовов print, что медленно. Может быть, вы можете использовать только одну строку в тройных кавычках?

world = """\
  X  
 XXX 
  X   """

print(world)

К какой такой строке можно получить доступ к элементу (i,j), подсчитав количество символов перед ним. В строке board_width + 1 символов (не забудьте посчитать символ новой строки), и у вас есть j строк перед элементом (i,j). Кроме того, при индексации 0 у вас есть i элементов в той же строке, что и (i,j), но слева от (i,j), поэтому элемент (i,j) равен world[(row_width + 1) * j + i].

Если вы хотите сохранить двойной массив, потому что он изменяемый, рассмотрите возможность объединения его в одну строку перед печатью. Для этого используйте map для объединения каждой строки в один вызов.

displayedWorld = "\n".join(map("".join, world))

edit1: вы могли бы использовать понимание списка, как это сделал TrebuchetMS, но на самом деле он создает список, в то время как в python3 map создаст итератор, которому не нужно хранить все преобразованные строки перед вызовом "\n".map, а скорее вычислить этот список преобразованных строк на лету, не сохраняя их в списке.

edit2: для частичного рендеринга мира просто используйте выбор диапазона вашего списка перед созданием строки. Например, world[j1:j2] содержит только мировые строки от индекса j1 (включено) до индекса j2 (исключено). Итак, если вы хотите отобразить прямоугольник, охватывающий (i,j) с размерами (w,h), сделайте:

displayedWorld = "\n".join(map(lambda row: "".join(row[i:i+w]), world[j:j+h]))

Здесь используется новая идиома, лямбда, которая представляет собой просто безымянную функцию. Лямбда lambda row: "".join(row) эквивалентна методу "".join. Следовательно, lambda row: "".join(row[i:i+w]) объединяет только наблюдения от i до i+w в строке. Обратите внимание, что мы также выбрали только строки с j по j+h в мире.

person Lærne    schedule 27.11.2018
comment
Это могло бы работать, если бы это был один мир, но не если бы это был большой мир с прокруткой. Я должен был указать - только часть мира будет когда-либо визуализирована. - person woodchuck321; 27.11.2018
comment
И я согласен с Феликсом, эта работа обычно лучше подходит для ncurses. Но если вы только начинаете программировать, не переусердствуйте и просто используйте стандартные инструменты. - person Lærne; 27.11.2018
comment
Думал что-то в этом роде с координатами. Спасибо! - person woodchuck321; 27.11.2018

Используйте .join(), чтобы быстро составить список.

print('\n'.join([''.join(row) for row in world]))

В IDLE много накладных расходов с print. Вы можете предпочтительно скомпилировать свою строку перед ее печатью, чтобы получить наилучшую производительность.

person TrebledJ    schedule 27.11.2018

вы можете проверить curses, если вы используете linux/osx. Используя библиотеку, вы можете рисовать пиксели по отдельности вместо того, чтобы постоянно перерисовывать каждый.

Когда дело доходит до огромной карты: рисуйте только ту часть карты, которая видна в данный момент.

person Felix    schedule 27.11.2018