Jump to content

Lua or C++?

reepblue

1,308 views

Through out the Leadwerks community you'll find two types of users. You'll find a large portion of the community using lua, and a small dosage of them using C++. This makes sense as people are more often going to purchase Leadwerks without any DLCs (including the Professional Edition), and get into developing. From experience, Leadwerks at the moment puts it's primary focus on Lua scripts with it's script editor and debugger, flowgraph editor, and the script property system. Everything is pretty straight forward and it's quick and easy to prototype and develop your games. Throw in an entity in the editor, attach a script to it, adjust some values, set up connections and you're done!

 

You'll also find a smaller chunk of the user base talking about C++. Unfortunately.as of writing this blog post, a life of a C++ user is more difficult. For one thing, we don't have any connection with the editor so any entitys we want to put in our game need to be done during run time. If you made this cool monster in C++, you'd also need to make a system so your level designers (or you) can place them in the levels. Some examples of this is people using editor placed pivot's names as spawn markers. And even if then, you'd have to make a Lua script for that pivot to send any custom/modifiable values or special events to the C++ class. Not to mention, you'll need to search around how to communicate both languages together. And if people are suborn about learning Lua, they'll end up making systems that conflict with existing features/editor Things get messy fast when making gameplay with C++.

 

Ok, so why do we bother then? While Lua is an ideal choice for gameplay, but what about the rest of your game? You still need to control how your window, context and world handles, how user settings get applied, and a lot other gross stuff that goes into a game. You can use Lua for that, but you'll run into two issues. For one, if you're working with a team, you'll have to trust them not to touch anything relating to the under the hood stuff unless they know what they are doing. You'll also have that paranoia of slow down due to using Interpreter for everything. You'll need a lot of script logic to cause any slow down, but who knows what you're doing when it comes to the background stuff.

 

My solution is easy, use both together!

 

My application Leadwerks Extended Executable is designed to handle all the yucky bits in the application side of things while you can use the engine as intended. All it does is instead of launching main.lua, it calls a App class which handles the window, context, and world along with reading user settings. As of version 2, you can communicate to the C++ classes in Lua with the AppManager Class

 

-- This line will spam We're Connected" if we're in a map.
if AppManager:IsConnected() then System:Print("We're Connected") end

 

All the guts are "locked out" for the rest of the team so you don't need to worry about Mike from the art department accidentally touching the window handling system, and setting the project back a few weeks.

 

LEX2 also has 2 classes to accommodate for C++ gameplay classes, Actors, and Puppeteers. Puppeteers act like a Lua script. You attach an entity to the class and write the code like if you were writting a Lua Script. We're still lacking an efficient way to connect an editor entity to a class. I tried to use a Lua script, but due to the fact you'd need a script per puppeteer for it's custom values and flowgraph support, you might as well just write the damn code in Lua and be done!

 


#if !defined( PUPPETEER_H )

#define PUPPETEER_H

#pragma once

 

#include "base.h"

 

namespace Leadwerks

{

// Puppeteer's are pretty much the C++ version of lua scripts.

// While using this class, keep note that this class doesn't exist in the game world.

class Puppeteer : public Object

{

public:

Puppeteer(Entity* pEntity);

virtual ~Puppeteer() {};

 

virtual void Start() {};

virtual void PostStart() {};

 

virtual void Collision(Entity* pEntity, float* position, float* normal, float speed) {};

virtual void Draw(Camera* camera) {};

virtual void DrawEach() {};

virtual void PostRender(Context* context) {};

virtual void UpdateMatrix() {};

virtual void UpdatePhysics() {};

virtual void UpdateWorld() {};

 

void Detach();

void RemoveAll();

 

Entity* GetPuppet()

{

return entity;

}

 

Entity* entity; // The entity we'll be controlling. Was gonna rename this to 'puppet', but I want programing Puppeteer classes to be the same as scripting in lua.

 

// We can get script values like this.

bool GetBoolValue(std::string pValve)

{

return entity->GetBool(pValve);

}

 

float GetFloatValue(std::string pValve)

{

return entity->GetFloat(pValve);

}

 

int GetIntValue(std::string pValve)

{

return static_cast<int>(entity->GetFloat(pValve));

}

 

std::string GetStringValue(std::string pValve)

{

return entity->GetString(pValve);

}

 

protected:

static void CollisionHook(Entity* entity0, Entity* entity1, float* position, float* normal, float speed);

static void DrawHook(Entity* entity);

static void DrawEachHook(Entity* entity);

static void PostRenderHook(Entity* entity);

static void UpdateMatrixHook(Entity* entity);

static void UpdatePhysicsHook(Entity* entity);

static void UpdateWorldHook(Entity* entity);

};

}

 

