domingo 18 de noviembre de 2007

El truco del hombre del tiempo

Tras mas de un mes atareado hoy voy a desvelar la "magia" que permite al hombre del tiempo, entre otros, para superponerse a un fondo virtual.

Básicamente el objetivo consiste en reemplazar unas zonas de la imagen original, y sustituirlas por fragmentos de una segunda imagen. La técnica mas comun es el chroma key.

Esta es la famosa técnica en la que los actores realizan su papel delante de paredes verdes "fosfi" y azules. Seguro que todos hemos visto esto en el "como se hizo" de algún DVD. Después de tomarse la imagen original, se procesa pixel a pixel, substituyendo el color que hemos puesto de fondo por nuestra imagen virtual, donde Anakin y ObiWan se dan leches sin parar sobre magma incandescente.

Así de primeras puede parecer sencillo, pero en la práctica surgen dificultades. Paso a explicar el algoritmo donde se apreciará con mas facilidad donde reside el problemilla. Recorremos el fotograma en cuestión pixel a pixel, si el pixel tiene el valor RGB que hemos configurado como fondo, substituimos el pixel en cuestión por su correspondiente en la imagen virtual. Fácil no? Esto con imagenes sintéticas funciona perfectamente, en la práctica no acaba de ir tan bien sin unos ajustes. Porque? Bien, porque el fondo nunca es homogéneo en un 100%, las cámaras arrastran también mayores o menores desviaciones en el color y por buena que sea la iluminación del plató, siempre habrán pequeñas sombras o brillos. Cuando el algoritmo tira a procesar la imagen, se encuentra con colores parecidos, pero no iguales dando como resultado un fracaso !

Que no cunda el pánico ! Solo sera necesario modificar el algoritmo para que admita colores parecidos. Imaginar los 3 ejes cartesianos, el centro es negro total (0,0,0) sobre un eje va creciendo el color rojo, de igual manera con los otros dos, verde y azul. De esta manera, cada color rgb se interpreta como un punto en el espacio cartesiano (x,y,z). Por tanto, cuanto menor sea la distancia entre dos colores, mayor su semejanza.

Tomemos una distancia, que la llamaremos Delta y dos colores, el del pixel de entrada P, y el de referencia para contrastar el chroma C. El valor de Delta se ajusta de manera empírica (en castellano: probando hasta que quede bien) ya que depende de las condiciones que tengamos a la hora de capturar la imagen.

//calculamos el vector entre los dos puntos
Vr = Cr - Pr
Vg = Cg - Pg
Vb = Cb - Pb

//modulo del vector
dist = sqrt(Vr*Vr + Vg*Vg + Vb*Vb)

//son colores parecidos ?
if(dist < Delta)
{
putPixel (..... )
}



Ajustar la distancia es primordial para que chroma de buenos resultados, valores muy bajos, provocaran que parte del fondo no consiga ser discriminado. Sin embargo valores muy altos tomarían como fondo demasiados colores, desintegrando el aspecto de la imagen. Por poner un ejemplo, es como si el hombre del tiempo, fuera deshaciendose conforme el Delta aumenta, viéndose solo el mapa metereológico.

Tras haber entendido todo esto, se intuye el porqué se emplean colores tan llamativos como fondo para el chroma key. Por un lado se debe de usar un color que no vaya a estar presente en los actores. Por otra parte, estos colores tan exagerados permiten aumentar el Delta reduciendo el riesgo de "amputarle" algún miembro a nuestro presentador :-)

Por supuesto el algoritmo aquí explicado es perfectamente mejorable, los chicos de George Lucas usan chroma keys bastante mas sofisticados, que permiten tratar transparencias y reflejos. Si alguien le da por jugar con la webcam, ya aviso que con webcams malas (si Logitech, estoy hablando contigo) los resultados son algo decepcionantes.

martes 9 de octubre de 2007

Una cita con la naturaleza

Como ya adelantaba la semana pasada, he aprovechado la festividad del 9 de Octubre para hacer una escapada mtb por tierras Valencianas. La escapada ha sido un auténtico éxito; buen tiempo, hermosos paisajes, ruta divertida...

