News | About | Download | Documentation | Development | Links

Resource API Overview

Abstract:

This document explains the fundamentals of resource management, and the rationale behind it. It explains how the resource system can be extended with new user defined resource types, and how the predefined basic ClanLib resource types can be used to instantiate ClanLib display and surface objects.

Resources in ClanLib

Resources are a fundamental aspect of any game. The graphics in the game, consists of sprites, and the sounds in the game typically consists of wave-samples or similar. Other data used in games, could be the data defining a "level" in a game, or the dialogue used in some scene in the game. As a matter of fact, anything except the actual game code in the game, can be viewed as resources.

We would like resources in a game to be separated from the game as much as possible. For instance, we don't want to change code, because we change the filename of some sprite graphics file, and we certainly don't want to update source code, if we change the dimensions or any similar aspect of a resource either. We wan't to have flexible control of the resources initialization, separated from the game code. For instance we want to be able to specify whether a sample loops, or set it's volume separately from the source code. We want to have as great resource flexibility as possible while developing the game. For instance we don't want to rebuild some resource data file each time we make a change, and when we make a release of the game, we don't want to have to change anything in the game code. Finally we would like our resources to be location transparent. If we have some netgame server that includes a level unknown to a joining client, we want that level to be transferred to the client game location transparently, as if the resource resided locally on that client.

To design a resource system, that provides an adequate solution to these problems, we need a level of abstraction between physical resource location/loading, and resource naming in the actual game code. This is where the resource manager in ClanLib comes in. The resource manager, CL_ResourceManager provides this level of abstraction, by presenting a uniform resource interface to ClanLib applications. The resource managers main responsibility is to parse a resource definition file, and load the resources using the proper resource loader, when requested. This of course demands a little explanation. A resource definition file (typically using a .scr extension), defines all the resources that a given game uses. All entries in the resource definition file are mappings from physical file locations, to resource id's. This looks something like this:

The above code is translated to mean, that when the game requests resource 'res_id', the resource loaded by the resource loader associated with 'some_resource_type' is returned.

Resource types

ClanLib defines a resource, simply as something that has a resource type, and which can be loaded and unloaded. ClanLib defines a range of built in resource types:

The purpose of these resource types should be self explanatory. Each resource type has several configuration options associated with it. All options in the resource definition file must be enterered within the parantheses following the physical resource location, and must be separated by commas. A later part of this overview will describe the options associated with each resource type.

A resource usage example

Let us look at an example resource definition file, and see how that can be translated to resources usable by the ClanLib classes during runtime:

As mentioned previously, this definition file is interfaced to via the CL_ResourceManager class. The CL_ResourceManager is created using the following constructor:

It receives as input the name of a file. If 'is_datafile' is true, the filename is assumed to be the filename of a datafile, containing both the resource definition file, and the resources. If not, the filename is assumed to be the name of the resource definition file. If the resource definition file cannot be found, or if a syntax error is found during parsing of the resource definition file, an exception of type CL_Error is thrown.

The instantiated CL_ResourceManager class, is in most cases only used indirectly. Classes like CL_Surface and CL_SoundBuffer have resource load constructors, receiving as argument a pointer to the instantiated resource manager, as well as a resource id specifying the specific resource to be loaded as data for that given object.

When using resources, make sure you include

Some example code could look like this:

Compiling resourcefiles

As mentioned briefly already, resource definition files can be compiled into a datafile, which will contain both the resource definition file, and the all resources in one big file.

To compile your datafile, add this code:

This compiles the resource-file my_resources.scr into a datafile called my_resources.dat. Normally, the datafile compiler can be made available through a command-line interface or similar.

Now, to create a resourcemanager from a compiled datafile, use the following code:

Resource sections

As you may have noted in the previous section, my_resources.scr, contains a 'section Surfaces' construct. 'section' is a keyword in ClanLib resource definition files, and sections can be build up, to provide better grouping of resources. Sections can be nested inside each other, but a resource can be a part of only one section (as the resource name is qualified with the section hierachy of which it is a part (as in "Surfaces/my_surface")). The syntax of a resource section is as follows:

'my_resource' has the following fully qualified resource_id: "MySection/MyNestedSection/my_resource".

One of the advantages of grouping is that you can load all resources in a group into memory at once. This allows your game to do all in-game loading at game start, instead of loading the resources as they are used in the game. The following code will do that:

When you load an entire section of resources, you will have to inform the resource manager when it can unload them from memory again. All the resources in clanlib are reference counted, and if you do not call the CL_ResourceManager::unload_section() function, your application will memory leak!

Move on to part two.



Questions or comments, write to the ClanLib mailing list.