miércoles, 3 de agosto de 2011

GameEngine: Capitulo 27 . GUI Manager

Hola a todos,

Bienvenidos a un nuevo capitulo de como crear tu propio game engine....

El tema de hoy es la creación de GUI (interfaces gráficas) más concretamente, el GUI Manager que nos permitrá gestionar tantas GUI como queramos.

Los que hayais hecho algún videojuego sabreis que una de las partes más pesadas de la producción de un juego es ir ajustando coordenadas de gráficos mediante ensayo y error una docena de veces. Si teneis coordenadas dentro del código no os podeis ni imaginar la de tiempo que se pierde simplemente compilando.

Así pues mi propuesta se basa en un pseudoscript que nos permita cargar como queremos pintar un GUI y lo podamos pintar directamente, haciendo que todo el proceso de ajuste se pueda realizar sin necesidad de recompilar.

El formato que propongo (vosotros podeis proponer otros) es el siguiente:
GRAF GUI 0 0 640 100
BAR GUIAMMO 100 10 500 20 AMMO MAXAMMO
BAR GUILIFE 100 40 500 50 LIFE MAXLIFE

Tipo Grafico xi,yi,xf,yf (valor actual y valor máximo para el caso de graficos de barra de progreso)

Las variables que se usen dentro del script del GUIManager serán las que se pongan dentro del DataManager que vimos en su momento http://lordpakus.blogspot.com/2011/07/curso-de-programacion-capitulo-5.html, así que tampoco estarán en el código.

La idea es que en el juego solo tengamos que poner una linea de código:
GUIManager::singleton().Draw("PLAY"); //Pintamos el GUI a usar durante el juego

Sin más os dejo con el código de la implementación:
/**************************************************************************************************/
// Código creado por F.Bordas (LordPakus) como ejemplo de creación de un game engine
// para el blog LordPakus (http://lordpakus.blogspot.com/).
// Prohibida la distribución fuera de este blog sin el permiso expreso del autor
/**************************************************************************************************/

/**************************************************************************************************/
// GUIManager.h : Código de la parte de audio del game engine
// Caracteristicas especiales: Esta clase implementa un singleton, es decir, solo podrá existir un objeto de esta clase en todo el proyecto
/**************************************************************************************************/

#include "MyGL.h"
#include "FileManager.h" //Sirve para cargar el archivo de loading de sonidos


#ifndef __GUIManager__
#define __GUIManager__

#define MAX_GUI 100

typedef struct
{
char id[32]; //Id de la operación a realizar
char graf[32]; //Id del grafíco a usar
int xi,xf,yi,yf; //Coordenadas de blit
char actual[32]; //Para el caso de barras, valor actual
char max[32]; //Para el caso de barras, valor máximo
}ItemGUI;

typedef struct
{
char id[32]; //Identificador de GUI
ItemGUI lista[32]; //Hasta 32 elementos por GUI (por ahora)
int num_item;
}GUI;

class GUIManager
{
private:
// Constructor y destructor de la clase
static GUIManager instance;
GUIManager();
~GUIManager();

public:
static GUIManager& singleton();

public:
//Funcion para inicializar el motor de GUI
void Init(int* argc, char* argv[]);

//Funcion para desinicializar el motor de GUI
void DeInit();

public:
void LoadGUI( char id[], char ruta[] );
void Draw(char id[]);
private:
FileManager filemanager;
GUI loaded[MAX_GUI];
int num_gui;
};

#endif // __GUIManager__

/**************************************************************************************************/
// Código creado por F.Bordas (LordPakus) como ejemplo de creación de un game engine
// para el blog LordPakus (http://lordpakus.blogspot.com/).
// Prohibida la distribución fuera de este blog sin el permiso expreso del autor
/**************************************************************************************************/

/**************************************************************************************************/
// GUIManager.h : Código de la parte de GUI del game engine
// Caracteristicas especiales: Esta clase implementa un singleton, es decir, solo podrá existir un objeto de esta clase en todo el proyecto
/**************************************************************************************************/
#include "GUIManager.h"
#include "MyGL.h"
#include "Core.h"
#include "DataManager.h"

#include <iostream> //Usada para imprimir por consola

using namespace std;

//Instancia única del GUI manager
GUIManager GUIManager::instance;

GUIManager::GUIManager()
{
}

GUIManager::~GUIManager()
{
}

//Devolvemos el puntero al singleton
GUIManager& GUIManager::singleton()
{
return instance;
}

