Game Development Community

C++ integration

by MrClam · in Torque Game Builder · 03/09/2005 (3:20 am) · 22 replies

Hi,

I've bought into T2D as it will hopefully make my life easier creating (or at least prototyping) a 2D game I have in mind.

However, as this game will be fairly complex, im a bit apprehensive about doing it all in script (debugging/profiling/etc etc will be a REAL pain if I have to use script for everything). I'd like to keep the script code for simple things in a level editor (for example) as you would do in a "real" game, but I'd like to have the c++ used for everything else.

So for example, I'd create a "evilBadGuy" class which handles the movement, ai, collision, etc etc of the "evilBadGuy", but I then add a script which spawns this "evilBadGuy" whenever a certain thing happens (for example, player standing on a switch, or colliding with an invisible collision box).

So this brings about a number of questions:

1. Has anyone managed to get the t2d project compiling in .net? I've just given it a quick bash, and it compiles in release but not in debug (I need to investigate this further).. but i imagine no biggy.

2. How easy is it to call T2D calls from within c++?

3. Im a bit worried about whether this will have major knock-ons when i get later versions of the Torque, but i guess as long as i write a "HAL" layer which calls Torque, then I just have to modify that? Does anyone see a problem with this? Is it likely the syntax for things will change THAT much? If not, maybe it's advisable not to have the performance overhead of a separate layer? Anyone got any thoughts?

4. How easy/hard is it to add my own C++ calls to withing torque script? I.e. If I have a class called "baddy" which contains various functions which i want to be open to the level scripter (i.e. me), can I expose these to the script tool easily?


Any other information anyone has? Anyone tried this yet? Or is everyone using the scripting system "properly"?
Page «Previous 1 2
#1
03/09/2005 (3:39 am)
As an additional request that I think fits well with the thread, would it be possible to give access to some TGE Official Docs to T2D owners? I mean stuff like input mapping, GUI and all the stuff that has remained as part of T2D.
#2
03/09/2005 (3:46 am)
2nd Addition, now i've managed to get the code up and running in debug mode, i notice that you're using directx7 calls such as "DrawPrimitiveVB".

Has any thought been made into moving accross to later versions of directx?

This would make it easier for me to implement some 3d features as and when i need them, and means i can turn d3d into debug mode for quicker debugging/optimisation purposes later on (debug mode doesnt work on dx7).

Or should I assume that glu2d3d, etc arent going to change between now and final release, and therefor will be okay for me to edit, improve and optimise for my needs?
#3
03/09/2005 (5:22 am)
@Manuel: Try here here. You should have access to all the TGE stuff like this, I know that others are using it fine.

@MrClam:

1) What do you mean in .Net exactly. T2D compiles using VC6 and VC7 perfectly, without problem. We've never done any C# integration work though.

2) Very easy although you'd need to be more specific for a better answer than that.

3) Hard to answer this, it all depends on what you're trying to achieve. I would highly recommend that you create your own objects and drive them from script. Don't fight the way T2D works and think that the scripts are slow. You should do all of your game logic here excluding stuff like AI, path-finding etc. Creating T2D compatible objects is so very easy to do. I'm trying to get the final round-one bugs out of the way then I want to spend a couple of hours doing a simple T2D template object that you can use to render or just use as a timebase or both.

4) Very easy. Here is the official doco on how to generate a Console Function (global function) and a Console Method (class member function).

To see an implementation for a global function (consoleFunction), look in "fxVector2D.cc". Look at the "vectorAdd2D" function for example. When retrieving arguments, T2D uses its own string functions to seperate values from strings. Conversion from strings to bool, integer, float is done with "dAtob()", "dAtoi()" and "dAtof()". As you can see, you access the variable arguments using argv[n]. Be aware that the first parameter is used by the system and I believe is the function name. Console methods use the first two which I believe are the function and the object ID so be careful there.

To see an implementation for a class member function (consoleMethod), look in "fxScroller.cc" (approx line 187) for the "setImageMap" function. As you can see here, all I do is define the "ConsoleMethod" macro which automatically generates me a pointer to the object called, suprisingly enough, "object". In this example, I just call the class member function and pass the only parameter. As I mentioned above, the first two are used by the system although can be used by you so the first user one is index#2.

These macros allow you to specify the return types, min/max parameters (which must include the system ones), the script-name of the function as well as a description which is dumped to the console if someone uses "%obj.dump()". Try this on any T2D object. Note that you get more info from a DEBUG build than a RELEASE one.

More info/examples to come though.

I hope this helps get your started.

