ZERO

Sign in to follow this  
  • entries
    20
  • comments
    79
  • views
    30,918

About this blog

Development notes

Entries in this blog

Roland

I have made a small class for helping with reading and writing parameters between C++ and LUA and also calling LUA functions from C++. I'm sharing this little thing here.

 

blogentry-395-0-01293300-1488719654_thumb.png

 

Using the class is quite simple as shown below

 

LUA - part

blogentry-395-0-18534700-1488720057.png

 

C++ - part

blogentry-395-0-59572000-1488719924_thumb.png

 

I have included is a test project which looks like this in the editor

blogentry-395-0-25132300-1488720141_thumb.png

 

And like this when executed

blogentry-395-0-63899000-1488720151_thumb.png

 

Here is the LuaBridge class source

Luabrigde.h

Luabrigde.cpp

 

And the complete test project

LuaBridge.zip

 

Note: Its says 'Click for next test', should be 'Hit Spacebar for next test'

Roland
blog-0025366001487075484.jpg

I have been working a bit on getting things realistic and found that the amount of work with that is just overwhelming. Maybe its me that is to nit-picking :) Anyway I have decided to go for a bit more cartonish fun style and hopefully that will make the art process a bit less time-consuming.

 

So here is my new hero, the little friendly robot Alfred. Making animations for that guy is something that I can handle and as my daugther said, he's also quite qute :)

 

I might try to use a carton-shader. There is one in the Workshop but its a bit to intense. Haven't really decided on that yet.

 

That was just a little update for now

Roland

Panic Disorder

Hi... Long time since last update.

 

The reason is that I have been through a period of Panic Disorder. This has been something that has followed me through my whole life in periods. Its something that is really hard to handle when it comes. Angst, worries, problems with stomac, irregular hearbeats, feeling really tired, problems with sleep and the list is long. To summarize its a state where just getting up from bed is an achievement. Anyway... new medication and therapy has now started to work and I'm up again. If anyone has the same kind of problems my first advice is "Dont be ashamed and speak to your friends about it, seek help". And I know that when its at its worst you feel like you are going to die. You wont! And it will be better, it Always does!

 

So ... Here I am trying to continue where I left of. First thing I will do is to skip the 3rd person mode. It takes far to much time and effort to develop. I will go for a first person game from now on. So first thing is to make some changes for that. Oh... And it's the same game Zero but in first person mode then.

 

I'll be back

Roland

A programmer making models. Well .. it takes some time to get a grip of how to make the models enough low poly to behave well in the engine but at the same time enough convincing to look real. And then we have the UV-mapping... If my hair wasn't (the little that's left) gray already it would have turn into to some of that flavor. I'm using Blender although I have Modo, but that's just because I really want to learn Blender as my incoming stream of money has gone down dramatically after my retirement. So better get used the poor-man tools.

 

So here is how it looks when rendered in Blender

blogentry-395-0-68960000-1477077039_thumb.jpg

 

and here in game.

blogentry-395-0-76846300-1477077057_thumb.jpg

 

The lighting is different. Actually I this is not the real game scene. Its just my test thing with not descent lighting applied and so on. The wood planks has to be textured better but I'll get there.

 

Actually I took a sidestep from man plan doing this. I should have been just blocking out things with simple primitives now but I felt I wanted to see how the art-pipeline worked first.

 

That pier will need to have some loose planks that will cause problems. That will then bring me into the 'getting a nice water' problem and also how to get the bits that falls of floating.

 

Here is the direction I'm going with this

blogentry-395-0-00390900-1477082671_thumb.jpg

Roland

After have been testing a bit in a more 'live'-development scene I found things that needed more attention (what else .. ). These things could maybe have been done in LUA but as I'm a C++ developer since long I moved over some basics to C++ and left some in LUA. During this operation I found some I could make some further improvements. Now my Code schematics looks like this.

 

blogentry-395-0-60697300-1476556157_thumb.png

 

The most important here is the GameItem class that all other items that exist in the Scene inherits. The GameItem handles the connection to the LUA-script, can save & load its data in a SQL database and also can send messages to registered message clients as the Player class which needs to be informed about various events.

 

I have as seen in the diagram following types of items.

 

Value

This can be either health or energy

 

Actor

This item will react when a trigger is applied to it (example. door is the actor, key is the trigger)

 

Trigger

Can be picked and will end up in screen list of trigger items which then can be used to 'trig' Actor events.

 

Tool

Can be picked and will end up in screen list of tools. (example. a flashlight or a hammer).

 

Area

An invisible area in the scene that will cause some kind of event when entered. Current the types are

'Checkpoint, FPS On, FPS Off and Die'

 

Carry

This is a simple object that can be carried by the player. It remember it position at last checkpoint

 

The Items described above are all childs of the GameItem class and has a LUA script part. Any LUA scripted item a been set to operate as one of the above item types using a quite simple system.

 

function Script:Start()
 self.entity:SetKeyValue( "itemtype", "tool" )
 self.entity:SetKeyValue( "class", "Tool" )
