3
\$\begingroup\$

Suppose I have a code like this in C++

// Game.cpp
Entity* hero;
Entity* witch;
... // entity initialization

if(/player near witch/) {
    if(hero->get<HealthComponent>()->getHealth() < 100) {
        say("Let me help you");
        witch->get<GraphicsComponent>()->setAnimation("witch.heal");
        hero->get<HealthComponent>()->setHealth(100); 
    }
    else {
        say("Go away!");
    }
}

Suppose I want to put this code into Lua script, so I make an "interact" function in C++

void interact(Entity* first, Entity* second);

And call it like this:

interact(witch, hero);

Then I can call lua script, which gets first and second entity IDs and does something like this:

-- Script.lua
function interact(firstId, secondId)
    if(getHealth(secondId) < 100) then 
        say("Let me help you")
        setAnimation(firstId, "witch.heal")
        setHealth(secondId, 100)
    else 
        say("Go away")
    end
end

And then I can define wrapper functions in C++ like this

void setAnimation(int firstId, const std::string& animationName) {
    Entity* e = entities[firstId];
    e->get<GraphicsComponent>()->setAnimation(animationName);
}
// etc.

and call it from Lua. But this gets quite troublesome as I need to write lots of binding and wrapping(like "setAnimation") functions. Is there any other methods to control entitity behaviour using Lua?

\$\endgroup\$
2
  • \$\begingroup\$ Find (or write) a library that automates the binding as much as possible. Do a search for "lua c++ binding" and you should find a lot on the subject. \$\endgroup\$
    – glampert
    Commented Jul 2, 2014 at 1:07
  • \$\begingroup\$ @glampert Maybe my question was not exactly clear,(I've edited my question) but my main question is: should I try to find a way for Lua to know about components or should I write wrapping functions like "setAnimation" in my example? \$\endgroup\$
    – user26550
    Commented Jul 2, 2014 at 6:31

1 Answer 1

1
\$\begingroup\$

Writing binding functions gets tiresome pretty fast, and is error prone. There are two ways I can think of on how to improve this:

1) Use some Lua wrapper code that creates the interface functions you need. I did see on your blog that you have used LuaWrapper. Not sure how much support that lib have but there are others that use templates to create the binding functions. For my own project, I wrote my own system that also have the name LuaW. This is an example of what my code looks like. All objects are managed (created/destroyed) in the C++ code:

C++ side:

LuaW_Class<CameraComponent>( scriptEngine->m_pkState, "CameraComponent");
LuaW_ClassFunction(scriptEngine->m_pkState, "CameraComponent", "GetName", &CameraComponent::GetName);
LuaW_ClassFunction(scriptEngine->m_pkState, "CameraComponent", "GetCamera", &CameraComponent::GetCamera);
LuaW_ClassFunction(scriptEngine->m_pkState, "CameraComponent", "AddTestRenderer", &CameraComponent::AddTestRenderer);

LuaW_RegisterGlobal<World>(scriptEngine->m_pkState, "World", m_world.get());

Lua side:

local cament = World:MainScene():CreateEntity("blueprints/camfront.blueprint", Vector3:new(0,0,0) )
camcomp = cament:GetComponent("CameraComponent")
camcomp:AddTestRenderer()

By using a wrapper lib like that you can stop writing binding functions, unless of course you wish to do something special like returning multiple values.

2) The second way is to keep the components and as much stuff as possible in Lua code. So most of your game will be in Lua and only the functions you really need to write in C++ will require a binding function.

\$\endgroup\$
2
  • \$\begingroup\$ Thanks for your answer! Two more questions: 1)Is my method of working with entities okay? I think it's easier to make some wrapper functions (like "setAnimation" in my example) than make a way to access components for each entity. Or should I do it the way you have shown? 2) You create entity in Lua in your example. How can you access it in C++? What if you have hundreds of entities? Is it possible to create them in Lua while still having fast access to them in C++? \$\endgroup\$
    – user26550
    Commented Jul 2, 2014 at 6:29
  • \$\begingroup\$ 1: I think both ways are fine. You can also try a mix of both by writing a custom wrapper generator. One that generate functions like you already have that get's the component and call the function. That way you do not need to expose the components to lua code. It's the next step i will look into for my own LuaW code. 2: Entitys are always created in C++ and returned to lua as userdata so it's no problem handling them in C++. I use MainScene():DestroyEntity() to remove them. \$\endgroup\$
    – Vim
    Commented Jul 2, 2014 at 10:41

You must log in to answer this question.