Реализация Скрипт-Движка.
Автор: Jan Niestadt
Часть I: Обзор
Часть II: Лексический Анализатор
Часть III: Синтаксический Анализатор
Часть IV: Таблица Идентификаторов и Синтаксическое Дерево
Часть V: Проверка семантики и генератор промежуточного кода
Часть VI: Оптимизация
Часть VII: Виртуальная Машина
Часть VIII: Исполняемый код
Часть IX: Дополнительные возможности
Часть I: Обзор
Итак. Вы решили, что вашему движку не достает языка скриптов. А почему? Потому что это просто круто, и сейчас они есть почти во всех играх.
Решите, для начала, какого рода скрипт-движок вам нужен. Генри Робинсон уже составил краткий обзор различных типов (обязательно взгляните на его работу, если вы этого еще не сделали). В этой серии учебных пособий я расскажу вам о системе компилятор/виртуальная машина, такой как UnrealScript.
Теперь пришло время разобраться, почему скрипт-движок не просто крут, но и на самом деле полезен.
Скрипт-язык обладает следующими преимуществами:
• Его можно наделить специфичными (и полезными) синтаксическими конструкциями, такими как состояния, скрытый код, и т.п.
• Скрипт-язык изолирован от игрового движка ("sandbox environment"), отчего никогда его не разрушит.
• Разные люди через скрипт смогут расширять геймплей игрушки, не обладая знаниями о внутреннем устройстве программы, без необходимости перекомпилирования ее отдельных частей.
• Скрипт-язык полностью независим от игровой платформы
Однако существует ряд недостатков:
• Относительно низкая скорость выполнения. По крайней мере в 15 раз медленнее, чем аналогичный код на машинном языке.
• Ограниченная область применения скрипта. Например, он не может быть использовать для создания новых графических спецэффектов. (Отчасти, из-за ограничений в скорости)
• Людям, которые создают новые возможности игрушки, приходится изучать новый язык.
Конечно же, эти штуки нас не остановят; мы уже все обдумали и решили двинуться дальше. С чего же начать?
То, что следовало бы прочитать
Я приступил к работе еще задолго, до того как выпустили Unreal. Искал их технический сайт в интернете, и нашел справочное руководство по UnrealScript. Безусловно, я слышал что-то об UnrealScript, но по сути дела понятия не имел, что это такое. Прочитал руководство и для себя решил, что скрипт-язык - по-настоящему крутая идея. Хотел написать свой собственный, прицепить его к игрушке, чтобы целый мир работал над созданием новых возможностей для моей игры.
К счастью, в том семестре у нас шли занятия по конструированию компиляторов, и в качестве практического задания, нам пришлось сотворить ОЧЕНЬ простой компилятор Паскаля. Параллельно я начал разрабатывать свой собственный урезанный Си-подобный компилятор. Работа заняла всего две недели, и внутренняя структура была ну очень страшной. В конечном счете, мне пришлось полностью ее изменить. Скорее всего, вы пережили нечто подобное в своей жизни. Поэтому я до сих пор над этим всем работаю, узнаю больше о компиляторах на практике.
Однако пора бы поговорить по сути дела.
В первую очередь, я советую всем, кто собирается написать компилятор, приобрести книгу Dragon book. Многие из вас (особенно студенты компьютерных специальностей, как и я сам) уже что-то об этой книге слышали. (Недавно перевод этой книги вышел и в России, в русском варианте она называется: "Компиляторы: принципы, технологии и инструменты", см. http://www.williamspublishing.com/Books/Bibliography/B_sci_Compilers.html, прим. пер.) Поверьте мне на слово, тот, кто когда-либо имел дело с компиляторами, листал в свое время эту книгу.
Если вам нужен краткий обзор того, как реализовать скрипт-язык на байт-коде, проверьте эту статейку на GamaSutra (см. вариант на русском, прим. перев.). Довольно занятная история о том, как разрабатывался скрипт-язык Jedi Knight. Я также охвачу весь, описываемый там, материал, однако все же это интересное чтиво.
Что нам нужно.
По существу, компилятор состоит из следующих компонентов:
• Таблица идентификаторов, которая содержит список идентификаторов, информацию о типах, "словарном запасе", и т.п.
• Лексический анализатор (Lexer). Преобразует последовательность символов (из файла-источника) в последовательность лексем (таких как, ключевые слова, операторы, и т.д.)
• Синтаксический анализатор (Parser). Берет последовательность лексем и строит по ним синтаксическое дерево.
• Блок семантического контроля (Semantic Checker). Проверяет синтаксическое дерево на наличие ошибок.
• Генератор промежуточного кода (Intermediate Code Generator). Преобразует синтаксическое дерево в промежуточный код.
• Оптимизатор (Optimizer). (не обязательно). Оптимизирует промежуточный код.
• Генератор байт-кода (Bytecode Generator). Создает байт-код по промежуточному коду.
• И последняя, но не самая примитивная штука: виртуальная машина, выполняющая этот байт-код.
Как только вы напишите все эти компоненты, они и будут представлять собой полнофункциональную скрипт-систему.
И это все?
Ошеломлены? Уже сомневаетесь в том, что скрипт язык такой крутой, и реальнее все-таки воспользоваться DLL? Не надо. Я расскажу подробно обо всех компонентах, и большинство из них не такие уж сложные. Правда, создание полнофункционального движка - это *огромная* работа, поэтому очень важно добиться структурной организации кода.
В оставшихся частях этого пособия мы разработаем очень простую систему "компилятор / виртуальная машина". Конечно, настоящий транслятор скриптов ей и в сравнение нельзя поставить, но все описанные функции она будет выполнять. Я задумал простейший язык для манипулирования строками текста.
15 июня 2002
Комментарии [6]