- Melv.
#4
03/09/2005 (6:08 am)
Hi, its not that i think the scripts are slow persay.. it'll just be a billion times easier to debug code which is in c++, as opposed to in script. Not to mention that managing large game code will be easier in c++ too (utilising objects, etc).

With regards to what im trying to do. Can you please give me a running start as to how to get a sprite on screen using c++ (and not script). I've got my compiler up and running, and it's all running through the debugger nicely.

now.. i've tried adding some simple code based on the tutorial scripts.. But I've been scratching my head a bit.. here's what i have so far, it doesnt work so i'm obviously assigning something wrong or doing something crazy?:

fxStaticSpriteDatablock2D DataBlock;
	DataBlock.assignName("PlayerShip");	//
	DataBlock.mImageMapName = "~/client/images/playerShip";
	DataBlock.onAdd();

	fxStaticSprite2D *player = new fxStaticSprite2D(); 
	player->setImageMap("PlayerShip", 0);
	player->onAdd();
	player->setPosition(fxVector2D(-35, 0));
	player->setSize( fxVector2D(14, 7) );
#5
03/09/2005 (6:13 am)
Why would you want to use C++ for something like that? Initializing a sprite isn't going to cost much in terms of execution speed since it's generally not going to be something that's done very often. You're making things more difficult than they should be. :)
#6
03/09/2005 (6:23 am)
>Why would you want to use C++ for something like that?

Just something simple to get me started.

As I said, im not worried about the speed. More of the code layout, etc.

For example, again keeping this simple, i know in a "real world" you wouldnt do this.. I could make a proper class heirachy where I have two baddies, both of which share a gun, the gun is offset in the same postiion for each baddy, so I have a gun class which sets up and draws the gun which is inherited by both baddies (which just differ in their sprites).

The project im working on (which im looking to port to t2d for various reasons) is complex, and so i dont want to further complicate things by having lots of unecessary objects, pointing to scripts unnecessarily, etc etc.

I *WILL* use scripts.. but purely as a higher level entity (create bad guy here, etc).

I need to store MUCH more about an item other than just its picture.

I also NEED proper compilation output, i dont want to spend hours trying to find which line the code hasnt compiled on. I want to be able to debug my code if something goes wrong, etc etc.

Having to work with scripts just for the exmaple was painful enough (save, run, crash, wonder why, go back, etc etc). I wouldnt want to begin using them too much for anything even remotely complex.
#7
03/09/2005 (6:57 am)
No problem.

All you need to do is register/unregister the objects in the T2D engine. You don't need to explictly call onAdd/onRemove as that is done for you.

Here's your code as an example:-
// Create a static sprite.
fxStaticSprite2D *player = new fxStaticSprite2D(); 
// Register with the T2D engine.
player->registerObject();

// Do some misc stuff...
player->setImageMap("PlayerShip", 0);
player->setSize( fxVector2D(14, 7) );

// Add to some scene.
someSceneGraph->addToScene( player );
... and when you've finished ...
// Unregister from the T2D engine.
player->unregisterObject();
// Destroy Object.
delete player;
... or the more safer engine helper ...
// Unregister and delete object.
player->deleteObject();
... or the even safer T2D one that defers deletion until the beginning of the next-frame processing...
// Next-frame, unregister and delete object.
player->safeDelete();
People should always try to use the "safeDelete" call which is a scheduled deletion as it is completely safe to use within script-callbacks. This obviously doesn't apply here but is also safe under other circumstances where you may want to continue to iterate a set of scene objects and don't want the list to be interrupted by the instantaneous removal of the object from a scene. "SafeDelete()" is as its name suggests, the best option.

Note that in all cases, the core fxSceneObject2D, in its "onRemove()" virtual function, removes itself from any scene and so you don't need to handle this.

Please don't hesitate to ask if you have any more queries.

- Melv.
#8
03/09/2005 (7:01 am)
I would just like to add that the whole of Tribes#2 and other games were completely scripted. Don't let some initial frustrations lead you to the wrong conclusions. There are excellent tools for debugging the scripts, line by line. The compiler tells you which line the problem is at and also highlights it in red.

If I were you, I'd be playing around with C++ as well so I'm not going to get on my soapbox but I would urge you to step back a little and consider the power of the scripts.

As I say, you're one of the first people to ask about this stuff and I'm more than happy to help you get up and running but please consider what you may be missing out on. :)

Good Luck,

- Melv.
#9
03/09/2005 (7:37 am)
Okay.. At the moment i have the script used in the example to set up the scenegraph.. i.e.:

