C++ as a scripting language for Cocos2d-x

I was googling around looking for examples on how to use C++ as a scripting language and found this:

  • In this post the author explains how they use runtime-compiled C++ code as a scripting language in the Molecule engine.

  • Also found something that loos as a good starting point for a library to add this feature to Cocos2d-x.

  • … and some kind of C++ interpreter at runtime.

Has anyone tried to use C++ code as a scripting language for Cocos2d-x?

Sounds like a crazy idea given the amount of infrastructure required to get a compiler toolchain to work (compiler, assembler, linker, libraries, other stuff).

I would have thought Lua was a better choice, however I don’t know if you can mix C++ and Lua with Cocos2d-x. I would certainly like to hear about what’s involved if anyone has done it.

As of v3.10, I think you can mix c++ and Lua (and JavaScript).

http://cocos2d-x.org/docs/programmers-guide/10/index.html

If i understood it correctly, it may be at least a good addition to CocoStudio/CocosCreator - so it can work with custom c++ nodes and components directly, without writing C# wrappers.

@MikhailSh I think that being able to edit code and immediately see the changes at runtime is a must-have feature, so Lua or JavasScript should be enough to do the job. But I’m aware at least of two game engines (Unreal Engine 4 and Molecule Engine) that are using C++ as a scripting language, and the way they do it is compiling and linking C++ code at runtime. Maybe something like this could be added too to Cocos2d-x.

@slackmoehrle Thanks for the info.

ChaiScript works well, especially if you’re using it for internal scripting, but if you want to support modders then Lua or Javascript) would be smarter.

Edit: removed paragraph since your first link explained this already.

I wish that were true.
From your link

“Script component supports both JavaScript and LUA. You should use the proper script component type for the language you are developing with. If you are developing with JavaScript, you would use ComponentJS, if you are developing with Lua, you would use ComponentLUA. But, you cannot mix them or use them in a c++ project! This is because the proper bindings for that language are required and these bindings are only available in their respective project types.”

I must admit, I didn’t understand completely - but that last sentence implies that I can’t just add scripting to my C++ project.
Which exactly what I would like to do. :frowning:

In principal what I would like to do is have a number of js files in my resources that perform some of the setup - say defining the terrain in a scroller.

Now, in principal, I could download a js at runtime, and execute that script for a new terrain.

But it seems I still can’t do that ‘natively’ in cocos2d-x - unless I create a Javascript project.

:frowning:

The repository for the project Runtime Compiled C++ provides a comprehensible list of some game engines and proof of concepts using C++ as a scripting language through realtime compilation.

From the list, livecode-cplusplus (simple C++ live coding environment based on openFrameworks) worth trying as a proof of concept by just swapping OF by Cocos2d-x. Although I wouldn’t mind to have a template with a couple of scripts to get a Cocos2d-x with C++ scripting support up and running in this way.

Also Cling (JIT C++ compiler) seems interesting. This one should take some work but it could be added as a command line tool to the game, so that one could tweak values at runtime. Although something like this could be easily accomplished using Lua or JavaScript.

I agree with you that it’s too complex, not documented well enough, or just isn’t built to allow adding the Javascript/Lua runtime into a game originally created with c++ and it definitely should be both possible and not to difficult to setup a simple command in the cocos tool to copy over the needed files or link to the correct libraries (or library projects) in the same manner as occurs when you specify a Lua/JS project type in the original cocos create.

That said, have you tried to create a new project with JS and then tested copying over all your C++ files and running the c++ game scene instead of the default runScript(script_scene) instead?

Scratch that: I just created one. It’s definitely possible.

It should be easier to add lua into c++ for scripting, without doing it this way, and so you can not include some of the bindings if you don’t need them.


Create Project

cocos new -p com.p.cpp-lua-test -l lua -d ~/dev/tests cpp-lua-test

AppDelegate

