Filed under: game development
The original concept
On 18-06-2008 i posted a game idea i was working on for a competition that required the game designer to come up with a new mechanic for death. To use death as a game mechanic. I decided on the concept of a doctor who goes around scaring patients to death, where the death aspect of his career was his achievement.

Over time, i have refined this idea a million times in my head and i have twirled the story and concept so many times and came up with some pretty ridiculous stuff. For example, each patient is procedurally generated and includes a handful of irrational fears that you can play on. Sometimes the fears are real world phobia's and sometimes they are a fear of burnt pizza. The idea is that you can influence the level of horror in patiences by carefully planning around things.

Leave a radio with sounds of [insert an irrational fear] in the cupboard, whip out a giant chainsaw for dramatic effect. You know. Scary stuff. 
You can even group patients, take all the emo patients and put them in the far corner alone. They are bound to get more scared just because they are together.
What happened to it?
I got distracted, sidetracked, over scoped etc etc. The point was i never finished it (in fact i had game play, it was just never playable). Now that i have learned so much from working in game development full time, working on projects all over the place - I am on a completion rampage. There are a handful of my smaller games chasing me down, and this is why i am posting.
The 2010 Version
Having scoped the game play differently (it may or may not be bigger scope, but a lot of the mechanics are the same), I am back to implementing the game mechanics first, and then implementing the rest if it is worth it. The major changes are obviously visual to the readers at this point - But there is a lot of cool stuff that i am working on.
I am currently implementing the mechanics and game play using my own Laboratory ( read what that is here ). I have also decided to rework the level and game art, because i have never really approached an isometric pixel art project before (i have only messed around while making a room for The joint).
I love pixel art but i also really love painting and lighting (see this). As with the original version of this game, i will be mixing the two. Below you can see a rough style test to see if i like the direction and so far I am not displeased.
Click the image to see a full scale version in a new tab.
So what am i saying?
Hold me to release this as a fully playable prototype. Once that is done, i move on.
I appreciate badgering, mailing, and general harassment to remind me that i need to finish things. I am saying this here so that i can always look back at my posts and hold myself to it as well.
Thanks for reading!
Ok, so i am confused.
Please give me reasons why people aren't using boost more?
I will do my own opinion on using boost at an engine level some time but it makes no sense.
"So you want a cross platform high performance engine? Well good luck doing all the low level code for each platform!"
Thats where boost comes in, it makes everything so easy. Threading? EASY. generics? EASY. EASY.
Imo, easy = quicker. Less code, easier to maintain.
Dependency oh noes! What year are you living in?
</rant>
Update : To clarify, I guess i am referring to the people using "non boost" c++, the people spending a long time doing low level OS stuff, making game engines with their own platform layers that just waste hordes of time ?
Not a lot of time at the moment but i finally fixed the key input issues i was having with my rendering. While i finish the other minor details, i can post something else.
I really love uplink.
In honour of its awesomeness, you may notice some resemblance to it in certain places.
The original :
My game :
Its intended as a tribute cos i really loved the original.
A formatting note - I have tried to clean the code a little to work with this width of page. The original code with less dumbassery is linked in the header file here for reference. Get the example code from here : LINK I know i needed one. When i had chosen v8 as my weapon of choice i found it to be incredibly easy to grasp. What i didnt expect is for the simplicity to grab me around the ankles and dangle me off the edge of confusion cliff. Before i realised i was scratching my head with a few good c++ books open wondering what on earth i had done wrong that was giving v8 exceptions from a single line of code. What i would advise, is try to avoid shortcuts. I was using CProxyV8, i had seen v8Juice and both of them are really neat, but every single error i ran into was related to me not understanding what it is v8 was actually asking for and most times it was because of the use of the wrappers. Finding my own way I learnt a few things along the way - using v8 from the ground up is actually easier to understand. The first thing that helps is to look at the v8 namespace comments as they usually reveal something important, if its related to the JS side, or if its related to the c++ side.Once i saw that i was attempting to use a JS object as a c++ class, yea things started to make more sense. What i needed from v8. Now while the point and line class example is so heavily leaned on, it still didnt really help me to figure out the route i needed to take to expose certain classes to the script environment. The included sample http process and the other samples also , did things in a very straightforward and limited way. Below i will present an empty class from my codebase, with the code i used to expose and gracefully use the script side easily. I needed to wrap and unwrap a class. In order to expose a class to JS, i wanted to use an EXISTING C++ class, and just pass a pointer/handle to the scripts. That way i can also control what part of my game/scripts they can actually overwrite and change, and what instances of class they can manipulate. For example, i dont want multiple instances of the core, or any subsystem of the core. I just want a script side global(used loosely here) that the script writer can access (and which also protects him from accidentally overwriting one of my objects). A template based helper function I wrote 2 functions that are free to use , and will wrap and unwrap a class accordingly. The usage of the code provided here is shown lower down, so it might not make sense here. Wrapping involves creating a JS object from a c++ class, and maintaining a handle to manipulate it, and unwrapping involves unwrapping an object to a c++ pointer again, normally from the v8arguments handle that a function passes in on being called. example use : ExposeClass< somenamespace::someClass >( somev8Context, someClassInstance, v8::String::New("someclass"), v8::ReadOnly);
//http://blog.owned.co.za v8 Javascript Helper Function ,
//Give this function the c++ object (an instance) to wrap,
//and it returns a JS object to expose things under.
//Note theres 2 functions here ,
//the top one is used by the ExposeClass function
template
v8::Handle WrapClass(T* y)
{
// Handle scope for temporary handles,
v8::HandleScope handle_scope;
v8::Persistent class_template_;
v8::Handle rt = v8::ObjectTemplate::New();
//The raw template is the ObjectTemplate
// (that can be exposed to script too)
//but is maintained internally.
rt->SetInternalFieldCount(1);
//Create the actual template object,
class_template_ = v8::Persistent::New(rt);
//Create the new handle to return, and set its template type
v8::Handle result = class_template_->NewInstance();
v8::Handle class_ptr
class_ptr = v8::External::New(static_cast(y));
//Point the 0 index Field to the c++ pointer for unwrapping later
result->SetInternalField(0, class_ptr);
//Return the value, releasing the other handles on its way.
return handle_scope.Close(result);
}
template
v8::Handle ExposeClass(v8::Persistent context,
T* y,
v8::Handle exposedName,
v8::PropertyAttribute props)
{
v8::HandleScope handle_scope;
v8::Handle obj = Core::Script::WrapClass(y);
context->Global()->Set(exposedName, obj, props);
return handle_scope.Close(obj);
}
And for unwrapping - (usually inside CALLED functions from script. use : someNamespace::someClass* sc = UnwrapClass< someNamespace::someClass >( myJSObjToUnwrap );
//http://blog.owned.co.za v8 Javascript Helper Function ,
//Give this function the v8 JS object to unwrap, and the class to unwrap to.
template
T* UnwrapClass(v8::Handle obj)
{
v8::Handle field;
field = v8::Handle::Cast(obj->GetInternalField(0));
void* ptr = field->Value();
return static_cast(ptr);
}
How i use the above templates Nobody is claiming magic in the code above, it might even be wrong and or, doing something badly. I just found it to work - any comments and fixes will be noted and adjusted if you comment. Now, the usage, at least MY usage of the above code was to expose c++ classes with existing c++ functions to the script context. Step 1 - A Class to expose, with some members id like in scripts. First, i have a c++ class declared, with some static functions that i would like to expose.
class cCore
{
public:
//This is a simple example,
//do not copy this as a real class.
cCore(){};
~cCore() {};
//We need a persistant handle to the core in scripts, a non persistant
//v8::Handle will get lost in the handle scopes,
//and throw some weird exceptions to hunt down.
//Wrap class and unwrap class return
//NON persistant handles, so store your own
//persistant ones if you want to
//use it outside of the first handle scope.
//core script object, "core" in scripts.
v8::Persistent cso_core;
//We expose some functions in our class to the scripts from c++,
//By wrapping an object (cso_core above) and the attaching functions
//to that object. Those functions, when called from javascript -
//end up here.
//The functions are self explanatory.
//Print some text to the console/ui console
static v8::Handle xecho(const v8::Arguments& args);
//execute a javascript file
static v8::Handle xexec(const v8::Arguments& args);
//exit all systems and shutdown
static v8::Handle xexit(const v8::Arguments& args);
}; //end class declaration
Step 2 - Creating the Javascript Object , of my class.
//Just for clarity sake, so you can see my workflow.
void cScriptSystem::startup()
{
//Create a script engine for the core
v8::HandleScope handle_scope;
//Create a context for the system to use
//(i have just one at this point)
coreContext = v8::Context::New(NULL, global);
//Enter the main context, making it active.
v8::Context::Scope context_scope(coreContext);
exposeCore(); //see below
};
//And the code to expose the class,
void cScriptSystem::exposeCore()
{
v8::HandleScope handlescope;
//This will be reused to expose multiple
//classes, short name for easy code.
v8::Handle cc;
//get the JS version of the C++ object,
//note that core is simply Core::cCore* core;
cc = ExposeClass< Core::cCore >(coreContext, core,
v8::String::New("core"),
v8::ReadOnly);
//set the persistant handle for use outside of this handlescospe
core->cso_core = v8::Persistent::New(cc);
//Give the functions to the object.
//This makes the functions come out as
//core.echo(), core.exec(), core.exit() in scripts.
Expose(core->cso_core, v8::String::New("echo") ,
v8::InvocationCallback(Core::cCore::xecho));
Expose(core->cso_core, v8::String::New("exec") ,
v8::InvocationCallback(Core::cCore::xexec));
Expose(core->cso_core, v8::String::New("exit") ,
v8::InvocationCallback(Core::cCore::xexit));
};
Step 3 - Actually handling the function calls on the c++ side. This is where the unwrapClass comes in... If you noticed the v8::Arguments& args on the functions, it hands in the class that the function is being called upon. So if i called core.exit() , the object that it will pass me is the core object (our C++ object, in JS form). See the code for clarity,
v8::Handle cCore::xexit(const v8::Arguments& args)
{
//args.Holder() is the object that the function was invoked upon.
//This means it could be exposed to 2 classes,
//under different types so be sure
//that you dont just randomly unwrap into the wrong container type.
Core::cCore* core = UnwrapClass( args.Holder() );
//The code inside the normal exit function is identical,
//so i can just call the normal c++ code directly.
core->startShutdown();
//This is to return void, basically.
return v8::Undefined();
}
Step 4 - The missing function. I left out a function along the way, you may have noticed. The function is called Expose,
void Expose(v8::Handle intoObject, v8::Handle namev8String, v8::InvocationCallback funcID)
{
v8::HandleScope handle_scope;
v8::Handle thisFunc;
thisFunc = v8::FunctionTemplate::New(funcID);
intoObject->Set(namev8String, thisFunc->GetFunction());
}
Conclusion I hope this helps clarify the v8 logic, and helps users figure out how easy it actually is to automate things with templates and macros. Theres still many ways to simplify the code above but for simplicity - take it as it is. In closing, v8 offers some super easy to use casting functions. Ill give some examples as i found these to be really nice but be wary, do exception handling, type checking and proper management of values handed to c++ from v8. It will save you some time looking through v8 exception callstacks if you manually handle possible exceptions.
//you can now use it std::string(*somestdstring)
v8::String::Utf8Value somestdstring ( args[0] );
//you can now use it *somecstring (same as const char* somecstring;)
v8::String::Utf8Value somecstring ( args[1] );
//normal double,
double somedouble = args[2]->ToNumber()->Value();
//booleans
bool somebool = args[3]->ToBoolean()->BooleanValue();
//and integers.
int someint = args[4]->ToInt32()->Int32Value();
//And one last thing, giving javascript meaningful return values.
//This should be more than enough to let you figure out how simple
//v8 makes things for you on the c++ side.
return handle_scope.Close(v8::Number::New(somedouble));
return handle_scope.Close(v8::Int32::New(someint));
return handle_scope.Close(v8::Boolean::New(somebool));
Out.
While i really love writing stories, i know that there are people who can do a better job than i could hope to. I thought about it a while ago and figured if i can give a story writer a tool that truly exposes the features they need to create an epic tale, it will make the world of difference right?
Well, to make things easier on everyone (and offer something interesting to look at) i have made a quick sketch of what i can see a mission editor might look like. Yes, its in game too.
NOTE : CLICK ON THE IMAGE TO SEE THE ACTUAL PREVIEW
[caption id="attachment_110" align="aligncenter" width="640" caption="Mission Editor Mockup"]
[/caption]
Keep in mind
This is an extremely rough mockup. Dont get too excited about bad layout and missing information and blah. Its just an idea to get the creative minds thinking. Comments and feedback are more than welcome,
How can the mission editor be something really awesome? DISCUSS :>
What's new code side
After spending a bit of time rethinking things for this multi UI experience i was testing and implementing a whole bunch of core code. I rewrote a good number of things that i wasn't happy with and i was implementing things in a more detached manner.
Once i had that all done i dug into splitting out my hacked up test code into a proper abstracted interface, i got to testing my first interface with my current interface. The test was here, could i have the console (debug window) based javascript shell running at the exact same time as the visual shell, AND, have them using the same core module? Can i tell the core i need a login, and the visual interface responds as well? All things considered i managed to achieve this and more over a few hours thanks to boost, and Jon Parrot (the anti-brain-mess filter i run sometimes).
[caption id="attachment_110" align="aligncenter" width="450" caption="Typing in console while the main UI runs asynchronous"]
[/caption]
Blog theme
While you may have noticed by now, i have updated the theme of my blog to something legible. Thanks for all the feedback and views on the last one, and as i continue to make this one better comments are always welcome.
Again, the awesome image in the background is from an awesome friend, Paul - Link
.Fin
Ok, so apparently the last post was a bit of a mess, i will try again.
What im looking for from the response of the reader.
Simple.
Would you, perhaps a programmer or not, be inclined to extend your client with your own tools if it were like the description below.
Its not complete, its not 100% in depth, its idea based speculation based on some prototyping i did.
The concept of the game
The game is a hacking simulator, a pretend world where there are other players, and NPC's that are hackable. If you ever played uplink from introversion then you will immediately know the premise.
In the game, a player has a/some computers at his disposable. Each of these computers in the world, can be logged into (unless protected).
The User Interface of the game is a futuristic desktop environment that is customisable via code, in game.
The gameplay consists of missions, storylines, and the usual stuff - mini games pretending to be hacking mechanics etc.
The concept of the "engine"
The idea behind the "engine" in game is to allow the player to extend the operating system. Do your best, to make yourself a better in game hacker. How do i take over the computer at server xyz? I need a tool that can list its users. Write one, steal one, copy one, buy one.
Alot of thought behind the engine i wont bother cramming in one post.
The in-game OS, your deskstop in game
This is where it all happens. You have a web browser, a few network tools (like ping below) and you have a developer priveledged account. What now?
a) Do something new. Make a new clock widget, make a cool flash based tracer. You choose.
b) Make something better. Add a user interface to the command line ping tool. Add a UI to the tracer, make it count in ms instead of seconds.
c) Give something back. Submit a new tool/modified tool for inclusion in the core OS.
The code sample
What the code below is demonstrating is an INGAME ping tool. This has nothing to do with server/game state. It is merely a tool that i would like in game. For example, if a users PC online is running on a slow connection, it will take much longer to get in, do stuff and get out.
This is important because you dont want to get caught, so i can now (based on the simple script below) tell if a user is taking a long time to respond to the server.
Keep in mind
Its a prototype code sample. It semi works and some things i just put in for brevity. I need to know if the direction im taking on exposing the core is worth taking.
WOULD YOU EVEN BOTHER to do something new in game. If its as easy as it is below, would you?
The Client side tool,
// Client side tool for pinging another player in the game
// Author : FuzzYspo0N
// Etc
//First, in order to create a tool on the client and server side,
//we simply assign a variable as a tool type. This might fail if
//there is already a tool with this name - this returns undefined.
var corePingTool = new core.tool("corePingTool");
//Maybe something simple to register a tool with a defined
//callback for users. This global tool shows up at the shell,
// as a "command line" tool,and if a tool invokes
//a ui then it is not run via command shell but explicitly
core.tool.registerGlobalTool("ping", "client name, ping count ");
//onExecute gets called whenever someone tries to ping
//(either called via ui or via the above command line)
//Variable arguments handed in
var corePingTool.onExecute = function(param)
{
// 0 is reserved, so 1 is client name. 2 is ping count.
var clientName = param[1];
var pingCount = param[2];
if(pingCount == core.invalid)
{
pingCount = 1;
}
//if we have a user like this, we can use em
var userId = core.users.isAUser(clientName);
if(userId != core.users.invalidUser)
{
//Create a new network javascript object.
//This object handles network packing/streams internally.
//The to dev, this is simple - a javascript object.
//Push data into the stream, and be done.
//The toolId is to header the packet type, for the server
//to know what to do with it.
var pck = new core.net.packet(this.toolId);
//Add our data into the packet for the server to care
pck.push(userId);
pck.push(pingCount);
//Give it a callback when its feeling talkative
pck.response = this.onResponse;
//Send it to the server
pck.send();
}
}
//The servers response to a ping command
var corePingTool.onResponse = function(param)
{
//0 reserved, 1 is always the response code, 2 is the result
//(known, from server side), 3 is the client requested
if(param[1] == core.net.success)
{
//should output something like
// ping response 128ms from " DumbassTeh"
var end = ' from " ' + param[3] + ' " ';
echo('Ping response ' + param[2] + 'ms' + end);
}
else
{
//message box failure
}
}
The server side response
// Server side tool for pinging another player in the game
// Author : FuzzYspo0N
// Etc
//expects - a packet with
//pop 1 - sourceUserId
//pop 2 - destUserId
//pop 3 - ping count
//context globals
//var toolId is handed in from the system
var corePingTool_Main = function( pck)
{
//Pck is basically a javascript array, and pop will
//simply keep a "stackIndex" internally. So in essence
//what you can see here is
// stackIndex += 1;
// return pck[stackIndex - 1];
var sourceId = pck.pop();
var destId = pck.pop();
var pingCount = pck.pop();
for(i = 0; i
Comments, views, ideas, etc - Welcome. Please, i like ideas.
Update!!
I am attaching a mockup of how the tools *could* work , for development of the OS features. This is why i need feedback, is it plausible to expect some non developers to enjoy modifiying their desktop more than just a background image? etc.
Click on the image to see the full one.
[caption id="attachment_110" align="aligncenter" width="450" caption="Developer tool interface? Why not."][/caption]
To celebrate the months wasted trying to find a way to make gameswf work for me, i am going to post the test build of the game here. There is not a lot to the UI yet, just a login screen and a "login complete" screen. After that, there is the escape key to exit.
For this test, the username is devcore , and so is the password. Iv attached some images below for post sake.
The tech so far
Currently im using v8 javascript engine for scripting,
PhoenixCore for rendering Link
And awesomium for the UI stuff Link
The rest of the story
Is still to come. I will post later today sometime maybe, the ideas behind the networking code on the client tool development side,
and i hope that there will be some discussion behind that. So if you can/want to please check back in a while for the networking part.
Candy
[caption id="attachment_110" align="aligncenter" width="431" caption="FLCore"]
[/caption]
[caption id="attachment_110" align="aligncenter" width="450" caption="FLCore"]
[/caption]
Notes :
Requires VC (vs2008) runtime libraries. Google these, if you dont have them. If you cant run the exe, open the html instead for now.
The Download
Self Extractor (3.8 MB)
Link
Meh, trying too hard to redo the same image, with more detail. Got bored so im gonna do something completely different instead.
[caption id="attachment_110" align="aligncenter" width="450" caption="ignore this one"]
[/caption]
Some concept art iv been messing around with.
[caption id="attachment_110" align="aligncenter" width="450" caption="no candy here"]
[/caption]
As an increasing effort to post more often, i will update with more screenshots and progress on all fronts that i work on.
For now, implementing the demo of shadowracer into Torque3D. The screenshots are intentionally ugly and washed out ;)
[caption id="attachment_110" align="aligncenter" width="958" caption="no candy here"]
[/caption]
As i mentioned, things were on hold. As i have now the things needed in my bag'o'tricks i will be reimplementing the game play over the next short while, and ill have a nicely polished video to display as well.
[caption id="attachment_110" align="aligncenter" width="766" caption="no candy here"]
[/caption]
Cant wait.
Taking on a challenge (while waiting for certain things to be finalised on shadowracer, and other things taking my time), I decided to challenge myself to some code architecture design. Like designing systems that are clean, simple and efficient while being powerful enough to maintain their stability and usability on a much larger scale. Things like networking, user interface design, game core runtime designs etc.
V8
One of those steps was getting the v8 javascript engine running nice and smoothly behind the scenes of the core code base, which was incredibly easy thanks to their simple approach. Using a modified base of CProxyV8, i have managed to expose entire classes to script on a whim via some really minimal preprocessing of class files and macros, which will be polished and released here as soon as its a viable tool.
Multi User Interface design
Allowing the switching of user interface engines at any time (even runtime) was another challenge i took on, which has also proven quite fruitful so far. While using the PhoenixCore engine for rendering at the moment and hooking up some gameswf flash UI code to that is quite powerful , i still have the flexibility to change those at any time with minimal wrapping of gameplay code.
Interesting Gameplay
While the engine may be all cool and dynamic it doesn't serve any good without a nice fun game to play. I wont be speaking on what exactly i have gotten into making with some friends but i can post some mockups that have come up so far.
[caption id="attachment_110" align="aligncenter" width="598" caption="Coming sometime"]
[/caption]
[caption id="attachment_110" align="aligncenter" width="800" caption="Coming sometime"]
[/caption]
Wow, this is some really awesome news.
During the month of December 2009, you can pickup full fledged binary (no source code) licence to the amazing Torque3D game engine. Not only that but that constitutes a $250 licence discount on the professional (full source code) version at any time.
Read the blog here : Link!
|