martes, 31 de mayo de 2011

GameEngine: Capitulo 2 . Graphics Manager

Hola a todos,

Bienvenidos a este segundo capitulo de como implementar un game engine y no volverte loco del todo en el intento....

Ayer hicimos la base general del proyecto, hoy implementaremos la base del GraphicsManager (o Graphic Engine como querais llamarle).

Estructurando el proyecto
Dado que a cada entrega (al menos ahora en estas primeras) tendremos que ir incluyendo archivos nuevos lo mejor que podemos hacer es estructurar el proyecto. Cada uno a su gusto, yo siempre lo que hago es : una carpeta "scr" donde pongo los .cpp y una carpeta "include" donde pongo los .h y a parte una carpeta "Data" donde pongo las imagenes, sonidos, modelos,etc... Cada uno a su gusto como más le plazca y se sienta más comodo para trabajar.

Una cosa importante es que os acordeis de incluir las rutas de la carpeta de includes en el proyecto, sino no os compilará .Para los que tengais mala memoria o no lo hagais hecho nunca, para incluir al proyecto la carpeta de include es tan sencillo como :
  1. Desde el VC++ click derecho encima del proyecto.
  2. Seleccionar propiedades
  3. En el menú de la izquierda seleccionar C/C++ y en el submenú seleccionar General
  4. En la primera opción de la derecha "Directorios de inclusión adicionales" poner la ruta de nuestra carpeta include.
  5. Compilar y comprobar que no da error.

Creando nuestra primera ventana gráfica
Está claro que nuestros juegos se tendrán que desarrollar dentro de una ventana gráfica debido a que, sin anímo de menospreciar la consola de DOS, ésta no es la más adecuada para desarrollar la visualización de nuestros videojuegos.

La creación de la ventana gráfica, por ahora, la realizaremos mediante GLUT. Ya que nos interesa que en cualquier momento podamos quitar GLUT y usar otro sistema para crear las ventanas , estas funcionalidades de pintado las englobaremos en una caja negra que llamaremos GraphicsManager (o Graphics Engine). Este modulo es el que se encargará en el futuro de realizar el pintado por pantalla de nuestras aplicaciones tanto 2D como 3D, así que será un código que estaremos modificando constantemente.

Para instalar GLUT en vuestro ordenador (si no lo teneis instalado) hay numerosas páginas que lo explicarán mucho mejor de lo que yo seria capaz de hacer. Una de ellas es la siguiente http://informatica.uv.es/iiguia/AIG/docs/tutorial.htm. Si no os funciona para vuestro caso concreto googlead un poco y vereis la solución rapidamente.

A fin de unir el código del Core de ayer con el Graphics Manager de hoy los cambios a realizar son mínimos. Os copio el código como quedaria. La parte que hace referencia a GLUT no le hagais mucho caso, miradla si quereis, pero no lo deis más importancia.

Core.h:
Respecto a lo que teniamos el otro dia incluid lo siguiente al final de la definición de la clase
private:
//Funciones del callback de glut
static void glut_idle();

Core.cpp
/**************************************************************************************************/
// 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
/**************************************************************************************************/

/**************************************************************************************************/
// Core.cpp : Código del core manager.
/**************************************************************************************************/


#include "Core.h"
#include "MyGL.h" //Includes standar para opengl,glut y compañia
#include "GraphicsManager.h" //Inclusión del motor gráfico

#include <iostream> //Usada para imprimir por consola
using namespace std;

//Instancia única del core manager
Core Core::instance;

//Constructor
Core::Core()
{
}

//Destructor
Core::~Core()
{
}

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

//Funcion para inicializar el bucle principal
void Core::Init(int* argc, char* argv[])
{
cout << "Inicializamos el Core Manager\n";
//Inicializamos el motor gráfico
GraphicsManager::singleton().Init(argc,argv);

//Asignamos todas las funciones de callback del glut
//a las funciones que definiremos posteriormente
glutIdleFunc(glut_idle);
}

