Предисловие
Возможно у вас наступал такой момент, что хотелось написать свой движок для игр, или просто вы хотели узнать, как такое реализовать, но по каким — то причинам вам это не удавалось.
Ну что ж, тема довольно обширная, поэтому я начинаю серию уроков по написанию своего 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 — интерпретатор.
В второй части приступим к выводу графики.
Автор: Wolf_Black