Предисловие
Возможно у вас наступал такой момент, что хотелось написать свой движок для игр, или просто вы хотели узнать, как такое реализовать, но по каким — то причинам вам это не удавалось.
Ну что ж, тема довольно обширная, поэтому я начинаю серию уроков по написанию своего 2д игрового движка, и поверьте он будет не хуже того же Love2d, именно такого стиля и будет наш движок.
Что нужно?
- Средние знания С++(на нем и будем писать двигатель).
- Базовые знания Lua (для описания игровой логики).
Как все устроено?
Вся игровая логика будет программироваться в файле, например — «main.lua». Движок будет читать этот файл и исполнять действия описанные в этом файле. Вывод графики будет с помощью SDL 2.0, физика — Box2D, аудио — OpenAl, скриптинг — Lua. IDE — Microsoft Visual Studio любой версии.
Нарисовал схему

Начинаем!
Сначала надо скачать:
- Lua
- SDL 2.0
- Box2D (надо будет скомпилировать самому)
- OpenAL
Скачайте и переместите все файлы в отдельную папку, например — «Engine SDK». Открываем MVS, создаем «пустое» консольное приложение, далее добавляем файл — «main.cpp».
Заполняем пока таким образом:
int main() { return 0; }
Компилируем, если скомпилировалось, идем дальше. Жмем «Project → project properties». Выбираем «C/C++ → General» и добавляем дополнительные папки включения (указывайте путь где вы извлекли из архива Lua). Указываем путь к «include» Lua.

После этого заходим «Linker → General» и добавляем путь к либе.

Применяем и изменяем «main.cpp»
int main(int argc, char * argv[]) { return 0; }
Компилируем, идем дальше. Далее нам нужно создать отдельный заголовочный файл, в котором будет основная часть движка. Добавляем файл «Engine.h». И сразу заполняем его таким образом.
#include<iostream> #include<lua.hpp> #pragma comment(lib,"lua53") // на момент написания статьи версия Lua 5.3. using namespace std; class Lua { private: lua_State * lua_state; public: void Init() // инициализируем и подключаем модули. { lua_state = luaL_newstate(); static const luaL_Reg lualibs[] = { { "base", luaopen_base }, { "io", luaopen_io }, { "os",luaopen_os }, { "math",luaopen_math }, { "table",luaopen_table }, { "string",luaopen_string }, { "package",luaopen_package }, { NULL, NULL } }; for (const luaL_Reg *lib = lualibs; lib->func != NULL; lib++) { luaL_requiref(lua_state, lib->name, lib->func, 1); lua_settop(lua_state, 0); } } void Open(const char*filename) // открываем файл с кодом (main.lua) { luaL_openlibs(lua_state); if (luaL_dofile(lua_state, filename)) { const char*error = lua_tostring(lua_state, -1); } } void Close() // закрываем { lua_close(lua_state); } void Reg_int(int value, char*name) { lua_pushinteger(lua_state, value); lua_setglobal(lua_state, name); } void Reg_double(double value, char*name) { lua_pushnumber(lua_state, value); lua_setglobal(lua_state, name); } void Reg_bool(bool value, char*name) { lua_pushboolean(lua_state, value); lua_setglobal(lua_state, name); } void Reg_string(char*value, char*name) { lua_pushstring(lua_state, value); lua_setglobal(lua_state, name); } void Reg_function(lua_CFunction value, const char*name) // регистр нашей функции { lua_pushcfunction(lua_state, value); lua_setglobal(lua_state, name); } int Get_int(int index) // берем числовой аргумент из функции { return (int)lua_tointeger(lua_state, index); } double Get_double(int index) { return lua_tonumber(lua_state, index); } char* Get_string(int index) { return (char*)lua_tostring(lua_state, index); } bool Get_bool(int index) { return lua_toboolean(lua_state, index); } void Return_int(int value) // возвращаем числовое значение из функции { lua_pushinteger(lua_state, value); } void Return_double(double value) { lua_pushnumber(lua_state, value); } void Return_string(char*value) { lua_pushstring(lua_state, value); } void Return_bool(int value) { lua_pushboolean(lua_state, value); } int Call_load() // вызываем при старте { lua_getglobal(lua_state, "Load"); lua_call(lua_state, 0, 1); return 0; } int Call_update() // вызываем пока работает приложения { lua_getglobal(lua_state, "Update"); lua_call(lua_state, 0, 1); return 0; } int Call_draw() { lua_getglobal(lua_state, "Draw"); // вызываем после "Update" lua_call(lua_state, 0, 1); return 0; } }; Lua lua;// lua экземпляр
Компилируем, если нет ошибок, идем дальше, если же есть, значит вы где- то накосячили. Изменяем «main.cpp»:
include "Engine.h" int main(int argc, char * argv[]) { lua.Init(); lua.Open("main.lua"); lua.Call_load(); lua.Close(); return 0; }
Компилируем, если без ошибок, двигаемся дальше. Создаем в папке проекта текстовый файл «main.lua». Заполняем его так:
function Load() print("Lua inited!") end function Update() end function Draw() end
Компилируем, бросаем «lua5*.dll» в папку проекта, запускаем, и Оппа! В консоле вывело «Lua inited!». По сути мы написали простой Lua — интерпретатор. В второй части приступим к выводу графики.
