Home - Forums - Documentation - Gallery - Bugs
m
Current revision (07:14, 18 July 2008) (edit) (undo)
(Step Two : Basic configuration handling)
 
(9 intermediate revisions not shown.)
Line 1: Line 1:
 +
[[Category:Tutorial]]
= Step Two : Basic configuration handling =
= Step Two : Basic configuration handling =
-
First, from that point we will use more and more cim-specific files, like
+
First, from that point we will use more and more cim-specific files, like pictures, map files, music, sound etc. It this tutorial we load the first version of cim’s configuration file.
-
pictures, map files, music, sound etc. It his tutorial we load the first version
+
The configuration handling is Crystal Space is very easy to use. Each plugin has its own configuration file, you can override the values with your own configuration file. You can add or override many options from command line. The manual describes this mechanism in depth, please read [http://www.crystalspace3d.org/docs/online/manual-1.2/Options.php#0 this section] for details.
-
of cim’s configuration file.
+
You can configure many things from your configuration file. We can load plugins from the configuration file, this is a very nice feature. You can dynamically change plugins without recompiling your application. For example, the cim.cfg (config file) has this line somewhere:
-
 
+
-
 
+
-
The configuration handling is Crystal Space is very easy to use. All plugin has
+
-
 
+
-
his own configuration file, you can override the values with your own
+
-
 
+
-
configuration file. You can add or override many option from command line. The
+
-
 
+
-
manual describes this mechanism in depth, please read [http://www.crystalspace3d.org/docs/online/manual-1.0/cs_4.5.php#4.5 link this section] for all details.
+
-
 
+
-
You can configure many thing from your configuration file.
+
-
 
+
-
We can load plugins from the configuration file, this is a very nice feature.
+
-
 
+
-
You can change dynamically the plugins, without recompile your application. For
+
-
 
+
-
example, the cim.cfg (config file) has this line somewhere:
+
<pre>
<pre>
Line 34: Line 18:
</pre>
</pre>
-
In that case the fancy console output awaits you, when you run the application
+
In that case the fancy console output awaits you, when you run the application (Note, we will change the console source a little bit., now it’s s load the standard plugin statically. When you edit the walktest.cfg file, in the ''/data/config directory'' , you can see the effect in walktest.).
-
(Note, we will change the console source a little bit., now it’s s load the
+
You can override any settings of the official CS plugins. For example:
-
standard plugin statically. When you edit the walktest.cfg file, in the
 
- 
-
''/data/config directory'' , you can see the effect in walktest.).
 
- 
- 
-
You can ovveride any settings of the official CS plugins. For example:
 
<pre>
<pre>
- 
Video.ScreenWidth = 800
Video.ScreenWidth = 800
Video.ScreenHeight = 600
Video.ScreenHeight = 600
Video.ScreenDepth = 32
Video.ScreenDepth = 32
Video.FullScreen = yes
Video.FullScreen = yes
- 
</pre>
</pre>
 +
When your configuration file has this lines, your app will start at 800*600 resolution, in fullscreen. You can change any system configuration key, by adding the name and the value in the config file.
-
When your configuration file has this lines, your app will start at 800*600
+
Note that the vfs.cfg is a standard configuration file but has it's own configuration space. So if you want to mount directories from your application configuration file you will need to write some code to process the VFS.Mount entries.
-
resolution, in fullscreen. You can change any system configuration key, by
+
So you have to put an '''vfs.cfg ''' file in the same directory, when your exe exists, with the following context:
-
 
+
-
adding the name and the value
+
-
in the config file.
+
-
 
+
-
You can mount directories at runtime. For example :
+
<pre>
<pre>
-
VFS.Mount.lev/cim = $@data$/cim$/
+
VFS.Mount.cim = $^$/
-
</pre
+
</pre>
-
will mount your real ''cim.exe/data/cim'' directory to ''lev/cim'' the
+
will mount your real ''cim.exe/'' directory to ''/cim/'' the virtual path. This solution prevents having to rewrite the original
-
 
+
-
virtual path. I always use this solution, it’s better, then rewrite the original
+
''vfs.cfg''.
''vfs.cfg''.
-
 
+
Since ''vfs.cfg'' is just a normal configuration file you can add your own configuration keys. Cim will use some of its own keys, for example:
-
Note, ''vfs.cfg'' is just a normal configuration file, with many mounting keys.
+
-
 
+
-
You can add your own configuration key. Cim will use some own key, for example:
+
<pre>
<pre>
Cim.Settings.StartLevel = terrain
Cim.Settings.StartLevel = terrain
Cim.Settings.EnableConsole = true;
Cim.Settings.EnableConsole = true;
-
</pre
+
</pre>
-
We have to handle this config keys from code, of course.
+
We have to handle these config keys from code, of course.
The whole ''cim.cfg'' will look like this:
The whole ''cim.cfg'' will look like this:
Line 111: Line 78:
;game specific settings
;game specific settings
-
Cim.Settings.StartLevel = /lev/terrain
+
Cim.Settings.StartLevel = /lev/terrainf
Cim.Settings.EnableConsole = false
Cim.Settings.EnableConsole = false
- 
</pre>
</pre>
This file you have to put into your ''CS/config/'' directory.
This file you have to put into your ''CS/config/'' directory.
-
To load a config file, first we need a pointer to the config manager. Add the
+
To load a config file, first we need a pointer to the config manager. Add the following private member to cim class in cim.h:
-
 
+
-
following private member to cim class in cim.h:
+
<pre>
<pre>
-
/// A pointer to the configuration manager.
+
/// A pointer to the configuration manager.
-
csRef<iConfigManager> confman;
+
csRef<iConfigManager> confman;
</pre>
</pre>
-
And in the cim.cpp, on the ''OnInitialize'' function:
+
And in the cim.cpp, on the ''OnInitialize'' function before you call RequestPlugins:
<pre>
<pre>
-
if (!csInitializer::SetupConfigManager (GetObjectRegistry (),
+
if (!csInitializer::SetupConfigManager (GetObjectRegistry (),
-
"/config/cim.cfg"))
+
"/config/cim.cfg"))
-
return ReportError ("Error reading config file 'cim.cfg'!");
+
return ReportError ("Error reading config file 'cim.cfg'!");
</pre>
</pre>
-
Your config file will be loaded and your settings will be applied. Put cim.cfg
+
Your config file will be loaded and your settings will be applied. Put cim.cfg in same directory, that your cim binary, recompile the application and run it. Try different Video.ScreenWidth Video.ScreenHeight, etc values (i.e 800*600, 1024*768), and you can see, Crystal Space respects your changes. This the real power of Crystal Space configuration handling.
-
 
+
-
in same directory, that your cim binary, recompile the application and run it.
+
-
 
+
-
Try different Video.ScreenWidth Video.ScreenHeight, etc values (i.e 800*600,
+
-
 
+
-
1024*768), and you can see, Crystal Space respects your changes. This the the
+
-
 
+
-
real power of Crystal Space configuration handling.
+
Our config file contents the following Cim-specific keys:
Our config file contents the following Cim-specific keys:
Line 150: Line 106:
Cim.Settings.StartLevel = terrain;
Cim.Settings.StartLevel = terrain;
Cim.Settings.EnableConsole = true;
Cim.Settings.EnableConsole = true;
- 
</pre>
</pre>
-
The StartLevel defines the name of the starting map, the EnableConsole decides,
+
The StartLevel defines the name of the starting map, the EnableConsole decides, the app creates a console or not.
-
the app creates a console or not.
+
Let’s now write the code. We make many changes. First, we introduce a variable to check whether we use console or not. This will a private member of the cimGame class, called use_console. When this flag is false, we don’t instance and use the console class. The event handlers first check, we have console or not, to avoid crashes :
-
 
+
-
Let’s go to to write the code.
+
-
 
+
-
 
+
-
We make many changes. First, we introduce a variable to check, we use console or
+
-
 
+
-
not. This will a private member of the cimGame class, called use_console. When
+
-
 
+
-
this flag is false, we don’t instance and use the console class. The event
+
-
 
+
-
handlers first check, we have console or not, to avoid crashes :
+
<pre>
<pre>
bool cimGame::OnKeyboard(iEvent& ev)
bool cimGame::OnKeyboard(iEvent& ev)
{
{
 +
// We got a keyboard event.
 +
csKeyEventType eventtype = csKeyEventHelper::GetEventType(&ev);
 +
if (eventtype == csKeyEventTypeDown)
 +
{
 +
// The user pressed a key (as opposed to releasing it).
 +
utf32_char code = csKeyEventHelper::GetCookedCode(&ev);
-
// We got a keyboard event.
 
-
csKeyEventType eventtype = csKeyEventHelper::GetEventType(&ev);
 
-
if (eventtype == csKeyEventTypeDown)
 
-
{
 
-
// The user pressed a key (as opposed to releasing it).
 
-
utf32_char code = csKeyEventHelper::GetCookedCode(&ev);
 
-
 
- 
//The user pressed tab to toggle console, when we have any console
//The user pressed tab to toggle console, when we have any console
if (use_console)
if (use_console)
{
{
if (code == CSKEY_TAB)
if (code == CSKEY_TAB)
-
{
+
{
-
console->Toggle();
+
console->Toggle();
-
return false;
+
return false;
-
}
+
}
-
//more code of course
+
//more code of course
</pre>
</pre>
-
(This is a very simple solution,. Cs provides us a better way to event handling,
+
(This is a very simple solution,. Cs provides us a better way to event handling, we will deal with this problem later.)
-
 
+
-
we will deal with this problem later. )
+
On the cimGame::Setup, we do the following changes:
On the cimGame::Setup, we do the following changes:
- 
- 
We have to change the ProcessFrame function from same reason:
We have to change the ProcessFrame function from same reason:
Line 204: Line 142:
void cimGame::ProcessFrame ()
void cimGame::ProcessFrame ()
{
{
-
// First get elapsed time from the virtual clock.
+
// First get elapsed time from the virtual clock.
-
csTicks elapsed_time = vc->GetElapsedTicks ();
+
csTicks elapsed_time = vc->GetElapsedTicks ();
-
csVector3 obj_move (0);
+
csVector3 obj_move (0);
-
csVector3 obj_rotate (0);
+
csVector3 obj_rotate (0);
-
 
+
-
if (use_console)
+
-
if(console->IsVisible() )
+
-
return;
+
-
// more code
+
 +
if (use_console)
 +
if(console->IsVisible() )
 +
return;
 +
// more code
</pre>
</pre>
-
We change the our console class a little bit. First, we change the plugin
+
We change the our console class a little bit. First, we change the plugin loading method, we don’t use concrete plugin name, since we give the used plugins from the configuration file:
-
 
+
-
loading method, we don’t use concrete plugin name, since we give the used
+
-
 
+
-
plugins from the configuration file:
+
<pre>
<pre>
bool cimConsole::Initialize(iObjectRegistry* obj_reg)
bool cimConsole::Initialize(iObjectRegistry* obj_reg)
{
{
-
object_reg = obj_reg;
+
object_reg = obj_reg;
-
conout = CS_QUERY_REGISTRY(obj_reg, iConsoleOutput);
+
conout = CS_QUERY_REGISTRY(obj_reg, iConsoleOutput);
-
if (!conout)
+
if (!conout)
-
{
+
{
-
csReport (object_reg,
+
csReport (object_reg,
CS_REPORTER_SEVERITY_ERROR, "cim.console",
CS_REPORTER_SEVERITY_ERROR, "cim.console",
"Can't load the output console!");
"Can't load the output console!");
-
return false;
+
return false;
-
}
+
}
-
conin = CS_QUERY_REGISTRY(obj_reg,iConsoleInput);
+
conin = CS_QUERY_REGISTRY(obj_reg,iConsoleInput);
-
if (!conin)
+
if (!conin)
-
{
+
{
-
csReport (object_reg,
+
csReport (object_reg,
CS_REPORTER_SEVERITY_ERROR, "cim.console",
CS_REPORTER_SEVERITY_ERROR, "cim.console",
"Can't load the input console!");
"Can't load the input console!");
-
return false;
+
return false;
-
}
+
}
-
 
+
-
//more code
+
 +
//more code
</pre>
</pre>
-
In the cimGame class, we introduce a new private function, called LoadConfig.
+
In the cimGame class, we introduce a new private function, called LoadConfig. This function parse the application’s special konfiguration keys, and makes the desired settings.
-
This function parse the application’s special konfiguration keys, and makes the
+
The configuration manager has some GetSomeType function to get the key values, these are GetInt. GetStr, GetBool, GetFloat. These functions look up in the configuration file, and return with the given key’s value (first parameter). You can give a default value, when the key was not found, in the second parameter.
-
 
+
-
desired settings.
+
-
 
+
-
 
+
-
The configuration manger has some GetSomeType function to get the key values,
+
-
 
+
-
these are GetInt. GetStr, GetBool, GetFloat. This functions look up in the
+
-
 
+
-
configuration file, and return with the given key’s value (first parameter). You
+
-
 
+
-
can give a default value, when the key was not found, in the second parameter.
+
<pre>
<pre>
bool cimGame::LoadConfig()
bool cimGame::LoadConfig()
{
{
-
csRef<iConfigManager> confman (CS_QUERY_REGISTRY (GetObjectRegistry(), iConfigManager));
+
csRef<iConfigManager> confman (CS_QUERY_REGISTRY (GetObjectRegistry(), iConfigManager));
-
use_console = confman->GetBool("Cim.Settings.EnableConsole ", true);
+
use_console = confman->GetBool("Cim.Settings.EnableConsole ", true);
-
startmap = confman->GetStr("Cim.Settings.StartLevel","terrain");
+
startmap = confman->GetStr("Cim.Settings.StartLevel","terrain");
}
}
- 
</pre>
</pre>
-
Finally, we learn the basics of the command line handling in CS. Cystal Space
+
Finally, we learn the basics of the command line handling in CS. Cystal Space heavily uses command lines and provides an easy way to process it by a CS based application. The iCommandLineParser helps to do it. So we extend the ''cimGame::Setup'' function:
-
 
+
-
uses heavily command lines and provides an easy way to process it by a CS based
+
-
 
+
-
application. The iCommandLineParser helps to do it. So we extend the
+
-
 
+
-
''cimGame::Setup'' function:
+
<pre>
<pre>
-
csRef<iCommandLineParser> cmdline(CS_QUERY_REGISTRY (object_reg,
+
csRef<iCommandLineParser> cmdline(CS_QUERY_REGISTRY (object_reg,
iCommandLineParser));
iCommandLineParser));
-
 
+
if (!cmdline)
-
if (!cmdline)
+
return ReportError("Failed to set up command line parser!");
-
return ReportError("Failed to set up command line parser!");
+
</pre>
</pre>
-
Then we look up for the option enable-python-console. When the user runs the
+
Then we look up the option enable-python-console. When the user runs the application with this option, we set up the console anyway:
-
 
+
-
application with this option, we set up the console anyway:
+
<pre>
<pre>
-
if( cmdline->GetOption("enable-python-console")) use_console=true;
+
if( cmdline->GetOption("enable-python-console")) use_console=true;
</pre>
</pre>
-
Many more is possible with the command line parser, but probably this function
+
Much more is possible with the command line parser, but probably this function you will use most often.
-
 
+
And finally, we organize the map loading and collosion detection init code to a new LoadMap (const char* mapname) function. This function can load any CS map file by name:
-
will you use most often.
+
-
 
+
-
And finally, we organize the map loading and collosion detection init code to a
+
-
 
+
-
new LoadMap (const char* mapname) function. This function can load any CS map
+
-
 
+
-
file by name:
+
<pre>
<pre>
bool cimGame::LoadMap (const char* mapname)
bool cimGame::LoadMap (const char* mapname)
{
{
-
//Delete the engine's content.
+
//Delete the engine's content.
-
engine->DeleteAll();
+
engine->DeleteAll();
-
// Set VFS current directory to the level we want to load.
+
// Set VFS current directory to the level we want to load.
-
csRef<iVFS> VFS (CS_QUERY_REGISTRY (GetObjectRegistry (), iVFS));
+
csRef<iVFS> VFS (CS_QUERY_REGISTRY (GetObjectRegistry (), iVFS));
-
VFS->ChDir (mapname);
+
VFS->ChDir (mapname);
-
// Load the level file which is called 'world'.
+
// Load the level file which is called 'world'.
-
if (!loader->LoadMapFile ("world"))
+
if (!loader->LoadMapFile ("world"))
-
ReportError("Error couldn't load level!");
+
ReportError("Error couldn't load level!");
-
 
+
-
+
-
// Initialize collision objects for all loaded objects.
+
-
csColliderHelper::InitializeCollisionWrappers (cdsys, engine);
+
 +
// Initialize collision objects for all loaded objects.
 +
csColliderHelper::InitializeCollisionWrappers (cdsys, engine);
-
// Let the engine prepare all lightmaps for use and also free all images
+
// Let the engine prepare all lightmaps for use and also free all images
-
// that were loaded for the texture manager.
+
// that were loaded for the texture manager.
-
engine->Prepare ();
+
engine->Prepare ();
-
// Find the starting position in this level.
+
// Find the starting position in this level.
-
csVector3 pos (0);
+
csVector3 pos (0);
-
if (engine->GetCameraPositions ()->GetCount () > 0)
+
if (engine->GetCameraPositions ()->GetCount () > 0)
-
{
+
{
-
// There is a valid starting position defined in the level file.
+
// There is a valid starting position defined in the level file.
-
iCameraPosition* campos = engine->GetCameraPositions ()->Get (0);
+
iCameraPosition* campos = engine->GetCameraPositions ()->Get (0);
-
room = engine->GetSectors ()->FindByName (campos->GetSector ());
+
room = engine->GetSectors ()->FindByName (campos->GetSector ());
-
pos = campos->GetPosition ();
+
pos = campos->GetPosition ();
-
}
+
}
-
else
+
else
-
{
+
{
-
// We didn't find a valid starting position. So we default
+
// We didn't find a valid starting position. So we default
-
// to going to room called 'room' at position (0,0,0).
+
// to going to room called 'room' at position (0,0,0).
-
room = engine->GetSectors ()->FindByName ("room");
+
room = engine->GetSectors ()->FindByName ("room");
-
pos = csVector3 (0, 0, 0);
+
pos = csVector3 (0, 0, 0);
-
}
+
}
-
if (!room)
+
if (!room)
-
ReportError("Can't find a valid starting position!");
+
ReportError("Can't find a valid starting position!");
-
// Now we need to position the camera in our world.
+
// Now we need to position the camera in our world.
-
view->GetCamera ()->SetSector (room);
+
view->GetCamera ()->SetSector (room);
-
view->GetCamera ()->GetTransform ().SetOrigin (pos);
+
view->GetCamera ()->GetTransform ().SetOrigin (pos);
-
// Initialize our collider actor.
+
// Initialize our collider actor.
-
collider_actor.SetCollideSystem (cdsys);
+
collider_actor.SetCollideSystem (cdsys);
-
collider_actor.SetEngine (engine);
+
collider_actor.SetEngine (engine);
-
csVector3 legs (.2f, .3f, .2f);
+
csVector3 legs (.2f, .3f, .2f);
-
csVector3 body (.2f, 1.2f, .2f);
+
csVector3 body (.2f, 1.2f, .2f);
-
csVector3 shift (0, -1, 0);
+
csVector3 shift (0, -1, 0);
-
collider_actor.InitializeColliders (view->GetCamera (),
+
collider_actor.InitializeColliders (view->GetCamera (),
legs, body, shift);
legs, body, shift);
-
return true;
+
return true;
}
}
</pre>
</pre>
Line 371: Line 273:
Look at the source for all changes.
Look at the source for all changes.
-
Thats it. We can configure ''CS'' engine and we can add more cim-specific option
+
Thats it. We can configure ''CS'' engine and we can add more cim-specific option later. In the next step we will create the basement of our window handling solution.
 +
 
 +
Get the sources from [http://www.crystaldoc.atw.hu/src/cim/step2.zip here]
 +
 
 +
 
 +
[[Tutorials|Tutorial Home]]
-
later. In the next step we will create the basement of our window handling solution.
+
[[Cimstep3|Next: Step3 - Event handling in CS]]

Current revision

Step Two : Basic configuration handling

First, from that point we will use more and more cim-specific files, like pictures, map files, music, sound etc. It this tutorial we load the first version of cim’s configuration file.

The configuration handling is Crystal Space is very easy to use. Each plugin has its own configuration file, you can override the values with your own configuration file. You can add or override many options from command line. The manual describes this mechanism in depth, please read this section for details.

You can configure many things from your configuration file. We can load plugins from the configuration file, this is a very nice feature. You can dynamically change plugins without recompiling your application. For example, the cim.cfg (config file) has this line somewhere:

System.Plugins.iConsoleOutput = crystalspace.console.output.standard

That means, Crystal Space will use the standard output plugin. When you change the line a little bit:

System.Plugins.iConsoleOutput = crystalspace.console.output.fancy

In that case the fancy console output awaits you, when you run the application (Note, we will change the console source a little bit., now it’s s load the standard plugin statically. When you edit the walktest.cfg file, in the /data/config directory , you can see the effect in walktest.).

You can override any settings of the official CS plugins. For example:

Video.ScreenWidth = 800
Video.ScreenHeight = 600
Video.ScreenDepth = 32
Video.FullScreen = yes

When your configuration file has this lines, your app will start at 800*600 resolution, in fullscreen. You can change any system configuration key, by adding the name and the value in the config file.

Note that the vfs.cfg is a standard configuration file but has it's own configuration space. So if you want to mount directories from your application configuration file you will need to write some code to process the VFS.Mount entries.

So you have to put an vfs.cfg file in the same directory, when your exe exists, with the following context:

VFS.Mount.cim = $^$/

will mount your real cim.exe/ directory to /cim/ the virtual path. This solution prevents having to rewrite the original vfs.cfg.

Since vfs.cfg is just a normal configuration file you can add your own configuration keys. Cim will use some of its own keys, for example:

Cim.Settings.StartLevel = terrain
Cim.Settings.EnableConsole = true;

We have to handle these config keys from code, of course.

The whole cim.cfg will look like this:

;mounting cim working folder
;VFS.Mount.lev/cim   = $@data$/cim$/

;cs plugins
System.Plugins.iGraphics3D = crystalspace.graphics3d.opengl
System.Plugins.iConsoleInput = crystalspace.console.input.standard
System.Plugins.iConsoleOutput = crystalspace.console.output.standard
System.Plugins.iImageIO = crystalspace.graphic.image.io.multiplexer
System.Plugins.iLoader = crystalspace.level.loader
System.Plugins.iDocumentSystem = crystalspace.documentsystem.xmlread
System.Plugins.iEngine = crystalspace.engine.3d
System.ApplicationID = Tutorial.Cim

;video settings
Video.ScreenWidth = 1024
Video.ScreenHeight = 768
Video.ScreenDepth = 32
Video.FullScreen = no

;mouse settings
MouseDriver.DoubleClickTime = 300
MouseDriver.DoubleClickDist = 2

;game specific settings
Cim.Settings.StartLevel = /lev/terrainf 
Cim.Settings.EnableConsole = false

This file you have to put into your CS/config/ directory.

To load a config file, first we need a pointer to the config manager. Add the following private member to cim class in cim.h:

    /// A pointer to the configuration manager.
    csRef<iConfigManager> confman;

And in the cim.cpp, on the OnInitialize function before you call RequestPlugins:

    if (!csInitializer::SetupConfigManager (GetObjectRegistry (),
            "/config/cim.cfg"))
        return ReportError ("Error reading config file 'cim.cfg'!");

Your config file will be loaded and your settings will be applied. Put cim.cfg in same directory, that your cim binary, recompile the application and run it. Try different Video.ScreenWidth Video.ScreenHeight, etc values (i.e 800*600, 1024*768), and you can see, Crystal Space respects your changes. This the real power of Crystal Space configuration handling.

Our config file contents the following Cim-specific keys:

Cim.Settings.StartLevel = terrain;
Cim.Settings.EnableConsole = true;

The StartLevel defines the name of the starting map, the EnableConsole decides, the app creates a console or not.

Let’s now write the code. We make many changes. First, we introduce a variable to check whether we use console or not. This will a private member of the cimGame class, called use_console. When this flag is false, we don’t instance and use the console class. The event handlers first check, we have console or not, to avoid crashes :

bool cimGame::OnKeyboard(iEvent& ev)
{
    // We got a keyboard event.
    csKeyEventType eventtype = csKeyEventHelper::GetEventType(&ev);
    if (eventtype == csKeyEventTypeDown)
    {
        // The user pressed a key (as opposed to releasing it).
        utf32_char code = csKeyEventHelper::GetCookedCode(&ev);
	
	//The user pressed tab to toggle console, when we have any console
	if (use_console)
	{
	if (code == CSKEY_TAB)
	{
	    console->Toggle();
	    return false;
	}
    //more code of course 

(This is a very simple solution,. Cs provides us a better way to event handling, we will deal with this problem later.)

On the cimGame::Setup, we do the following changes:

We have to change the ProcessFrame function from same reason:

void cimGame::ProcessFrame ()
{
    // First get elapsed time from the virtual clock.
    csTicks elapsed_time = vc->GetElapsedTicks ();

    csVector3 obj_move (0);
    csVector3 obj_rotate (0);

    if (use_console)
        if(console->IsVisible() )
	    return;
    // more code

We change the our console class a little bit. First, we change the plugin loading method, we don’t use concrete plugin name, since we give the used plugins from the configuration file:

bool cimConsole::Initialize(iObjectRegistry* obj_reg)
{
    object_reg = obj_reg;

    conout = CS_QUERY_REGISTRY(obj_reg, iConsoleOutput);
    if (!conout)
    {
        csReport (object_reg,
	    	CS_REPORTER_SEVERITY_ERROR, "cim.console",
		"Can't load the output console!");
        return false;
    }

    conin = CS_QUERY_REGISTRY(obj_reg,iConsoleInput);
    if (!conin)
    {
        csReport (object_reg,
	    	CS_REPORTER_SEVERITY_ERROR, "cim.console",
		"Can't load the input console!");
        return false;
    }

    //more code

In the cimGame class, we introduce a new private function, called LoadConfig. This function parse the application’s special konfiguration keys, and makes the desired settings.

The configuration manager has some GetSomeType function to get the key values, these are GetInt. GetStr, GetBool, GetFloat. These functions look up in the configuration file, and return with the given key’s value (first parameter). You can give a default value, when the key was not found, in the second parameter.

bool cimGame::LoadConfig()
{
    csRef<iConfigManager> confman (CS_QUERY_REGISTRY (GetObjectRegistry(), iConfigManager));
    use_console = confman->GetBool("Cim.Settings.EnableConsole ", true);
    startmap = confman->GetStr("Cim.Settings.StartLevel","terrain");
}


Finally, we learn the basics of the command line handling in CS. Cystal Space heavily uses command lines and provides an easy way to process it by a CS based application. The iCommandLineParser helps to do it. So we extend the cimGame::Setup function:

    csRef<iCommandLineParser> cmdline(CS_QUERY_REGISTRY (object_reg,
  	iCommandLineParser));
    if (!cmdline) 
        return ReportError("Failed to set up command line parser!");

Then we look up the option enable-python-console. When the user runs the application with this option, we set up the console anyway:

    if( cmdline->GetOption("enable-python-console")) use_console=true;

Much more is possible with the command line parser, but probably this function you will use most often.

And finally, we organize the map loading and collosion detection init code to a new LoadMap (const char* mapname) function. This function can load any CS map file by name:

bool cimGame::LoadMap (const char* mapname)
{
    //Delete the engine's content.
    engine->DeleteAll();

    // Set VFS current directory to the level we want to load.
    csRef<iVFS> VFS (CS_QUERY_REGISTRY (GetObjectRegistry (), iVFS));
    VFS->ChDir (mapname);
    // Load the level file which is called 'world'.
    if (!loader->LoadMapFile ("world"))
        ReportError("Error couldn't load level!");

    // Initialize collision objects for all loaded objects.
    csColliderHelper::InitializeCollisionWrappers (cdsys, engine);
		
    // Let the engine prepare all lightmaps for use and also free all images 
    // that were loaded for the texture manager.
    engine->Prepare ();

    // Find the starting position in this level.
    csVector3 pos (0);
    if (engine->GetCameraPositions ()->GetCount () > 0)
    {
        // There is a valid starting position defined in the level file.
        iCameraPosition* campos = engine->GetCameraPositions ()->Get (0);
        room = engine->GetSectors ()->FindByName (campos->GetSector ());
        pos = campos->GetPosition ();
    }
    else
    {
        // We didn't find a valid starting position. So we default
        // to going to room called 'room' at position (0,0,0).
        room = engine->GetSectors ()->FindByName ("room");
        pos = csVector3 (0, 0, 0);
    }
    if (!room)
        ReportError("Can't find a valid starting position!");

    // Now we need to position the camera in our world.
    view->GetCamera ()->SetSector (room);
    view->GetCamera ()->GetTransform ().SetOrigin (pos);

    // Initialize our collider actor.
    collider_actor.SetCollideSystem (cdsys);
    collider_actor.SetEngine (engine);
    csVector3 legs (.2f, .3f, .2f);
    csVector3 body (.2f, 1.2f, .2f);
    csVector3 shift (0, -1, 0);
    collider_actor.InitializeColliders (view->GetCamera (),
  	legs, body, shift);

    return true;
}

Look at the source for all changes.

Thats it. We can configure CS engine and we can add more cim-specific option later. In the next step we will create the basement of our window handling solution.

Get the sources from here


Tutorial Home

Next: Step3 - Event handling in CS

| Article | Discussion | View source | History |