Изначально это планировалось как консольная игра на C# с возможностью моддинга при помощи Lua-скриптов — обычный проект для обучения языку и правильной архитектуре.
Но теперь это нечто большее.
Это песочница для создания игр (а может, и не только). Её ядро написано на C# и использует Lua-скрипты. Не нужно перекомпилировать программу: можно создавать, редактировать, удалять скрипты в реальном времени и видеть результат в терминале. Ядром предоставляются инструменты для взаимодействия с консолью и C#-окружением.
(Взаимодействие со скриптами Lua осуществляется при помощи NLua. Мне не удалось обрезать неиспользуемый код в Visual Studio 2022, сохранив работоспособность NLua, а разработчик не дал ответа, как это исправить. Поэтому качайте 70 Мб вместо ~12 Мб :D)
Запустите программу. Необходимые каталоги создадутся сами. Откроется консоль с сообщением об отсутствии сцены MainMenu.lua — это точка входа, самая первая сцена, с которой начинается всё. Создайте в каталоге game/scenes/ файл MainMenu.lua.
После создания пустой сцены MainMenu.lua она сразу же загрузится, но вы увидите сообщения об ошибках вызова функций FrameRenderer() и EngineUpdater(). Это потому, что их нет в этой сцене.
Каждая сцена должна хранить в себе реализации трёх глобальных функций с точными именами: InputHandler, EngineUpdater, FrameRenderer. Их можно оставить пустыми.
function InputHandler()
end
function EngineUpdater()
end
function FrameRenderer()
endБез local.
Отвечает за обработку нажатий. Вызывается каждый раз при нажатии на клавишу на клавиатуре и никогда больше. Принимает два аргумента из окружения C#: KeyName — имя клавиши (например, Spacebar, Tab или Oem6); KeyChar — символ клавиши (например, g, }, ~ и т.д.).
Вызывается каждый кадр. Не принимает аргументов. Можно использовать для обработки логики, не засоряя другие функции.
Не принимает аргументов. Вызывается каждый кадр самым последним из всех трёх, после очистки консоли из окружения C#. Это значит, что любой вывод print(), прописанный там, не будет удалён в отличие от других функций (кроме метода WriteLayer). Очевидно, используется для отрисовки символов в консоли.
Они доступны для использования как в сценах, так и в скриптах, подключенных через include.
include('твой_скрипт.lua')
-- Одна из основных функций. Выполняет скрипт из каталога game/lua/ указанный в аргументе.
-- Подключая его в основное окружение Lua.
-- Так вы можете разделять функционал на разные файлы, создавая подобие ООП.
Write('Hello ')
Writeln('World!')
-- Являются красивой копией функций io.write() и print() соответственно.
WriteLayer(слой, Left, Top, сообщение)
-- Функция вывода сообщений по слоям. Слой с числом выше будет показан поверх числа ниже.
-- Функции установки курсора на позицию не влияют на этот вывод.
-- Поэтому (не обязательно) можно указать позицию, на которой будет отрисовано сообщение:
-- Left — левый край консоли, Top — верхний край.
-- Её можно вызвать в любой точке кода, и сообщение всё равно будет показано.
-- Так как вывод осуществляется после очистки консоли.
-- WriteLayer(228, 30, 5, 'Магия Lua: ', "5" + 5)
ScrW()
ScrH()
-- Возвращают текущий размер консоли в символах: Width, Height соответственно.
CurL()
CurT()
-- Возвращают текущую позицию текстового курсора в консоли: Left, Top соответственно.
-- После любого вывода (например, print()) эти значения меняются.
SetCursorPos(Left, Top)
-- Устанавливает текстовый курсор на указанную позицию.
-- SetCursorPos(30, CurT()) — например, с сохранением текущей высоты.
SetScene('Имя')
-- Меняет текущую сцену на указанную (без расширения .lua).
-- Сцена изменится независимо от наличия файла в каталоге game/scenes
-- Просто будет ошибка на экране, пока сцена там не появится.
ShutDownGame()
-- Меняет состояние игры IsRunning на false.
-- После завершения текущего игрового цикла консоль закроется.
CreateConVar('имя', любое значение, min, max)
-- Создаёт "консольную переменную" с указанным именем и значением.
-- Если значение — число, то можно указать лимиты.
-- Такие переменные используются в game/cfg/config.lua для гибкой настройки ядра C#.
-- Вы можете использовать их как глобальные переменные.
-- CreateConVar('sv_cheats', false) Значение НЕ может быть nil.
SetConVar('имя', значение)
-- Устанавливает значение указанной консольной переменной.
-- SetConVar('sv_cheats', true)
GetConVar('имя')
-- Возвращает текущее значение переменной. Если её не существует вернёт nil.
SpawnEntity('Имя', {Left, Top})
-- Создаёт сущность и возвращает её объект.
-- Объект имеет поля и методы класса Entity.
-- Имя может повторяться.
-- Позицию обязательно указывать в фигурных скобках.
-- local rock = SpawnEntity('Rock', {5,4})
-- rock:Move(6, 5, 1)
-- rock:Kill() — удаляет сущность только из словаря C#.
GetEntityTable(таблица)
-- Получает таблицу и заносит в неё все существующие сущности из словаря C#.
-- local EntityTable = {}
-- GetEntityTable(EntityTable)
Находится по пути game/cfg/config.lua. Необходим всегда. Загружается туда программой автоматически, если отсутствует. Если допущена ошибка, то выполняется внутренний файл конфигурации.
CreateConVar('game_title', 'Terminal Warrior')
-- Название окна консоли. Загружается один раз, не меняется.
CreateConVar('second_scene_name', 'cmd')
-- Поддерживается вторая сцена на уровне ядра, на которую можно переключиться в любой момент.
-- Можно сделать сцену cmd.lua и реализовать в ней "терминал" ввода команд, и менять сцены.
CreateConVar('second_scene_char', '~')
-- Клавиша, на которую переключается вторая сцена.
CreateConVar('hot_lua_reload_char', '}')
-- Клавиша горячей перезагрузки Lua.
-- Пересоздаёт окружение со всеми стартовыми параметрами.
-- Если вы словили отвал стека, то просто нажмите на эту клавишу.
CreateConVar('fps_target', 20, 1)
-- Частота обновления консоли.
CreateConVar('DebugChar', ' ')
-- Символ-заполнитель, которым очищается консоль.