RSS
 

Posts Tagged ‘LUA’

No title, really…

18 Dec

This is one of those posts that have a bit of everything, so no decent title for it… Smile

Anyway, as you might have seen in the Spellcaster Studios blog, me and Rincewind gave up on the Indie Speed Run, mainly because of scope issues… We went a little wild with it, Rincewind because of lack of 48-hour compo experience, and me because I thought that without needing to do graphics I could do much more…

Anyway, it was a good exercise, and I’m definitely finishing this one, not because it is brilliant, but it’s great to figure out bugs on SurgeEd and SurgePlayer, which I used for the game. Already figured out some nasty bugs which would have taken a lot of time to fix on the “Grey” scripts, specially one that only seems to manifest in specific conditions…

If you’ve been following this blog, you know I’m using Lua to drive the game logic, and specifically LuaJIT, and I found an odd behavior…

The offending piece of code was something that tested a condition and acted on that:

function do_something(param)
   if (ffi.C.test(param)) then
      change_object()    end end

test is a function declared on the FFI, that returned a bool:

ffi = require("ffi")
ffi.cdef[[

bool test(const char* str);

]]

Which had a C counterpart like:

extern "C"
{    bool __declspec(dllexport) test(const char* str) {
        bool b=do_some_test();

return b;
}
}


 

Simple enough…

Problem is, “change_object” was never reached… First I thought it was the “do_some_test” function that was failing, and I added some tracing to it (writing to the logger) with the output, and it turned true eventually…

Then I added some tracing in the “do_something” function, and mysteriously, it started working properly… After a lot of tests, I found that if I used any function that called normally bound functions before the “ffi.C.test” call, the system worked properly… But if I added FFI based functions, it wouldn’t work!

This was driving me crazy… then I had a silly idea… “bool” is a C++ type, not C type, so I changed the declaration of the C function (not the FFI declaration) to “int __declspec(dllexport) test(const char* str)”, returning 1 if “do_some_test” was true, and 0 otherwise… And now the system worked properly!

So, I arrived to the conclusion that you can’t output “bool” directly from the C code (although you can declare it that way on the FFI declaration, to get a proper bool and not an int). I imagine the problem was the size of a bool and the stack manipulation of LuaJIT, which caused the system to access corrupted memory (that was probably zeroed before being used, and that’s why the function apparentely always returned “false”, although the C output was “true”).

Anyway, 2 hours of my life getting to the bottom of this… Had to change all the functions that return a bool to return an int instead…

Anyway, on other news, take a look at this Hamnasya game… It’s a cross-media kind of game, where you’re reading a book, but you can affect the outcome and fight battles à lá RPG… Very cool stuff indeed, and has an excellent trailer:

 

I haven’t picked it up (I had too many pending games at the moment), but it looks pretty good…

If I don’t write anything in the meantime (highly likely), Merry Christmas and a Happy New Year! Smile

 

GUI work and more internal structure…

19 Jan

Nothing much to add to the post at Spellcaster Studios… Writing for two blogs is kind of a pain from time to time… Smile

Spent the last couple of nights working on scripting internal structures, streamlining some functions and inventing a way to pass arrays/lists from LuaJIT to C++ and vice-versa…

image

My problem was that the raycasting should return a set of intersections (not just the first one)… The way I found to do this was to create a semi-templated class to handle the array itself, get some functions to access it/destroy it and do the conversion in the raycasting function itself…

The end result is something like this:

ffi = require("ffi")
ffi.cdef[[

	int             LuaIntersectionArray_get_size(LuaIntersectionArray* ar);
	LuaIntersection	LuaIntersectionArray_get(LuaIntersectionArray* ar,
                                                 int index);
	void            LuaIntersectionArray_free(LuaIntersectionArray* ar);
]]