end

 

This will cause the C++ framework to create a Tool instance connected to the Lua-scripted item. You can still use the LUA script as usual but have the support of GameItems database. Here is an example of a Area item which will force a first person view.

 

LUA-SCRIPT

Script.areatype = "fps-on"
Script.visited = false

function Script:Start()
-- C++ GameItem support
self.entity:SetKeyValue("itemtype", "area") -- this is an Area
self.entity:SetKeyValue("class", "Area") -- Create C++ the GameItem derived class Area

-- Make us invisible
local material = Material:Create()
material:SetBlendMode(Blend.Invisible)
self.entity:SetMaterial(material)
material:Release()

self.entity:SetCollisionType(Collision.Trigger);
self.entity:SetMass(0);
self.entity:SetViewRange(Entity.NearViewRange);
self.entity:SetShadowMode(0);
self.entity:SetNavigationMode(false);
end

 

C++ Header

#pragma once
#include "icy.h"

class Area :
public icy::GameItem,
public icy::ClientServer<AreaClient>
{

public:

enum AreaType
{
	Checkpoint,
	FPS_ON,
	FPS_OFF,
	Die,
	Undefined
};

Area(Leadwerks::Entity* e);
~Area();

//  --- GameItem
virtual void init(icy::LuaBridge& lb); // called when LUA-script is connected
virtual void create_table(icy::DB& db); // called when database table should be initialized
virtual void save(icy::DB& db); // called when database save should be done
virtual void load(icy::DB& db); // called when database load should be done

 //  --- LUA ACCESS
void set_visited(bool visited);
bool is_visited() const;

const AreaType& get_areatype() const;
const std::string& get_message() const;

private:
AreaType _areatype;
bool _visited;
std::string _message;
};

 

C++ Source

#include "area.h"
using namespace Leadwerks;
using namespace icy;

Area::Area(Entity* e)
:   GameItem(e)
{
}

void Area::init(LuaBridge& lb)
{
_areatype = str_to_areatype(lb.get_string("areatype"));
_visited = lb.get_bool("visited");
_message = lb.get_string("message");
}

void Area::create_table(icy::DB& db)
{
_dbtable = get_suggested_tablename(); // auto-named table = "area"
_dbcols.push_back(DB::Column("name", &_name)); // bind table column "name" to the _name member
_dbcols.push_back(DB::Column("areatype", reinterpret_cast<int*>(&_areatype)));
_dbcols.push_back(DB::Column("visited", &_visited));
db.create(_dbtable, _dbcols); // will create table if needed
}

void Area::save(DB& db)
{
db.write(_dbtable, _dbcols);
}

void Area::load(DB& db)
{
db.read(_dbtable, _dbcols);
}

void Area::set_visited(bool visited)
{
_visited = visited;
}

bool Area::is_visited() const
{
return _visited;
}

const Area::AreaType& Area::get_areatype() const
{
return _areatype;
}

const std::string& Area::get_message() const
{
return _message;
}

 

To at least have something that's not code I have started on modeling one of the first items in the first scene "A Field Full Of Secrets". Its a pier that you need to walk on .. can be tricky. I use Blender. Haven't textured it yet. Hmmm.. Maybe I could call the model "Bridge Over Trouble Water" smile.png

 

blogentry-395-0-47888000-1476558544_thumb.jpg

Roland

Had to make something that made my database handling a bit simpler so as I'm a kind old man I though I would share it. I have attached a zip file with all you need and a working Visual Studio 2013 project including an empty database. The important part is the DB class.

 

DB hides the details of using SqlLite3 and

SQL-syntax to handle tables.

 

You can define a number of table columns

and then use that list of defined colums to

create, delete and update a database table,

without having to deal with the SqlLite3 details

or know any SQL syntax.

 

Each column has 3 members

- "name" wich is the name of the colum

- "type" tells witch data type the column has

- "value" binding to a value

 

To keep things down to what's needed for storing

simple values of an object 4 datatypes are

supported. Those are booleans, integers, floats

and text.

 