La ruta está bastante bien definida, puesto que transcurre en su mayoría por carriles bici. Además, si no dispones de vehículo o manera de transportar las bicis en él, no es problema, ya que esta ruta tiene la especial peculiaridad de poder valerse del transporte público tanto en la ida como en su regreso.

El recorrido nace donde finaliza la linea de metro con destino a Lliria. Desde este histórico pueblo pedaleamos dirección Olocau, valiéndonos de un magnifico carril bici que une sendos pueblos. Una vez visitado Olocau, ya por terrenos algo mas abruptos, realizamos un divertido descenso hasta la localidad de Bétera.

Aunque no recomiendo la ruta para principiantes, puesto que tiene dos ascensos pronunciados, sus casi 35 km si son altamente recomendables para cualquier amateur de la bici. Eso si, de montaña ! no importa si rígidas o dobles, puesto que un tramo del trayecto (el mas divertido) no esta asfaltado.

Ciclistas que te devuelven un cordial buenos dias, hermosas vistas y hermosos árboles, y siempre relativamente cerca de núcleos habitados por si tenemos un susto. Que maravilla ! :D

Por cierto quiero aprovechar para saludar al chaval con la topbike del carrefour que en un intento de impresionarnos con sus acrobacias ha reventado la cámara trasera con su característico Bloom! Ha sido la nota cómica del día :_D

Os dejo un link con toda la información necesaria para llevar acabo la excursión. Aunque los datos no son muy precisos, con una brújula y preguntando a los paisanos se completan los detalles.

Aquí va el link: LLíria-Olocau-Bétera (33,8 Km)

Y aquí unas cuantas fotos:

Para los ciclistas, el cielo no esta arriba, mas bien el infierno.



Asi se ve el mundo desde la Calderona.


Alguien estaba muy nervioso y se lió a tiros :S

Las bicis, bautizadas como "Agonia" y "Sufrimiento" en el vagón de regreso a casa. Les vendrá bien una buena lavada y un engrase....vaya, igual que a mi :D

jueves 4 de octubre de 2007

Fallo de diseño

Vaya ! Ando algo atascado con el scalextric digital casero. La etapa lógica se ha comportado bien, pero en la etapa de potencia es donde no consigo pasar. Tras un medio-éxito con un L298, decidí simplificar el esquema usando transistores en su lugar. Me decanté por un TIP-41, sinceramente sin tener las ideas demasiado claras. Monté un pequeño prototipo y no parecía hacer mención alguna. Polímetro en mano me percaté que el voltaje que proporcionaba la etapa lógica era de no mas de 4.8 V, voltaje que creo que es insuficiente para que el tip-41 abra entre colector y emisor. Bueno...de los errores se aprende, ahora manos a la obra en busca de una solución.

Mientras tanto, dejo colgada un esquema de lo que es la etapa lógica para una sola pista (extenderlo a dos es replicar parte del circuito, no tiene demasiado misterio).

Por supuesto se admiten críticas ! :D

Aprovecho para adelantar que en este primer puente de octubre voy a marcarme una pequeña ruta BTT por tierras Valencianas, y de paso igual hago un pequeño reportaje fotográfico de la sierra Calderona ^_^

Que tengáis buen finde !

viernes 21 de septiembre de 2007

Contacto en 3,2,1.... BANG !!!

Para que luego digan que la electrónica es aburrida. Cual cerdo en barro me he reido hoy al ver explotar un pequeño integrado. Si es que... los datasheets no estan llenos de cifras para impresionar a los novatos, esas cifras estan para algo. Y cuando no respetas o no te da al gana respetarlas pasa lo que debe de pasar. En mi caso una pequeñita explosión.

Estabamos usando un L293 a modo de etapa de potencia, faltos de un transistor que encajara mejor ahi. Y se nos ha ido la mano con la corriente, supongo que fruto de las prisas y la ignorancia dando como resultado un pequeño cráter en la superficie del integrado. Imagen que obviamente adjunto con orgullo :D



Según mi colega, una burbuja del aire que se ha dilatado debido a las altas temperaturas ha sido la causante de tal explosión. Y yo los habia visto medio derretirse, pero esto... ha sido gracioso !!! Y tu?? Que has hecho explotar en esta vida ?? :_D