LuaIntersectionArray_mt = {
   __index = {
      type = function(a) return "LuaArray<LuaIntersection>" end,
      log = function(a,log_type,pre_text) std.log(log_type,pre_text..type(a)) end,
      size = function(array) return ffi.C.LuaIntersectionArray_get_size(array) end,
      get = function(array,index) return ffi.C.LuaIntersectionArray_get(array,index) end,
      free = function(array) ffi.C.LuaIntersectionArray_free(array) end,
   },
}
LuaIntersectionArray = ffi.metatype("LuaIntersectionArray",LuaIntersectionArray_mt)


function get_lua_array(c_array)
   local lua_array={}
   for i=0,c_array:size()-1 do
      local obj=c_array:get(i)
      table.insert(lua_array,obj)
   end
   c_array:free()
   return lua_array
end

 

Of course I have to do this for every type of array I want to support on Lua (except the get_lua_array function, that is generic).

On the C/C++ side, I create the LuaIntersectionArray class, with the access methods, using a #define directive that declares all the functions, etc.

Then, on the Lua side, when I want to receive an array of intersections, I can do something like this:

ffi = require("ffi")
ffi.cdef[[

	LuaIntersectionArray*	raycast_static_mesh_array(LuaRay ray);
]]
----------------------------------------------------------------------
-- Shortcut functions
function raycast_static_mesh_array(ray)
   return get_lua_array(ffi.C.raycast_static_mesh_array(ray))
end

 

It’s not that elegant, can lead to memory leaks (although it shouldn’t happen if I keep things contained like this), but it’s pretty simple to use, since the return of raycast_static_mesh_array (which only raycasts static meshes and returns an array) is a simple Lua array/table (same thing there, really).

 

On other notes, check out the animation system on the new Max Payne game, it’s fantastic!

I wish I could spend 4 or 5 months just researching IK and animation to do such good looking stuff! Smile

 

LUA JIT

05 Jan

Following the suggestion of one of my readers, I decided to take a deeper look into LUAJIT.

At first glance, LUAJIT is a Just-In-Time compiler for Lua, that uses exactly the same interface as the normal Lua library, but compiles the code instead of interpreting, resulting in very significant speed improvements.

Just that is enough reason to use it, and I intended to do it later in the project…

But what caught my attention was the FFI library that enables me to bind functions and C structures in a much easier fashion…

Under normal circumstances, if I wanted to have a function available to Lua (for example purposes, a sum function that takes two arguments and returns the sum of both), I’d have to:

  1. Write the function itself
  2. Write a bind function (a C function)
  3. Bind that function to the environment

 

On the example:

int sum(int a,int b)
{
   return a+b;
}
 
LuaGlue lua_sum(lua_State* L)
{
   int a=lua_get_number_argument(L,1);
   int b=lua_get_number_argument(L,2);
 
   lua_push_number(L,a+b);
   return 1;
}
 
env->add_function(“sum”,lua_sum);
 

This is of course a simplification, and misses parameter validation, etc…

With Lua JIT, I can just:

  1. Write the function itself
  2. Bind the function directly in LUA

 

Step 1 is almost the same as before:

extern “C” int __declspec(dllexport) sum(int a,int b)
{   
   return a+b;
}
 

The difference is that now I have to say that the function is to be implemented through C call, instead of stdcall (the extern “C” part) and that the function has to be exported (the __declspec(dllexport) part).

Then, for step 2 on LUA, I just have to do:

extern “C” int __declspec(dllexport) sum(int a,int b)
local ffi=require(“ffi”)
ffi.cdef[[
   int sum(int a,int b);
]]
 
local var=ffi.C.sum(10,20)
print(var)
 

Much simpler and safer, I think!

The benefits aren’t just here, you can declare C structs in both sides (C and Lua) and use them without incurring performance penalties, which allied to the metatype tables allow you to actually add something like a Vec3 class or something like that… Check out the part on “Defining Metamethods for a C Type” on the FFI Tutorial. It really shows off what you can do with this…

The only issue I see is that class support is tricky, although you can use classes like this:

C code (assuming a classA):

extern "C" classA __declspec(dllexport) *classA_new() 
{ 
   return new classA; 
}

extern "C" void __declspec(dllexport) classA_set_a(classA* __this,int a) 
{ 
   __this->set_a(a); 
}    