Here is an example of how to use this class


   #include "db.h"
   #include <string> // string
   #include <iostream> // cerr

   using namespace std;

   // reports database errors
   void errout(const std::string& error)
   {
       cerr << "Database Error: " << error << endl;
   }

   // Program entry
   int main(int argn, char** args)
   {
       string myname = "test";
       bool mybool = false;
       int  myint = 123;
       float myfloat = 123.45f;
       string mystring = "hello";

       // Open database
       DB db;
       db.open("my.db");
       db.error(errout);
       db.debug("debug.txt"); // turn out debugging to 'debug.txt'

       // Define columns
       // Yhe first column will always be set as a primary key
       DB::Columns cols;
       cols.push_back(DB::Column("TheName", &myname));
       cols.push_back(DB::Column("TheBool", &mybool));
       cols.push_back(DB::Column("TheInt", &myint));
       cols.push_back(DB::Column("TheFloat", &myfloat));
       cols.push_back(DB::Column("TheString", &mystring));

       // Create the table
       // If the table already exist nothing will be done
       db.create("mytable", cols);

       // Save data to database
       // Will write data to a row defined by 'myname', here 'test'
       // If the row already exist it will be updated
       // else if will be created
       db.write("mytable", cols);

       // Read data back
       // Will read data from a row defined by 'myname', here 'test'
       // If no such row exist read will return false
       db.read("mytable", cols);

       // make a new row called 'second-test'
       // and store
       myname = "second-test";
       myfloat = 3.14f;
       mybool = true;
       mystring = "leadwerks";
       db.write("mytable", cols);

       // We now have two rows in the the table 'mytable'
       // TheName      TheBool TheInt  TheFloat    TheString
       // test         false   123     123.45      "hello"
       // second-test  true    123     3.14        "leadwerks"

       // delete the first row 'test'
       myname = "test";
       db.del("mytable", cols);

       // print row 'secont-test'
       myname = "second-test";
       mystring = "this has changed";
       db.read("mytable", cols);

       for each (auto col in cols)
       {
           switch (col.type)
           {
           case DB::Column::Bool:
               cout << col.name << " = " << (*col.value.b ? "true" : "false") << endl;
               break;

           case DB::Column::Int:
               cout << col.name << " = " << *col.value.i << endl;
               break;

           case DB::Column::Float:
               cout << col.name << " = " << *col.value.f << endl;
               break;

           case DB::Column::String:
               cout << col.name << " = " << *col.value.s << endl;
               break;
           }
       }
       cout << endl;

       // should be the same as our variables
       cout << "myname   = " << myname << endl;
       cout << "mybool   = " << (mybool ? "true" : "false") << endl;
       cout << "myint    = " << myint << endl;
       cout << "myfloat  = " << myfloat << endl;
       cout << "mystring = " << mystring << endl;
       cout << endl;

       // close database
       db.close();

       // wait for user
       cout << "Hit ENTER to continue?" << endl;
       cin.get();
       return 0;
   }

 

The output of running the program becomes


TheName = second-test

TheBool = true

TheInt = 123

TheFloat = 3.14

TheString = leadwerks

 

myname = second-test

mybool = true

myint = 123

myfloat = 3.14

mystring = leadwerks

 

Hit ENTER to continue?

Roland

Saving the Game State

One last thing I had to look over before diving into blocking out my levels was the saving and restoring of the game state. I had made this by using Leadwerks Streams but I found that it became quite clumpsy for doing the task of saving and restoring hundreds of items. Saving the Game State means that I save everyting that has been moved or tampered in any means. If you kick a small stone 2 meters it should be in the new position even after a new programstart or when respawning at the last checkpoint. So I gave the whole thing a new approach. This is what I came up with and its working just great.

 

Added SQL database support in my executable (read - added SqlLite source C files to my project). Source can be found here SQLite. The integration was quite straight forward. Just added the C-source files and there you go.

 

Created a C++ class DbItem with a LUA interface. This class can save and read data from a SQL database using two simple LUA available methods DbItem:save() and DbItem:store().

 

In a LUA script its easy to implement the Database support. Looks like this

Script.dbitem = nil

function Script:Start()
self.dbitem = DbItem:new(self)
end

function Script:Save()--in
self.dbitem:save()
end

function Script:Load()--in
self.dbitem:load()
end

  • When the C++ DbItem is created it checks if the object already exists in the database. If it doesn't, it adds it self to the database.
  • When Save is called the C++ DbItem saves the Entity's Position, Rotation, Scale, Visibility and some other things to the SQL database.
  • When Load is called those values are read back and implemented.

Save and Load can be called by the FlowGraph although I just used that for testing.

 

When I load a map, each loaded entity is check for existence of the function Save and Load. If those exists, the entity is stored in an internal list. Then when I want to save the Game State I call the Save function for each member of the list. Same thing for Loading.

 

I found this solution quite simple to use. Its fast and supports my needs well. Its very easy to use as the objects registers them self to the database.

Roland

Game Mechanics Done.

So finally I have base of my Game Mechanics coding done in LUA. I do stick to the plan and have in fact not needed to change much. I introduced an new class UserInterface to handle the interaction with the user but else its the same plan as I showed in a previous blog post.

 

Below is the new code schematics with the UserInterface added. All is now implemented and I'm ready to start blocking out the scenes and what's needed in them according to my Game Manuscript. I will continue using simple proxy-models as shown in the video and then replace them with real models when all scenes are working.

 

blogentry-395-0-33124800-1475154113_thumb.jpg

 

So where does this leave me in my plan. If you have a look at my plan below the green areas are done and the blue areas remains to do. Just as a note you can see a arrow leading back from each box to the beginning. This is to remind me that each change leads back to the top again. So getting in right in each box at first really saves work. Trying to keep my self focused here and prevent my self from rushing things.

 

