martes, 14 de junio de 2011

GameEngine: Capitulo 9. Graphics2DManager

Hola a todos,

Bienvenidos a otro capitulo de como crear tu propio game engine desde 0...

El capitulo de hoy tratará del Graphics2D Engine, o lo que es lo mismo, como pintar graficos 2D por pantalla.

La forma como he abordado el problema (hay diferentes maneras, yo creo que he elegido la más actual) es mediante la texturización de un cuadrado ortogonal a la vista de la camara de manera, que el jugador no sabe que lo que ve realmente es un cuadrado 3D orientado hacia el.

El código es sencillo y se ha modificado parte del pintado de fuentes de otros capitulos para colocarlos dentro del graphics 2D engine. Si observais el código vereis que realmente no está acabado, pero que por ahora nos permite pintar algo 2D por pantalla. En capitulos posteriores iremos puliendo este módulo.

Sin más, os dejo con el código:

Graphics2DManager.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
/**************************************************************************************************/

/**************************************************************************************************/
// Graphics2DManager.cpp : Código de la parte del motor gráfico 2D
/**************************************************************************************************/

#include "Graphics2DManager.h"
#include "MyGL.h"
#include "TextureManager.h"
#include "FontManager.h" //Inclusión del gestor de fuentes

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

#include <ctime> //Funciones de tiempo

using namespace std;

//Instancia única del graphics 3D manager
Graphics2DManager Graphics2DManager::instance;

//Constructor
Graphics2DManager::Graphics2DManager()
{
}

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

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

//Funcion para inicializar el motor gráfico
void Graphics2DManager::Init(int* argc, char* argv[])
{
cout << "Inicializamos el Graphics 2D Manager\n";
FontManager::singleton().Init(argc,argv); //Inicializamos la parte de fuentes.
}

//Funcion para desinicializar el bucle principal
void Graphics2DManager::DeInit()
{
cout << "Desinicializamos el Graphics 2D Manager\n";
FontManager::singleton().DeInit(); //Desinicializamos la parte de fuentes.
}

void Graphics2DManager::Draw(float x, float y, char cad[])
{
TextureManager::singleton().Texture(cad); //Usamos la textura

glBegin(GL_QUADS);
glTexCoord2f( 1.0f, 1.0f); glVertex2i( x + 256 , y + 256); // Top Right Of The Quad (Front)
glTexCoord2f( 0.0f, 1.0f); glVertex2i( x , y + 256); // Top Left Of The Quad (Front)
glTexCoord2f( 0.0f, 0.0f); glVertex2i( x , y ); // Bottom Left Of The Quad (Front)
glTexCoord2f( 1.0f, 0.0f); glVertex2i( x + 256 , y ); // Bottom Right Of The Quad (Front)
glEnd();
}


//Pasamos a modo 2D
void switchToOrtho(void)
{
glDisable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glOrtho(0, 640, 0, 480, -5, 1);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
}

//Volvemos al modo 3D
void switchBackToFrustum (void)
{
glEnable(GL_DEPTH_TEST);
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
}

//Función de calculo de FPS
int CalcFPS()
{
static clock_t timer = clock(); //Temporizador para los FPS
static int FPS = 0;
static int LastFPS = 0;
FPS++;

if ( (clock() - timer) > 1000 )
{
LastFPS = FPS;
FPS = 0;
timer = clock();
}

return LastFPS;
}

//Funcion que se ejecuta automaticamente desde glut (por ahora)
void Graphics2DManager::Render()
{
char cadFPS[50];

glLoadIdentity(); // Reset The View
switchToOrtho();

glEnable(GL_TEXTURE_2D);

Draw(200,200,"TITULO");
//Pintamos FPS
sprintf(cadFPS,"FPS: %d",CalcFPS());
FontManager::Print(10,10,cadFPS);

switchBackToFrustum();

glDisable(GL_TEXTURE_2D);
}

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


Graphics2DManager.h
/**************************************************************************************************/
// 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
/**************************************************************************************************/

/**************************************************************************************************/
// Graphics2DManager.h : Código de la parte de 2D 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 __Graphics2DManager__
#define __Graphics2DManager__

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

public:
static Graphics2DManager& 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();
//Funcion para pintar nuestros gráficos
void Render();
//Función para reescalar los gráficos
void Reshape();

//Función para pintar un gráfico 2D
void Draw(float x, float y, char cad[]);

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

#endif

Las uniones con el resto del código las dejo para vosotros (no es diferente que para el Graphics3DManager), si teneis cualquier problema decidlo y lo solucionaremos.

El video de como deberia quedar es el siguiente:


Vereis que aunque este módulo es muy sencillo es la base para TODOS los juegos de 2D que se os puedan ocurrir (que no son pocos). Es uno de los modulos con los que más trabajaremos, así que si teneis dudas de su funcionamiento idlas haciendo ahora.

LordPakusBlog
Sin más, espero que os hayais divertido y hayais aprendido algo.

Nos vemos

1 comentario :

  1. Ya he llegado a este capítulo. Por si a alguien l einteresa, estoy incluyendo el código de cada capítulo en:
    http://www.megaupload.com/?f=7ICHYH16

    ResponderEliminar

Entradas populares