//Funcion para ejecutar el bucle principal
void Core::Run()
{
//Pasamos el control del bucle principal al glut
//que nos gestionara los eventos y llamara a las
//funciones de callback.
glutMainLoop();
}

//Funcion para desinicializar el bucle principal
void Core::DeInit()
{
cout << "Desinicializamos el Core Manager\n";
}


//CALLBACKS DE GLUT
//Esta funcion se llama cuando el sistema no hace nada (por ahora gestionada por glut)
void Core::glut_idle()
{
//Repintamos la escena
glutPostRedisplay();
}

MyGL.h: Este archivo, la verdad, no recuerdo de donde lo saqué, pero es muy práctico para todo el tema de opengl,glut,etc...
/**************************************************************************************************/
// 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
/**************************************************************************************************/

/**************************************************************************************************/
// MyGL.h : Includes para todo el tema de OpenGL
/**************************************************************************************************/

#ifndef __MyGL__
#define __MyGL__

#if defined(__APPLE__)
# include <Carbon/Carbon.h>
# include <OpenGL/OpenGL.h>
# include <GLUT/GLUT.h>
#elif defined(__linux__)
# include <GL/gl.h>
# include <GL/glut.h>
#elif defined(WINDOWS) || defined(_WIN32)
//# include <windows.h> // Header File For Windows//Se ha de quitar este include ya que si no genera errores con la raknet
# include <gl\gl.h> // Header File For The OpenGL32 Library
# include <gl\glu.h> // Header File For The GLu32 Library
# include <gl\glut.h> // Header File For The GLUT Library

#define GL_CLAMP_TO_EDGE 0x812F

#endif

#endif // __MyGL__

GraphicsManager.h (notar que también funciona con singletons como el core)
/**************************************************************************************************/
// 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
/**************************************************************************************************/

/**************************************************************************************************/
// GraphicsManager.h : Código del motor gráfico.
// Caracteristicas especiales: Esta clase implementa un singleton, es decir, solo podrá existir un objeto de esta clase en todo el proyecto
/**************************************************************************************************/

#ifndef __GraphicsManager__
#define __GraphicsManager__

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

public:
static GraphicsManager& singleton();

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

//Funcion para desinicializar el motor de gráficos
void DeInit();
private:
//Funciones que no se llamarán desde nuestro código sino desde los callbacks de glut (por ahora)
//Funcion para pintar nuestros gráficos
static void Render();
//Función para reescalar los gráficos
static void Reshape();

private:
//Aqui irán los diferentes objetos que complementen el graphicsmanager
};

#endif

GraphicsManager.cpp
/**************************************************************************************************/
// 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
/**************************************************************************************************/

/**************************************************************************************************/
// GraphicsManager.cpp : Código del motor gráfico.
/**************************************************************************************************/

#include "GraphicsManager.h"
#include "MyGL.h"

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

using namespace std;

//Instancia única del graphics manager
GraphicsManager GraphicsManager::instance;

//Constructor
GraphicsManager::GraphicsManager()
{
}

//Destructor
GraphicsManager::~GraphicsManager()
{
}

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

//Funcion para inicializar el motor gráfico
void GraphicsManager::Init(int* argc, char* argv[])
{
cout << "Inicializamos el Graphics Manager\n";
//Creamos la ventana principal del programa utilizando la libreria GLUT
glutInit(argc, argv);
glutInitDisplayMode(GLUT_RGBA | GLUT_DOUBLE | GLUT_DEPTH);
glutInitWindowPosition(0, 0);
glutInitWindowSize(640, 340);
int mainWindow = glutCreateWindow("Lord Pakus Engine!!!"); //Viva la originalidad!!! :)
glutSetWindow(mainWindow);

//Asignamos todas las funciones gráficas de callback del glut
//a las funciones que definiremos posteriormente
glutDisplayFunc(Render);
// glutReshapeFunc(Reshape); //Por ahora la dejamos comentada por que no nos hace falta
}