function setupT2DScene()
{
	// Create fxSceneGraph2D.
	new fxSceneGraph2D(t2dSceneGraph);
	
	// Associate Scenegraph with Window.
	sceneWindow2D.setSceneGraph( t2dSceneGraph );
	
	// Set Camera Position to be centered on (0,0) with
	// view width/height of (100/80).
	sceneWindow2D.setCurrentCameraPosition( "0 0 100 75" );
}

How do I then get that scene graph back from within code?

btw.. thanks for this...
#10
03/09/2005 (8:38 am)
First, no problem, I'm here to help. :)

You need a little background first though ...

When an object is registered, it is automagically added to the simulation system and is therefore available for searching. When you create an object, you may have noticed that you can create it and just reference it in a variable or you can
create it and name it or both!

We can create objects without a name like this ...
// Create and don't assign a name.
%scene = new fxSceneGraph2D();
// Clear Scene.
%scene.clearScene();
... now this is good because we avoid naming collisions but are then forced to reference with a variable, probably a global one. You'd probably do this for the mother-load of objects created in a game but you'd probably have key objects, such as the scene, named so that the syntax is easier, like this ...
// Create and assign a name.
new fxSceneGraph2D(myScene);
// Clear Scene.
myScene.clearScene();
... and you can even do both like this...
// Create and don't assign a name.
%scene = new fxSceneGraph2D(myScene);
// Clear Scene Twice!
%scene.clearScene();
myScene.clearScene();
.. or defer the naming afterward like this ...
// Create and don't assign a name.
%scene = new fxSceneGraph2D();
// Assign a name.
%scene.setName("myScene");
// Clear Scene.
myScene.clearScene();
Okay, why all this info?

Well, the reason I describe this is because it's very important to understand when you want to interrogate the simulation system. One thing that is vitally important to understand is that you can choose whether to give an object a name (as described above) or ignore that. The point being that the simulation system ignores names to some degree and uses its own internal ID system. Every object that's created is assigned and ID. You can get to this from the scripts using the following ...
// Create and assign a name.
%scene = new fxSceneGraph2D(myScene);
// Dump the scene ID using different notation.
echo( myScene.getId() );
echo( %scene.getId() );
Okay then, with all this background done, it's a simple matter to understand that you've got the choice whether to search the simulation for an object by either name or ID, it's up to you but as you can understand, not every object would have a name so it's more common to pass an ID. Obviously, it's more user-friendly to use names, that's why the "playAnimation()" command for the "fxAnimatedSprite2D" allows the user to pass the name of the animation datablock, not its ID.

So, now you're armed with all the info you need to see two examples of searching the simulation, one searching by name and one by ID...
// Dump scene (selected using Name).
ConsoleFunction( sceneDumpByName, void, 2, 2, "(scenename) - Finds a scene (by name) and dumps the object count just for a test!")
{
	// Find the scene graph by name.
	fxSceneGraph2D* pSceneGraph2D = static_cast<fxSceneGraph2D*>(Sim::findObject( argv[1] ));

	// Dump the object count (if we find the scene-graph).
	if ( pSceneGraph2D )
		Con::printf( "The scene '%s' has %d object(s) in it.", pSceneGraph2D->getName(), pSceneGraph2D->getSceneObjectCount() );
}


// Dump scene (selected using ID).
ConsoleFunction( sceneDumpById, void, 2, 2, "(sceneId) - Finds a scene (by id) and dumps the object count just for a test!")
{
	// Find the scene graph by name.
	fxSceneGraph2D* pSceneGraph2D = static_cast<fxSceneGraph2D*>(Sim::findObject( dAtoi(argv[1]) ));

	// Dump the object count (if we find the scene-graph).
	if ( pSceneGraph2D )
		Con::printf( "The scene '%s' has %d object(s) in it.", pSceneGraph2D->getName(), pSceneGraph2D->getSceneObjectCount() );
}
... continued ...
#11
03/09/2005 (8:46 am)
... continued ...

As you can see, you use the Simulations' "findObject" call that has many overloads but I think you should, at least initially, stick to the ones that search by name or ID. It is then a simple matter to do a cast from the parent "SimObject" (simulation object) to your object. Notice that in the case of the ID version, we use the "dAtoi()" call to convert the ID in string-form into an integer (S32 to be precise). Also, I show the use of the "getName()" function which is a "SimObject" function to return the name as described above.

Here's how you would call it from the scripts...
// Create a named scenegraph.
%scene = new fxSceneGraph2D(t2dSceneGraph );

// Access by object-name.
sceneDumpByName( t2dSceneGraph );

// Access by object-ID.
sceneDumpById( t2dSceneGraph.getId() );

// Access by object-name.
// NOTE:- Objects pass the name, not the ID!
sceneDumpByName( %scene );

