domingo, 16 de diciembre de 2012

Poco a poco vamos progresando

Tras casi seis meses de desarrollo, el port del proyecto dx_lib32 a C++ va cogiendo forma.

Poco a poco la funcionalidad de la librería se va acercando a la de la original. Aunque por ahora solo estoy abarcando el tema de gráficos, éstos empiezan a tener unas características aceptables. Dibujo de sprites, polígonos, texto, líneas, etc. La última incorporación han sido splines y polylines, ambas no soportadas por la librería original. Realmente no estoy portando el código "tal cual", suelo implementar las cosas a mi manera; tendiendo en cuenta el diseño y funcionalidad originales por supuesto.

Un ejemplo de polyline


El rendimiento creo que empieza a ser también bastante aceptable. Normalmente hago test sobre un Asus Eee PC 1005PE, que cuenta con un Intel Atom a 1.2GHz y una Intel GMA 3150. Mi filosofía es que si algo funciona bien ahí, funcionará bien en cualquier lado. Y parece que por ahora la teoría se cumple: He conseguido mover cerca de 100 sprites + 100 strings + 100 polígonos (Entre pentágonos y decágonos) a unos 30FPS. En un sobremesa corriente ronda los 300FPS. Y todavía puedo hacer muchas más optimizaciones.

Captura de uno de los test de stress

Por otro lado, he reorganizado completamente la API. Ahora la librería se basa en el lanzamiento de excepciones para informar sobre errores. En un primer momento consideré implementar la API, sobretodo en la rama de matemáticas, de manera que no comprobara errores. Es decir, el usuario era responsable de introducir datos correctos. Pero ésto a la larga no es viable.
Por ejemplo, la clase dl32Matrix implementa una matriz de dimensión cualquiera. Las operaciones con matrices tienen ciertas restricciones. Cuando dichas restricciones no se cumplen, las funciones de dl32Matrix lanzan una excepción del tipo dl32InvalidMatrixOperationException:
 static dl32Matrix Add(dl32Matrix m1,dl32Matrix m2)throw(dl32InvalidMatrixOperationException);
 static dl32Matrix Sub(dl32Matrix m1,dl32Matrix m2)throw(dl32InvalidMatrixOperationException);
 static dl32Matrix Mul(dl32Matrix matrix,float mul)throw(dl32InvalidMatrixOperationException);
 static dl32Matrix Mul(dl32Matrix m1,dl32Matrix m2)throw(dl32InvalidMatrixOperationException);

 dl32Matrix operator+(dl32Matrix matrix)throw(dl32InvalidMatrixOperationException){return Add(*this,matrix);};
 dl32Matrix operator-(dl32Matrix matrix)throw(dl32InvalidMatrixOperationException){return Sub(*this,matrix);};
 dl32Matrix operator*(dl32Matrix matrix)throw(dl32InvalidMatrixOperationException){return Mul(*this,matrix);};
 dl32Matrix operator*(float factor)throw(dl32InvalidMatrixOperationException){return Mul(*this,factor);};

Además la librería cuenta con un sencillo sistema de ventanas que cuenta con lo básico necesario para implementar un juego: Una clase dl32Window que permite crear ventanas, redimensionarlas, cambiar el título, etc. Ëstas implementan un  sencillo sistema de eventos que hacen la programación del juego mucho más sencilla:

#include "dl32Window.h"
#include "dl32Graphics.h"
#include "dl32Math.h"

typedef struct Box
{
    dl32AABB2D area;
    dl32Color color;
};

void OnMouseMove(dl32MouseData mouseData);
void OnIdle();//Éste evento se ejecuta cuando no han llegado mensajes a la ventana

dl32Window* window;
dl32GraphicsClass* gfx;

Box box;

INT WINAPI wWinMain(HINSTANCE,HINSTANCE,LPWSTR,INT)
{
    window = new dl32Window("dx_lib32 example",0,0,800,600);//x,y,width,height
    gfx = new dl32GraphicsClass(Window);

    window->MouseMove.AddHandler(OnMouseMove);
    window->Idle.AddHandler(OnIdle);

    box.color = DL32COLOR_ORANGE;
    box.area = dl32AABB2D(0,0,100,100);//x,y,width,height

    dl32Window::Start();//Inicia el procesamiento de mensajes (Empieza el juego)

    delete gfx;
    //Las intancias de dl32Window son gestionadas internamente. No es necesario delete

    return 0;
}

