Сначала небольшое предисловие. Как и обещал ранее, напишу в виде прямолинейного описания, о своем скриптовом модуле, что использую сейчас. Модуль простой, ничего особенного нет. Но, думаю, может чем и пригодится людям, только начинающим изучать Lua и стремящихся встроить поддержку скриптов в свою программу. К модулю приложил 4 демки, представляющими из себя простенькие программы, демонстрирующие способ привязывания скриптов к логике основного приложения. Вообще, скрипты в своих программах я использовать начал недавно, пожалуй, плотно занялся скриптами начиная с AiWar, где использование скриптов было обязательным условием конкурса. Потом начал преобразовывать работу с ними, изучать более оптимальные подходы и т.д. Предупрежу сразу: сам язык Lua знаю не шибко хорошо, поэтому супер накрученных мета-таблиц и имитации ООП не использую вообще. Цель рассказал, задачу поставил, обо всем предупредил, так что... в путь!... | ![]() |
Итак, начну с того, что сам модуль uScriptManager состоит из главного класса TScriptManager и дополнительного TQueueFunction. Скриптовой класс обладает способностью строить очереди из функций, которые он должен выполнить. Далее, стоит только вызвать TScriptManager.DoAllScripts(), как вся очередь скриптов развернется, выполнится, а затем полностью очистится от только что проигранных скриптовых-объектов. Зачем все так сложно? Дело в том, что я любитель применять физические симуляции в своих программах. Зачастую, многие физические библиотеки не имеют возможности менять параметры объектов и системы в целом из произвольных мест, тем более из callback-функций, срабатывающих при вызове событий изнутри физического движка.
Например, столкнулись два тела, и я хочу в этот момент соединить их сочленением. Как будто гвоздь вбился в доску, и мне нужно создать сочленение в месте их контакта. Так вот, Box2d не позволит мне этого сделать из callback-функции столкновения объектов. Как быть? Эти события нужно только фиксировать, а выполнять различные действия после прохождения полного шага симуляции. Именно поэтому в модуле имеется дополнительный класс TQueueFunction, который и хранит внутри себя всю информацию о скриптовой функции, которую нужно будет выполнить. При вызове события теперь я вызываю TScriptManager.AddFunctionToQueue(), имеющий ряд параметров, таких как: aFunctionName - имя lua-функции, которую надо выполнить; aArguments - массив аргументов, передающихся в функцию (здесь я поленился и оставил возможность передавать только single-параметры); aSelfObject - ссылка на объект, численное значение которой будет доступно из скрипта через переменную self. Вот и все.
Вообще, для более адекватного понимания происходящих вещей рекомендую прочесть базовые уроки здесь и посмотреть/сохранить ссылки, данные в этом сообщении. Это убережет вас от непонимания таких вещей как регистрация функций в луа-машине, даст понимание функций вроде Lua_ToNumber()/Lua_ToString()/Lua_PushNumber() и т.д., по этим ссылкам сможете прочесть о стеке Lua и других простых, но важных вещах.
Давайте для закрепления пробежимся разок по обычной схеме работы с Lua.
Думаю, можно приступить к описанию демо-программ. Кстати, особо внимательные наверно заметили, что пропущена папка Demo-4, так и есть. Я сначала создал простенький пример, но потом он мне разонравился и я его убрал. Возможно, вы сами меня натолкнете на то, что внести в последний пример, что я упустил и чего не хватает во всех остальных программах.
Сначала скриншоты:
Кстати, хотел отметить, что писать здоровенные сообщения - не мой конёк, поэтому я разнесу описание демок по разным заметкам, чтобы было проще читать.
Например, столкнулись два тела, и я хочу в этот момент соединить их сочленением. Как будто гвоздь вбился в доску, и мне нужно создать сочленение в месте их контакта. Так вот, Box2d не позволит мне этого сделать из callback-функции столкновения объектов. Как быть? Эти события нужно только фиксировать, а выполнять различные действия после прохождения полного шага симуляции. Именно поэтому в модуле имеется дополнительный класс TQueueFunction, который и хранит внутри себя всю информацию о скриптовой функции, которую нужно будет выполнить. При вызове события теперь я вызываю TScriptManager.AddFunctionToQueue(), имеющий ряд параметров, таких как: aFunctionName - имя lua-функции, которую надо выполнить; aArguments - массив аргументов, передающихся в функцию (здесь я поленился и оставил возможность передавать только single-параметры); aSelfObject - ссылка на объект, численное значение которой будет доступно из скрипта через переменную self. Вот и все.
Вообще, для более адекватного понимания происходящих вещей рекомендую прочесть базовые уроки здесь и посмотреть/сохранить ссылки, данные в этом сообщении. Это убережет вас от непонимания таких вещей как регистрация функций в луа-машине, даст понимание функций вроде Lua_ToNumber()/Lua_ToString()/Lua_PushNumber() и т.д., по этим ссылкам сможете прочесть о стеке Lua и других простых, но важных вещах.
Давайте для закрепления пробежимся разок по обычной схеме работы с Lua.
- сначала создаем объект класса TScriptManager, который, в свою очередь, создаст виртуальную машину Lua, загрузит библиотеку и подготовит все к работе.
- регистрируем функции для сообщения хост-программы и луа-скриптов.
- загружаем скрипты с помощью метода TScriptManager.LoadScriptFile() или TScriptManager.LoadScriptStream()
- в любой момент времени теперь можем вызвать TScriptManager.DoScript() для выполнения скриптовой функции, ранее загруженной в память.
- убиваем объект, созданный в первом пункте.
Думаю, можно приступить к описанию демо-программ. Кстати, особо внимательные наверно заметили, что пропущена папка Demo-4, так и есть. Я сначала создал простенький пример, но потом он мне разонравился и я его убрал. Возможно, вы сами меня натолкнете на то, что внести в последний пример, что я упустил и чего не хватает во всех остальных программах.
Сначала скриншоты:
Кстати, хотел отметить, что писать здоровенные сообщения - не мой конёк, поэтому я разнесу описание демок по разным заметкам, чтобы было проще читать.
Ссылка на описание первой демо.
Ссылка на описание второй демо.
Ссылка на описание третьей демо.
Ссылка на описание пятой демо.