extern "C" int    __declspec(dllexport) classA_get_a(classA* __this) 
{ 
   return __this->get_a(); 
} 

Lua code:

local ffi = require("ffi")ffi.cdef[[
   typedef struct { void *__this; } classA;

   classA*    classA_new();   
   void       classA_set_a(classA* t,int a);   
   int        classA_get_a(classA* t);
]]

local classAlocal classA_mt = 
   {  __index = 
        {   
           set_a = function(t,a) ffi.C.classA_set_a(t,a) end,   
           get_a = function(t) return ffi.C.classA_get_a(t) end,  
        },
   }
classA = ffi.metatype("classA", classA_mt)

function test()   
   local object=ffi.C.classA_new()
   print(object)
   local value=object:get_a()
   std.log(log_debug,string.format("Value=%i",value))
   object:set_a(25)
   std.log(log_debug,string.format("Value=%i",object:get_a()))
end

Very convenient indeed!

Only problem is that I designed the SurgePlayer Lua structure without this in mind, and suddenly I have what seems like a better way of doing things available…

Now I need to rethink the whole system to take advantage of this, but still keep some of the benefits I had on the previous system.

I believe it will be well worth the trouble! Smile

By the way, there’s a new post down at http://www.spellcasterstudios.com, with video! Check it out!

Until next time!

 

Vacations and Ludum Dare

19 Aug

Back from my vacations, all over Portugal… Well deserved, I might add! Open-mouthed smile

Anyway, what better way to finish vacations that with a Ludum Dare 48-hour game development competition?!

I’ll be cross-posting the progress on my game throughout the competition, so stay tuned!

Anyway, I’m using the same framework as last time, done by me, just added a 3d tilemap system (doesn’t have any type of querying yet, just rendering at the moment, I’ll add the rest during the competition, according to needs).

You can download the framework here, if you want to use it (it has two sample applications that show most if not all the features):

  • D3D9 initialization and some helpers
  • FMOD interface for sound
  • 2d Sprites (with sprite caching, etc)
  • 2d Particle System
  • Text
  • 3ds file loading (only tested with 3ds generated by 3d Studio Max). Loads lights, meshes and cameras.
  • Small simple math library (vectors and quaternions)
  • Simple 3d camera handling system (just with a “look at” operation)
  • XML loading/saving (might come in handy for configuration files, load/saves, etc. The XML loader was created by Frank Berghen, not me… the writer is all me, although the loader also has save functions, but I’m too lazy to figure out how they work)
  • 3d particle system (based on the 2d one, so very rudimentary)
  • 3d sprite system (quads that always face the camera)
  • LUA library support (it’s actually ripped from my engine, so it’s a good support system for LUA)… Last time I used cutscenes and scripting, and loads of the game code was much simpler because of that…
  • DDS image loading for an offscreen buffer (just supports R8G8B8A8 images). Might be useful for some level design stuff, although I’ll probably go back to my old days of text files
  • 3d Tilemap (Kind of a blocky heightmap with an automatic texture atlas generation and partition of the map in chunks for possible culling (not implemented))

 

On the tools side:

  • Visual Studio 2005 (hope I can get used to it again, been using 2010 at work)
  • Photoshop CS5 (for 2d graphics and textures if I decide to adventure into 3d, and for map creation, etc)
  • 3d Studio Max (for modelling if I go 3d, or for title screens and such otherwise)
  • sfxr (or Bfxr) (for audio effects)
  • Wolfram Tones (for the music creation – fun tool, saves loads of time) and MIDI Converter Free (to convert the MIDI generated by Wolfram Tones to OGG)
  • Live Writer for blogging

 

About the themes, I have a gut feeling that “Dreams” is going to win, although I don’t have any ideas for that… or any of the others, to be honest, since the times in the past when I tried to think of an idea for all the themes it didn’t work that well… Smile

Anyway, very excited about this all!

Good luck if you’re participating (and you totally should, it’s great fun!)

 
No Comments

Posted in Games