Быстрый движок на C# в Fluent-стиле
Чисто ради любопытства за пару часов накидал рыбу парсерного (можно и менюшного) движка, позволяющего писать игры на C# в Fluent-стиле (это последовательность вызовов методов, смотрите пример кода ниже).
Выглядит самый простенький пример так:
Полный код программы выглядит так (без упоминания namespace и usings):
А при запуске выводит текст в консольном окне:
Если вы ошибаетесь с ссылками, например, на локацию, в которой начинает игрок (пишете «ПещерО» вместо «Пещера»), то запуск обрабатывает ошибку так:
Это то, что получилось навскидку. Вообще, можно, например, создание локаций вынести в отдельную конструкцию, чтобы потом было просто на них ссылаться, а не писать текстом, в котором можно ошибиться. Попробую, наверное, сделать такой вариант позже.
Как тогда выглядит разработка? Думаю, примерно так: качаете и ставите бесплатную Visual Studio Community Edition (или лёгкую кроссплатформенную Visual Studio Code), качаете один файл библиотеки с движком, добавляете его в Cтудии в проект как библиотеку и пишете игру.
А можно пойти чуть дальше и сделать так: писать код с проверками и подсказками в Visual Studio Code, а вставлять его в специальный уже собранный движок, который будет его сам компилировать на лету и запускать или делать что-то ещё.
У меня сходу компилируется exe-файл для запуска под Windows, но, по идее, современный .NET Core позволяет собирать и под *nix.
Кроме того, можно не запускать игру методом ЗапуститьИгру(), а, например, выгрузить всю игру в какой-то файл исходного кода, например, в XML для ЯРИЛа или urq-файл (если делать менюшку).
Что думаете о таком способе разработки? Насколько сложно? Насколько удобно? Плюс кода на C# в том, что Студия контролирует вводимый код и не даст писать несовместимые инструкции, выдаёт кучу подсказок.
UPD. Проект на GitHub.
Выглядит самый простенький пример так:
Игра.Новая()
.Имя("Пробная игра")
.Локации()
.Локация("Пещера", "Холодная и мрачная пещера")
.Локация("Поляна", "Светлая и приветливая полянка")
.КонецЛокаций()
.Настройки()
.НачатьВЛокации("Пещера")
.КонецНастроек()
.ЗавершитьСоздание()
.ЗапуститьИгру();
Полный код программы выглядит так (без упоминания namespace и usings):
Код
class Program
{
static void Main(string[] args)
{
try
{
Игра.Новая()
.Имя("Пробная игра")
.Локации()
.Локация("Пещера", "Холодная и мрачная пещера")
.Локация("Поляна", "Светлая и приветливая полянка")
.КонецЛокаций()
.Настройки()
.НачатьВЛокации("Пещера")
.КонецНастроек()
.ЗавершитьСоздание()
.ЗапуститьИгру();
}
catch (ОшибкаОписания ошибкаОписания)
{
Игра.Вывести(ошибкаОписания);
Игра.ОжидатьКлавишу("Нажмите любую клавишу для выхода.");
}
}
}
А при запуске выводит текст в консольном окне:
Запускается игра "Пробная игра"...
Локации игры: "Пещера", "Поляна".
Игрок начинает в локации "Пещера".
Игра запущена.
Нажмите любую клавишу для выхода.
Если вы ошибаетесь с ссылками, например, на локацию, в которой начинает игрок (пишете «ПещерО» вместо «Пещера»), то запуск обрабатывает ошибку так:
При загрузке игры произошла ошибка:
Настройка "НачатьВЛокации" ссылается на несуществующую локацию "ПещерО".
Нажмите любую клавишу для выхода.
Это то, что получилось навскидку. Вообще, можно, например, создание локаций вынести в отдельную конструкцию, чтобы потом было просто на них ссылаться, а не писать текстом, в котором можно ошибиться. Попробую, наверное, сделать такой вариант позже.
Как тогда выглядит разработка? Думаю, примерно так: качаете и ставите бесплатную Visual Studio Community Edition (или лёгкую кроссплатформенную Visual Studio Code), качаете один файл библиотеки с движком, добавляете его в Cтудии в проект как библиотеку и пишете игру.
А можно пойти чуть дальше и сделать так: писать код с проверками и подсказками в Visual Studio Code, а вставлять его в специальный уже собранный движок, который будет его сам компилировать на лету и запускать или делать что-то ещё.
У меня сходу компилируется exe-файл для запуска под Windows, но, по идее, современный .NET Core позволяет собирать и под *nix.
Кроме того, можно не запускать игру методом ЗапуститьИгру(), а, например, выгрузить всю игру в какой-то файл исходного кода, например, в XML для ЯРИЛа или urq-файл (если делать менюшку).
Что думаете о таком способе разработки? Насколько сложно? Насколько удобно? Плюс кода на C# в том, что Студия контролирует вводимый код и не даст писать несовместимые инструкции, выдаёт кучу подсказок.
UPD. Проект на GitHub.
UPD2. Вынес создание локаций для упрощения ссылок.
Локация пещера = Локация("Пещера", "Холодная и мрачная пещера");
НоваяИгра()
.Имя("Пробная игра")
.Локации()
.Локация(пещера)
.Локация("Поляна", "Светлая и приветливая полянка")
.КонецЛокаций()
.Настройки()
.НачатьВЛокации(пещера)
.КонецНастроек()
.ЗавершитьСоздание()
.ЗапуститьИгру();
UPD3. Доработал движок для менюшек.
Теперь код выглядит так:

Ветвь проекта с этими правками: github.com/realsonic/IFluent/tree/feature/menu
Локация пещера = Локация("Пещера", "Холодная и мрачная пещера.");
Локация полянка = Локация("Поляна", "Светлая и приветливая полянка. Рядом чернеет вход в пещеру.");
НоваяИгра()
.Имя("Пробная игра")
.Локации()
.Локация(пещера)
.Кнопка("Выйти из пещеры", полянка)
.КонецЛокации()
.Локация(полянка)
.Кнопка("Войти в пещеру", пещера)
.КонецЛокации()
.КонецЛокаций()
.Настройки()
.НачатьВЛокации(пещера)
.КонецНастроек()
.ЗавершитьСоздание()
.ЗапуститьИгру();
А игра так:
Ветвь проекта с этими правками: github.com/realsonic/IFluent/tree/feature/menu
Мне всегда казалось, что fluent-стиль красив на бумаге, а на практике это неудобно дебажить, рефачить и поддерживать code-style потому что у всех свое представление, где нужен отступ, а где нет.
Но c# это круто!
По идее, при написании игры уже не нужно дебажить код движка, а для дебага кода игры можно вставить специальные методы логирования и проч. С code-style да, есть проблема — студия их может переформатировать.
А делать из шарпа декларативный DSL при наличии в мире XML, JSON (ну json не фонтан, пусть будет json5) и YAML как-то странно, имхо. Можно же написать XSD или json-схему и писать в любимом редакторе с автокомплитом и подсказками, и перегонять в тот же xml или urq-файл какими-то скриптами.
Есть ещё мысль приспособить JetBrains MPS для этих целей, но это прорва работы.
Программистам тоже хочется писать удобно и без лишнего мусора, кстати говоря.
Программисты обычно хотят написать игру, а не изобретать очередной движок.
На западе с движками и писателями всё получше.