Jump to content

  • Log In with Google      Sign In   
  • Create Account

A Keyboard and the Truth

Update

Posted by , 28 April 2005 - - - - - - · 91 views

So the last three days have been...interesting.

In my pursuit to get a save-game mechanisim working, I found that somthing I fixed a while ago (which was to actually making saving games easier) didn't quite work well.


The Scripting Engine:

our scripting engine allows for multiple scripts to be running at once (synched though). When one runs a script, that script is loaded from file, compiled, and cached,(if the script was cached it wouldn't do this process over), then a new ScriptProcess object is created, and the Script object is 'plugged' into it; The ScriptProccess, contains a local variable store, as well as the Execution Head. The ScriptProccess is then added to the list of proccesses, and then Execute() is called on it.

Now for 'normal' code in the script file, this code will execute(and block) until it is finished, just like real C++ code. However, ScriptProcesses have a handly little feature, any function that the script executes, can tell the script to 'LOCK'. When a script is locked, it is locked with a certain condition, more specificaly, an event, the script abandons it's execution, until a specific event is raised on a specific object, then that event will open the lock on the script and resume the execution.

This functionality allows you to do things in script code that you cant in normal C++, for instance.

Animate(sprite,"yay");
Move(sprite,10,10);
Animate(sprite,"foo");
Move(sprite,20,20);

wherein, Move takes more than a single frame of time to complete. In the case of the script code, the Move function's underlying implementation would tell the script to lock itself, with the condition of EventSpriteMoveDone, on the object, sprite.

It's really very nice =D and is the basis for most of the game logic.

The Scripting Problems:

The scripting engine can use two scopes of variables and two types of variables:

Global/Local
Number/String

Global variables look like this: $myglobal
and can be shared between all scripts.

Local variables look like this: mylocal
and are unique only within a single script file.

variables are dynamically typed:

$global="wow!";
local="wow!";

$global=10000;
local=10000;

$global=10.2;
local=10.2;

Now this is all well and good, but issues began to crop up when we needed to represent object references in script code.

Since the language wasn't built with an object type (dumbass.), some kind of hack improvisation was required.

The answer was simple: just use the Number type to store an object pointer =)

and it worked, so then we had things like:

$morning=CreateSprite("morning","Sprite","MorningDelegate","data/morning.sprite");

and the CreateSprite implementation would just return the real object's pointer as a number, no sweat.

However =D
Then we came to realize that, if we needed to save the state of a script (for a save-game), saving a bunch of pointers wasn't all that helpful; sure it was easy to save, but when you loaded up the game those saved pointers wouldn't match the new pointers of the deserialized objects, so it would make it impossible to re-bind the variables. PLUS! when doing straight deserialization, how would we know what variables we want to re-bind, since all we know is that they are numbers, not neccisarily meant as object pointers, oh the woes of type ambiguity =D

The Really Really DUMB solution:

So, in an effort to stave off this doom, I came up with a solution, that eventualy proved to be more harm than help.

Since each entity object in the game can have a string name, we decided:

"Hey, why not use the name of the object to reference it"

At the time it sounded brilliant, however it came with problems. The main problem was that, objects found thier associated scripts based on thier name, so a sprite named "raymond" would try to use "raymond.script" this was perhaps a bad move, but we were married to it now, a better solution would have been to have a "scriptname" variable. But the problem, was now, certain objects should use the same script, and to do that it means the objects need to be named the same thing, and here comes the gotcha! if you are referencing an object by some identifier(a name) and there is more than one object with that same identifier(which we wanted to be possible to allow shared script use) then the reference becomes ambiguous =/

We got around this by making sure that no two objects could have the same name (if they wanted to be referenced), and it stunk of kludge =/

The Better Solution:

So now that the save game feature is absolutely neccisary, I have revisited this issue, and amazingly enough I have found an elegant solution, and here is the basis of how it works:

Each object has a previousPointer variable.

When an object is created (not loaded from file), previousPointer is set to NULL.

When an object is saved, the first value saved is the current pointer(this).

When an object is loaded, previousPointer is set to the value that was saved(see above^)

With this system, when we load an object we will always know what the LAST pointer of an object was, this is important, because it provides a unique pool of referencing, which is readily availible when the game is saved.

Now, for the script integration. It was neccisary to modify the scripting engine a bit for this to work. I had to implement a system of 'Re-Bind', that is, when a script is deserialized, all of it's variables that are objects, use thier values (which are the pointers that the objects WERE when they were saved) and it searches through the object store(which contains all game objects)looking at the object's previousPointer variable, trying to match it with theirs. If a match is found, it means that this object WAS the object that this script variable WAS referencing, so now, the script variable can take on the new object's pointer, and the reference will be restored.

The change that was neccisary, was to add an Object type to the script engine, so that i could identify what variables needed to be re-bound, this was a 'fairly' simple change, and really, it simply used a modification of the Number type, and can only be passed directly, for instance:

