Tutorial Index

Tutorial 22 - Levels


Introduction

In this tutorial we will demonstrate one way to add multiple levels to your game engine, each containing different game objects.

Concepts

Revisiting osg::Group
Multiple Scenes

Revisiting osg::Group

We must remember when a child is attached to an osg::Group two links are created: One going from the child to the parent, and one going from the parent to the child. Adding children is easy, but what happens when we remove a child from an osg::Group?

osg::ref_ptr<osg::Node> somenode = new osg::Node();
osg::ref_ptr<osg::Group> somegroup = new osg::Group();
somegroup->addChild(somenode.get());
...
somegroup->removeChild(somenode.get());

As we would expect, the osg::Group::removeChild() function breaks the link between both parent and child:
1. The parent removes the child from the parent's list of children.
2. The child loses one reference via the unref() function.
IF ( number of references for the child <= 0)
    child is deleted
ELSE
    child deletes reference to parent

Multiple Scenes

How does this help us? Remember that Scene contains an osg::Group that acts as the root for the scene. This root is then attached directly to the osg::SceneView in Window via the osg::SceneView::setSceneData() function. In reality, the osg::Group is actually attached to an osg::Camera contained by the osg::SceneView.

The reason for explaining that detail is that osg::Camera is derived class of osg::Group... meaning it can have children! Meaning we can add and remove any children via the process described in the previous section. Thus to change levels (scenes), the current scene (osg::Group) must be removed from the game (osg::Camera), a new scene (osg::Group) must be created and then attached to the game (osg::SceneView). Demonstration:

osg::ref_ptr<osg::SceneView> sceneview = new osg::SceneView();

//Note that these groups represent 'scenes' of objects. Levels, if you will.
osg::ref_ptr<osg::Group> firstlevel = new osg::Group();
...
//Attach the first level
sceneview->setSceneData(firstlevel.get());
...
//Create a new scene (level)
osg::ref_ptr<osg::Group> secondlevel = new osg::Group();
...
//Remove the first level from the parents. Note that the parent of this level
//is actually the osg::Camera
const vector<osg::Group*>& parents = firstlevel->getParents();
for(unsigned int i = 0; i < parents.size(); ++i){
    osg::Group& parent = *parents[i];
    parent.removeChild(firstlevel.get());
}
//Attach the second level
sceneview->setSceneData(secondlevel.get());

Note that for the tutorial code, the two classes of importance are Scene and System_Controller.

Controls

The tutorial code can be manipulated via the following keyboard input:

Esc - Exit
1 - Change to a level with a single star
2 - Change to a level with two stars
3 - Change to a level with three stars

References

osg::SceneView
osg::Camera
osg::Group
Tutorial Code

Conclusion

As can be noted, changing 'levels' is as easy as removing old objects from the scene and adding new ones. However, one must be sure that the old objects are removed properly, so careful use of ref_ptrs is well advised.