blogentry-395-0-96571800-1475158294_thumb.jpg

 

Here is video showing the LUA Game Mechanics is a test scene. As usual with video recording things get at bit jerky but at least you can see what's going on. Not every detail is covered but the video show how things works in general. What you can't see in the video is when coming to checkpoints, the game state is save. The means that everything moved, picked and so on is saved. Then if you die (yes...its a non violent game but you can die of exhaustion, sticks from insects and much more) you will be returned to last checkpoint with the game state which existed at that moment.

 

Roland

And let there be music

Have been working a bit on some music for the Zero game and came up with this. Will use variations on this through the game as background music (not all the time). I recorded this using my Fender Telecaster, Fender Precision Bass through a Focurite external sound card into the PC recording program Tracktion. The music idea is my own.

 

Roland

I never, ever in my wildest dreams thought I would do what I have been doing during the last week.

 

I have converted my C++ code to LUA and at the same taken advantage of the FlowGraph system.

Yes! You did read correctly ... FROM C++ TO LUA!!! not the other way

 

So why this then. Well. Actually it started with me testing out some things in LUA before coding them in C++ and then noticed how simple things was in LUA. I hadn't made to much LUA coding before. Then I tested with rewriting one of my more complicated C++ things to a LUA version and found that it work really nice and by using the FlowGraph it could be done much simpler. Maybe I overcomplicated things in my C++ code, maybe not. However this lead me to convert the complete code base in LUA and I'm very satisfied with how that turned out. The code is simpler (mostly because my use of the FlowGraph) and if there is and speed loss its so minor that I cant notice it. So now everything is moved over to LUA and I will continue using LUA. One nice side effect by this is that the code is platform independent ..Yay smile.png

 

This block chart shows my game mechanics. I said I would make a video showing what's done and I will. However its a bit delayed as the C++ to LUA took an extra week of work, but definitively worth the trouble.

 

blogentry-395-0-49071300-1474458921_thumb.jpg

Roland

Game Mechanics progress

blog-0179558001473888829.jpg

Have been working quite intensely on the game mechanics since last blog post. In that one I was going for a First Person and a Third Person View which could be switched by the TAB key or automatically when going inside a building (forcing FPS view). Now my Third Person camera works so well that I found that I can achieve this by instead of switching to a FPS camera I can just move my Third Person camera to a point just in front the characters eyes. Works quite well, so that will be kind of First Person view without having to handle two different camera systems. Besides the work on animations and camera I have come up with a system of picking and using different object which are divided into following category's.

 

HealthItem

Can be picked to increase the characters health up to a max level.

This max level will raise when the character is rewarded at some points

 

EnergyItem

Can be picked to increase the characters energy up to a max level

This max level will raise when the character is rewarded at some points

 

Checkpoint

A place where the game state is save and where you will be returned to

in case of sudden death or after a programstart

 

Equipment

Various tools that can be used during the game such a Flashlight.

You can pick tools and then use them by selecting them. Those are not

the same as Inventory Items described below. Once found you will have

them through the whole game.

 

InventoryItem

This is items that can be picked, store in the inventory and recalled at any time.

A good example is a key to unlock at door.

 

Trigger

When you collide with this object it will trig an event of some kind

 

Zone

The system act in a different way when you are inside a zone.

An example is forcing First Person view at some places

 

Actor

This object will only act if an object a specific kind exist in your

inventory. If no such object exist you will get a hint on what to look for

 

Besides this I have the GUI's need done. Those are

 

MessageWindow

Any of the items described above including the character it self can send

a message to the MessageWindow at it will fade in and be visible for short

while and then fade out. Messages are stacked

 

Healthbar

Shows current health

 

Energybar

Shows current energy

 

Inventory

A list of inventory items picked up. Each item is showed as an icon

which can be selected by the keys 1-9. If you select an item it will

be removed from the inventory and will be carried in front of the character.

You can then choose to drop it and leave it or add it back. Some items

can be used as 'key's to Actors,

 

CustomCursor

A simple custom cursor that toggles between a crosshair and a hand.

You have seen it in the Leadwerks demos although I use decals as cursor.

 

I will now assemble all in a test track to troubleshoot for problems. Will record

a video to show you the whole in action. So until then. Have a great time.

Roland

"That's needed" list

Been going through my game manuscript and notes to see what I will basically need to implement to get the basics going. Below you will find a list showing that. Some actions are divided into 'outside' and 'inside'. In my last blog I shown how my camera/charcter will operate. I have an "outside" mode (which is a 3rd person camera following the character) which is used for outdoor scenes mostly and an "inside" mode which then used for indoors scenes (First person view). An action like opening a door is quite different in those modes. Outside its a matter of starting a 'open door' animations while inside its more just opening the door.

 

  • Open door outside
  • Open door inside
  • Push button outside
  • Push button inside
  • Pickup item from ground outside
  • Pick items by mouse inside
  • Store picked items in inventory
  • Apply/Use inventory items
  • Key/Unlock mechanism for doors
  • Health meter/return to checkpoint at 0
  • Stamina meter/decrease on movement/increase on idle or food found
  • Messages to user
  • Checkpoints
  • Boids for birds/insects
  • AI for rats/snakes and insects
  • Ground aware footsteps
  • Game theme music
  • Event sounds - event driven

 

