martes, 13 de septiembre de 2011

GameEngine: Capitulo 29. ASCII Manager

Hola a todos

De mientras que estoy trabajando en la remodelación del game engine para hacer que sea más mantenible un colaborador del engine (JamQue) me ha comentado que le gustaria hacer juegos en ASCII con el motor.

Los juegos de tipo ASCII tuvieron su apojeo hace muchos y muchos años (para algunos, nos parece que no tantos :D) y hoy dia todavia se mantienen proyectos en ASCII realmente interesantes. Uno de estos proyectos es el del siguiente link , hay muchos más.

Así pues, he implementado dentro del motor de 2D, un motorcillo de ASCII muy muy sencillo (a la espera que JamQue le vaya añadiendo cosas) basado en un sola función:

DrawASCIIElement(int x, int y, char bgred,char bggreen,char bgblue, char clred ,char clgreen,char clblue, char car)

Le pasamos coordenadas, color de fondo, color de caracter y caracter y nos lo incluye en la matriz de pintado, así de sencillo.

Un ejemplo de uso sería el siguiente:
ASCIIManager::singleton().DrawASCIIElement(i,j,0x55,0x00,0x00,0x00,0x55,0x00, (i*i+j*j)%255 );

A nivel de código los cambios no son muchos:

ASCIIManager.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 "ASCIIManager.h"
#include "MyGL.h"

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

#include <ctime>        //Funciones de tiempo
#include <math.h>        //Funciones de matematicas.

//Textos renderizados
#include "glQuickText.h"

using namespace std;

//Pantalla de 80*25*16 colores
#define ASCIIX 80
#define ASCIIY 25
char ASCIIMatrix[ASCIIX][ASCIIY][7]; //80 columnas, 25 filas, (012- color background, 345- color texto, 6- caracter)

//Instancia única del ASCII manager
ASCIIManager ASCIIManager::instance;

//Constructor
ASCIIManager::ASCIIManager()
{
}

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

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

//Funcion para inicializar el motor gráfico
void ASCIIManager::Init(int* argc, char* argv[])
{
    cout << "Inicializamos el ASCII Manager\n";
   
    for( int i = 0; i < ASCIIX ; ++i)
    {
        for( int j = 0; j < ASCIIY ; ++j)
        {
            ASCIIMatrix[i][j][0]= 0;
            ASCIIMatrix[i][j][1]= 0;
            ASCIIMatrix[i][j][2]= 0;

            ASCIIMatrix[i][j][3]= 0;
            ASCIIMatrix[i][j][4]= 0;
            ASCIIMatrix[i][j][5]= 0;

            ASCIIMatrix[i][j][6]= 0;
        }
    }
}

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

//Pintamos un elemento ASCII en pantalla
void ASCIIManager::DrawASCIIElement(int x, int y, char bgred,char bggreen,char bgblue, char clred ,char clgreen,char clblue, char car)
{
    ASCIIMatrix[x][y][0]= bgred;
    ASCIIMatrix[x][y][1]= bggreen;
    ASCIIMatrix[x][y][2]= bgblue;

    ASCIIMatrix[x][y][3]= clred;
    ASCIIMatrix[x][y][4]= clgreen;
    ASCIIMatrix[x][y][5]= clblue;

    ASCIIMatrix[x][y][6]= car;
}

//Funcion que se ejecuta automaticamente desde glut (por ahora)
void ASCIIManager::Render()
{
    float xi,yi,xf,yf;
    char text[2];

    glDisable(GL_TEXTURE_2D);

    for( int i = 0; i < ASCIIX ; ++i)
    {
        for( int j = 0; j < ASCIIY ; ++j)
        {
            if(!ASCIIMatrix[i][j][6])
                continue;

            xi = (int) (i * 640)/ ASCIIX;
            yi = (int) (j * 480)/ ASCIIY;
            xf =  xi + 8;
            yf =  yi + 20;
           
            glPushMatrix();
                glLoadIdentity();
                glTranslatef( xi , yi , 0);
                glColor3f(ASCIIMatrix[i][j][0],ASCIIMatrix[i][j][1],ASCIIMatrix[i][j][2]);
                glBegin(GL_QUADS);                       
                        glVertex2i( (xf - xi)/2   , (yf - yi)/2 );        // Top Right Of The Quad (Front)
                        glVertex2i( -(xf - xi)/2   , (yf - yi)/2  );    // Top Left Of The Quad (Front)
                        glVertex2i( -(xf - xi)/2   , -(yf - yi)/2  );    // Bottom Left Of The Quad (Front)
                        glVertex2i( (xf - xi)/2   , -(yf - yi)/2  );    // Bottom Right Of The Quad (Front)
                glEnd();   
            glPopMatrix();
        }
    }

    for( int i = 0; i < ASCIIX ; ++i)
    {
        for( int j = 0; j < ASCIIY ; ++j)
        {
            if(!ASCIIMatrix[i][j][6])
                continue;
           
            xi = (int) (i * 640)/ ASCIIX - 5;
            yi = (int) (j * 480)/ ASCIIY - 7;

            glColor3f(ASCIIMatrix[i][j][3],ASCIIMatrix[i][j][4],ASCIIMatrix[i][j][5]);
            sprintf(text,"%c",ASCIIMatrix[i][j][6]);
            glQuickText::printfAt((double)xi,(double)yi, 0.0f ,0.85f , text );
        }
    }

    glEnable(GL_TEXTURE_2D);
    glColor3f(1.0f,1.0f,1.0f);
}


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

/**************************************************************************************************/
// ASCIIManager.h : Código de la parte de ASCII 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 __ASCIIManager__
#define __ASCIIManager__

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

public:
    static ASCIIManager& 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();
   
    //Pintamos un elemento ASCII en pantalla
    void DrawASCIIElement(int x, int y, char bgred,char bggreen,char bgblue, char clred ,char clgreen,char clblue, char car);

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

#endif

Dentro del draw del playstate, un ejemplo:
void draw ()
    {
       
        for( int i = 0; i < 80 ; ++i)
            for( int j = 0; j < 25 ; ++j)
                ASCIIManager::singleton().DrawASCIIElement(i,j,0x55,0x00,0x00,0x00,0x55,0x00, (i*i+j*j)%255 );

        ASCIIManager::singleton().DrawASCIIElement(10,10,0x55,0x00,0x00,0x00,0x55,0x00, 'H' );

    }



Los demás cambios menores que se hayan podido implementar los vereis en el repositorio en el siguiente link. (NOTA para JamQue: Pilla el código de aqui :D)



Espero que os haya gustado y que en breve haya más gente que se apunte a colaborar y hacer sus juegecillos...


Nos vemos

0 comentarios :

Publicar un comentario

Entradas populares