jueves 20 de septiembre de 2007

Cacharreando con PyGame

Como echo de menos mi adolescencia, cuando tenía mas horas para programar juegos. Antaño (1999) surgió un lenguaje de programación llamado DIV Games Studio que causó furor entre la comunidad hispana de programadores. Como toda idea revolucionaria, tenía sus seguidores y sus detractores, pero el caso es que se llegó a editar una revista sobre DIV, y noche tras noche nos reuníamos cerca del centenar de usuarios en el irc-hispano para hablar sobre la programación de videojuegos. Pero la empresa que sacó DIV al mercado cerró al poco de sacar su segunda versión, y esto sentenció la vida de este lenguaje. La gente lejos de quedarse de brazos cruzados, trató de mantener al dia este lenguaje y surgieron varios proyectos con su versión libre de DIV (Fenix y eDIV). A varios colaboradores de sendos proyectos he tenido el gusto de charlar con ellos y aprovecho para mandarles un saludo :)

Aunque proyectos como Fenix han conseguido mantener el lenguaje DIV hasta nuestros dias, su poca aceptación fue desperdigando a la gente hacia otras alternativas. Yo encontré la mia en la combinación de C con SDL, pero quedaba lejos de ser tan fácil como DIV, y los lenguajes basados en BASIC siempre han estado ligados a licencias no libres y a una baja o nula portabilidad.

En python he encontrado la manera mas productiva de desarrollar juegos caseros y seguir disfrutando de este mundo fruto de la combinación de técnica y arte.

Vamos a comentar un ejemplo sencillito, que puede servir a su vez como un esqueleto básico con el que hacer unos primeros pinitos.

Empezaremos incluyendo la/s librerias que nos hacen falta, que por ahora será exclusivamente pygame:

import pygame

Tecnicismos a un lado, esto es algo similar al import de java o al include de C. Ahora veamos como ponemos la maquinaria a rodar:

def main():
print "Python game tutorial 01"

pygame.init()

screen=pygame.display.set_mode( (800,600),pygame.DOUBLEBUF)

Para los nuevos en python, respetar las tabulaciones ! es la forma que tiene este lenguaje para delimitar los bloques de código. Aunque al principio parece algo bizarro, cuando te acostumbras te ayuda a mantener el código algo mas elegante. Bien, pasemos a comentar este trozo. Las tres primeras lineas no tienen mucho que decir, se define la funcion main, se imprime por consola una cadena de texto y se inicializa pygame. Es necesario llamar a pygame.init() antes de cualquier otra función de pygame. Analicemos ahora la cuarta instrucción: pygame.display.set_mode establece el modo gráfico y si lo consigue nos devuelve el buffer para dibujar en el. En el ejemplo se desea una resolución de 800 x 600 pixeles y con la opción de doble buffer (para animaciones mas suaves). Si no se especifica lo contrario, será en modo ventana. La pantalla completa suele dar algun problema que otro, no recomiendo usarla hasta no tener algo estable.

Una vez en marcha pygame y el modo gráfico establecido, es un buen momento para poner a punto las variables de nuestro juego:

 default_fnt=pygame.font.Font(None,24)

quit_request=False
x=0
y=0
dx=1
dy=1

De aquí poco hay que comentar, se genera una fuente de tamaño 24 y se inicializan unas cuantas variables que mas tarde se usarán. Para los mas culebrines, es fácil ver que no hemos declarado las variables, se declaran en el mismo momento que se les asigna por primera vez un valor, a la par que toman el tipo del tipo de dato que se les asigna (Integer, bool, string....) que comodidad no !??? :D

Teniendolo todo preparado, es momento ahora de entrar en un bucle y comenzar la animación. En la primera parte del bucle, vamos a leer la cola de eventos de pygame buscando aquellos eventos que nos interesen, como es el caso de las pulsaciones de teclado. Esto quedaría asi:

while not quit_request:
for event in pygame.event.get():
if event.type == pygame.QUIT:
quit_request=True
if event.type == pygame.KEYDOWN:
if event.key==pygame.K_ESCAPE:
quit_request=True