So there is quite a bit to do before even thinking of models, trees, water and all that stuff. I will use simple primtives while implementing the code needed.

Roland

Have been working with mostly coding things lately, getting LUA/C++ connection to work, animating my character and making a camera that will meet my needs. I will go for a third person view when possible, that's more or less when walking outside in nature. Then when going into a house, cave or something that makes a third person view a bit hard to handle, the program will switch to first person view automatically. The first person view is also needed for some different puzzles in the game. You can switch between the cameras using the TAB-key when its possible. Pressing TAB at a place where the third person view is not allow wont have any effect though. I have also implemented '1st person view' zones using invisible boxes as triggers. When player enters such a zone the camera is forced to 1st Person View.

 

This now works although there some work remaining like smoothing and such. Then there is a problem with flickering between 1'st and 3rd person state when leaving 1'st person view. It's like a "Should I stay or should I go" problem. This needs further work. All in all things are going like planned. I attached a video showing current state.

 

Roland

To FPS or not?

I have been thinking quite a bit if I'm going for a FPS or 3rd Person game with this Zero thing. The manuscript is open for both alternatives and so far I haven't decided where to go on this. A 3rd Person game is in my view way cooler than a FPS game, however being cool has a cost. Getting animations that look right isn't easy not to talk about having them play in correct speed at the correct time. I made some tests but isn't quite satisfied. FPS is less work, A LOT OFF LESS WORK. As you may or may not now I'm an old guy (62 years) and I want to get the game done BEFORE I die of age :).

 

So I'm leaning against a FPS game. However I have some ideas of short cut-scenes in 3rd Person view at some parts. If I make such cut-scenes I could make them in Blender which would be quite a bit more easy as the animation then is limited to a specific task. I have to think about that. Anyway such cut-scenes would come quite late in the development as they would be more a nice decoration. As I said in a previous blog I will do the visual things later on and concentrate on the game play following my manuscript at first hand.

 

Writing those blogs are quite good for me. When I started I didn't quite know how to go about this but now while writing it comes more clear in my mind. I will go for FPS with some short cut-scenes at some critical places.

Roland

If you are compiling a C++ project I'm sure you have noticed all those warning LNK4099. Here is how that looks (shortened down )