// ... 
#include "CCComponentLua.h"
// ...
#else
    if (engine->executeScriptFile("src/main.lua"))
    {
        log("ERROR EXEC main.lua");
        return false;
    }
#endif

// Add test and run scene from c++ instead of main.lua
    auto scene = Scene::create();
    {
        auto sprite = Sprite::create();
        sprite->setTextureRect(Rect(0,0,100,100));
        sprite->setColor(Color3B::WHITE);
        scene->addChild(sprite);

        // create a Sprite and add a LUA component
        auto luaComponent = ComponentLua::create("src/player.lua");
        sprite->addComponent(luaComponent);
        log("created!");

        // test c++ side actions
        scene->scheduleOnce([sprite](float dt){
            log(dt);
            auto move = MoveBy::create(.5f, Vec2(100,20));
            auto seq = Sequence::create(move, move->reverse(), nullptr);
            sprite->runAction(RepeatForever::create(seq));
        }, 2.f, "asdf");
    }
    Director::getInstance()->runWithScene(scene);

src/player.lua

local player = {
    onEnter = function(self)
        print("entering")
        local director = cc.Director:getInstance()
        local winSize = director:getVisibleSize()
        local visibleOrigin = director:getVisibleOrigin()

        local me = self:getOwner()
        local contentSize = me:getContentSize()
        me:setPosition(winSize.width/2 - contentSize.width/2 + visibleOrigin.x,
                       winSize.height/2 - contentSize.height/2 + visibleOrigin.y)
    end,

    onExit = function(self)
        print("exiting")
    end,

    update = function(self)
        -- on update
        local color = cc.c3b(math.random() * 255, math.random() * 255, math.random() * 255)
        self:getOwner():setColor(color)
    end
}
print("test")
-- it is needed to return player to let c++ nodes know it
return player

src/main.lua (comment out the lua side mvc app and scene creation)

local function main()
    --require("app.MyApp"):create():run()
    math.randomseed(os.time())
end
1 Like

Mr Tranby, I am indebted to you!
It took me a while to get your code working (I had to change the path from src/player.lua to just player.lua - which is probably just me creating it in the wrong place

But I now have a randomly flashing square bouncing around my screen :smile:

I’ll have a play to see if I can add my existing game to this source, so I can use scripting like the big boys!

Heck - not I need to learn LUA !!

It’s certainly worth considering using Lua as a scripting language, especially for more game-designer-level coding, like deciding that a level is complete or for working with more complex puzzles involving triggers, etc. Something that you wouldn’t want to hard code into C++.

However does the Lua script effectively subclass the node it’s attached to and therefore have access to its instance variables? What is the relationship between the C++ Node subclass and the Lua script?

I also assume the script will be in the Resources folder and would be called something like scripts/player.lua and found using the normal FileUtils search logic?

The file is found through the normal search facilities of FileUtils, yes. Note that using cocos Node/Sprite methods like setPosition and setColor require some of the initialization that is done by calling the register script ‘main.lua’.

One could instead include Lua separately by downloading the standard Lua *.c and *.h files and integrate everything yourself. You’ll find that cocos2d-x has the lua binding facilities that make it easier to write the glue code between Lua and C++ (similarly with JS as well).

Please don’t consider my example as something to use directly in a production game. It effectively sets up the entire cocos2d-Lua framework and may be overkill. You’ll probably want to prune down what gets loaded and what is exposed on the Lua side of things. Anyway, have fun.

Using ComponentLua and/or utilizing the scripting bindings that cocos2d-x provides will give access to all properties and methods which have generated bindings. So any methods or properties you add to the class in c++ will not be available until you generate bindings for them. You should also be able to add any fields or properties you want to be called to/from Lua, but you’ll have to use the binding generator or write the binding code by hand.

This setup is mainly useful for the game development team and only appropriate for modders if you don’t mind them having full control and access to node properties.

Thanks for the update; I will consider using Lua in my game shortly…