Game Development Community

Enhancements to the way levels are loaded

by Evan Ogawa · in Torque Game Builder · 02/16/2007 (12:26 pm) · 1 replies

I have a concept for loading levels that would allow greater flexibility in the process of putting a level up on the user's screen and transitioning between levels.

I want to remove the assumptions that the Gui to be set up is named "mainScreenGui", the scene window is named "SceneWindow2D" and the canvas is named "Canvas".

In my concept, the level (.t2d) file would know the name of the main Gui object required for its use. Also, the main Gui object would detect a root-level t2dSceneWindow and use that as its scene window of choice.

With this scheme in place, a t2dSceneObject would be able to point all the way back to the Canvas:

t2dSceneObject <-> t2dSceneGraph <-> t2dSceneWindow(SceneWindow2D) <-> GuiControl (mainScreenGui) <-> GuiCanvas (Canvas)

Accessors already exist to allow many of these connections to be made: GuiCanvs::getContent(), t2dSceneWindow.getParent(), t2dSceneWindow::getSceneGraph(), etc.

What is needed to complete the picture is some simple changes.

1. When t2dSceneWindow::loadLevel() calls onLevelLoaded() on the scenegraph it has loaded, it should pass a reference to itself, just as the scenegraph does when calling onLevelLoaded on its child scene objects. From /games/common/gameScripts/levelManagement.cs: change to
if( %scenegraph.isMethod( "onLevelLoaded" ) )
         %scenegraph.onLevelLoaded(%scenewindow);
Also, the scene window would set a member variable when it loads the scene graph which could be accessed via t2dSceneGraph::getSceneWindow() and -setSceneWindow().

2. The Level Editor would maintain the level file's GuiWindow member field (default "mainScreenGui"). Then the following code in function startGame( %level ) would extract it for use in loading the main Gui:
exec( %level ) ; 
	if ( isObject( %levelContent ) && %levelContent.isMethod( getGuiControl ) ) { 
		%theGuiControl = %levelContent.getGuiControl( ) ; 
	} else {
		%theGuiControl = "mainScreenGui" ; 
	} 
	%theCanvas.setContent( %theGuiControl ) ; 
	%theGuiControl.setFieldValue( GuiCanvas, %theCanvas ) ;
The cognoscenti know that, by convention of the LevelEditor, the level file has an assignment statement in it: %levelContent = new t2dSceneGraph() {} ; So the code just looks looks inside the object of that name to find the name of the Gui object, which it passes to the canvas.

Note that this code also ensures that the Gui knows the name of the GuiCanvas. I know that
Quote:there is only one GuiCanvas and its name is "Canvas"
But there is no need to propagate this assumption further than necessary.

Then instead of passing the name of the level file to the scene window's loadLevel function, we would pass the reference. Change startGame() from
if( isFile( %level ) || isFile( %level @ ".dso"))
		%scenegraph = %theSceneWindow.loadLevel( %level ) ;
to
%scenegraph = %theSceneWindow.loadContent( %levelContent ) ;
where we have created a new method loadContent().

The benefits of these changes are manifold:

1. Objects know their context container hierarchy completely. The game code can completely forego using dedicated, magic word, strings like "Canvas", "SceneWindow2D", "mainScreenGui" that lock us into a single, inflexible scheme.

2. Multilevel creation and loading is facilitated. A level knows which Gui it needs, so the game developer is not stuck with a single Gui for all levels. (I know: you can work around this limitation. But why should a workaround be necessary?)

In the end, the code in startGame() should not assume that the game has only one level. Instead, it should be generalized into code that accomodates multiple levels and also, for heaven's sake, facilitates placing pre- and post-game splash screens.

So, that's my idea. I would welcome feedback on the concept. Particularly along the lines of how suitable the new functionality is and how much this functionality is important to you. (Implementation details aside.)

#1
08/27/2009 (1:19 pm)
Hi Evan!

Have you done any big improvement on this? Is there a working example?

I will buy soon TGB and will love to use something like that to my games.