Game Development Community

dev|Pro Game Development Curriculum

Torque Game Engine Understanding Diary, part #1

by Vitla · 10/21/2006 (6:47 pm) · 4 comments

Torque Engine Understanding Diary

What is it?

This is a sort of TGE Guide for those, who are programming, scripting and doing art for themselves. More or less good at everything, while being pro only at one section. Also this serves the goal to make me understand what I am looking at, when I am looking at piece of C++ engine code or extension. Or at least where to look at to understand it.

How?

This is a way that I went while learning Torque Engine. This is not a description of something - but this is the path of thoughts, a road, or "how I made a map", which would serve me much better then plain description, if I met someone's "diary" like that before. Supposing that this is not only me, I decided to post my TGE Understanding Diary for others.

1.

(From memory) Digged up here, there, understand nothing while remembered much. Have pieces and no whole picture. Alright, I thought, if my goal is doing RTS, I need to study RTS documentation and files. Initially, I checked several places for that:
- forums on that (including private)
- resources about that (articles)
- TDN pages about that
- take a look into C++ and script files of RTS starter kit.
But, the same again - I got modules and module description without proper understanding their place in whole engine. I started to think...

2.

What if I made an RTS from scratch (having game design already on hands) - where would I start? I would start with an idea, an programming model. Usually I start with general "A man is playing a game". Rather stupid :). Considering RTS it changes to "A man is operating the game world through GUI". This is a truly description. Another model or idea for 3D modeling and animating soft, various C++ rendering engines is "We are on scene making a movie/theatre drama". This describes what's going on and WHY it is going on on a SUCH way - camera, actors, scene. It's just like it was the most simple way to understand the situation to solve it for developers - to think of this in terms of actors and camera. Even I, starting simple scroller game from scratch in ActionScript at the end came up with a camera object - it was the most simple and descriptive idea of what's going on and should be with all this perspective scaling, clipping, moving the "viewable part of game" (=camera) and so on. So now when I see camera object I know what to think and expect.

So know you understand what I am talking about when I say that I wanted to know the ideas or models that stand behind important TGE modules along with the whole engine idea to understand which exactly place is occupied by that crazy RTSUnit creature :)

3.

That was better. First stop here is General Torque Documentation, part IV, Engine Overview. Introduction started to slowly save my soul.

"Because different platforms can have different main() entry points for applications, the Torque Engine main() function resides in the target OS platform library. In the case of Windows, this is in file engine/platformWin32/winWindow.cc, where both main() (for console apps) and WinMain() are defined. These in turn call run() which calls Game->main(int argc, const char **argv). Game is a global object pointer referencing an instance of the GameInterface class that can be overridden for specific game behavior."

I found a border after which lies something I will never bother - it was my first truly understanding. I got the place of "platformWin32" folder contents in my TGE universe :). It was "far, far away place". I don't bother how, but when I hit Enter on exec file (Torque Demo or my future game) in the end they call Game->main() and this start all the show. That was an entrance to TGE C++ stronghold I fought for so hard. Game is single instance of GameInterface class. Specific game can override it. Excellent. Obviously, if game as a whole has an interface, there is somebody or something that wanted to interact with it or through it. Cool. So we found main guy here. I quickly memorized it's methods for when something suddenly will call processTimeEvent() or loadJournal(), I will know for sure that I am looking at this main guy calls. That is already something.

So, main guy - GameInterface class. Resides in engine/platform/gameInterface files.

4.

Then they say:

"The Torque example program's main initialization occurs in engine/game/main.cc in DemoGame::main(). "[/]

Take a look into main.cc file - I understand nothing. But, HAHA - at line 65 they declare variable "GameObject" of the type DemoGame. I checked definition of DemoGame. Derived - bingo - from GameInterface.

But there is no DemoGame.cc file as expected... Strange... Alright, back to main.cc... - sweet, it contains an implementation of DemoGame class - at the end of file. All other functions considered by me being as helper funcs for something unimportant now. Now I check what's going on in that DemoGame::main() method at line 380 (remember why we want it? Check step 3, extract from docs). Aha, now I understand the use of that other "unimportant" helper classes in this file - some of them are called here, in DemoMain::main(). Suppose that other DemoGame methods do it too.

5.

DemoGame (derived from the GameInterface - the main guy)::main() method says at 391 line: if(!initLibraries()), then everything will to hell. Obviously initLibraries() is helper function somewhere here, in main.cc - bah, at the beginning...

Wow, wow, wow -we have here is pack of single objects - some kind of engine parts - being initialized or started. Obviously in shutdownLibraries() they will be deactivated. Nice.

Net,
Platform,
TextureManager,
ResourceManager,
Con,
TelnetConsole,
Processor,
Math,
InteriorInstance,
And other things.

More or less understanding what these guys are intended for, I want to note that they are all looked like being some variation of a singleton - or at least share the same goal to be single objects across all system and as such, i can suppose their use and role in the whole sheme.

Now, in general, we have main guy, which call his friends in initialization phase.

6. Reading on:

[i]"This function initializes libraries, initializes game functions and then cycles in the main game loop until the program is terminated"


Ah! Yes, we seen that. Initializes his friends.

Alright then, back to DemoGame::main() inside main.cc. Understanding nothing after previously checked line 391, we meet familiar guy at line 415. They do something with Con library. Reading the comments I understand that this is really something that concern that Console (scripting and all) I am looking at - maybe even Console object itself... And at 419 line they start up another helper function - initGame()... Bah, this is (419 line of main.cc) game initialization point! Again scroll up to study initGame() function...

...Aha...