obj1=FunctionThatReturnsAnObjectExplicitly();
obj2=obj1;
FunctionThatTakesAnObjectExplicitly(obj2);

you cannot express a specific address though:

obj=10238740;
//above would be of type Number not Object

and numerical manipulation will always result in a number type

obj3=obj1+obj2;
//obj3 will be a number even if obj1 and obj2 are objects

these limitations arn't that big of a deal, since most of them (barring PERHAPS direct address assignment) you would never want to do; All logical operations are intact and work just like numbers.

//numerical comparison
if(obj1!=0)
{
//woot!
}

//numerical comparison
if(obj1==obj2)
{
//woot!
}

In short, a much more elegant solution, and small development time (3 days * 6 hours = 18hours)

Hopefully somone finds this informaative =D


*yawn*

Posted by , 26 April 2005 - - - - - - · 107 views

So, what have I been doing lately? (I hear nobody in particular ask)

Well, mainly I have been at work(real work) working on the game I am developing for them. But in my free time (~6 hours each night Monday->Friday and most of the day Saturday and Sunday),
I have been working on Morning's Wrath.

(When is Morning's Wrath gonna be fricken done!?) I hear you say.
Hopefully soon, here are a list of potential excuses reasons as to why it isn't already done.

  • Games take a LONG time to make

  • A very core member is swamped by college

  • Real-Life Work is keeping me busy

  • Games take a LONG time to make!!


  • So what all have I been doing with the time I have on MW?

  • Cleaned up the workspace and data directory(needed it)

  • Put a nice coat of pollish on the first quater of the game

  • Tuning the game engine for performance and reducing memory footprint

  • Fixing lots and lots of bugs

  • Modeling, Animating and Rendering graphics

  • Writing/Revising dialogue

  • Ensuring the story is coming across properly

  • Working to implement the save-game feature(not easy)


  • In reality, Real-Life work takes a lot out of me, it is hard to do game development for 8 hours, and then come home to do MORE game development; So because of that, Saturday and Sunday are the big-work days, which is good, since I can(and ususaly do) dedicate the whole day to it(9am to 2am on saturday, 9 am to 12pm - 4pm to 8pm on sunday).

    Any other good news? Sure there is =)

    Adam Frechette, our composer, is working on THE LAST piece of music for Morning's Wrath, it is The Morning's Wrath theme, and so far it is sounding awesome.

    Aaron Brown, our sound designer, has had the game's sound effects finished since about November, so we are all set on that front.

    Morgan Chaput, our concept artist, has finished all of the in-game hand-drawn inventory item icons, he also did the artwork for the intro cinematic, and our box art and concept art.

    Jenna Hoffstein, our character modeler, has finished all of the character models and texturing (now i just have to animate and render them =D)

    Zac Todd, our designer, has finished 90% of all the game scripting, once college is out things should once again be pumping on his end.

    All of our testers, did very well with our first beta session, identifying bugs and giving feature requests, and are looking forward to our next beta session, which is coming in May.

    Voice Tallent, at this point is still up in the air, given the amount of dialogue in MW it is fixing to be a logistics nightmare, as far as casting and recording are concerned, also the use of 'relatively(they arn't professional)' unskilled voice actors, may yeild a lesser experience rather than a greater one. Once Zac is back in action we will make the final decision as to weather we will have voice in MW, since it is not a trival exercise and could easily decide the fate of MW.

    So, as you can see (I hope you can see at least), we are nearing the end of the road; there is still PLENTY of work to be done, but we are plugging along. If you count engine development(2001 to 2003 plus this last year (march 2004 to march 2005) then Morning's Wrath has been in development for Three Years however, this isn't exceptionaly uncommon, especialy for adventure games(which, along with RPGs, tend to be the most resource intensive games to create), I was recently reading that the most recent Myst game, took about three years to produce, and was with a dedicated full-time team with proper funding;

    We however, are FIVE people, with jobs/school, working to create somthing amazing, with all of the odds against us, and even though it is taking a long time, damnit...

    WE ARE GOING TO DO IT!

    *catches breath*
    so there is the 'offical' update as to where the MW project currently is, hopefully noone has lost faith in us, we are doing the best we can, hang in there =)


    Finally =D

    Posted by , 19 April 2005 - - - - - - · 73 views

    After a long weekend of work,

    all of morning's actions have been animated and rendered.

    here is a shot of Morning's 'emotion sheet'




    Research, blah.

    Posted by , 13 April 2005 - - - - - - · 73 views

    Finally getting somewhere,

    been doing research on how best to implement expressive motions into our primary characters.

    The basic idea is to use an 'emotion' sheet, this sheet, contains 8 'emotions' each one frame long, and each with it's proper direction.

    "one frame!?" I hear you say, well, we could animate everything but this would lead to some bad stuff.

    'huge memory requirements'
    'larger game download'
    'longer animating/rendering development times'

    none of which we want =)

    in this way we can display a wide range of emotions during dialogue and regular gameplay, which will likely add to the over-all realisim of the game dialogue.

    here is a basic sheet layout for some basic animation


    {Idle}
    {0}-{0}{1}{2}{3}{4}{5}{6}{7}
    {1}-{0}{1}{2}{3}{4}{5}{6}{7}
    {2}-{0}{1}{2}{3}{4}{5}{6}{7}
    {3}-{0}{1}{2}{3}{4}{5}{6}{7}
    {4}-{0}{1}{2}{3}{4}{5}{6}{7}
    {5}-{0}{1}{2}{3}{4}{5}{6}{7}
    {6}-{0}{1}{2}{3}{4}{5}{6}{7}
    {7}-{0}{1}{2}{3}{4}{5}{6}{7}

    {Move}
    {0}-{0}{1}{2}{3}{4}{5}{6}{7}
    {1}-{0}{1}{2}{3}{4}{5}{6}{7}
    {2}-{0}{1}{2}{3}{4}{5}{6}{7}
    {3}-{0}{1}{2}{3}{4}{5}{6}{7}
    {4}-{0}{1}{2}{3}{4}{5}{6}{7}
    {5}-{0}{1}{2}{3}{4}{5}{6}{7}
    {6}-{0}{1}{2}{3}{4}{5}{6}{7}
    {7}-{0}{1}{2}{3}{4}{5}{6}{7}

    {Talk}
    {0}-{0}{1}{2}{3}{4}{5}{6}{7}
    {1}-{0}{1}{2}{3}{4}{5}{6}{7}
    {2}-{0}{1}{2}{3}{4}{5}{6}{7}
    {3}-{0}{1}{2}{3}{4}{5}{6}{7}
    {4}-{0}{1}{2}{3}{4}{5}{6}{7}
    {5}-{0}{1}{2}{3}{4}{5}{6}{7}
    {6}-{0}{1}{2}{3}{4}{5}{6}{7}
    {7}-{0}{1}{2}{3}{4}{5}{6}{7}

    {Die}
    {0}-{0}{1}{2}{3}{4}{5}{6}{7}

    {Emo}
    {0}-{use}{take}{anger}{fear}{disgust}{joy}{sorrow}{special}
    {1}-{use}{take}{anger}{fear}{disgust}{joy}{sorrow}{special}
    {2}-{use}{take}{anger}{fear}{disgust}{joy}{sorrow}{special}
    {3}-{use}{take}{anger}{fear}{disgust}{joy}{sorrow}{special}
    {4}-{use}{take}{anger}{fear}{disgust}{joy}{sorrow}{special}
    {5}-{use}{take}{anger}{fear}{disgust}{joy}{sorrow}{special}
    {6}-{use}{take}{anger}{fear}{disgust}{joy}{sorrow}{special}
    {7}-{use}{take}{anger}{fear}{disgust}{joy}{sorrow}{special}

    use:
    -arm out stretched in a 'using' motion

    take:
    -bent on one knee, with an arm in a reaching 'take' motion

    anger:
    -eyes narrowed
    -brows down and slanted(anger wise)
    -mouth closed (teeth griting), no smile
    -hand clenched and partialy up or down
    -one leg forward, weight shift/leak forwards

    fear:
    -eyes wide
    -brows up and slanted(worry wise)
    -mouth open, with a frown
    -hands up and out repelling
    -one leg backwards, weight shift/lean backwards

    disgust:
    -brows raised, slight slant(anger wise)
    -eye roll
    -mouth closed, one side slanted up
    -arms folded tightly
    -look away
    -one leg outwards, increasing stance, slight body twist and shoulder shrug

    joy:
    -brows up, no slant
    -mouth slightly open, large smile
    -hands slightly up, maybe clenched (excitement)
    -straight and tall posture, very vibrant and energetic

    sorrow:
    -eyes open or closed
    -brows down and slanted(worry wise)
    -mouth slightly open, no smile
    -hands limp and hanging
    -slouching posture, head slightly down, averting eye contact

    special:
    -a single frame expression that is different for each character



    as you can see, a complete 'action' is fairly costly, even after we cut down the frames substantialy (14 to 12 now to 8)

    if we assume an 100x100 frame size (normaly larger), that is an 800x800 sized image (32 or 16 bpp depending on selected settings) just for a single action (such as moving), so as you can see, things tend to add up =)


    Animating Morning

    Posted by , 11 April 2005 - - - - - - · 65 views

    I am doing her animation sequences, thus far I have:

    Idle 12Frames
    Walk 12Frames
    Run 12Frames

    I still need to add:
    Neutral Talk 12Frames
    Angry 4Frames
    Sad 4Frames
    Happy 4Frames

    Die 12Frames


    fun, lol.






    Games & Links

    Recent Comments