//Funcion para desinicializar el bucle principal
void GraphicsManager::DeInit()
{
cout << "Desinicializamos el Graphics Manager\n";
}

//CALLBACKS DE GLUT, por ahora

//Funcion que se ejecuta automaticamente desde glut (por ahora)
void GraphicsManager::Render()
{
//AQUI IRÁ NUESTRA FUNCIÓN DE PINTADO. Por ahora vacia
}

//Funcion que se ejecuta automaticamente desde glut (por ahora). Por el momento la dejamos comentada por que no nos hace falta
//void GraphicsManager::Reshape()
//{
// //AQUI IRÁ NUESTRA FUNCIÓN DE REESCALADO. Por ahora vacia
//}



Eliminando la consola
Una vez ya tenemos nuestra ventana gráfica funcionando a más de uno de vosotros os sobrará totalmente la consola de DOS. Eliminarla es sencillo. Lo único que teneis que hacer es copiar esta linea...

//Delete console
#pragma comment(linker, "/subsystem:\"windows\" /entry:\"mainCRTStartup\"")

..al inicio del main.cpp, justo debajo de los includes. Esta linea es la que le dirá al compilador que no cree la consola de DOS durante la ejecución de nuestro programa. Si en algún momento os hace falta para tracear o lo que sea, es tan sencillo como comentar la linea y volveréis a tener la consola.

Probando que todo funciona ok
La primera demostración que todo está ok es que os compile a la primera :). Una vez consigáis que os compile, si ejecutáis tendríais que ver algo de este estilo:


Como os dije en el capitulo anterior, por poco lo que parezca que avanzamos, al menos avanzamos. Ya llegará el momento (de aquí a no mucho) a poder ver cosas más impresionantes.
En breve os colgaré el código en un servidor de archivos para que os los podáis bajar directamente y no tengáis que ir haciendo copy-paste.

LordPakusBlog
Nos vemos, hasta el siguiente capítulo

