Как написать текстовую игру на python
Перейти к содержимому

Как написать текстовую игру на python

  • автор:

Я пишу текстовую игру на Python: первый прототип

Я пишу текстовую игру на Python: первый прототип. Изображение № 1.

В прошлый раз мы разобрались, как подготовить компьютер к работе с Python, и теперь можем перейти к написанию игры. В создании любой игры чуть ли не самое важное — это как можно скорее начать её прототипировать, чтобы сразу выявить основные уязвимости и устранить их. У нас, конечно, игра довольно простая, да и главное для нас не её качество, а упражнения с кодом. Тем не менее раннее прототипирование — это полезная привычка в разработке чего угодно, поэтому давайте ей следовать.

Для тех, кто успел подзабыть за две недели суть того, что мы делаем, напомню. LAM-40 — это текстовая игра, где вы играете за человека, которому нужно успеть за девять часов получить справку на 40-м этаже загадочного государственного учреждения, переполненного бюрократами. Каждый этаж учреждения генерируется случайным образом: игроку попадаются бюрократы разного уровня, к каждому из которых нужно искать особый подход, чтобы пройти дальше и добраться до последнего этажа.

Примечание: весь код приводится для Python версии 3.0 и старше, а потому может не работать на более старых версиях.

Для начала давайте вспомним, какой код остался у нас с прошлого раза, и разберёмся, чем мы его хотим дополнить.

У нас есть простенький класс бюрократа, умеющего здороваться с игроком и обладающего двумя характеристиками — рангом и настроением. Задача на сегодня — создать простейший, бесконечно повторяющийся цикл «сражений» с бюрократами, что, по сути, и есть основная механика нашей игры. Получившийся у меня в итоге прототип занял 95 строк — начнём его разбирать по порядку (последняя пустая строка должна быть по стандартам PEP 8, но embed’ы её обрубают).

Строка 2: помимо random, в начале программы мы импортируем модуль sys. Из него нам понадобится функция exit() — возможность выйти из игры, пока что не указанная эксплицитно.

Строки 5–13, 16: я добавил списки положительных и отрицательных реакций бюрократов. Обратите внимание, как используются переносы. Дело в том, что, согласно PEP 8, максимальная длина строки должна быть 79 символов, иначе код будет слишком сложно читать. Именно поэтому для удобства каждое новое высказывание находится на новой строке и написано с тем же отступом, что и предыдущее. Ещё я добавил переменную ACTIONS типа данных string с основными действиями игрока (обычным вопросом, подкупом, мольбой, давлением и угрозой), чтобы не делать слишком длинной строку, где мы будем выводить все эти действия.

Строки 25, 34–44: у класса Bureaucrat появилась характеристика negative логического типа данных (то есть истина или ложь) со значением False. Она показывает, был ли ход игрока удачным — если нет, то её значение становится True, и игра предлагает нам совершить новое действие на том же самом бюрократе, а не создаёт нового бюрократа. Для того чтобы отобразить реакцию бюрократа на действие игрока, используются функции с говорящими названиями react_positively() и react_negatively(), которые меняют значение переменной negative и выводят случайную реакцию бюрократа на случившееся.

Строки 46–85: функция act() выводит на экран все возможные действия игрока и предлагает ему выбрать одно из них, введя первую букву слова. Именно для того, чтобы не загружать эту строку, мы вывели string со всеми действиями в отдельную переменную ACTIONS. Следом за этим идёт ветвление, и мы впервые в этом блоге используем ключевое слово elif — сокращение от else if. Оно задаёт условие помимо того, что указано в if, а блок с ним — следующие за выполнением этих условий действия. В нашем случае мы проверяем, что ввёл игрок. Если он ввёл строчную букву Q, выполнение программы завершится из-за упомянутой ранее функции sys.exit(). Если игрок введёт строчную букву W (wait), то ему выпадет новый бюрократ — это тоже пока что незадокументированная возможность. Если же игрок введёт какой-нибудь другой символ, то программа перейдёт в функцию react(), где ветвление выходит на новый уровень. На текущем этапе я сделал так, что для определённых сочетаний ранга и настроения бюрократа срабатывает лишь одно действие. Более того, есть непобедимые сочетания (например, высокий ранг и плохое настроение), в случае с которыми приходится вводить W, чтобы выпал следующий бюрократ.