A, yes. Alright, I got you all, nasty TGE modules. Everyone is here - console(some TorqueScript related action), terrain, action map, particle, simulation, net. Another gang of friends initializes here. From now on I can study these modules separately knowing their place in the core architecture. Freedom at last!

7.

Thinking about RTSUnit and other game objects I understand that the things I just discovered can be called "core" scheme. Summarizing: there is GameInterface class. He is God. DemoGame implement it. Libraries and other engine parts are initialized in the overridden by DemoGame "main" method of GameInterface. As I understand, platform-specific things through GameInterface interface :) call this DemoGame's "main" method - so it become our application entry point. Also as I noticed, the whole platform-specific things are packed into Platform single object and we deal only with general Platform interface. So specific win32 things inside that platformWin32 folder on disk are thanks gods really of not my concern and wont be. Maximum my depth that can be - to use Platform methods.

8.

Now I quickly dove into Platform class definition to realize how my machine is seen from the engine, and what can and can not be done. Platform/platform.h: inline functions... categorizing processors... ah - struct Platform... struct Net... struct NetAddress... struct memory... Well this is definitely place for future stop. As for my machine in Platform structure - it is seen as something dull, but potentially understandable. Very good, goodbye platform.h.

9.

I made a coffee.

10.

Now I tried to start step by step - from initLibraries() in main.cc file:

Line 110. Net::init(). Search for initial Net class definition failed along with the attempt to locate where the hell they create that Net object. I searched " Net::" string and find that winNet.cc has such methods - bool Net::something() { and so on }; Heh. But there is no winNet.h file, which means.... Which means - where the hell is definition?! Oh man, back inside that Platform.h file. They made struct "Net" and then each platform - also PlatformMacCarb, also PlatformX86UNIX - include their macCarbNet.cc, X86UNIXNet.cc files, where each one write their own Net::something() methods.

Hmm - and this somehow works? Never met such things... I still something didn't know about C++, compiling, linking and coding tactics. Oh well, anyway this is already the border of detail for me here. Next "lib".

12.

Platform::AlertOK(). Oh, this is good. Not a lib, actually, but this is easy call - the goal is clear, the implementation is unimportant. Well, maybe only for Windows users is clear, who met various windows system alerts way too often :). Next libs obviously were immediately skipped...

ResourceManager pointer - interesting, that he is created in separate core/resManager.cc file but freely accessed from here (main.cc function) - another coding news for me...

Con lib is truly Console itself, as stated in console/console.* files...

Oh well, another libs I just read again but didn't dive in - enough just assumptions of their role and the fact that they initialized here.

13.

At this point my Doxigen wizard ended up parsing the whole engine and shows me nearly the same that official TGE Brutal Deadly Cold Unfriendly And Without Mercy Source Code Documentation does, but I feared nothing and went straight for the Main Boss: GameInterface class description.

Ah, great, here I noticed that they repeated their trick - in this file they declare Game pointer (look very much like they did with ResourceManager pointer). Is that means it became global to everything?

Also an object GameObject, declared in main.cc and being of type DemoGame seem to be not using by anything at all... Everyone use Game pointer itself...

And I still cant find where they call DemoGame...

Alright, I falled back in hell - how exactly goes the show around Game, DemoGame and GameInterface?!

Aha, got one - in file winWindow.cc, at line 1279 they say Game->main() in the function "run", which is called from.... WinMain! Hahaha!. Alright, now I realized that I was stupid - we just rediscovered first documentation passage:

"Because different platforms can have different main() entry points for applications, the Torque Engine main() function resides in the target OS platform library. In the case of Windows, this is in file engine/platformWin32/winWindow.cc, where both main() (for console apps) and WinMain() are defined. These in turn call run() which calls Game->main(int argc, const char **argv). Game is a global object pointer referencing an instance of the GameInterface class that can be overridden for specific game behavior."

Well, at least I now exactly know what this means... Last piece that I don't understand is how this Game pointer connected with that DemoGame class we discover. I still didn't find the place where they do something like Game = new DemoGame(). When DemoGame (Torque game example) really turns into main global Game pointer - into current version of God?

14.

Figured out their trick. I will remember it. Check it out in GameInterface.cc, in the beginning:

GameInterface *Game = NULL;

GameInterface::GameInterface()
{
   AssertFatal(Game == NULL, "ERROR: Multiple games declared."); <-- [b]minor place of Trick[/b]
   Game = this; <----- [b]Place of trick[/b]
   mJournalMode = JournalOff;
   mRunning = true;
}

So that means that anyone who made at least one GameInterface object (they do it by "DemoGame GameObject;" string in game/main.cc file at line 65) will automatically "fill" Game global pointer with that object. This also prevent us from unnoticed overwriting. Oh yeah, now we will surely notice this fact :)

Phew! :) Gone for coffe - continued in next post.

#1
10/22/2006 (2:08 am)
Nice... a good example of how one learns to read the torque source code and UNDERSTAND it :)

Believe me, we all do exactly this.
#2
10/22/2006 (2:50 pm)
Thanks!

As for learning - my dream is of that times, when developers along with official guides will be able to publish their line, path of thoughts, which brings them to result. When one will invent thought-tracing recorder & converter to text :)))
#3
10/22/2006 (5:18 pm)
Excellent resource Vitla, keep up the good work
#4
10/22/2006 (10:49 pm)
I kind of skipped this last week while teaching a boot camp, but I'm literally amazed at how you have analyzed the source code and made outstanding observations about what is going on.

I teach Torque for a living, and I wish even half my camp attendees had your drive and intuition!