RSS
 

Archive for January, 2012

More RPG work…

30 Jan

New blog post on Spellcaster Studios about some more consideration on the RPG system…

image

I’m loving the design of my own RPG system, but it has a downside: every single time I have to work on a new component, it just raises 10000 more questions, from a game design standpoint (will the player like the summons to be instant, or is it better if it has a cast time), from a math standpoint (will this new derived attribute break the existing systems? How does it evolve over time?) and from a technology standpoint (how can the summoned creature access the talents of the summoner creature?). It’s fun, but at the same time you’re always second-guessing yourself…

On another note, video of the day:

 

Awesome… Smile

 

More work on Grey…

26 Jan

New blog post over at Spellcaster Studios: the first textured model for “Grey”! Sneak preview:

grey_texture02

I finished yesterday the health and resource system. In Grey, a “resource” is a kind of expendable pool of something related to the class. For example, for a mage, the resource is “mana”, for a warrior, the resource is “bravado”, for a life shaper is is “resolve”. This works as “fuel” for spells and abilities.

I’ve also laid the groundwork for the ability system (you can see the icons for abilities in the GUI element on the screenshot below). The icons are some I got from the internet, done by user Ails at www.pixeljoint.com, seemingly free to use (you can see them at http://www.pixeljoint.com/pixelart/37532.htm).

image

The formulas for the health and resolve are pretty simple, but I’ll go into that in a post in the Spellcaster Studios blog when I have more information (like the life-shaping mechanic).

 

Designing RPG systems…

24 Jan

New blog post over at Spellcaster Studios, about the initial work for the RPG system we’re going to use on “Grey”: equations are fun! Smile

On a completely unrelated note, if you haven’t already, try BIT.TRIP RUNNER… Excellent game, I picked it up with the Humble Indy Bundle 4 and it was worth the money just for this one… Fun game when you have 10 mins to burn in front of your computer, although it can be very frustrating… The integration of music and gameplay just adds to the enjoyment (of course, if you’re not a fan of electronic music, you might get the urge to kill yourself after 10 levels)…

It’s available for Wii, PC, Mac and Linux, so you can choose your platform (would be win on smartphone as well, I think!)

 

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

 

Rant: The Old Republic

17 Jan

starwars-tor

I’ve been playing SWTOR since it came out, and while I’m having fun overall, the game manages to be so annoying at times I just have to cease playing for some hours…

I can excuse bugs (and this game has a lot, but much less than normal MMOs at launch), but just bad design really pisses me off…

First of all, Bioware: IT’S NOT FUN TO WALK, EVER!

The game spends an inordinate amount of time treating you like a carrier pigeon (go here, then go there, then go back to where you started)… This is normal on a MMO, to stretch out the play time, but the distances you have to travel in SWTOR are just too big, with nothing happening between locations… Yeah, of course, you can beat up everything you find between you and your destination, but that’s just killing something that you’ve already killed 10000 times, with no challenge in most cases… And if you take the roads (which should be safe transit, but aren’t), you take twice as long to reach anywhere because there’s always a bloody cliff or mountain in the way! Whoever designed the locations should be shot, to be honest…

On WoW, Cataclysm was the occasion to fix some of these kind of things (making the Barrens less “empty”, for example), because they acknowledged that it was boring… why couldn’t Bioware learn with Blizzard?

Sometimes I feel that the guys at Bioware just didn’t play WoW at all, which seems like a gross mistake, considering they’re competing with it and you should know where your competition stands… But considering some mistakes I see in the game all the time, they probably didn’t spend any decent amount of time on it…

For example, the security system… Secret questions with answers that you can’t misspell… For example, the question about your street address, that can be spelled in hundreds of different ways, and a space makes a difference! And God forbid you forget how you spelled any… you’re stuck phoning their helpdesk, where you have to talk to someone who has even worse English than you (I’m not a native speaker, so that’s a hassle anyway), paying an international call, all in the name of security…

It’s not my bank details, it’s a damn game! Couldn’t there be a form where you typed in your game key, or your phone number? Because that’s all they actually do by the phone, so what’s the point? It makes more sense asking you for your email and having you spell it out letter by letter?

And if you fork over for a security key, you still have the questions from time to time (according to the rep), so what’s the point of the security key?!

This is just bad design decisions (not game design, but helpdesk design)…

It’s a pity, to be honest, because the game is very interesting in a lot of things… the class storylines are very cool, and the general stories for the quests themselves are interesting and make for less repetitive gameplay than usual in this kind of games…

The lack of addons is also very annoying, not only because I want to replace that ugly, non-functional UI, but because I don’t have any idea on my performance without a damage meter… how can I experiment with skill rotations and whatnot if I don’t have any way to measure it? Still, that may be address in a later patch (fingers crossed)…

I’ll write some more when I finally get to level 50 and do all the Flashpoints (another very interesting concept, and mostly well executed), if I ever get there (takes forever to level from level 45 onwards, seems badly balanced in that regards, to be honest)…

 
No Comments

Posted in Games

 

More work…

12 Jan

Haven’t had much time for anything else but work on the SurgePlayer, lately. In case I haven’t mentioned it yet, the SurgePlayer is the “game” counterpart of SurgeEd. It’s to SurgeEd as FlashPlayer is to Adobe Flash.

Basically, SurgePlayer is the runtime that takes content created in SurgeEd (and loads of scripts) and actually implements the game rules, etc.

It has been a challenge developing it because I really want to create an open framework, in terms of usability… I want to be able to use the same executable file to drive all my games from now on (which is a big challenge).

Most of the work lately was trying to integrate the changes brought on by the additional capabilities of LuaJIT, but I finally have the system up and running again, with spawning “creatures” that use the underlying navigation mesh to adjust their “random” position, that gets requested by the helper object that actually spawns them. It’s very cool!

player01

Not impressive looking, I know, but the underlying code is very nice and elegant (for my taste, of course).

The framerate is low because there are about 1200 distinct objects in this scene (the ground is made of very small tiles), and because of the shadows and no primitive clustering (yet), the frame rate takes a dive…

Anyway, there’s a new post on Spellcaster Studios, showing off the first model built for “Grey”, check it out!

 

Sherlock

10 Jan

Last week, the beginning of BBC’s “Sherlock” second series aired.

 

It is an awesome show, taking the normal “Sherlock Holmes” formula and taking it to the 21st century. It’s also some of the best writing in TV that I’ve seen for a long time.

It’s written by Steven Moffat, the guy behind a lot of Dr. Who shows and Steven Spielberg’s “The Adventures of Tintin”, and he did a brilliant job in reimagining Sherlock Holmes.

It’s a completely different TV show, since every episode is about 1h30 (instead of the more normal 20 or 40 min format), and it requires people actually paying attention, since it’s paced so fast that you get lost in the complicated plot easily. It also features the normal BBC quality in terms of cinematography, which is quite refreshing.

So, it’s definitely worth a look!

On other news, there’s a new blog post up at Spellcaster Studios, about path-finding and my experience with Recast.

 
No Comments

Posted in TV

 

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!

 

Happy new year!

02 Jan

Hope you all had a merry Christmas and a good new year party… I know I did! Smile

Anyway, sorry about the lack of updates, but time was scarce, with Star Wars: The Old Republic and family gatherings.

The haul was pretty good this Christmas: I got the Star Wars Bluray, Skylanders (yes, the kids game, I was fascinated by it for some reason!) and Skyrim (haven’t tried it yet, too busy with other stuff).

Anyway, I won’t delve too deep into any topic today, since I’m waiting for my character to hit level 50 to do a full (pre end-game) review of SWTOR, and I will go back to work tomorrow and have a million things to organize, between the projects I have running and “Grey”.

Anyway, there’s a new post about Grey on Spellcaster Studios’ website. Go check it out and share and all that social jazz! Smile

So you don’t go away empty handed, there’s some very interesting posts up at the “Tales of the Rampant Coyote” blog, about class vs. skill systems in RPGs. You can start reading here.

So, to end this post, I hope you all have a very good 2012 (353 days to the end of the world, it seems!)

star-wars-happy-new-year-party

 
No Comments

Posted in General