lunes, 8 de agosto de 2011

Curso de programación: Capítulo 9. Usar XML


Tal y como os prometí, aquí teneis un minitutorial de como usar xml como sistema de gestión de carga.

He usado la libreria tinyXML ya que es la que me ha parecido más sencilla de instalar. De hecho solamente es incluir los .cpp y los .h y compilar. La podeis obtener de http://www.grinninglizard.com/tinyxml/  Por lo que he visto tiene algún fallito y alguna cosa que no cumple el standard pero para lo que a nosotros nos atañe  (archivos de carga y poco más) va a ir perfecto.

El ejemplo lo he implementado modificando la función de carga del TextureManager para que cargue un .xml en vez de un .txt. Espero no tener que explicar nada ya que el ejemplo es bastante autoexplicativo, pero bueno.. si alguien tiene dudas, no vacileís en hacermelas llegar.


void TextureManager::Init(int* argc, char* argv[])
{
    char id[256];    //Cadena donde guardaremos el identificador de cada recurso   
    char ruta[256];    //Cadena donde guardaremos la ruta de cada recurso
    int num_id;        //número que nos asigna la función de carga del recurso.... un -1 significa que no lo ha podido cargar
   
    TiXmlDocument doc( "Data\\LoadTexture.xml");

    cout << "Inicializamos el texture manager\n";

    if ( !doc.LoadFile() )
    {
        printf( "Could not load test file 'Data\\LoadTexture.txt'. Error='%s'. Exiting.\n", doc.ErrorDesc() );
        exit( 1 );
    }

    TiXmlElement *root = doc.RootElement();
    for(TiXmlElement* element = root->FirstChildElement(); element; element = element->NextSiblingElement())
    {
        //Leemos el elemento
        sprintf(id,"%s", element->FirstChild("ID")->FirstChild()->Value());            //tomamos el ID
        sprintf(ruta,"%s",element->FirstChild("ROUTE")->FirstChild()->Value());        //tomamos la RUTA   
       
        num_id = LoadTexture(ruta) - 1;                //Cargamos el recurso
        cout << "Intentamos cargar textura con ruta:" << ruta << "\n";
        if (num_id == -1)                        //Si el recurso no se ha podido cargar, vamos a cargar el siguiente recurso
            continue;
        cout << "textura cargada con identificadores:" << id << " " << num_id << "\n";
        sprintf( loaded[ num_id ] ,"%s" , id ); //Nos guardamos la referencia al recurso
    }
}

El archivo de carga LoadTexture deja de ser un txt para ser un xml :
<list>
<element>
    <ID>INTRO</ID>
    <ROUTE>Data/Texture/intro.png</ROUTE>
</element>

<element>
    <ID>STATS</ID>
    <ROUTE>Data/Texture/Stats.png</ROUTE>
</element>

<element>
    <ID>PACK</ID>
    <ROUTE>Data/Texture/pack.png</ROUTE>
</element>

<element>
    <ID>FONT</ID>
    <ROUTE>Data/Texture/Font.png</ROUTE>
</element>

<element>
    <ID>PLAYER</ID>
    <ROUTE>Data/Texture/Characters/Player.png</ROUTE>
</element>

<element>
    <ID>FOE1</ID>
    <ROUTE>Data/Texture/Characters/Foe1.png</ROUTE>
</element>
<element>
    <ID>FOE2</ID>
    <ROUTE>Data/Texture/Characters/Foe2.png</ROUTE>
</element>
<element>
    <ID>FOE3</ID>
    <ROUTE>Data/Texture/Characters/Foe3.png</ROUTE>
</element>
<element>
    <ID>MOUSE</ID>
    <ROUTE>Data/Texture/Mouse.png</ROUTE>
</element>
<element>
    <ID>MATERIAL0</ID>
    <ROUTE>Data/Texture/Materials/material00.png</ROUTE>
</element>
<element>
    <ID>MATERIAL1</ID>
    <ROUTE>Data/Texture/Materials/material01.png</ROUTE>
</element>
<element>
    <ID>MATERIAL2</ID>
    <ROUTE>Data/Texture/Materials/material02.png</ROUTE>
</element>
<element>
    <ID>MATERIAL3</ID>
    <ROUTE>Data/Texture/Materials/material03.png</ROUTE>
</element>
<element>
    <ID>MATERIAL4</ID>
    <ROUTE>Data/Texture/Materials/material04.png</ROUTE>
</element>
<element>
    <ID>MATERIAL5</ID>
    <ROUTE>Data/Texture/Materials/material05.png</ROUTE>
</element>
<element>
    <ID>AMMO</ID>
    <ROUTE>Data/Texture/Items/Ammo.png</ROUTE>
</element>
<element>
    <ID>COIN</ID>
    <ROUTE>Data/Texture/Items/Coin.png</ROUTE>
</element>
<element>
    <ID>EXIT</ID>
    <ROUTE>Data/Texture/Items/Exit.png</ROUTE>
</element>
<element>
    <ID>LIFE</ID>
    <ROUTE>Data/Texture/Items/Life.png</ROUTE>
</element>
<element>
    <ID>GUI</ID>
    <ROUTE>Data/Texture/GUI/GUI.png</ROUTE>
</element>
<element>
    <ID>GUIAMMO</ID>
    <ROUTE>Data/Texture/GUI/Ammo.png</ROUTE>
</element>
<element>
    <ID>GUILIFE</ID>
    <ROUTE>Data/Texture/GUI/Life.png</ROUTE>
</element>
</list>


Podeis observer que, por ahora al menos, el filemanager queda obsoleto (es posible que le demos otro uso más adelante) y que la forma de cargar información es ,cuanto mínimo, un poco más limpia. Para sistemas más complejos de datos (GUI por ejemplo) este sistema nos irá muy bien.

Espero que os lo hayais pasado bien y que hayais aprendido.


LordPakusBlog

3 comentarios :

  1. ¿No sería más apropiado incluir la ruta de las imágenes en el XML que guarda la info de los objetos? Ejemplo:


    Enemigo cabrón
    monster/nave1


    Si haces coincidir el nombre de archivo con el nombre del identificador (esto es, identificador="monster/nave1"; nombre de archivo="monster/nave1"+".png"), el XML del texturemanager sobra.

    Ejemplo:

    1. Se quiere cargar el enemigo 'Gordaco'.

    2. Se consigue su información a partir de monster.xml:

    Gordaco
    monster/enemigo1



    3. El texturemanager busca entonces el elemento "monster/enemigo1" dentro de un contenedor que, por cada imagen, guarda un nombre y la imagen cargada en memoria. Si durante la iteración no encuentra el elemento "monster/enemigo1", el texturemanager lo carga en memoria. De este modo, sólo hay en memoria las imágenes que se estén usando.

    ¡Un abrazo!

    ResponderEliminar
  2. Damnit, desaparecieron los símbolos de las llaves.

    Quise decir:

    Ejemplo:
    [element]
    [name]Enemigo cabrón[/name]
    [textura]monster/nave1[/textura]
    [/element]

    .....

    2. Se consigue su información a partir de monster.xml:

    [element]
    [name]Gordaco[/name]
    [textura]monster/enemigo1[/textura]
    [/element]

    ResponderEliminar
  3. Sip, es otra manera de verlo que ya la discuti conmigo mismo hace un tiempo(:D) Al final lo importante de estos cursos es que la gente aprende, asi que poco importa realizarlo de una manera u otra, aunque bien visto por tu parte.

    ResponderEliminar

Entradas populares