Самая большая головная боль на первых порах — это использование ключевого слова self, когда вы ссылаетесь на функцию или характеристику класса внутри этого класса, и оператора сравнения == вместо оператора присваивания = рядом с условными операторами. Вероятно, и о том, и о другом вы будете забывать, так что следите за этим. Кстати, обратите внимание на ключевое слово and, которое используется рядом с операторами ветвления — оно обозначает, что должны выполняться оба условия, находящиеся рядом с ним.

Строки 87–94: наконец, в самом низу заканчивается описание класса и начинается логика основной программы. Мы создаём образец класса Bureaucrat, присваиваем его переменной bureaucrat и используем функцию с приветствием бюрократа. После этого запускаем бесконечный цикл, внутри которого запускаем функцию с выводом и вводом действий игрока, а также условное исполнение создания и приветствия нового бюрократа — в зависимости от того, каково текущее значение bureaucrat.negative. Обратите внимание на две вещи: оператор else при желании можно не использовать, а в случае с логическими типами данных в Python вместо оператора == применяют ключевое слово is.

Первый прототип LAM-40 готов. Конечно, он ещё далёк не то что от финальной, а даже от альфа-версии, поэтому нам предстоит порядочно поработать. Сейчас я вижу кучу проблем с этим прототипом, которые собираюсь устранить в следующий раз:

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

Не обойтись без элемента неожиданности в «сражениях» с бюрократами — иначе игра быстро наскучит. Вероятно, это также поможет избежать дикого ветвления, которое есть сейчас в нижней части кода.

Игре требуется больше разнообразия во фразах, характеристиках, действиях и прочем, а также в том, как всё это выводится, чтобы внести разнообразие в повествовательную часть.

Желательно описывать текстом все действия, что возможны в игре, в том числе выход из неё и ожидание.

Из возможных действий желательно сделать список, а не отдельный string, чтобы туда можно было при определённых условиях добавлять новые действия. Кроме того, на ввод нужно применить функцию upper(), чтобы не требовалось каждый раз вводить строчные буквы. Также надо сделать адекватную реакцию на неверно введённые символы.

В основной логике игры есть повторяющиеся две строчки, нарушающие правило DRY. Да и сам цикл не очень красив — пожалуй, стоит над ним подумать, когда он начнёт расширяться.

Куча мелочей вроде описания функции act(), комментариев к некоторым частям кода, использования sys.exit() и характеристики negative, которая тоже не очень изящное решение. Так что поищу ему альтернативу.

Как видите, работы предстоит полно. Надеюсь, к следующему разу игра примет уже более целостный вид. Если вам что-то непонятно, пишите комментарии под материалом и в социальных сетях — буду рад и любым другим отзывам. Если вы более опытный в программировании человек, чем я, то с удовольствием выслушаю содержательную критику. Спасибо, и до следующего раза!

Полные курсы Python на Codeacademy и Treehouse*

* — платные курсы, но есть пробный период

Развитие программистского мышления на Udacity

Учебники по Python на LearnPython.org и Python Course

Постановка задачи: текстовый квест

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

Также, как и в настольной ролевой игре (а такие тоже бывают), в текстовом квесте вам нужно принимать решения в различных ситуациях, только играете вы в одиночку, а вместо ведущего — компьютер или мобильное устройство.

Текстовый квест может быть как интерактивным рассказом, так и полноценной бродилкой или рпг с подбором предметов, квестами и сражениями, просто вместо 3д графики — текст и картинки, записанные символами. Если чуть позже добавить графику, то получится уже интерактивная новелла (комикс с возможностью выбора, например, бесконечное лето) или интерактивный сериал (как, например, игры от Telltale Games или эпизод Bandersnatch черного зеркала от Netflix).

Вот несколько примеров (и еще примеров) таких игр, в которые вы можете попробовать поиграть на досуге. Очень советую попробовать поиграть перед тем, как придумывать свой.

Как спроектировать квест?

Если мы хотим придумать собственный тестовый квест, нам понадобится какая-то схема, чтобы описать его сценарий.

Если бы мы писали книгу, все было бы просто — ее сюжет был бы линеен и события разворачивались последовательно. А вот в случае с текстовыми квестами все сложнее — сюжет зависит от выбора пользователя, и надо как то фиксировать, какие события случаются при каких условиях.

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

Любой текстовый квест состоит из частей информации, которую программа сообщает пользователю между которыми игрок должен сделать выбор, или иными словами, что-то ввести.

