В первой части мы познакомились с архитектурным паттерном Entity-Component-System, часто используемым в разработке игр, и металингвистической парадигмой программирования, заключающейся в построении и использовании собственных языков, наиболее полно и точно описывающих предметную область создаваемой программы. На сей раз мы используем эти приёмы для создания небольшой, но полноценной игры на Common Lisp в жанре dungeon crawler (рус. надмозг. "подземное ползание") с пользовательским интерфейсом и рассмотрим на её примере системный дизайн реального игрового приложения с использованием ECS.
TL;DR: готовую к запуску демонстрацию (бинарники под все распространённые ОС) и её исходный код можно найти на github.
Освежив при необходимости знания синтаксиса Common Lisp с помощью краткого руководства Изучите X за Y минут, где X=Common Lisp или более подробного "Практическое использование Common Lisp", и предполагая, что у нас уже настроено рабочее окружение для геймдева на Common Lisp по инструкциям из первой части, обновим локальные версии установленных пакетов, запустив REPL компилятора SBCL командной в терминале sbcl и передав ему на исполнение следующий фрагмент кода:
(ql-util:without-prompting (ql:update-all-dists))
Затем, как и в прошлый раз, начнём с использования cookiecutter-шаблона:
cookiecutter gh:lockie/cookiecutter-lisp-game
Ответим утвердительно на вопрос cookiecutter "Is it okay to delete and re-download it?" для того, чтобы скачать обновлённую версию шаблона игры, и ответим на вопросы о новом проекте следующим образом:
full_name (Your Name): Alyssa P. Hacker
email (your@e.mail): alyssa@domain.tld
project_name (The Game): ECS Tutorial 2
project_slug (ecs-tutorial-2):
project_short_description (A simple game.): cl-fast-ecs framework tutorial.
version (0.0.1):
Select backend
1 - liballegro
2 - raylib
3 - SDL2
Choose from [1/2/3] (1): 1
Снова добавим ссылку на каталог проекта в наш локальный репозиторий пакетов Quicklisp:
ln -s $(pwd)/ecs-tutorial-2 $HOME/quicklisp/local-projects/ # для UNIX-подобных ОС
mklink /j %USERPROFILE%\quicklisp\local-projects\ecs-tutorial-2 ecs-tutorial-2 # для Windows
mklink /j %USERPROFILE%\portacle\projects\ecs-tutorial-2 ecs-tutorial-2 # для Windows при использовании Portacle
Сразу увеличим в коде размер игрового окна до 1280⨉800, чтобы покрыть бо́льшую площадь подземелья, заменив в начале файла src/main.lisp значения констант +window-width+ и +window-height+ (в Common Lisp принято ставить знак + в начале и конце имён констант, чтобы в коде было сразу понятно, что это не переменная — это совершенно корректно синтаксически):
(define-constant +window-width+ 1280)
(define-constant +window-height+ 800)
И, наконец, убедимся в работоспособности нового проекта, запустив sbcl и передав ему следующий код на выполнение:
(ql:quickload :ecs-tutorial-2)
(ecs-tutorial-2:main)
В результате мы увидим чёрное окно нужного разрешения с одиноким счётчиком FPS:

Подземелья
Чтобы дать возможность игроку ползать по подземельям, первым делом нам понадобится карта подземелья.

Для её создания воспользуемся замечательным опенсорсным редактором карт Tiled, который является не только кроссплатформенным, но и кросс-движковым, так как сохраняет данные карт в тривиальном XML, который поддерживается буквально везде, включая, конечно же, Common Lisp. Более того, существует библиотека cl-tiled, загружающая файлы в формате Tiled в виде Lisp-объектов, которой мы будем пользоваться.
Для быстрого старта можно начать с нехитрой карты подземелья, использующую комплект элементов карты (т.н. тайлсет) Dungeon Tileset II - Extended, которая выглядит в редакторе примерно следующим образом:

Готовые файлы карты (тайлсет и файл для Tiled level1.tmx, содержащий внутри себя XML) можно скачать здесь, однако давайте разберёмся, как получить такой же результат. Сначала нужно подогнать размер тайлсета, так как 16⨉16 пикселей — это мелковато. Увеличим его вдвое, скачав по ссылке архив dungeontiles-extended v1.1.zip (можно задонатить автору тайлсета, если есть возможность, а можно скачать бесплатно, нажав ссылку "No thanks, just take me to the downloads"), распаковав файл dungeontileset-extended.png из архива в каталог Resources нашего проекта и обработав его с помощью ImageMagick следующей командой:
convert dungeontileset-extended.png -filter box -resize 200% dungeontileset-extended2.png
После этого мы можем создать файл карты, запустив Tiled и сначала выбрав пункт меню Файл