#endif //PUPPETEER_H

 

 

There are also Actors. Unlike how Puppeteers work in which you assign an entity to it, this time you're building on top of the object. and it exists in the world. It's only really good for players, but I ran into a pickle recently where the player would not spawn in the position I tell it to. I ended up translating the entire code to Lua and it works as intended. with the bonus of the flowgraph mind you.

 


 

#if !defined( ACTORS_H )

#define ACTORS_H

#pragma once

 

#include "base.h"

 

namespace Leadwerks

{

// Actors are the entites, but behaving like it's under a lua script or Puppeteer.

// Unlike scripts or Puppeteers, this class was ment to be the base of controlling the ACTUAL entity, without a middle class.

class PivotActor : public Pivot

{

public:

PivotActor(Entity* parent = NULL);

virtual ~PivotActor();

 

virtual void Collision(Entity* entity, float* position, float* normal, float speed) {};

virtual void Draw(Camera* camera) {};

virtual void DrawEach() {};

virtual void PostRender(Context* context) {};

virtual void UpdateMatrix() {};

virtual void UpdatePhysics() {};

virtual void UpdateWorld() {};

 

protected:

static void CollisionHook(Entity* entity0, Entity* entity1, float* position, float* normal, float speed);

static void DrawHook(Entity* entity);

static void DrawEachHook(Entity* entity);

static void PostRenderHook(Entity* entity);

static void UpdateMatrixHook(Entity* entity);

static void UpdatePhysicsHook(Entity* entity);

static void UpdateWorldHook(Entity* entity);

};

 

class ModelActor : public Model

{

public:

ModelActor(std::string pPath, Entity* parent = NULL);

virtual ~ModelActor();

 

virtual void Collision(Entity* entity, float* position, float* normal, float speed) {};

virtual void Draw(Camera* camera) {};

virtual void DrawEach() {};

virtual void PostRender(Context* context) {};

virtual void UpdateMatrix() {};

virtual void UpdatePhysics() {};

virtual void UpdateWorld() {};

 

protected:

static void CollisionHook(Entity* entity0, Entity* entity1, float* position, float* normal, float speed);

static void DrawHook(Entity* entity);

static void DrawEachHook(Entity* entity);

static void PostRenderHook(Entity* entity);

static void UpdateMatrixHook(Entity* entity);

static void UpdatePhysicsHook(Entity* entity);

static void UpdateWorldHook(Entity* entity);

};

 

class CameraActor : public Camera

{

public:

CameraActor(Entity* parent = NULL);

virtual ~CameraActor();

 

virtual void Collision(Entity* entity, float* position, float* normal, float speed) {};

virtual void Draw(Camera* camera) {};

virtual void DrawEach() {};

virtual void PostRender(Context* context) {};

virtual void UpdateMatrix() {};

virtual void UpdatePhysics() {};

virtual void UpdateWorld() {};

 

protected:

static void CollisionHook(Entity* entity0, Entity* entity1, float* position, float* normal, float speed);

static void DrawHook(Entity* entity);

static void DrawEachHook(Entity* entity);

static void PostRenderHook(Entity* entity);

static void UpdateMatrixHook(Entity* entity);

static void UpdatePhysicsHook(Entity* entity);

static void UpdateWorldHook(Entity* entity);

};

 

// TODO: Maybe make a SpriteActor?

}

#endif //ACTORS_H

 

 

It was kind of hard writing this entry as I work with both languages. I guess the overall message is to chose you're battles and do what's in your skill set and preferences. I'd still love there to be an easy way to code gameplay elements in C++ like I do with Source. The class hierarchy system really comes in handy as you can just make a bunch of base classes and build off of them as needed. Hopefully, this will get addressed soon. In-fact, I actually made this blog post in reflection of this forum post. Maybe someday we can make our games fully in C++ and have access to the flowgraph editor and to be able to set custom properties!



2 Comments


Recommended Comments

From my own experience I do combine sometimes. Lua is very good for the object script system and you can with some planning get a tidy scripted game.

However lua sucks on math and other procedural stuff like simplex noise (which are all math)

 

So what you can do, is to write the intensive parts in c++ and just expose yourself to lua.

 

The drawback is that you can't deploy on the player, but need and download and installation, which might scare away some players.

Share this comment


Link to comment

If Josh would create a key/value system for each entity in the editor (when an entity is selected have this option in the properties area) then it can help people attach information to an entity without having to attach a lua script to it. This information could be details C++ would use. This would give people a Lua free option if they wanted. I've pushed for this a couple times but since he wasn't in the C++ mindset like he is now, I don't think he saw much value in it.

Share this comment


Link to comment

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...