В зависимости от выбора, случайности (а в настолках — от кубиков), наличия предметов в инвентаре или предыдущих действий игроку выводится следующая информация.

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

Варианты квестов

Если пробовать рисовать графы квестов от совсем простых к более сложным, то у нас получиться три разных варианта.

1. Самый простой: линейный квест (квест-линия).

В линейном квест программа игра просит пользователя что-то ввести, но в конечном итоге это никак не влияет на сюжет. Например, программа может запоминать имя персонажа, название его фермы, кличку любимый собаки, но в игре с любом случае будет ферма и собака, и собака будет жить на ферме, и игрок в любом случае ее покормит, просто имена у героев меняются. С одной стороны ничего особенного, а с другой — приятно.

2. Квест с ветвлением (квест-дерево).

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

Кстати, почему дерево? Деревом в дискретной математике называется граф без циклов, т.е. тот, в котормо нельзя ходить кругами (как раз наш случай). Визуально он правда похож на перевернутое дерево.

3. Произвольный квест с инвентарем (квест-граф).

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

План действий

План действий следующий.

  1. Придумать название и сюжет для квеста.
  2. Нарисовать его граф, чтобы примерно представить сюжет.
  3. Запрограммировать квест на питоне.
  4. Протестировать и исправить все баги.
  5. Провести бета-тест среди друзей и собрать обратную связь.

Кажется, что все более менее реализуемо, кроме, пока что, среднего пункта — «запрограммировать». Но это ненадолго, уже в следующем уроке ты научишься описывать на питоне произвольные текстовые квесты, для чего понадобится:

  • установить питон на компьютер и использовать IDLE для вычислений (уже сделали!);
  • научиться выводить текст на экран и просить пользователя вводить ответы (уже можно будет сделать линейный квест);
  • разобраться с условным оператором, чтобы создавать квесты с ветвлением;
  • научится создавать свои функции, использовать глобальные переменные и рекурсию для созданий сложных квестов с возвратами и инвентарем;
  • объединить все это, использовать ascii графику, добавить звуки и разбить на несколько модулей, чтобы создать итоговую версию квеста.

Выглядит план, скорее всего страшно, но ты точно справишься! ��

Как создать текстовую игру в PYTHON? [закрыт]

Хотите улучшить этот вопрос? Переформулируйте вопрос так, чтобы он был сосредоточен только на одной проблеме.

Закрыт 5 лет назад .

  1. Подскажите пожалуйста, кто с чего начинает, чтобы создать текстовую игру в PYTHON 3!? (прим. План, алгоритмы, или еще что то. )
  2. И что вообще это такое текстовая игра, как она класифицируется?
  3. Если можно какой нибудь код текстовой игры и пояснить, что да как устроено в ней!

Отслеживать
задан 3 ноя 2017 в 21:42
19 7 7 бронзовых знаков
так там же Python/Ren’Py, да и еще и 2, а я просил только на Python 3
3 ноя 2017 в 22:17
2. текстовая игра — игра, взаимодействие пользователя с которой, ограничено текстовым вводом-выводом
4 ноя 2017 в 8:14

1 ответ 1

Сортировка: Сброс на вариант по умолчанию

Ответы на ваши вопросы, скорее всего, получатся слишком объёмными и пространными. Предлагаю Вам поискать в Сети книгу Эла Свейгарта «Invent your own computer games with Python», в которой автор на простых примерах объясняет как создавать игры, начиная с простых текстовых и заканчивая играми с использованием графики при помощи сторонней библиотеки PyGame.

Отслеживать
ответ дан 4 ноя 2017 в 8:11
Adventurer Adventurer
58 5 5 бронзовых знаков

  • python-3.x
  • разработка-игр
  • text
    Важное на Мете
Похожие

Дизайн сайта / логотип © 2023 Stack Exchange Inc; пользовательские материалы лицензированы в соответствии с CC BY-SA . rev 2023.10.27.43697

Нажимая «Принять все файлы cookie» вы соглашаетесь, что Stack Exchange может хранить файлы cookie на вашем устройстве и раскрывать информацию в соответствии с нашей Политикой в отношении файлов cookie.

Мини-туториал по созданию текстового RPG на Python

Мини-туториал для новичков по созданию текстовой PRG-игры на языке Python. Внутри — код с подробными комментариями.

Я в этом особо не шарю, но попробовал сделать хоть что-то. Данный пост для новичков, которые заинтересованы данной темой, но не понимают, что надо делать.