void OnMouseMove(dl32MouseData mouseData)
{
    box.area.Position = mouseData.Location;
}

void OnIdle()
{
    gfx->DRAW_Box(box.area,box.color);
    gfx.Frame();
}

Todavía me queda mucho por recorrer. La parte de gráficos está casi completa, solo falta el tema de render-targets. Pero ésto solo es el principio. También hay sonido vídeo, e input. Pero no me faltan ganas. Todavía estoy a la espera de encontrar a un colaborador que esté a la altura. El tiempo me lo dará.

Si estáis interesados en los progresos del proyecto, visitad los foros de stratos que mencioné en el primer post, además de seguir mi cuenta de twitter, @Manu343726 , donde suelo escribir mientras programo.

domingo, 16 de septiembre de 2012

Introducción a dx_lib32

El proyecto dx_lib32 es un pequeño API de programación multimedia diseñado para programar videojuegos mediante Visual Basic 6.

El proyecto nació hacia el año 2000 de la mano de José Miguel Sánchez Fernández, [EX3]; quien vio que sus ganas  de desarrollar un videojuego se enfrentaban con las pobres herramientas con las que contaba VB6 en esa época. Por esa razón, decidió desarrollar una él mismo. La historia completa de dx_lib32 la podéis encontrar aquí.

A través de los años, dx_lib32 ha desarrollado una pequeña pero importante comunidad de usuarios a través de los foros de la librería en Stratos-AD , entre los que yo me incluyo. A través de estos foros, empecé a conocer las posibilidades de dx_lib32, y algunos impresionantes proyectos que la gente a desarrollado con ella, incluidos algunos que yo mismo desarrollé.

Por esto, tras casi dos años trabajando con ella, cuando el proyecto dx_lib32 fue liberado como proyecto de código abierto en junio de este año, me pareció el momento perfecto para intentar portar la librería a un lenguaje más "apto" para la programación de videojuegos, como es C++.

Por supuesto, nada puede ser fácil.

Desde el primer momento que empiezas a trabajar con la biblioteca, te das cuenta de la comodidad de esta, y del gran trabajo que tiene que haber sido desarrollar algo como esto. Como  cualquiera que se haya metido en las "entrañas" de DirectX sabe, su utilización es de todo menos "cómoda". Todo esto se confirma cuando accedes al código fuente (Gracias [EX3]!) y ves esa jungla originada tras diez años de desarrollo.
Luego añades las "particularidades" de C++ y tienes un bonito cóctel listo para explotar. Pero eso no me quitó las ganas.

Pero claro, viniendo de VB6 y .NET, todo son particularidades. Empezando por la GUI. Además de la propia dx_lib32, tuve que implementar todo el sistema de ventanas, manejo de eventos, e interacción con teclado/ratón. Lo que implicaba meterse con la Windows API, otra dura de roer. Pero parece que he aprovechado bien el verano, y toda esa parte la doy por finalizada por ahora.

A estas alturas, mi implementación va avanzando, pero no tiene nada que ver todavía con la funcionalidad de dx_lib32, pero por algo se empieza. Decidí empezar por la parte de gráficos, ya que es con la que estoy más familiarizado, y en un futuro buscaré colaboradores para implementar el resto, véase input, sonido, y video. En estos momentos mi colaborador Miguel Oliver y yo estamos terminando la implementación de las primitivas matemáticas básicas, desde resolución de sistemas de ecuaciones, hasta transformaciones 3d/2d. Todo esto pensado para ofrecer al usuario de la biblioteca una interfaz potente y sencilla para trabajar con las funciones de dibujo, además de proveer los aspectos básicos en cuanto a matemáticas se refiere.

En un futuro el código será liberado, de hecho ya hemos preparado un repositorio en github. Todo el que desee acceder al código es libre de hacerlo. Solo pido alguna mención si es utilizado por terceros. (Ya arreglaré la licencia GPL en un futuro).

Vamos a utilizar éste blog para mostrar poco a poco el desarrollo del proyecto. Si surgen sugerencias y/o comentarios sobre el proyecto, son bienvenidos. Cuantos más, mejor.