viernes, 6 de julio de 2012

Aerial Wild Adventure

Tras mucho tiempo sin actualizar el blog, me autopublicito un poco.

He estado trabajando en la creación de juegos 3D para Android en los último meses, y el primero está ya disponible:


Está siendo muy divertido crear un motor 3D desde cero para esta plataforma, con shaders avanzados: iluminación dinámica por píxel, mapas de normales, parallax, etc.

Espero escribir aqui más a menudo :D

viernes, 29 de julio de 2011

Cambiando de base

Hace poco me he visto en la necesidad de tener que cambiar de base algunos números, desde la típica base 10 a cualquier otra elegida arbitrariamente. No limitandome a sólo esto, también introduje la posibilidad de cambiar el alfabeto, de forma que se obtienen interesantes resultados.

De esta forma, el alfabeto (conjunto de símbolos) que habitualmente usamos para contar es 0123456789, el alfabeto que usamos en binario es 01 y el alfabeto que por lo general usamos para hexadecimal es 0123456789ABCDEF. Sin embargo podríamos definir cualquier otro, representando igualmente los mismos números.

El algoritmo para cambiar de base un número consiste en ir obteniendo los restos de ir dividiendo el número original por la base. El primer resto representa la cifra menos significativa del número en la nueva base, el segundo la segunda cifra, y así hasta que el cociente resulte menor que la base no pudiéndose realizar más divisiones. Cuando el algoritmo termina se añade el último cociente como cifra más significativa al resultado. Para cada una de las nuevas cifras se busca cada resultado en la cadena del alfabeto, para saber qué símbolo lo representará.

Implementando todo lo descrito en C++ el algoritmo quedaría así:

string rebase(const unsigned int number,
     const string& alphabet)
{
 const unsigned int base = alphabet.length();
 string rebased = "";
 unsigned int rem = 0;
 unsigned int n = number;
 while (n >= base)
 {
  rem = n % base;
  n = n / base;
  rebased = string(1,alphabet[rem]) + rebased;
 }
 rebased = string(1,alphabet[n]) + rebased;
 return rebased;
}

Vamos a ver qué resultados se obtienen probando con distintas bases:

Numero: 24
Alfabeto: 01
Conversion: 11000

Numero: 24
Alfabeto: 01234567
Conversion: 30

Numero: 24
Alfabeto: 0123456789
Conversion: 24

Numero: 24
Alfabeto: 0123456789ABCDEF
Conversion: 18

Como se puede observar hemos transformado el número 24 a sus distintas representaciones en base 2 (binario), 8 (octal) y 16 (hexadecimal).

Veamos ahora qué sucede si, por ejemplo, queremos aprovechar este algoritmo para realizar un numerado usando sólo letras, tal y como puedan hacer algunos tipos de listas de procesadores de texto o las columnas de una hoja de cálculo. De esta forma habría que empezar por A, luego B, C y así hasta Z. Tras Z llegaría AA, AB, AC, ..., AZ, BA, BB, BC, ..., ZZ, AAA, AAB, AAC, etc.

Tentativamente podemos tomar como alfabeto ABCDEFGHIJKLMNOPQRSTUVWXYZ y ver los resultados iniciales:

Numero: 0
Alfabeto: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Conversion: A

Numero: 1
Alfabeto: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Conversion: B

Numero: 25
Alfabeto: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Conversion: Z

Hasta ahí tiene buena pinta. Veamos ahora qué sucede con números un poco más grandes:

Numero: 26
Alfabeto: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Conversion: BA

Numero: 27
Alfabeto: ABCDEFGHIJKLMNOPQRSTUVWXYZ
Conversion: BB

Al pasar a dos cifras no ha aparecido una A como primer caracter tal y como nos gustaría, sino una B. Analicemos el problema para hallar una solución.

Cuando contamos en base 10, 2, 16 o la que sea tenemos el cero, elemento neutro en la suma, por el cual se empieza. Tras agotar los símbolos del alfabeto se incrementa la cifra a la izquierda y se vuelve a empezar a la derecha. Por ejemplo: tras el 9 incrementamos la cifra a su izquierda (que es cero pero no se representa) y sustituimos el 9 por el primer símbolo de nuevo, cero. Así, tras el 9 viene el 10. Al llegar al 19 incrementamos el 1 y sustituimos de nuevo el 9 por 0, teniendo 20.

Aplicando esto a nuestro caso particular de letras, la A representaría el 0, y la B el 1. De esta forma al llegar a la Z incrementamos el caracter a su izquierda (la A-cero, que no estaba representada) y sustituimos la Z por el primer símbolo del alfabeto, la A, quedando BA.

Visto el origen del problema vamos a hallar una solución.

string alphaOrder(const unsigned int number)
{
 const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 const unsigned int base = alphabet.length();
 string rebased = "";
 unsigned int rem = 0;
 unsigned int n = number;
 while (n >= base)
 {
  rem = n % base;
  n = n / base - 1;
  rebased = string(1,alphabet[rem]) + rebased;
 }
 rebased = string(1,alphabet[n]) + rebased;
 return rebased;
}

En la línea 11 añadimos un -1. De esta forma se ajusta en cada iteración el cociente para que la A aparezca como primer caracter con valor (haciendo las veces de 1) y se solucione nuestro problema.

Con este cambio aplicado veamos cómo se comporta el código, ya de forma correcta.

Numero: 0
Conversion: A

Numero: 1
Conversion: B

Numero: 25
Conversion: Z

Numero: 26
Conversion: AA

Numero: 27
Conversion: AB

Numero: 100
Conversion: CW

Numero: 1000
Conversion: ALM

Como era de esperar se obtienen los resultados que deseamos. Ya para terminar listo a continuación la totalidad del código que he empleado para estos ejemplos, de forma que cada uno pueda experimentar con él como le plazca :D

// rebase.cpp - Created on 2010.10.24

#include <iostream>
#include <string>

using namespace std;

string rebase(const unsigned int number,
     const string& alphabet)
{
 const unsigned int base = alphabet.length();
 string rebased = "";
 unsigned int rem = 0;
 unsigned int n = number;
 while (n >= base)
 {
  rem = n % base;
  n = n / base;
  rebased = string(1,alphabet[rem]) + rebased;
 }
 rebased = string(1,alphabet[n]) + rebased;
 return rebased;
}

string alphaOrder(const unsigned int number)
{
 const string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
 const unsigned int base = alphabet.length();
 string rebased = "";
 unsigned int rem = 0;
 unsigned int n = number;
 while (n >= base)
 {
  rem = n % base;
  n = n / base - 1;
  rebased = string(1,alphabet[rem]) + rebased;
 }
 rebased = string(1,alphabet[n]) + rebased;
 return rebased;
}

void testRebase(const unsigned int number,
     const string& alphabet)
{
 cout << "Numero: " << number << endl;
 cout << "Alfabeto: " << alphabet << endl;
 cout << "Conversion: " << rebase(number,alphabet) << endl << endl;
}

void testAlpha(const unsigned int number)
{
 cout << "Numero: " << number << endl;
 cout << "Conversion: " << alphaOrder(number) << endl << endl;
}

int main()
{
 testRebase(24, "01");
 testRebase(24, "01234567");
 testRebase(24, "0123456789");
 testRebase(24, "0123456789ABCDEF");
 testRebase( 0, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
 testRebase( 1, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
 testRebase(25, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
 testRebase(26, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
 testRebase(27, "ABCDEFGHIJKLMNOPQRSTUVWXYZ");
 testAlpha(0);
 testAlpha(1);
 testAlpha(25);
 testAlpha(26);
 testAlpha(27);
 testAlpha(100);
 testAlpha(1000);
 return 0;
}


domingo, 6 de junio de 2010

Integrar Google Chrome en KDE

El navegador Google Chrome (y por extensión Chromium) presenta un aspecto nada integrado con el sistema cuando se ejecuta en un sistema operativo GNU/Linux. El sistema de temas hace que su aspecto sea completamente distinto al del resto de aplicaciones del escritorio y las decoraciones de ventana en cliente hacen que no tenga un comportamiento ni aspecto consistente con el gestor de ventanas.

Como usuario habitual de KDE SC esto siempre me ha molestado, principalmente porque elijo Chromium como navegador por su velocidad y rendimiento (si bien soy consciente de la voracidad en cuanto a memoria se refiere, nada que no se solucione reiniciándolo cada pocas horas).

¿Cómo solucionar esta situación? Por fortuna, el navegador ofrece la posibilidad de dejar la decoración de la ventana al gestor de ventanas y emplear el tema visual de GTK. Puesto que KDE SC emplea Qt como librería de controles hay que elegir un tema GTK de colores y diseño parecido al usado en Qt. Para activar estas opciones hay que realizar estos cambios en el cuadro de opciones:


En la sección Appearance, dentro de la pestaña Personal Stuff, hay que marcar Use GTK+ theme y Use System title bar and borders. Tras reiniciar el navegador el borde de la ventana pasará a ser el empleado por el gestor de ventanas, y el aspecto visual el elegido para GTK. Para acabar una muestra en mi escritorio, usando KDE SC y Compiz-Fusion como gestor de ventanas:


Nótese la similitud de Chromium con Dolphin, el gestor de archivos que aparece tras la ventana del navegador.

lunes, 10 de mayo de 2010

Convertir secuencia de imágenes en vídeo

Hace poco me he visto en la necesidad de convertir secuencias de imágenes en vídeos. ¿Por qué? En mi caso genero animaciones fotograma a fotograma, y luego compongo el vídeo a partir de ellas, pero puede emplearse para montar presentaciones, crear time-lapses, etc.

Buscando en Google he visto que la forma más sencilla (trabajo sobre GNU/Linux) es empleando FFmpeg. Con una sencilla orden puedo convertir la secuencia de imágenes en vídeo alterando algunos parámetros. Tras mis investigaciones por foros, he guardado estas distintas opciones como útiles para mis fines.

ffmpeg -f image2 -i frame%04d.png -r 24 out.mpg

Esta orden convierte todos los archivos de nombre frame####.png (donde #### es el número de secuencia) en un vídeo llamado out.mpg que reproduce a 24 fotogramas por segundo (-r 24). Si queremos variar el número de cifras de la parte de secuencia del nombre del archivo (digamos que frame01 en vez de frame0001) hay que variar el número que aparece entre el %0 y la d (en el ejemplo, quedaría %02d).

Variando la extensión del archivo de salida se consigue que emplee diversos formatos. A mí me ha funcionado con flv, mpg, mp4 y avi. Sin embargo, es con el codec h.264 con el que he conseguido los mejores ratios de calidad/tamaño. Para ello, hay que ejecutarlo de la siguiente manera:
ffmpeg -f image2 -i frame%04d.png -r 24 -vcodec libx264 out.mp4
Para obtener la máxima calidad con una compresión bastante decente con el codec h.264 conseguí encontrar una serie de parámetros que dieron muy buenos resultados. Lamentablemente no guardé el enlace del foro en donde se discutían, sólo anoté la combinación que me funcionó. Se trata de la siguiente orden:
ffmpeg -f image2 -i frame%04d.png -threads 0 -r 24 -vcodec libx264 -level 41 -crf 20 -bufsize 20000k -maxrate 25000k -g 250 -coder 1 -flags +loop -cmp +chroma -partitions +parti4x4+partp8x8+partb8x8 -flags2 +dct8x8+bpyramid -subq 7 -me_range 16 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -rc_eq 'blurCplx^(1-qComp)' -bf 16 -b_strategy 1 -bidir_refine 1 -refs 6 -deblockalpha 0 -deblockbeta 0 out.mp4
Se puede hacer acto de fe y creer que funciona ciegamente, pero para los curiosos: en la web de FFmpeg se explican todos y cada de estos parámetros.

Con esto ya cubro mis necesidades de creación de vídeos. En los próximos días crearé un nuevo post con resultados.

domingo, 2 de mayo de 2010

Atontaus in Town

Actualización: Al final no pudo ser, pero llegamos a la final. ¡Muchas gracias a todos los que nos votaron! Dejo el enlace al corto original:







Recientemente he participado en la realización de un corto titulado "Atontaus in Town" con diversos amigos. El motivo ha sido la participación en un concurso de cortos para promover el aprendizaje de distintas lenguas.

Desde aquí pido la ayuda de los lectores para conseguir ganar ^^ Podéis verlo, votarlo y comentarlo en la siguiente dirección:

"Atontaus in Town"

Por otro lado, podéis hablar con gente del equipo y ver imágenes del making of en el grupo de Facebook:


¡Muchas gracias a todos!

PD: Uno de los fondos realizados en 3D (el que me correspondió a mí) fue hecho con Blender 2.5:

Ceiling (Blender 2.5 Alpha 2)

miércoles, 10 de marzo de 2010

Jugar a Starcraft II Beta Offline

Por fin ha comenzado el periodo de beta de uno de los juegos de estrategia en tiempo real más esperados: Starcraft II. La beta es cerrada, sólo para personas a las que Blizzard haya seleccionado (vía registro online en su web) y sólo permite el juego online en battle.net.

Para los que tengáis el cliente de la beta y no tengáis conexión a internet, o simplemente queráis practicar jugando contra el ordenador, existe un lanzador que permite elegir jugadores, razas, colores, mapa e inteligencia artificial. No hay más que descargarlo, descomprimirlo en el directorio del juego, y ejecutarlo. Presentará una sencilla interfaz para configurar todo. La web para descargarlo es:

lunes, 15 de febrero de 2010

HTML 5 Vídeo y Youtube

Recientemente me he percatado de que en Youtube ya ofrecen soporte experimental para el tag video de HTML 5 y puede emplearse en lugar del reproductor Flash. Lo he estado probando con Google Chrome y funciona perfectamente, además de aparecer una nueva opción: variar la velocidad de reproducción.

Espero que sea el principio del fin de tener que utilizar un plugin para reproducir contenido multimedia y depender de un tercero para poder visualizar vídeos. A ver si por fin se comienza a emplear el estándar y la gente de Microsoft lo implementa, o los usuarios de Internet Explroer serán los únicos que necesiten plugins para ver vídeos.

Más información en Youtube: YouTube HTML5 Video Player