Для начала нам нужен randint.

from random import randint 

Теперь можем сделать классы.

class Player: hp = 100 damage = 10 # Записываем в переменную, чтобы было удобно. p = Player() class Enemy: # Рандомно получает хп врага от 70 до 130, рандомно получает дамаг врага от 6 до 13. hp = randint(70,130) damage = randint(6,13) # Записываем в переменную, чтобы было удобно. e = Enemy() 

Пожалуй, можно сделать меню.

def menu(p): while True: print("1) Сражаться") print("2) Посмотреть статистику") # try и except просто фиксят ошибки. Не обращайте внимания. try: n = input("Введите число: ") if n == 1: menu_fight(p) if n == 2: menu_stats(p) else: print("Чего ждем?") except NameError: print("Введите число") except SyntaxError: print("Введите число") 

Статистика тоже не помешает.

def menu_stats(p): print("Статистика игрока") print("*****************") # Попробую обьяснить, что значит %s. Она по последовательности списка вписывает в %s переменную. print("hp ") print("damage: ") input("Нажмите Enter для продолжения.") 

Теперь потруднее, нужно сделать сражение.

def menu_fight(p): while e.hp > 0: # Также, как я и сказал по последовательности списка расставляет переменные. print(f"Вы hp: damage: ") print(f"Враг hp: damage: ") print("**********************") print("1)Ударить") print("2)Хил 0-5") n = input("Введите число: ") if n == 1: # Здоровье врага отнимает от вашего дамага. e.hp -= p.damage print("Вы ударили противника, у него осталось %s hp")%(e.hp) # Здоровье игрока отнимает от дамага врага. p.hp -= e.damage print("Противник ударил вас, у вас осталось %s hp")%(p.hp) print("*********************") if n == 2: # Рандомно от 0 до 5 добавляет хп. p.hp += randint(0,5) # Если здоровье игрока больше, то хп игрока будет равна 100. if p.hp > 100: p.hp = 100 print("Ваши хп %s")%(p.hp) else: print("Чего ждем?") if p.hp < 0: print("Вы проиграли") if e.hp < 0: print("Вы победили") print("******************")

Под конец осталось просто вызвать меню.

# Вызов меню. menu(p) 

Полный код

from random import randint class Player: hp = 100 damage = 10 # Записываем в переменную, чтобы было удобно. p = Player() class Enemy: # Рандомно получает хп врага от 70 до 130, рандомно получает дамаг врага от 6 до 13. hp = randint(70,130) damage = randint(6,13) # Записываем в переменную, чтобы было удобно. e = Enemy() def menu(p): while True: print("1) Сражаться") print("2) Посмотреть статистику") # try и except просто фиксят ошибки. Не обращайте внимания. try: n = input("Введите число: ") if n == 1: menu_fight(p) if n == 2: menu_stats(p) else: print("Чего ждем?") except NameError: print("Введите число") except SyntaxError: print("Введите число") def menu_stats(p): print("Статистика игрока") print("*****************") # Попробую обьяснить, что значит %s. Она по последовательности списка вписывает в %s переменную. print("hp %s."%(p.hp)) print(f"Вы hp: damage: ") print("damage %s."%(p.damage)) input("Нажмите Enter для продолжения.") def menu_fight(p): while e.hp > 0: # Также, как я и сказал по последовательности списка расставляет переменные. print("Вы hp: %s damage: %s")%(p.hp, p.damage) print("Враг hp: %s damage: %s")%(e.hp, e.damage) print("**********************") print("1)Ударить") print("2)Хил 0-5") n = input("Введите число: ") if n == 1: # Здоровье врага отнимает от вашего дамага. e.hp -= p.damage print("Вы ударили противника, у него осталось %s hp")%(e.hp) # Здоровье игрока отнимает от дамага врага. p.hp -= e.damage print("Противник ударил вас, у вас осталось %s hp")%(p.hp) print("*********************") if n == 2: # Рандомно от 0 до 5 добавляет хп. p.hp += randint(0,5) # Если здоровье игрока больше, то хп игрока будет равна 100. if p.hp > 100: p.hp = 100 print("Ваши хп %s")%(p.hp) else: print("Чего ждем?") if p.hp < 0: print("Вы проиграли") if e.hp < 0: print("Вы победили") print("******************") # Вызов меню. menu(p)

Спасибо, что прочитали. Можете дать советы, мне будет интересно почитать.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *