Custom scripting engine for games using C ++ and Lua (part - 1)
- Tutorial
Foreword
Perhaps you had such a moment that you wanted to write your own engine for games, or you just wanted to find out how to implement this, but for some reason you did not succeed.
Well, the topic is quite extensive, so I'm starting a series of lessons on writing my 2d game engine, and believe me it will be no worse than the same Love2d, this is the style our engine will be.
What do you need?
- Average knowledge of C ++ (we will write the engine on it).
- Basic knowledge of Lua (for describing game logic).
How is everything arranged?
All game logic will be programmed in a file, for example, “main.lua”. The engine will read this file and perform the actions described in this file. Graphics output will be using SDL 2.0, physics - Box2D, audio - OpenAl, scripting - Lua. IDE - Microsoft Visual Studio any version.
Drew a diagram

Getting started!
First you need to download:
- Lua
- SDL 2.0
- Box2D (you will need to compile yourself)
- Openal
Download and move all the files to a separate folder, for example - “Engine SDK”. Open MVS, create an "empty" console application, then add the file - "main.cpp".
So far we are filling in this way:
intmain(){
return0;
}
Compile, if compiled, move on. Click “Project → project properties”. Select “C / C ++ → General” and add additional inclusion folders (indicate the path where you extracted from the Lua archive). Specify the path to "include" Lua.

After that, go to “Linker → General” and add the path to the lib.

Apply and modify “main.cpp”
intmain(int argc, char * argv[]){
return0;
}
Compile, move on. Next, we need to create a separate header file in which the main part of the engine will be. Add the file “Engine.h”. And immediately fill it in this way.
#include<iostream>#include<lua.hpp>#pragma comment(lib,"lua53") // на момент написания статьи версия Lua 5.3.usingnamespacestd;
classLua
{private:
lua_State * lua_state;
public:
voidInit()// инициализируем и подключаем модули.{
lua_state = luaL_newstate();
staticconst 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);
}
}
voidOpen(constchar*filename)// открываем файл с кодом (main.lua){
luaL_openlibs(lua_state);
if (luaL_dofile(lua_state, filename))
{
constchar*error = lua_tostring(lua_state, -1);
}
}
voidClose()// закрываем{
lua_close(lua_state);
}
voidReg_int(int value, char*name){
lua_pushinteger(lua_state, value);
lua_setglobal(lua_state, name);
}
voidReg_double(double value, char*name){
lua_pushnumber(lua_state, value);
lua_setglobal(lua_state, name);
}
voidReg_bool(bool value, char*name){
lua_pushboolean(lua_state, value);
lua_setglobal(lua_state, name);
}
voidReg_string(char*value, char*name){
lua_pushstring(lua_state, value);
lua_setglobal(lua_state, name);
}
voidReg_function(lua_CFunction value, constchar*name)// регистр нашей функции{
lua_pushcfunction(lua_state, value);
lua_setglobal(lua_state, name);
}
intGet_int(int index)// берем числовой аргумент из функции{
return (int)lua_tointeger(lua_state, index);
}
doubleGet_double(int index){
return lua_tonumber(lua_state, index);
}
char* Get_string(int index){
return (char*)lua_tostring(lua_state, index);
}
boolGet_bool(int index){
return lua_toboolean(lua_state, index);
}
voidReturn_int(int value)// возвращаем числовое значение из функции{
lua_pushinteger(lua_state, value);
}
voidReturn_double(double value){
lua_pushnumber(lua_state, value);
}
voidReturn_string(char*value){
lua_pushstring(lua_state, value);
}
voidReturn_bool(int value){
lua_pushboolean(lua_state, value);
}
intCall_load()// вызываем при старте{
lua_getglobal(lua_state, "Load");
lua_call(lua_state, 0, 1);
return0;
}
intCall_update()// вызываем пока работает приложения{
lua_getglobal(lua_state, "Update");
lua_call(lua_state, 0, 1);
return0;
}
intCall_draw(){
lua_getglobal(lua_state, "Draw"); // вызываем после "Update"
lua_call(lua_state, 0, 1);
return0;
}
};
Lua lua;// lua экземпляр
We compile, if there are no errors, go ahead, if there is, then you have messed up somewhere. Change "main.cpp":
include "Engine.h"intmain(int argc, char * argv[]){
lua.Init();
lua.Open("main.lua");
lua.Call_load();
lua.Close();
return0;
}
Compile, if without errors, move on. Create a text file “main.lua” in the project folder. Fill it like this:
functionLoad()print("Lua inited!")
endfunctionUpdate()endfunctionDraw()end
Compile, drop “lua5 * .dll” into the project folder, run, and Oppa! In the console, "Lua inited!" Essentially, we wrote a simple Lua interpreter. In the second part, we proceed to the conclusion of the graphics.