1>	 Creating library C:\Users\rstra\Documents\Leadwerks\Zero\Projects\Windows\..\..\Zero.debug.lib and object C:\Users\rstra\Documents\Leadwerks\Zero\Projects\Windows\..\..\Zero.debug.exp
1>Leadwerks.lib(NewtonDynamicsVehicle.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(NewtonDynamicsVehicle.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(Decal.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(Decal.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(Probe.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(Probe.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(Vegetation.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(Vegetation.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(WaterPlane.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(WaterPlane.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(EventQueue.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(EventQueue.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(GUI.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(GUI.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(dMat4.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(dMat4.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(dVec4.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(dVec4.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(mt19937ar.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(mt19937ar.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(Mouse.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(Mouse.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(Text.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(Text.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(Vehicle.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(Vehicle.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info

--- snip --- snip --- snip --
--- snip --- snip --- snip --
--- snip --- snip --- snip --

1>Leadwerks.lib(OpenGL4Shader.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(OpenGL4Shader.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(OpenGL4SpotLight.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(OpenGL4SpotLight.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(OpenGL4Surface.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(OpenGL4Surface.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(OpenGL4Uniform.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(OpenGL4Uniform.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(OpenGL4VertexArray.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(OpenGL4VertexArray.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1>Leadwerks.lib(OpenGL4GraphicsDriver.obj) : warning LNK4099: PDB 'vc120.pdb' was not found with 'Leadwerks.lib(OpenGL4GraphicsDriver.obj)' or at 'C:\Users\rstra\Documents\Leadwerks\Zero\vc120.pdb'; linking object as if no debug info
1> Zero.vcxproj -> C:\Users\rstra\Documents\Leadwerks\Zero\Projects\Windows\..\..\Zero.debug.exe
========== Build: 1 succeeded, 0 failed, 0 up-to-date, 0 skipped ==========

 

Now I really hate that because if there really was a warning to bother about I would miss it among all the others. There is a simple way to get rid of this mess. Add the /ignore:4099 like shown below

blogentry-395-0-73729800-1471598154_thumb.png

 

Now the compilation looks like this which is far better

1>	 Creating library C:\Users\rstra\Documents\Leadwerks\Zero\Projects\Windows\..\..\Zero.debug.lib and object C:\Users\rstra\Documents\Leadwerks\Zero\Projects\Windows\..\..\Zero.debug.exp
1> Zero.vcxproj -> C:\Users\rstra\Documents\Leadwerks\Zero\Projects\Windows\..\..\Zero.debug.exe
========== Rebuild All: 1 succeeded, 0 failed, 0 skipped ==========

Roland

For this Zero project I have a need to call C++ classes from LUA. I have gone the same way as Josh has and used 'tolua++' for this. This works like this

 

1 - Create PKG

For each class you need to export you have to write a corresponding 'pkg' file which is a version of the C++ header file suitable for the 'tolua++' program.

 

2 - Use 'tolua++'

Then send the 'pkg' file to 'tolua++' which then will generate a source file with the LUA-export version of the class and a header file which defines the function to call in order to export the class.

 

3 - Add & Compile

The two generated files should be included in your C++ project and you have to call the function defined in the header at some time after LUA has been initialized by Leadwerks. After compilation and linking you should be able to use the C++ class in you LUA scripts

 

Here is a simple example:

 

C++ header file: CppTest.h

#pragma once
#include <string>
class CppTest
{
int _value;
std::string _string;

public:
CppTest();
virtual ~CppTest();

int get_value() const;
void set_value( int value );

std::string get_string() const;
void set_string( const std::string& value );
};

 

C++ source file: CppTest.cpp

#include "CppTest.h"

CppTest::CppTest()
{
_value = 0;
}

CppTest::~CppTest()
{
}

int CppTest::get_value() const
{
return _value;
}

void CppTest::set_value( int value )
{
_value = value;
}

std::string CppTest::get_string() const
{
return _string;
}

void CppTest::set_string( const std::string& value )
{
_string = value;
}

 

PKG file: CppTest.pkg

$#include <string>
$#include "CppTest.h"

class CppTest : public Temp
{
CppTest();
virtual ~CppTest();

int get_value() const;
void set_value( int value );

std::string get_string() const;
void set_string( const std::string& value );
};

 

After you written the CppTest.pkg file you have to compile it using 'tolua++' like this. Note that I use the same filename for the outputs but with an '_' added. That way its easy to keep track of things

 

tolua++ -o CppTest_.cpp -n CppTest -H CppTest_.h CppTest.pkg

 

Now tolua should have generated two files.

 

Generated CppTest_.h

/*
** Lua binding: CppTest
** Generated automatically by tolua++-1.0.92 on 08/18/16 11:36:39.
*/

/* Exported function */
TOLUA_API int tolua_CppTest_open (lua_State* tolua_S);

 

Generated CppTest_.cpp (shortned down)

/*
** Lua binding: CppTest
** Generated automatically by tolua++-1.0.92 on 08/18/16 11:36:39.
*/

#ifndef __cplusplus
#include "stdlib.h"
#endif
#include "string.h"

#include "tolua++.h"

/* Exported function */
TOLUA_API int tolua_CppTest_open (lua_State* tolua_S);

#include <string>
#include "CppTest.h"

/* function to release collected object via destructor */
#ifdef __cplusplus

static int tolua_collect_CppTest (lua_State* tolua_S)
{
CppTest* self = (CppTest*) tolua_tousertype(tolua_S,1,0);
delete self;
return 0;
}
#endif
--- snip --- snip --- snip ---
--- snip --- snip --- snip ---
--- snip --- snip --- snip ---

/* Open function */
TOLUA_API int tolua_CppTest_open (lua_State* tolua_S)
{
tolua_open(tolua_S);
tolua_reg_types(tolua_S);
tolua_module(tolua_S,NULL,0);
tolua_beginmodule(tolua_S,NULL);
#ifdef __cplusplus
tolua_cclass(tolua_S,"CppTest","CppTest","Temp",tolua_collect_CppTest);
#else
tolua_cclass(tolua_S,"CppTest","CppTest","Temp",NULL);
#endif
tolua_beginmodule(tolua_S,"CppTest");
tolua_function(tolua_S,"new",tolua_CppTest_CppTest_new00);
tolua_function(tolua_S,"new_local",tolua_CppTest_CppTest_new00_local);
tolua_function(tolua_S,".call",tolua_CppTest_CppTest_new00_local);
tolua_function(tolua_S,"delete",tolua_CppTest_CppTest_delete00);
tolua_function(tolua_S,"get_value",tolua_CppTest_CppTest_get_value00);
tolua_function(tolua_S,"set_value",tolua_CppTest_CppTest_set_value00);
tolua_function(tolua_S,"get_string",tolua_CppTest_CppTest_get_string00);
tolua_function(tolua_S,"set_string",tolua_CppTest_CppTest_set_string00);
tolua_endmodule(tolua_S);
tolua_endmodule(tolua_S);
return 1;
}


#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 501
TOLUA_API int luaopen_CppTest (lua_State* tolua_S) {
return tolua_CppTest_open(tolua_S);
};
#endif

You should include both of those in your project. You also have to call tolua_CppTest_open somewhere after Leadwerks has initialized LUA. I do it here in my App.cpp. Remember to #include "CppTest_.h" at the top of App.cpp.

 

App.cpp (shortned down)

#include "App.h"
#include "CppTest_.h"

using namespace Leadwerks;

App::App() : window(NULL), context(NULL), world(NULL), camera(NULL) {}

App::~App() { delete world; delete window; }

bool App::Start()
{
int stacksize = Interpreter::GetStackSize();

//Get the global error handler function
int errorfunctionindex = 0;
#ifdef DEBUG
Interpreter::GetGlobal("LuaErrorHandler");
errorfunctionindex = Interpreter::GetStackSize();
#endif

//Create new table and assign it to the global variable "App"
Interpreter::NewTable();
Interpreter::SetGlobal("App");

std::string scriptpath = "Scripts/Main.lua";
if (FileSystem::GetFileType("Scripts/App.Lua") == 1) scriptpath = "Scripts/App.Lua";

// ADDED to initialize the CppTest LUA implemenation
tolua_CppTest_open(Interpreter::L);

//Invoke the start script
if (!Interpreter::ExecuteFile(scriptpath))
{
System::Print("Error: Failed to execute script \"" + scriptpath + "\".");
return false;
}
--- snip --- snip --- snip ---
--- snip --- snip --- snip ---
--- snip --- snip --- snip ---

LuaParser

I read somewhere that Josh has a parser that automates this a bit by parsing lines in the header file that is commented with //lua and generates pkg-files. What a good idea. As I think programming is better that watching lousy programs on TV, I made my own version of this and called it "LuaParser". I have attached this program for those who like to use it. Here is what it does

 

1. Parses all C++ header files (*.h) in the folder and subfolders for lines commented with //lua

2. For such files it creates a pkg file suitable for tolua++ compilation

3. It complies the generated pkg files into _.h and _.cpp files to be included into you project

 

Here is same example from above declared for LuaParsing

 

C++ header file: CppTest.h prepared for LuaParser

#pragma once
#include <string>//lua

class CppTest
{
int _value;
std::string _string;

public:
CppTest();//lua
virtual ~CppTest();//lua

int get_value() const;//lua
void set_value( int value );//lua

std::string get_string() const;//lua
void set_string( const std::string& value );//lua
};


 

Extract the LuaParser.zip into you Source folder and open a command prompt there. The just type LuaParser and hit Enter. A number of files ending with '_' in the name will be generated. Include them in your project and call the function in each of the '_.h' files as mentioned.

 

Windows version

LuaParserWin-1.5.zip

 

Linux version

LuaParserLinux-1.0.tar.gz - support discontinued

 

History

1.0 Initial version

1.1 Comment header in PKG files was inside class declaration instead of at top of file

1.2 Didn't handle class inheritance

1.3 - 1.5 Various minor fixes

 

You can read more about tolua++ here

tolua++ - Reference Manual

Roland

In last blog entry I prepared for development in Linux/Ubuntu. Now its time to setup the tools for development in Windows. Most is the same thing except a few tools that differs.

 

blogentry-395-0-32915300-1471434512.png

Steam - The obvious or else I wouldn't have Leadwerks

 

blogentry-395-0-22285500-1471434537.png

Leadwerks - The even more obvious Leadwerks Engine. As I'm a curious man I do use the Beta branch.

 

blogentry-395-0-06152800-1471434520.png

3DCoat - Great for organic modeling but also a really good program for UV-mapping and Texturing

 

blogentry-395-0-48818900-1471434546.png

ShaderMap Pro - Used to create normal-, specular- and all those maps from a color image

 

blogentry-395-0-90797000-1471434526.png

Blender - After some initial struggling I have learned to just love Blender modeling smile.png

 

blogentry-395-0-16690000-1471434568.png

Visual Studio C++ - Programming C++ for Leadwerks needs this

 

blogentry-395-0-67957000-1471434586.png

Gimp - Poor mans PhotoShop. Works great

 

blogentry-395-0-14838800-1471434558.png

Tracktion - Using this for sound and music

Roland

Back after 3 weeks on the road and 3600 km done. Time to get started with the Zero game project from really scratch by formatting a hard-drive and installing Ubuntu 14.04 TLS which is the current version supported by Leadwerks. After having done that I continued with installation of the programs I plan to use.

 

blogentry-395-0-38938200-1471201010.png

Steam - The obvious or else I wouldn't have Leadwerks

 

blogentry-395-0-76880000-1471201033.png

Leadwerks - The even more obvious Leadwerks Engine. As I'm a curious man I do use the Beta branch.

 

blogentry-395-0-10576400-1471200964.png

3DCoat - Great for organic modeling but also a really good program for UV-mapping and Texturing

 

blogentry-395-0-82276300-1471200970.png

AwesomeBump - Used to create normal-, specular- and all those maps from a color image

 

blogentry-395-0-90640900-1471200979.png

Blender - After some initial struggling I have learned to just love Blender modeling smile.png

 

blogentry-395-0-92780400-1471200987.png

CodeBlocks - The C++ IDE used for Leadwerks C++ programming

 

blogentry-395-0-54467800-1471201000.png

Gimp - Poor mans PhotoShop. Works great

 

blogentry-395-0-84905900-1471201018.png

Tracktion - Using this for sound and music

 

After having installed all those programs I made some notes worth sharing.

 

--- Leadwerks C++ Libs ---

After installing Ubuntu 14.04 TLS and Leadwerks

following libs are needed for C++ compiling

  • mesa-common-dev
  • libglu1-mesa-dev
  • libopenal-dev

Install them by

"sudo apt-get install mesa-common-dev libglu1-mesa-dev libopenal-dev"

 

 

--- Blender GPU ---

I have a GeForce GTX 980 grahpics card. In order to get Blender using

that one I had to start blender as root once and select GPU/Cuda in the

User Preferences. After that Blender can be used normal with GPU enbled

My graphics driver was nVidia 352.63 at that time

 

 

--- Leadwerks path in CodeBlocks

The path variable to the Leadwerks files was not set in Codeblocks.

Had to do that by adding a Custom Variable in the Project Build Options.

LeadwerksPath="/home/rstralberg/.steam/steam/steamapps/common/Leadwerks"

 

Besides that I have arranged a 2-stage backup system like this

 

My work is done in my Documents/GameDev folder as its on a SSD-drive which is fast. Using 'rsync' the GaveDev folder and all its subfolders are backed up to a standard hard-drive each day I have installed OverGrive which syncs the backup to GoogleDrive in the background

 

So that's how my development system looks like for now.

 

My first thing to do once things was up and running was as said in a previous post, to create a class that acts as a bridge between LUA scripts and C++ classes. Its really nothing that fancy as my idea is to use LUA only for setting parameters that C++ can use. I have though made it possible to call LUA methods from C++ at the same time, with or without arguments.

 

blogentry-395-0-79190000-1471202552_thumb.png

 

I connect a LUA script to a given C++ class by declaring a script member CppClass which tells which class that the script will work with.

 

Script.CppClass = "name of c++ class"

 

To keep things together I have made a ItemPool wich is a Singleton that parsers all objects loaded in a scene (world) and creates the class instances given by the loaded objects who has a script with the CppClass declared. The instances are then tied together with that object and its script using the LuaBridge class. I have made some tests and the arrangement seems to work quite good.

 

Well well ... that was all for now

Roland

After 4 days of working I got the manuscript for the whole game written. It divides the game into 11 parts, each with its own environment and difficulties. I won't go into any details here as that would give away the joy of exploring unknown areas. However I can at least give the titles of the parts

 

1. A field full of secrets

2. The lake house

3. A tunnel of distortion

4. The gas station

5. The Henge

6. Concrete rooms

7. The water lock

8. Bridge over troubled water

9. Labyrinth in the fog

10. Powering the Void

11. At Zero

 

All game play, puzzles, events and models needed are defined for each part so now the work of implementing the manuscript starts. My plan is to roll out everything as simple box primitives as a start and the begin the coding. The visuals, gui and music comes last. As I'm making this as a combined C++ and LUA project, first thing will be to write a LuaBridge class that can handle data exchange and function calls between the LUA scripts and the C++ classes.

Roland
blog-0623957001470309762.png

Second attempt of making this game. Here is the background story. Probably it has grammar errors as I'm not a native English speaker. Please tell where those errors are.

 

 

 

I will develop this on Ubuntu Linux using mostly free tools as Blender and GIMP. I plan to use a combination of C++ and LUA. The game-style is solving puzzles to get forward finding your way to the solution. So here we go. Oh,, and if you want to know more about it all, then head over to YouTube and make a search for Die Glocke


 

When you first heard about the place you took it as yet another of those Internet story's, far from reality. Then when going deeper into it, things started to get more and more convincing having some valid background.

 

In short the rumors goes like this.

 

 

Back in the 40’s at the very end of World War II, the Germans had managed to create a machine that could do strange things as manipulate both time and gravity. The code name for the machine was “Die Glocke”, better known among those who worked with it, as “ZERO”. The nickname Zero was given as the machine could generate a zero-gravity field around it when running at full power. This field could also cause various time anomalies not fully understood.

 

Zero was contained in a facility called the Void. Now, more than 70 years later a chest with old documents has been found in a church ruin next to the Czech border. Government documents written by a German SS Scientist, Otto Chernaw. Here Otto talks about a gravity weapon named the Void, being developed in their underground laboratories in the mining district of Wenceslaus not far from the small village Sokolec near the Czech border. Your mission is to find the laboratories, take photos and blueprints of the Zero machinery before destroying all of it. Those blueprints and photos is of most concern for your government and you will be greatly rewarded on success.

 

When the game begins you find your self standing on an open field surrounded by trees. There is a small lake in the middle of the field and you can see some cliffs in the distance.

 

This start view is not complete

blogentry-395-0-06067900-1470316774.jpg

Sign in to follow this