19 comentarios :

  1. que pasa leandro?? no has conseguido que te funcione?

    ResponderEliminar
  2. Este comentario ha sido eliminado por el autor.

    ResponderEliminar
  3. Me parece que mi error se basa en compilar todo por separado en vez de todo como un proyecto...

    Que tonto que soy pero
    ¿Que diferencia habia, Lord Pakus?

    ResponderEliminar
  4. Uff basicamente que no te linkaria y que no te podria generar un .exe, por el resto nada importante :D :D :D.

    Lo importante es que finalmente lo tengas funcionando, ya verás que fallos como este te los encontrarás a cientos.

    ResponderEliminar
  5. ¿Por que usas en las clases las funciones init() y deinit()?
    ¿No se supone que para eso ya estan los constructores y destructores de la clase?

    ResponderEliminar
  6. Pues si y no. Para lo que se usa aquí, con un constructor y un destructor tendriamos suficiente, pero, como política de programación creo que es mejor tener un Init y un DeInit... te permite tener un solo objeto y controlar en todo momento como se inicia y como se finaliza, permitiendo reiniciar el funcionamiento de un modulo en particular sin tener que reiniciar toda la aplicación. Es decir, tienes razón, para lo que lo usamos, no nos haría falta, pero es una manía mia hacerlo así... :D

    ResponderEliminar
  7. Bueno, ya me quedé hehehe
    Seguí el tutorial que indicaste para instalar el GLUT. Pero algo no esta funcionando bien, creo que es por la versión. Yo estoy usando VS2010.
    Cuando compilo me sale un listado largo de errores(350+), en la que la mayoría son de sintaxis.

    Por ejemplo:

    Error 1 error C2144: syntax error : 'void' should be preceded by ';' c:\program files\microsoft visual studio 10.0\vc\include\gl\gl.h

    ERROR 309 IntelliSense: expected a ';' c:\program files\microsoft visual studio 10.0\vc\include\gl\glu.h 228 15

    ERROR 376 IntelliSense: variable "GLint" is not a type name c:\program files\microsoft visual studio 10.0\vc\include\gl\glut.h 634 82

    ResponderEliminar
    Respuestas
    1. Bueno, descomente la inclusión de windows.h y aparentemente funciona. Pero ahora tengo otros 3 errores....

      Error 1 error LNK2019: unresolved external symbol __imp____glutInitWithExit@12 referenced in function _glutInit_ATEXIT_HACK@8 ..\GraphicsManager.obj

      Error 2 error LNK2019: unresolved external symbol __imp____glutCreateWindowWithExit@8 referenced in function _glutCreateWindow_ATEXIT_HACK@4 ..\GraphicsManager.obj

      Error 3 error LNK1120: 2 unresolved externals ..\FeozGameEngine.exe 1 1

      Asi es como quedaron los enlaces del proyecto:
      kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;opengl32.lib;glu32.lib;glaux.lib;glut.lib;odbccp32.lib;%(AdditionalDependencies)

      Alguna idea ? :(

      PD: oculte la ruta de los archivos.

      Eliminar
  8. Uff me costo poco pero lo logré compilar ! hehe
    Tenía problemas con las versiones....

    ResponderEliminar
    Respuestas
    1. A saber... con el tiempo llegas a creer que el mundo del linkado de librerias y de la compilación en general se rige más por mágia que por lógica....

      Si tienes muchos problemas puedes mirarte también este link: http://lordpakus.blogspot.com/2012/02/arnow2d-como-crear-una-ventana-sin-glut.html Con lo que tendrias hecho más o menos lo mismo pero sin glut.

      Espero que te sirva william

      Eliminar
  9. Hola, pues yo he me quedado aquí tambien. He copiado los archivos de glut a sus directorios correspondientes, imagino, pero no sé configurar el proyecto para que lea las librerías. Me imagino que es eso, pues me salen 1000 errores!! me podríais ayudar.?
    Tengo visual Studio 2010

    ResponderEliminar
  10. Snake.. sin más información no puedo ayudarte... pero si gogleas lo encontrarás.... Si inluso así no lo encuentras dimelo y le buscaremos solución

    ResponderEliminar
  11. -_-' Conseguí hacer funcionar con freeglut en codeblocks nightly build 13.12. con mingw-w64(no es el que viene por defecto). a continuacion dejo un link que explica como instalar freeglut para codeblocks en windows y linux, y como reconfigurar el proyecto en ese mismo IDE para que funcione, todo eso lo hice en un windows7 de 32 bits.
    http://wiki.codeblocks.org/index.php?title=Using_FreeGlut_with_Code::Blocks

    Hay que crear un proyecto para glut o no funcionará nada.

    Paso a los siguientes tutoriales =). suerte.

    ResponderEliminar
    Respuestas
    1. Eiii, te felicito!!! Lo que has hecho no es trivial y le puede ir muy bien al resto de gente que pase por aqui...

      Cuando tengas algo visible ya me lo enseñaras...

      Gracias por tu aportación.

      Nos vemos

      Eliminar
    2. Perfecto... Gracias y mucha suerte XD

      Eliminar
    3. Me da error de sisntaxis en las librerías de glut.h , gl.h y GL.H

      Eliminar
    4. Uso Visual Studio 13 , me he bajado todos los archivos varias veces de varios sitios y los he instalado varias veces y sigen sin irme

      Eliminar
    5. Eduardo, has probado los links que han colgado los compañeros? Igual hay alguno que te sirve.

      Hace 4 años que hice este tutorial y ya no tengo los fuentes para echarte un cable.

      Por lo que explicas es algun problema con la glut y esto con los links que hay puestos en los comentarios deberias de ir mejor...

      Ya nos explicarás.

      Eliminar

Entradas populares