//Sounds functions
void GUIManager::Init(int* argc, char* argv[])
{
char cad[256]; //Cadena donde guardaremos cada linea que leamos
char id[256]; //Cadena donde guardaremos el identificador de cada recurso
char ruta[256]; //Cadena donde guardaremos la ruta de cada recurso
cout << "Inicializamos el GUI manager\n";

filemanager.Init("Data\\LoadGUI.txt");

num_gui = 0;

//Todo este código tendrá que ir al filemanager, pero por el momento lo dejamos aquí
//Leemos cada linea del archivo
while( filemanager.GetLine(cad) )
{
for( int i = 0 ; i < strlen(cad); ++i)
{
if ( cad[i] == '=' )
{
cad[i]='\0';
sprintf(id,"%s",cad);
sprintf(ruta,"%s",&cad[i+1]);
i = 257;
}
}

LoadGUI(id,ruta); //Cargamos el recurso
//cout << "Intentamos cargar GUI con ruta:" << ruta << "\n";
//cout << "GUI cargada con identificadores:" << id << " " << num_id << "\n";
//sprintf( loaded[ num_id ] ,"%s" , id ); //Nos guardamos la referencia al recurso
}
}

void GUIManager::DeInit()
{
cout << "Desinicializamos el GUI manager\n";
filemanager.DeInit();
}


//Carga el GUI cad y devuelve su posición en la que se ha guardado
void GUIManager::LoadGUI( char id[], char ruta[] )
{
FILE *fp;
char type[32],graf[32],var[32],max[32];
int xi,yi,xf,yf;

fp = fopen(ruta,"r");

if (fp == NULL)
return;
sprintf(loaded[num_gui].id,"%s",id);
loaded[num_gui].num_item = 0;

while(!feof(fp))
{
fscanf(fp,"%s",type);

if(!strcmp(type,"GRAF"))
{
fscanf(fp," %s %d %d %d %d\n",graf,&xi,&yi,&xf,&yf);
}

if(!strcmp(type,"BAR"))
{
fscanf(fp," %s %d %d %d %d %s %s\n",graf,&xi,&yi,&xf,&yf,var,max);
}
//cout << type << " " << graf << " " << xi << " " << yi << " " << xf << " " << yf << "\n";
//Introducimos la información de este item
sprintf(loaded[num_gui].lista[loaded[num_gui].num_item].id ,"%s" , type );
sprintf(loaded[num_gui].lista[loaded[num_gui].num_item].graf ,"%s" , graf );
loaded[num_gui].lista[loaded[num_gui].num_item].xi = xi;
loaded[num_gui].lista[loaded[num_gui].num_item].yi = yi;
loaded[num_gui].lista[loaded[num_gui].num_item].xf = xf;
loaded[num_gui].lista[loaded[num_gui].num_item].yf = yf;

if(!strcmp(type,"BAR"))
{
sprintf(loaded[num_gui].lista[loaded[num_gui].num_item].actual ,"%s" , var );
sprintf(loaded[num_gui].lista[loaded[num_gui].num_item].max ,"%s" , max );
}

loaded[num_gui].num_item++;
}
fclose(fp);
num_gui++;
}


void GUIManager::Draw(char id[])
{
int i,j; //Iterador
int xi,yi,xf,yf;

for ( i = 0 ; i < num_gui ; ++i ) //Para cada elemento cargado
{
if( !strcmp( loaded[i].id , id ) ) //Hemos encontrado la cadena que nos interesa
{
for(j = 0 ; j < loaded[i].num_item; ++j)
{
//Pintamos un gráfico normal
if( !strcmp( loaded[i].lista[j].id , "GRAF" ) )
{
LPE.DrawBlit( loaded[i].lista[j].xi,
loaded[i].lista[j].yi,
loaded[i].lista[j].xf,
loaded[i].lista[j].yf,
loaded[i].lista[j].graf);
}

//Pintamos una barra de progreso
if( !strcmp( loaded[i].lista[j].id , "BAR" ) )
{
xi = loaded[i].lista[j].xi;
xf = loaded[i].lista[j].xf;

xf = ( (xf-xi) * DataManager::singleton().Get(loaded[i].lista[j].actual) ) / DataManager::singleton().Get(loaded[i].lista[j].max) ;

xf += xi;
LPE.DrawBlit( loaded[i].lista[j].xi,
loaded[i].lista[j].yi,
xf,
loaded[i].lista[j].yf,
loaded[i].lista[j].graf);
}

}

return;
}
}
}


En la zona de descargas que podeis encontrar en el indice del blog (http://lordpakus.blogspot.com/search/label/Indice%20del%20LordPakusBlog) hay la carpeta comprimida con el ejecutable, el código y demás. Para ver como queda podeis ver el video de youtube:


LordPakusBlog
Espero que os guste. Preparaos, que lo siguiente será mejorar el GUIManager para que acepte pintar textos y pueda devolvernos eventos.

LordPakusBlog
Nos vemos

0 comentarios :

Publicar un comentario

Entradas populares