Finally then, note that these are essentially global functions (ConsoleFunction) and that you can create class member functions (ConsoleMethod) which allow you to call public accessors straight into your scripts in a few lines of code, how cool is that?

Hope this helps,

- Melv.
#12
03/09/2005 (12:04 pm)
@Melv: I know this has been asked a million times before, and I apologize for beating a dead horse, but are there docs on the simulation system?

I see that there's a section in the docs but it's inaccessible. I don't know if that means it doesn't actually exist or whether I just can't access it.
#13
03/09/2005 (2:13 pm)
I presume you just can't access it. I'll look into the issue of documentation access soon for everyone and get back to you.

- Melv.
#14
03/11/2005 (7:41 am)
Well. I actually purchased Torque2D thinking it was an OpenGL-enabled 2D library for C++, which was just the ticket for my multiplatform project, all written on C++...! I have no use for TorqueScript, and would find essential to be able to access Torque2D from within C++.
#15
03/11/2005 (8:43 am)
And you can access T2D from C++, where's the problem? Althought you can't see the Torque C++ documentation that would not help *a lot* either, since it's not T2D related doesn't cover every aspect of TGE.
#16
03/11/2005 (10:54 am)
Thanks, Manuel, as I have seen no documentation at all about C++, and only about TorqueScript, I wrongly asumed that Torque2D didn't support it. I guess Torque2D is going to be properly documented in the near future...
#17
03/11/2005 (11:04 am)
When you purchase T2D, you get the entire source code. You can do anything you like with it!

The primary target of T2D is for those looking for a two dimensional game development platform, not just those looking for an SDK of functions they can call--that's the general strategy of all Torque platforms. What this means is that the code isn't organized to act as simply lib calls as some other, lower market target SDK's are, but the source is all there and you can do pretty much what you want with it (barring license violations obviously, like releasing a game-maker style SDK to the public).
#18
03/21/2005 (1:29 am)
I don't usually post but this time I feel compelled to, as I felt the same as you until I got into the game industry.

Take it from me my friend, scripting is where its at, and is where all game code should be.


I've been writing game code in c++ for many a year, went to Digipen where we made games in 3 months ( 1 per semester ). One of them got an award at GDC.. man those were good times.

Ok so after school I got to work with a company that was using the Unreal engine. When i started i was expecting to work in c++, but instead we were mostly in the scripting language. I was confused at first but after i worked through it i saw why we decided to go that route.

I now work at Gas Powered Games on Dungeon Siege 2 which, believe it or not it has 2 scripting languages. One is like torque script, a c++ like language with game specific features. The other is a language I put together specifically for the level designers and designers. It's very high level and reads like a movie script, but with it the level designers can put together half life 2 like interactive sequences and movie style cut scenes without needing an engineer assistance whatsoever ( because there is little to no complexity ).


In c++ you deal with complexity all over the place, some functions you cannot call at certain times due to where your code path is from the game's pipeline, or what thread you might be on, or if your the client instead of the host, I can go on and on. Oh not to mention how every programmer thinks there code is the *right* way to do things so you loose consistency with interfaces and class structure when writing game code in c++.. oh and the compile times.. geez!

As with all software layers, every time you abstract yourself from complexity the less you have to deal with it. And because game code is so volatile and destructive there's just no better answer than using a scripting language for your game.

I hear you on the debugging front.. but its actually not that bad, your just not used to it. When using a scripting language its good to do a lot of reports ( that you can turn on/off ). It is possible to set a breakpoint in the script itself.. I forgot what the torque fuction for that is.. but its there. After you hit the breakpoint you know what functions are going to be called next so you can then set another breakpoint in those c++ functions and go from there.

Man oh man the pros of a game scripting language outweigh the con of not having a debugger. less bugs, little/no compile times, game specific features such as state machines and latent functions ( functions that take time to complete ), script class properties exposed to an editor, the list goes on and on.

Alrighty I hope I helped spark your interest into scripting a bit more.. especially if your looking to do game code.
#19
03/21/2005 (1:48 am)
Mrclam,pablo,

If you really know your C++ you can make a copy of the engine docs using doxygen. It will basically format all the engine information in html.

I put up a resource here

www.garagegames.com/mg/forums/result.thread.php?qt=27249

Granted that I did it fast and if you read some of the posts after it, you can see there are ways to simplify it.

But it is a good resource to have
#20
03/21/2005 (9:49 am)
Well, I am the AI programmer at Starbreeze so I am pretty much entrenched in the C++ camp.
I bought T2D as a tool to write games with my daughter and naturally I also want to teach her programming and having access to a fullblown debugger makes it much easier to teach her that. Edit and continue doesn't hurt either.
Page «Previous 1 2