Tenemos un while, cuyo comportamiento es idéntico al de otros lenguajes, sin misterio alguno, iteraremos mientras se de la condición. La que viene a continuación es un bucle For algo mas propio de lenguajes mas modernos como el caso de C# o java. La función pygame.event.get() nos devuelve una lista con todos los eventos pendientes de ser procesados y la variable event se emplea como variable iteradora. Ahora mismo hacemos mas bien poco, tan solo damos la condición de salir del bucle principal si detectamos que se ha hecho click en cerrar la ventana o se ha pulsado la tecla ESCAPE.

Bueno, de el siguiente código poco hay que comentar, nos valdrá para darle algo de movimiento al programa.

  x=x+dx
y=y+dy
if x>799:
dx=-1
if x<0:
dx=1

if y>599:
dy=-1
if y<0:
dy=1

Hemos leido los eventos del usuario, actualizamos las variables que le dan la lógica a nuestro juego... pero como dibujamos cosas? Hoy solo dibujaremos algo de texto en pantalla.

  screen.fill((0,0,0))  

text_srf=default_fnt.render("Hello World",False,(255,0,0))

screen.blit(text_srf,(x,y))
pygame.display.flip()

Como se vio anteriormente, en screen se guarda la referencia a nuestro buffer gráfico. Se suele emplear el nombre de Surface o Superficie a las imágenes que residen en la memoria RAM. Como no sabemos en que estado está el buffer, lo primero que debemos hacer es limpiarlo, llenandolo ( screen.fill() ) de otro color, como en este caso, que se emplea un negro total para limpiar el buffer. En la segunda linea se genera una superficie con un texto dibujado en su interior, no es dificil ver que se trata de la cadena "Hello World" ^_^

Como si de pegatinas se tratara, tenemos que ir montando el buffer "pegando" en el las imágenes que formaran la animación, personajes, fondo, textos... A estos pegados se les llama blits. Ahora mismo no nos vamos a lucir tanto, y tan solo pegaremos en la pantalla esa imagen con el texto que se ha generado anteriormente, indicando además, las coordenadas donde se debe pegar, siendo las variables x e y en este caso.

Cuando hemos acabado de componer la escena, pygame.display.flip() manda el buffer al monitor y se nos da otro buffer para que en la siguiente iteración del bucle, dibujemos otra vez la escena.

Con todo esto, solo nos queda añadir un par de lineas para completar el ejemplo básico de pygame:

if __name__=="__main__":
main()

Esto no tiene mucho que ver con pygame, es algo de Python. De aquí simplemente entender que cuando se lance el programa se ejecutará la función main anteriormente definida.

Pues esto es python y pygame ! A mi parecer, es tremendamente fácil aunque nunca hay nada exento de polémica. No hay que olvidarse de que no deja de ser un lenguaje de programación imperativo y que como tal, es necesario tener experiencia programando. Querer hacer juegos sin programar normalmente acaba por no dar muy buenos resultados.

Tengo que hacer un par de proyectillos con pygame (Entre ellos el scalextric pseudo digital) así que aprobecharé para colgar mas tutoriales sobre pygame :)

lunes 17 de septiembre de 2007

Empezamos con Python !

Bueno, acabados los exámenes, nos ponemos manos a la obra con los videojuegos y python.

Antes de empezar a picar código sin mas, repasemos la estructura habitual de un juego:

A diferencia del software convencional, en los videojuegos es habitual que el código vaya tan rápido como sea posible con el fin de tener FPS generosos. Con lo cual, una primera aproximación seria:

  1. Inicialización del juego y carga de recursos (sonidos, imágenes,...)
  2. Un bucle donde se dibuja y se le da vida al juego, optimizado en la medida de lo posible.
  3. Descarga y cierre del juego.
Aquí la parte que mas chicha tiene es la segunda. Ese bucle que le da la vidilla a nuestro juego, a su vez consta de otros tres apartados:
  1. Lectura de dispositivos de entrada (teclados,ratones, joysticks...)
  2. Cálculo del juego, posiciones de los personajes, física ...
  3. Dibujado de la escena
Si alguien anda algo perdido, que imagine por un momento como funcionan las reproducciones en los cines, todos los fotogramas de la película son proyectados uno a uno en la pantalla con una velocidad tal que nos hace ver una animación. Esto es practicamente lo mismo, solo que los fotogramas no estan previamente dibujados, si no que se dibujan al vuelo.

La tarjeta gráfica proporciona hueco para dos de estos fotogramas. El primero de ellos es lo que se envia al monitor mientras que en el segundo es donde esta nuestro juego preparando el siguiente. En el momento que consideremos que el fotograma esta listo, se le da la orden a la tarjeta gráfica y entonces ocurre un intercambio (conocido como Page Flipping o Page Swapping): El fotograma que hemos dibujado pasa a ser mostrado por la pantalla, y el que se estaba mostrando sale de la pantalla y cae en nuestras manos para que vayamos preparando en él, el próximo fotograma.

Con esta pequeñisima introducción teórica, en la próxima entrega lo veremos como se plasma toda esta gallufada en el código, que es realmente sencillo. Y sobre un ejemplo mínimo, se irán añadiendo interactividad hasta hacer un juego... cutre no vamos a negarlo, pero nuestro cutre juego! hecho por nosotros mismos que es lo importante.

Antes de despedir esta entrada, me gustaría dar un par de consejos, que a su vez, la vida a mi me los dio.

  • Hacer un juego 2D, si tienes nociones de programación, es relativamente sencillo, dependerá casi en mayor medida de tus dotes de artista. Unos gráficos elegantes y buen gusto para los colores es vital para que un juego 2D sea respetado.
  • Hacer un juego 3D al estilo "quake" y compañía, puede ser mas difícil que bailar la banda sonora de tiburón. Es altamente recomendado tener experiencia programando, soltura con el álgebra, e interminables horas de dedicación. Amén de que es aconsejable de partir de un motor 3D ya hecho o incluso, hacer un Mod.
  • No trates de impresionar a nadie que no sea otro programador, y a ser posible de videojuegos. La informática esta infravalorada, la gente prestará mas atención a un perro que trata de morderse la cola, que a tu juego que has tardado 6 meses en hacer tras leerte truñocientos tutoriales y howto's.
  • Es difícil que el juego de tus sueños salga a la primera, empezarás a hacerlo y llegarás a algún punto que no sabrás resolver. Esto le ha pasado hasta a John Carmack. Cada vez que intentas hacer algo, aprendes cosas, funcione o no tu juego.
Bueno, os dejo que le deis vueltas a la sesera y meditéis :)

sábado 8 de septiembre de 2007

Próximamente... Programación de juegos con Python

Cuantas veces has visto un videojuego y has creido poder hacerlo mejor? Cuantas de esas veces te han echado atrás los escasos conocimientos de programación? Nunca mais ! Devuelve a la biblioteca ese libro de programación en C del tamaño de un coco, desinstala esos 12Gb de Visual Studio y grábate a fuego esto: "Python".

Python yo lo defino como el BASIC de los tiempos modernos. Es un lenguaje fácil de aprender, moderno, altamente productivo y... bueno, obviamente no es tan rápido como C/C++, pero no debe de ser un problema. El espectro de aplicaciones que se pueden llevar a cabo con python es muy amplio, este tiene soporte para interfaces gráficas (via Qt,Gtk e Wx entre otras), threads, comunicaciones, Bases de datos, audio, OpenGL... y está portado a un gran número de sistemas operativos !

Como el tema a tratar es la programación de videojuegos, nos valdremos de la libreria pygame. El nombre ya lo dice todo, python & juegos :D Aunque he de remarcar que pygame solo cubre juegos 2D, para gozar del 3D hay que apoyarse también con pyOpenGL.

Aunque python es fácil y hay inmensidad de tutoriales por la red, partiré de que el que sigue el tutorial no tiene idea de python. (Aunque es altamente recomendable algo de experiencia con lenguajes de programación).

Asi que, mientras negocio los exámenes de septiembre podeis ir descargando python y trasteando con él. Aunque no os agrade el mundo de los videojuegos, dadle una oportunidad a python, es un gran lenguaje :)

No hagais maldades! Pero si las haceis, documentadlas :D