Mostrando entradas con la etiqueta proyectos. Mostrar todas las entradas
Mostrando entradas con la etiqueta proyectos. Mostrar todas las entradas

A Tuenti le molan los developers yonkis

Esto viene a ser en cierto modo un epílogo a mi serie de entradas sobre mi participación en el concurso Tuenti Challenge. Si las leíste, probablemente pensaste: este tío es un patán. Vueltas y revueltas raras a los ejercicios del concurso, interpolaciones que no vienen a cuento, falta de sueño, notitas tontorronas en los comentarios a los revisores... pfffff, seguro que has pensado que tú lo harías mejor.

Pues bien, amigo lector... quiero compartir contigo que a pesar de todo esto (o quizá incluso por eso), dentro de nada voy a empezar a trabajar en Tuenti.

Echaré de menos a los que han sido durante muchos años mis compañeros en DIGIBIS, y con los que realmente da gusto trabajar. Doy ahora un giro y cuando ya casi casi entendía a los bibliotecarios, me aparto de ese mundillo. Y eso que en algún momento hasta había llegado a plantearme sacarme la carrera de Biblioteconomía, ya que con el tiempo mis conocimientos de MARC21 y otros estándares infernales del mundo bibliotecario han llegado a ser bastante decentes. Y que poco a poco me he descubierto a mi mismo, cada vez más a menudo, pidiendo silencio a la gente.

No sé todavía en qué departamento de Tuenti entraré, ni siquiera con qué tecnologías, lo mismo puede ser Java o Android que iOS, Erlang o... sí, PHP. Pero en cualquier caso espero que la experiencia me sirva para crecer profesionalmente y sea todo un reto.

La lectura para ti, sin embargo, debería ser... ¡ey!, si yo, con esa cochambrosa interpolación en el segundo ejercicio, he conseguido entrar en Tuenti... ¡entonces tú también puedes!. Ya sabes, espera unos mesecitos y dentro de nada se abrirá la convocatoria para la Tuenti Challenge 2015.

Y si te encuentras un ejercicio con personajes divertidos pero desarrollo infernal... sospecha. Probablemente lo haya puesto yo.

Jugar mientras conduces ES POSIBLE

Tanto cacharrito, tanto Internet de las cosas, tanto móvil, tablet, reloj, gafas, pulsera, ¡tanta leche!... y oye... ¡¡¡que KITT, el coche fantástico, sigue sin existir!!!.

El glamour y chulería de David Hasselhoff van aparte, practica todos los días frente al espejo y lo conseguirás. ¡Tú puedes!

"Smart cars"

Lo cierto es que se está trabajando en ello, pero claro, no se tarda lo mismo en hacer un coche que una pulsera. El camino se está marcando: BMW y Chevrolet apuestan por los iPhone y su Siri Eyes Free, y parece que ya ha salido algún modelo y se esperan más durante este mismo año. Otros como Ford apuestan por un sistema Sync de Microsoft, sobre el cual tengo unas ganas enormes por ver cómo reproducirán de forma sonora los pantallazos azules (apuesto a que sonará como los pitidos de carga de juegos del ZX Spectrum).

Audi parece hoy por hoy la más atrevida, y apuesta por su propia pantalla Virtual Cockpit integrada en lugar del clásico cuadro de mandos, y apuesta por la estandarización de Android y se alía con Google y otros fabricantes como General Motors, Honda y Hyundai para crear la Open Automotive Alliance.

En fin, aparentemente la baraja está lista y sólo queda echar las cartas. La referencia por ahora es el CES2014, que es donde se han presentado todas estas novedades de los coches, y según eso aparentemente este mismo año se empezarán a ver cosillas en la calle. De hecho, si comparamos las fotos que se están mostrando ahora de los cuadros de mandos de Audi con el de KITT la verdad es que por ahí ya vamos ganando.

Audi Virtual Cockpit
Más Audi, ¡leche!
KITT, vintage a tope pero... ¡más mono!

¿Y qué harán estos smart cars, o como vayan a llamarlos?. Navegador GPS, claro. ¿Y aparte?... ayudas para aparcar, que el coche te lea los wasap y correos, ayudas a la conducción... ¡BOBADAS!. Vale, seguro que el coche conduce mejor que mucha gente pero ¿de verdad te vas a fiar hoy por hoy de lo que conduzca?.

A mi todo eso me da igual. Yo lo único que quiero es que ya que tiene tanto cacharro y tanta gaita, cuando tenga un viaje en el que vaya yo solo conduciendo no tenga que estar aburrido oyendo música o cualquier chorrada que pongan en la radio. Lo que yo quiero es que... ¡PUEDA JUGAR!.

Sin matarme al hacerlo, claro.


¿Cómo puedo jugar sin usar las manos ni apartar la vista?

Esta es la pregunta clave: ¿es posible?. Previsiblemente, al menos cuando la cosa esté lo bastante avanzada, el interfaz con el smart car tiene que ser fundamentalmente a través de la voz. Cada vez que quieras que el coche haga algo, le hablas. Para que reconozca que quieres hablar con él, supongo que al principio seguramente tengas que pulsar un botón o una palanca del volante, pero lo normal es que llegue un momento en que el coche esté continuamente activo esperando a que le digas algo, y que reaccione ante una palabra clave: su nombre. Incluso, se podría poner en "modo conductor solitario" y que reaccionase ante cualquier cosa que le dijeras sin tener que decir su nombre.

Se ha trabajado mucho en reconocimiento de voz últimamente. Antes en inglés todavía, pero en español no reconocía ni papa. Ahora con los avances del Siri de Apple y el Google Now, más otros "outsiders" como Sherpa (que además es español), el reconocimiento de voz está mejorando cada vez más. Ya se puede hablar con el móvil y mientras lo hagas con cierta calma, funciona bastante bien. Cualquiera podéis hacer la prueba con vuestro smartphone, si no lo habéis probado aún. Creo que todavía le falta un puntito para que sea más cómodo, para poder hablar con menos cuidado y que te siga entendiendo, pero no me cabe duda de que se conseguirá.

El coche, por supuesto, también responderá con la voz. La síntesis de voz también funciona muy bien actualmente. Cualquiera que hayáis usado un GPS en vuestro móvil lo habréis visto. Existen otros motores de síntesis de voz más avanzados, que a menudo son de pago. El reto en este caso es conseguir que la voz tenga alma. Que sea capaz de entonar un poco, no sólo leer. ¡Diablos, al menos como lo hacía KITT, que tampoco era el alma de la fiesta!

Entonces, de lo que se trataría es de encontrar un tipo de juego que se pueda jugar sólo con la voz, hablando con el coche. Y que no sea el "veo veo", vaya.

El caso es que existe un tipo de juegos que encaja perfectamente con esta forma de comunicación: las aventuras conversacionales.


Aventuras conversacionales

Sin gráficos: Fotopía

Las aventuras conversacionales, o interactive fiction (IF) como se las conoce en inglés, son un tipo de juego antiiiiiiiiiiiiguo. La primera se considera que es Adventure, data del año 1975 y se programó en Fortran en un PDP-10. O sea, tela. Sin embargo, vamos a ver cómo su simplicidad y su falta (o no necesidad) de gráficos juegan muy en su favor en este caso.

Distribución típica, con gráficos arriba: Alien

En una aventura conversacional, se te cuenta una historia y se te pone en situación y describe tu localización actual mediante texto. Entonces tú, el jugador, escribes también por texto y en lenguaje "natural" lo que quieres hacer. El juego devuelve el resultado de tu acción otra vez como texto, y así sucesivamente, de forma que se crea una conversación entre el juego y tú. La historia va evolucionando con lo que vas haciendo, y se te van presentando retos y puzzles a resolver.

de computeremuzone.com
Puede que te suenen porque en España tuvieron su época dorada en los años 80-90, cuando Aventuras AD lanzó para los ordenadores de 8 bits juegos como La aventura original, Don Quijote, El Jabato o La Diosa de Cozumel. Incluso, por entonces llegaron a España varios juegos en inglés, especialmente El Hobbit, y que obligaron a muchos jóvenes de la época a tirar de diccionario. Aunque ya por entonces la mayor parte de los juegos tenían gráficos descriptivos de las localidades, lo cierto es que dichos gráficos eran normalmente superfluos y no afectaban al desarrollo del juego, y su objetivo fundamentalmente es hacer los juegos más atractivos a la vista (cosa que nos importa poco mientras conducimos).


Este tipo de juegos, evidentemente, encaja perfectamente con un interfaz de voz. Tú dices lo que quieres hacer, el coche responde. Curva cerrada a la derecha, te callas y te concentras. Vuelves al juego, dices lo siguiente... te puedes tirar un montón de tiempo así. Y creo que a la vez, aparentemente no es tan inmersivo como para que pierdas la concentración en la conducción.

Y además... ¡son un tipo de juegos muy divertidos! (incluso si no los comparamos sólo con el veo-veo).

Esta sería una hipotética transcripción de una conversación entre KITT (obviamente llamaríamos así a nuestro coche) y tú, que dé paso a una sesión de jugar una aventura:


KITT: Buenos días, Andrés

Andrés (reemplázalo con tu nombre para disfrutarlo más): Hola, KITT

K: ¿Dónde vamos?

A: Vamos a casa

K: ¿A casa, a la calle Ríos Rosas?

A: Sí, eso es

(KITT programa el GPS y tú mientras arrancas y te pones en camino)

A: KITT, vamos a jugar a Olvido mortal

K: Cargando Olvido mortal. Continuamos la partida que dejaste ayer. ¿Correcto?

A: Sí

KITT: Oficinas
Estás en una especie de oficinas.
No ves ningún cartel que te indique qué lugar es este. La cola se extiende por la alargada localidad, enorme. Por detrás, una pared te impide ver dónde acaba. La fila de gente continúa por una puerta abierta en la pared.
En el otro sentido, las cabezas te impiden ver qué hay al principio de la cola.

La mujer de delante en la cola parece ser la única persona que te presta algo de atención.


(un chalao se te cruza en ese momento y te centras en lo tuyo)

A: Perdona, KITT, ¿puedes repetir?

K: Oficinas.......... (y repite toda la descripción, ¡más majo!)

A: Resumen

K: Despertaste en la cola sin recordar quién eras ni dónde estabas.

A: Inventario

K: Llevas: una cartera (que está cerrada)

A: Abre la cartera

K: Abres la cartera, descubriendo un carnet de identidad y una foto.

A: Mira el carnet

K: Es un carnet de identidad normal y corriente. La foto del carnet está un poco difuminada, pero se ve lo suficiente.

"¿Es posible que ese sea yo?. Desde luego, la cara me resulta familiar, pero no soy siquiera capaz de asegurar tajantemente que sea la mía."


(...)
(y así pasa el tiempo y cuando te quieres dar tiempo estás ya en casa... ¡y no quieres dejar de jugar!)



¿Qué tal, te convence?. ¡¡¡A mi sí!!!

Otra buena noticia es que muchos de estos juegos son multi-plataforma y se ejecutan sobre una máquina virtual. O dicho de otra forma: es muy muy fácil adaptar un intérprete de estos juegos para que se ejecute en un coche y se juegue con la voz. Y automáticamente, en cuanto tengas hecho el intérprete, tienes disponibles cientos, miles de juegos, listos para jugar.

En español, el mejor sitio donde encontrar juegos es la web del CAAD, el sitio donde se reúnen todos los "chalaos" de este tipo de juegos y aúnan esfuerzos alrededor de la aventura. Una de las grandes ventajas que tienen estos juegos, además, es que casi cualquiera puede programar uno. No hace falta ser programador, ni tampoco saber dibujar ni componer música. Esto ha hecho que se cree una comunidad alrededor de ellos y que se sigan programando juegos. En inglés, por otra parte, la comunidad es aún más activa y para descargar juegos tenemos el Interactive Fiction Archive.

Si queréis probar con alguno de estos juegos, ¡qué demonios!. ¡Prueba alguno de los que he hecho yo! Sí, así a lo tonto y mientras hablaba de "esos chalaos" en tercera persona, os metía de tapadillo mis juegos (hechos hace ya un buen montón de años, en el 2001, ahí es ná): Olvido mortal, que ya habéis probado un poco con KITT pero podéis jugar online aquí, y Akbarr.

Forma original en forma de libro: Akbarr


Conclusión

Esto no es más que elucubrar pero, ¿por qué no?. Está todo ahí: los coches ya produciéndose integrados con tecnologías móviles como Android e iPhone, los motores de reconocimiento y síntesis de voz a un puntito de ser cómodos y molones, justo ese puntito de más que daría el interés por el mercado de los coches... y las aventuras conversacionales ahí, listas para que las juguemos charlando con nuestro coche mientras hacemos un viaje.

¿Y vosotros, qué pensáis de todo esto?...

¿Y tú, KITT?. ¿Te apetece que juguemos?.


Proyecto Picross: haciendo un videojuego HTML5 en Dart

Ya lo dije en mi anterior entrada sobre el lenguaje Dart: Dart está muy bien, puede suponer una revolución en la web y su futuro potencialmente es muy prometedor. Pero claro, una cosa es el posible futuro y otra es el presente. ¿Cuál es realmente el estado actual de la plataforma Dart?.

Por otra parte, otra tecnología que me llama la atención es la de los videojuegos HTML5. Sobre todo para videojuegos 2d, sencillos, que aparentemente ya deberían poder hacerse en la web. Con la gran ventaja de ser multiplataforma, que se puedan jugar en Android, en iOS, o hasta desde el Facebook, y en este último caso sin tener que instalar nada. ¿Están estas tecnologías suficientemente maduras?.



Con ánimo de comprobarlo y a la vez divertirme, me lié la manta a la cabeza, uní las dos inquietudes y me puse a hacer ¡un videojuego en Dart!. Y aquí cuento todo el proceso, que duró sólo una semana, pero que me dio para asistir a la Gameme5  e incluso participar en la PiWeek.


La GameMe5

Yo de videojuegos en HTML5, la verdad, ni idea. Afortunadamente, estaba apuntado a la GameMe5, un evento organizado por HTML5 Spain y Wimi5 en el que ofrecían un taller de programación de videojuegos en Javascript el Viernes y varias charlas el Sábado.

El taller lo daban Carlos Benítez (@EtnasSoft) y Sergio Ruiz (@serginator), y en él fueron explorando un juego que se habían currado aposta y que era muy muy completito, desarrollado enteramente en Javascript a pelo y sin librerías.

Fueron avanzando poco a poco en el desarrollo y cubrieron muy bien muchos aspectos del desarrollo de videojuegos en general y de Javascript en particular, desde los temas más básicos como el loop principal y el doble buffer hasta otros más complejos como las rotaciones, los fondos por trocicos (en mosaicos), los métodos de detección de colisiones, algoritmos de búsqueda (pathfinders), manejo de física y sistemas de partículas. Lo mejor del taller es que aparte de estos aspectos más o menos generales de los videojuegos, iban comentando también temas de rendimiento y problemas de Javascript. Dijeron que un buen juego JS puede llegar a estar a la altura de un juego de PS2, si es 2d, o entre PS1 y PS2, si es 3d. Pero además comentaron problemas que tenían los navegadores si querían hacer efecto espejo automáticamente en las imágenes, usar base64 o como no tuvieran cuidado con los arrays y el recolector de basura (al eliminar un elemento de un array no lo elimina de verdad, sino que lo deja pendiente de GC, lo cual puede llegar a causar un parón sensible en un videojuego).

En las charlas del día siguiente hubo de todo, pero me gustaría destacar sobre todo 3 que fueron especialmente interesantes. En la primera, José Javier García-Aranda de Alcatel-Lucent hablaba sobre un algoritmo en el que están trabajando para compresión de imágenes y vídeo, LHE (Logarithmical Hopping Encoding), y que puede ser muy potente para el Cloud Gaming y las videoconferencias, ya que se consiguen tiempos de codificación rondando los 2ms y una calidad decente a 0,1 bits por pixel. Fue una de esas charlas que destacan porque lo que se cuenta es muy interesante, se entiende muy bien y además el ponente es muy ameno.

En la segunda Jorge del Casar (@jorgecasar) hablaba sobre WebSockets, y nos hacía una demo con un Tetris multi-jugador.

Y por último Imanol Fernández (@MortimerGoro) de Ludei nos daba una apabullante lección sobre rendimiento de Javascript, haciendo una demostración de un pequeño programa que tardaba 600 veces más en su versión Javascript que en la versión C++, y luego le aplicaba muchos trucos hasta conseguir que fuera "sólo" 6 veces más lenta. Sobre todo se usaron técnicas para conseguir que el compilador JIT de Javascript hiciera "inline caching" de las funciones más importantes, ya que es muchísimo más rápido, con cosas tan aparentemente absurdas como borrar un comentario o borrar un try-catch. Por ahí rondaron conceptos como las "hidden classes" (que se crean cuando añades atributos nuevos en tiempo de ejecución, y que ralentizan bastante) y arrays de más de 64K (leeentos). Pero vamos, si os interesa el tema, lo mejor es que veais la presentación completa.

Aparte de eso, también nos habló de CocoonJS, una herramienta que ha hecho que permite publicar tus videojuegos HTML5 en móviles, pero que al contrario que Phonegap, en lugar de utilizar los browsers que vienen de serie en las respectivas plataformas, utiliza uno propio, con su propia implementación de canvas, audio, webGL, etc., y con un rendimiento optimizado respecto a los otros (are we crazy? yes, but we're from Bilbao). La verdad es que tenía una pinta tremenda.



El videojuego: Picross

La verdad es que la GameMe5, en la práctica, sirvió a mi proyecto sobre todo para una cosa: acojonarme. Tanta optimización, tanto comportamiento extraño de los motores JS, tanto lío con los navegadores, tanta facilidad para quedarse sin memoria... y voy yo y le meto una capa más de riesgo por encima, Dart.

Así que decidí que ya tenía bastante cubierto mi cupo de riesgo y decidí hacer un juego sencillito, que no requiere gran rendimiento pero que a la vez escala muy bien, y da para ir añadiéndole cositas poco a poco. Y por supuesto, ¡muy divertido!.

Picross es un juego de tipo puzzle que se conoce por muchos otros nombres de los cuales el parecer el más oficial es "nonogramas".  Habrán salido millones de versiones del juego, tanto para ordenador como en papel, pero la que se hizo más famosa en su día fue la versión de Nintendo DS, o al menos esta es la que yo conocía y de la que me vicié hace años. Como buen juego de puzzles, se puede dejar el rendimiento un poco de lado y que siga siendo jugable, y eso es lo que a mi me importaba llegado a este punto. Sobre todo, porque tenía que tener una versión presentable en una semana, ya que me había presentado a la PiWeek.

El funcionamiento del juego es sencillo: hay una matriz de celdas, y cada una de ellas es un píxel, que puede ser blanco o negro. Todas juntas forman un dibujo binario que es el que hay que averiguar. Para hacerlo, cada fila y cada columna tienen una serie de números que indican los grupos de píxels negros que son consecutivos. Por ejemplo, si en una fila pone "3 2" significa que hay 3 píxels negros seguidos y luego separados otro grupo de 2 píxels negros. Entre medias, antes y después, hay un número indeterminado de píxels blancos. Combinando las pistas de las filas y las columnas, se va averiguando el dibujo.


La PiWeek

Kaleidos es una empresa de desarrollo que probablemente pueda presumir de tener el mayor ratio de densidad de geeks por metro cuadrado en toda España. Se definen como una empresa orientada a proyectos de innovación, así que tienen varias iniciativas muy interesantes orientadas a la innovación y la mejora. Una de ellas es la PiWeek ("Pi" de "Personal innovation"), una semana entera en la que paran por completo todos los proyectos que estén haciendo en ese momento para hacer... lo que le dé la gana a cada uno. Así, tal cual, lo que sea que le interese. Las únicas reglas son usar software libre para el desarrollo, y tener algo enseñable para una demo el Viernes.

La PiWeek tiene vocación abierta, y por tanto admite gente que no sean empleados de Kaleidos, ya sean individuos o empresas. El caso es que a mi me quedaba todavía una semana de vacaciones, sin ningún plan concreto, y de hecho tenía pensado dedicarla a este proyectillo, así que, ¿por qué no presentarme a la PiWeek, y así por un lado obligarme a hacer algo y por otro poder compartir proyectos con más gente?. Dicho y hecho, el Viernes anterior a la PiWeek se presentan propuestas de proyectos para formar equipos... y allí estuvo Picross.

Yo ya conocía a unos cuantos de Kaleidos, sobre todo a través del grupo de usuarios de Groovy Madrid GUG, pero la semana me dio la ocasión de charlar con todos, y la verdad es que es una gozada, en general son gente muy preparada y sobre todo derrochan pasión por la tecnología y el desarrollo. Entre los proyectos que se presentaron a la PiWeek había algunos como un clon de Twitter usando Redis y Spring integration, un visor de comics Android con detección de viñetas, un plugin de Chrome capaz de capturar pantallazos como GIF animados, un traductor de Python a Javascript (bautizado como CobraScript) o un aplausómetro hecho en Arduino, junto a otros más... rarunos, como un MUD hecho en Eiffel o una librería que permite crear parsers en Clojure. Salieron un montón de proyectos, pero todos tenían algo que contar. El ambiente que se crea durante la PiWeek es impresionante.


Haciendo el juego

Y llegó el momento de ponerse con el juego. Las primeras sensaciones con Dart son muy buenas, no es un lenguaje ni unas herramientas a las que estés acostumbrado, no son ni mucho menos tu "zona de confort", pero tanto las herramientas como el lenguaje y las librerías resultan cómodos e intuitivos. Esperaba encontrarme con alguna característica del lenguaje que echara de menos (el típico "no me puedo creer que esto no exista aquí"), pero no encontré ninguna.

Integración de Dart con Javascript
Mi primera intención era hacer un interfaz Dart para una librería Javascript de videojuegos. Después de estar echando un vistazo a unas cuantas me decidí por MelonJS, ya que había oído hablar bien de ella y era más pequeña y ligera que otras como Cocos2D. Después de varias pruebas básicas que aparentemente funcionaron, fui creando clases "proxy" que intermediaran con la librería, usando sólo lo que iba necesitando... hasta que de repente una prueba, justo después de haber hecho un montón de código, dejó de funcionar.

Tras un rato pegándome con ello, descubro que no podía llevar a cabo lo que pretendía. El caso es que Dart permite hacer llamadas a funciones y objetos Javascript sin ningún problema, y de una forma bastante cómoda, convirtiendo colecciones de una manera sencilla. También se le pueden mandar funciones Dart que sirvan de "callback" y se las llame desde JS. Sin embargo, la integración tiene una limitación importante, y es que no se puede llamar a objetos Dart desde código Javascript. Esto invalida por completo la posibilidad de usar un framework como es MelonJS, ya que en él todas las entidades del juego se definen como objetos a los que invoca el núcleo Javascript de la librería.

Un día entero perdido con la tontería. Y en realidad es culpa mía, porque lo ponía muy claro en la documentación. Odio los Lunes.

Problemas APIs HTML5
Como había oído que el sonido daba problemas, decidí usar la librería Howler para que ella se encargue de elegir el fichero de audio adecuado según el navegador, poniendo versiones de los sonidos en mp3, ogg y wav. En este caso al no tratarse de un framework no tuve ningún problema para encapsularla en clases Dart. Pensaba que con esto ya conseguiría que los sonidos y músicas sonaran en todos los navegadores modernos pero... craso error. Ni así. El tema del audio en los navegadores es un berenjenal de cuidado. He ido probando en varias versiones y nunca sabes si te va a funcionar o no, a veces incluso versiones del mismo navegador con muy poca diferencia entre ellas. Con Chrome por ejemplo, en Dartium no funciona la música pero sí los sonidos, y lo mismo en otras versiones de Chrome que he probado. Sin embargo, en mi Chrome y la mayor parte de versiones que he probado sí funciona también la música. En Firefox más de lo mismo, aunque aquí a veces me ha ocurrido lo contrario, que funcionaba la música pero no los sonidos.

Rendimiento
La verdad es que hasta ahora no he cuidado nada el rendimiento del juego, ni siquiera dentro de las limitaciones que pudiera tener usando Dart, pero aun así los resultados son curiosos. En Chrome en general el juego parece funcionar bastante bien, al menos en los ordenadores en los que he probado (imagino que en ordenadores antiguos le costará más). Curiosamente, parece que funciona igual de rápido en Chrome, es decir, ejecutando el código compilado a Javascript, que en Dartium, ejecutando el código de forma nativa. En Firefox, al menos en Linux, sufre mucho más, notándose mucha mucha diferencia según el tamaño del dibujo que se intenta averiguar. En Windows me pareció que funcionaba un poco mejor, aunque pudo ser por la máquina.

En el Chrome de mi tablet Android el juego funciona, justita de rendimiento, pero funciona. Parece sufrir bastante en cuanto tiene que usar cualquier sonido, lo cual me hace sospechar que los sonidos pueden ser causantes en buena parte de los problemas de rendimiento. Al final se acabó quedando colgado. En cualquier caso no me parece muy preocupante por el momento, porque como ya he dicho no he mirado todavía nada del rendimiento, y para la versión móvil probaré con el ya mencionado CocoonJS, que espero que no tenga problemas con el sonido (y si los tiene ya les vale).

Imagino que Dart debe estar ralentizando en general todo el código, y de hecho puede que la lentitud en Firefox sea por eso, aunque tampoco me extrañaría nada que fuera sencillamente un tema de rendimiento de las librerías HTML5, que no las veo demasiado optimizadas. Aunque la conclusión principal que saqué de charlas del GameMe5 es que el rendimiento de Javascript es muy muy muy sensible, y un pequeñísimo cambio puede causar de repente un gran aumento en la velocidad. En cualquier caso, en principio para este juego me vale.

Programando en Dart
Esperaba que Dart me diera algún problema: que las herramientas no funcionaran bien, que me encontrara con algún bug molesto en alguna librería, que no encontrara documentación sobre las librerías... Sin embargo, no ha sido así, todo ha funcionado como la seda.

El IDE funciona muy bien. A pesar de tener tipado opcional, hace una buena inferencia de tipos y permite autocompletar, buscar referencias, refactorizar o navegar por las clases incluso en variables sin tipo explícito declarado. Encontré algunos errores en esto, en cuanto a variables de las que de repente es incapaz de inferir el tipo aunque un rato antes sí lo hacía, pero lo considero errores menores e imagino que se arreglarán. También detecta errores de llamada a métodos o propiedades inexistentes, aunque al ser un lenguaje dinámico los marca como warnings en lugar de errores. Hubiera preferido lo segundo, pero me vale, e imagino que en el futuro permitirán esta opción.

Dartium, el navegador que incluye la máquina virtual Dart para ejecutar de forma nativa, funciona también muy bien, y el debugger tampoco me dio ningún problema. Incluso, me encontré alguna sorpresa agradable como que cuando el debugger te muestra los atributos de un objeto, te incluye también los valores de sus getters, es decir, de las propiedades que tenga que se calculan a partir de una función en lugar de devolver directamente el valor de una variable. Esto es comodísimo.

Me encontré muy cómodo también con el lenguaje. Me fastidia el que las reglas de estilo recomienden tabulaciones de dos espacios, que creo que hacen el código menos legible, y al venir yo de lenguajes de tipado estático me costó un rato hacerme a la idea de que no tenía por qué declarar tipos en variables locales (en propiedades de clases y parámetros de métodos yo que tú sí lo haría siempre). Todo lo demás me encantó desde el principio. No eché nada de menos al plasmar un diseño orientado a objetos, tiene sus clases, objetos, clases abstractas, e incluso modificadores de atributos interesantes para el control del código como const y final. Pero sobre todo el lenguaje tiene un montón de "azúcar sintáctico", con comodidades muy importantes como los getters/setters implícitos, las funciones lambda, los parámetros opcionales y/o nombrados en los métodos, los constructores con inicialización directa de propiedades con argumentos, el operador en cascada y el manejo de colecciones.

Las librerías estándar también son muy completas y están muy bien documentadas, existen clases para cualquier cosa básica que se te puede ocurrir a hacer y, también muy importante, se encuentra cualquier cosa muy rápido buscando en http://api.dartlang.org/. Si se quiere hacer algo más especializado (aunque a mi no me ocurrió), también existe un repositorio de librerías en el que es fácil buscar: http://pub.dartlang.org/ y gracias al gestor de paquetes incluido en Dart, pub, usar cualquiera de esas librerías es muy sencillo.

Lo más importante que puedo decir es que olvidé por completo la sensación de que estaba programando para el navegador. Creo que la separación entre programación "front" y "back", aunque tenga cierto sentido, es un poco artificial. Se ha hecho muy necesaria de unos años a esta parte en programación web porque programar para la parte cliente era un infierno, en el que contaba más conocer los truquillos y las compatibilidades en los navegadores que la programación real. Pero eso está cambiando mucho: con jQuery y demás librerías JS nos podemos olvidar de las incompatibilidades en el acceso al DOM, con Bootstrap (como ya comenté en otro artículo) y otras librerías de LESS y SASS nos podemos olvidar en buena parte de los dolores de cabeza con el CSS. Con Dart podemos dar un paso más y olvidarnos de la problemática de Javascript y sus librerías, comenzando a programar exactamente igual a como se hace en la parte back, al menos en mi caso, con un diseño orientado a objetos, con encapsulación, con librerías potentes, con tipado, con las facilidades de un buen IDE...


El resultado

Se puede acceder al juego online en esta direcciónhttps://googledrive.com/host/0B-qqsnsC2gHuS210TnQ4cENGSkk/index.html

Es completamente jugable, aunque sólo tiene 4 niveles y a veces le pasan cosas raras. Esta es la versión que presenté en la demo del Viernes de la PiWeek. Tampoco hay instrucciones, así que lo cuento aquí: botón izquierdo del ratón = negro, botón derecho = blanco (se ve como una X con sombras).

Mi intención es mejorarlo y convertirlo en un "juego de verdad". Se pueden hacer un montón de cosas, como:

  • Añadirle muchas más fases: una de las grandes ventajas (y también alicientes) de este juego es que añadir más fases es tan fácil como añadir un pequeño dibujo pixelado... y si empiezas a tirar del hilo de los juegos retro ¡hay un montón!. Tres de los cuatro dibujos de la demo están hechos así, uno de ellos incluso con un gráfico propio de un mono que era el sello de mi "marca" de juegos de Spectrum, ¡sniffffff!. ¿Reconoces los otros dos?.
  • Mejorar el código, sobre todo el loop principal del juego y la carga de recursos, ya que me basé en el código del taller de Gameme5 y no me gusta mucho cómo les quedó esta parte. Tengo localizada ya una librería para el loop y otra para la carga de recursos, ambas con buena pinta.
  • Versión para móviles (probando CocoonJS)
  • Modo "duelo" multijugador, que me permitiría también probar a hacer un mini servidor en Dart (y reutilizar clases de la parte cliente), y probar los WebSockets.
  • Conectarlo con Facebook y/o Google Play Games.

En definitiva: Dart me ha funcionado muy bien, HTML5 un poco más regular, y sobre todo me ha encantado la experiencia y me lo he pasado muy bien. Y lo mismo... hasta acaba saliendo como resultado un juego de verdad. Permanece atento a la pantalla.

Haciendo un juego en Android: lecciones aprendidas (2)

Después del primer capítulo que publiqué hace unas semanas, ya tenemos lo básico para hacer un juego en Android "a pelo". ¡Pero no nos conformamos con eso! Hoy contaré otras cosillas más que fui añadiendo a mi librería personal para el juego según iba avanzando.

Componentes gráficos

Para los que hemos trabajado con interfaces de ventanas, el diseño basado en componentes gráficos resulta muy natural. ¿Por qué no aplicarlo también a un juego?.

La idea es muy sencilla: hacer que el código de cada componente no tenga que preocuparse de coordenadas globales, ni de lo que ocurre en el resto del juego, sino que vive "en su propio mundo" y preocupado de sus cosas. Orientación a objetos pura, vaya. Así, la pantalla se va formando a base de componentes, unos dentro de otros, que acaban conformando todo lo que hay en el juego. Cada uno tiene su propia dinámica, y luego pueden reaccionar ante lo que hagan los otros.

Todas estas librerías tradicionales de componentes de ventanas, como las MVC del Visual C++, o la del Borland C++, o incluso las del más moderno SWT suelen tener un problema gordo en su diseño: abusan mucho de las subclases. Se puso de moda diseñar esto así, y como documentación de la librería aparecía, tachán!, ¡la jerarquía de clases!. O sea, todo el diseño estaba hecho en forma de jerarquía de subclasificación.

El caso es que a mi las subclases en general me dan un poco de urticaria. Los interfaces son mucho más limpios. Las subclases me gustan para reutilizar implementaciones por defecto o sencillas de los interfaces, pero poco más. Así que en lugar de hacer una jerarquía de clases como las de toda la vida (curiosamente Swing, con todo lo que se le ha criticado, está mucho mejor diseñada que todas las demás), me dediqué a darle unas vueltas más (y liar un poquito el tema, ya puestos).

¿Qué necesita cada uno de estos componentes?. Según vimos en la entrada anterior, lo mínimo que necesita cualquier entidad independiente del juego es:
  • Que sea capaz de reaccionar a eventos
  • Que sea capaz de actualizarse sola por cada unidad de tiempo
  • Que sea capaz de dibujarse
Además de esto, nuestros componentes gráficos necesitarán:
  • Una posición relativa a su componente padre
  • Un tamaño
Y por supuesto, necesitaremos entidades contenedoras, a las que podamos meter otras entidades dentro de forma relativa.

Así que hice un interfaz GameEntity para lo básico que tienen que tener todas las entidades de cualquier juego (los tres primeros puntos), y reservé dos interfaces para los otros dos: un Positionable y un Measurable. ¿Por qué usar interfaces para estos dos en lugar de beans?. Porque me puede dar más juego. Por supuesto, creo implementaciones beans que implementen esos interfaces, y un DelegateComponent que cree un componente a partir de una composición de objetos que implementen cada interfaz (y que no tienen por qué ser objetos distintos).

Una vez que te acostumbras a esta forma de trabajar, resulta comodísima, y sobre todo, muy potente. Este es el diseño resultante:




Animaciones, efectos y el estado

Cada objeto normalmente tendrá su estado e irá cambiando según las cosas que le ocurran. Eso ya dependerá de cada entidad. Sin embargo, hay algo que también es muy interesante facilitar, que son las animaciones y efectos. Aunque pueda confundirse, lo cierto es que estos se gestionan mucho mejor si se separan un poco del propio estado del objeto.

Por ejemplo, un personaje puede estar caminando. Su estado es "caminando". Sin que el estado cambie demasiado, se estará moviendo hacia la derecha. Y habrá una animación de caminar que irá cambiando sola cada X frames. Podríamos gestionar todo esto de forma explícita dentro de cada objeto, pero si lo facilitamos para que se declare desde el principio como funciona, nos evitaremos el tener que gestionar cosas incómodas como cuál es el frame actual que se debe mostrar.

Para eso, creé una clase AnimatedComponent, que decora cualquier otro componente. A este componente se le registrarán una serie de estados de transiciones o animaciones posibles, representadas con el interfaz Transition. Al registrar cada transición se indica cómo funciona: qué propiedades modificará, cada cuánto tiempo y qué ocurrirá cuando acabe (¿será cíclica?, ¿se quedará en el estado en el que estaba?, ¿desaparecerá el objeto?). Estas transiciones son las que se ocupan de hacer efectos y transiciones sin que el objeto tenga por qué preocuparse mucho por ello.

Como ejemplos de transiciones están las animaciones de gráficos, movimiento, efectos de "fade", cortinillas... A pesar del tinglado anterior del diseño de componentes por interfaces separados, lo cierto es que en la práctica casi todos los objetos utilizarán un bean para la posición. También bastantes para el tamaño, aunque no tantos, ya que muchas veces puede depender del tamaño de su bitmap o de su texto, por ejemplo. Por supuesto, también las animaciones es lógico que vayan con una propiedad explícita... en definitiva, una de las transiciones más sencillas que podemos hacer es que automáticamente se vaya incrementando o decrementando el valor de una propiedad del componente. De aquí surgió la clase BeanPropertyTransition. Para controlar de forma independiente a qué ritmo se va modificando el valor de la propiedad, se hace que utilice un interfaz IntPropertyChange, con una implementación sencilla que aumente el valor de la propiedad de forma lineal, es decir, de forma constante en el tiempo.

Así quedó el diseño:


Agrupando objetos "globales"

En las primeras versiones del juego, los constructores de los distintos objetos cada vez eran más grandes. Había una serie de objetos, digamos, prácticamente globales, que se podían utilizar casi en cualquier sitio.

Dos de ellos son clases que creé para encapsular, facilitar y/o mejorar el rendimiento de la reproducción de sonido: SoundManager para efectos de sonido, y Jukebox para música. A ellos se les suma el necesario Context de Android, con el que se cargan todos los recursos, y que face falta básicamente en... todos los sitios donde haga falta un recurso. Y otros que iban apareciendo y desapareciendo según se iba refinando el diseño, como por ejemplo una clase que facilita la carga de Bitmaps.

La solución en este caso es muy clara, encapsular todos estos objetos, que además son genéricos y valen para cualquier juego, en una sola clase GameContext, que permita acceder a ellos. Así, sólo será este objeto el que habrá que pasar a todos los demás (junto a otros objetos del propio juego que potencialmente también harán falta). Además, si en algún momento aparece otro objeto del sistema que nos venga bien de forma global, se puede añadir también sin tener que tocar todas las demás clases para que se lo pasen de unas a otras.

Esto parece una tontería, pero lo cierto es que si no se tiene un poco de cuidado, en un juego es muy fácil acabar con miles de objetitos que se van pasando a troche y moche de unos a otros, y eso se convierte en un caos. También hay que tener mucho cuidado de no mezclar churras con merinas, y no encapsular dentro del mismo objeto todo lo global que pueda necesitar el juego. Una cosa son estos objetos que pueden hacer falta en cualquier juego y son, digamos, del sistema y sus recursos, y otra muy distinta meter también por ejemplo los objetos que controlen la dinámica del juego concreto.

En nuestro caso, este es el diseño que quedó:



Acabando, que es gerundio

¡Buah, menudo coñazo de serie que me he marcao! Todavía el primer capítulo tenía su aquel, pero en este me he metido más bien en detalles de diseño e imagino que ha quedado bastante espeso. Y no he puesto chistes ni chorradinas ni ná. Así que nadie estará leyendo esto ya, ¡snif!.

El mensaje fundamental de todo esto es el primero que di: si estáis dudando en poneros o no a hacer un juego con Android, no lo dudeis: hacedlo. Es muy agradecido, con poco que hagáis van saliendo cosas. La librería de Android es genial, da muchas facilidades. Es más, yo hay cosas en las que me he complicado la vida porque he querido, porque lo cierto es que creo que algunas de las cosas que he hecho yo están ya en la propia librería estándar de Android. Y eso por no hablar del resto de librerías que existen para hacer juegos. Simplemente, me apeteció hacerlo así. Y ojo, mientras refinaba un poco la librería me dio tiempo a hacer otro juego, un Reversi (este ya no lo voy a publicar, porque Reversis hay montones y seguro que juegan mejor que el mío, que es un pobre patán...).

El secreto de todo esto de hacer juegos para móviles, lo que lo hace genial, es que es pequeño. No necesitas dedicar meses y meses de tu vida para hacer un juego. En una tarde ya ves avances. Cada tarde que te pongas haces algo, consigues algo nuevo. Es muy gratificante. Estoy convencido de que los juegos pequeños tienen su espacio, que no todo tienen que ser grandes producciones. Dan más pie a la imaginación, a la innovación, a atreverse a hacer cosas que pensabas que no iban a salir... en definitiva, ¿a qué estás esperando?, ¡¡¡ponte ya a hacer tu juego, leche!!!.



Bola extra

Has intentado entender el artículo. Realmente lo has intentado. Te lo has leído de principio a fin, has imprimido los diagramas en grande para seguir las flechitas, has buscado por ahí a ver qué leche es esa mierda de los componentes gráficos... y eso sólo te ha desorientado más aún. Finalmente, has llegado a una conclusión ineludible: ¡no hay dios que entienda este artículo!

Pues bien, aprovechando que hoy es el "día Somos", que propone darle la vuelta al mundo, he apoyado la causa y he hecho una nueva versión del mismo en la que le he dado la vuelta por completo. Jamás la Informática había sido tan sencilla, jamás algo complejo se había visto de una forma tan clara. Jamás había sido tan fácil conseguir que cualquier no iniciado puede comprenderlo con facilidad.

No te pierdas la versión revisada del artículo. De repente verás la luz y lo comprenderás en toda su extensión.

Haciendo un juego en Android: lecciones aprendidas (1)

Uno de los principales motivos por los que hace unos meses me puse con el desarrollo del West Bank es porque tenía ganas de empezar a aprender algo de Android. Android te permite algo que ya se había perdido un poco, y es que puedas hacer una aplicación más o menos pequeña, pero que a la vez esa aplicación sea publicable e incluso sea útil. Y en algunos casos, hasta te haga ganar dinero. Para los que no tenemos casi tiempo libre eso es genial, claro. En este artículo cuento un poco algunas de las cosas que me fui encontrando y lecciones aprendidas..

Hacer juegos con Android es muy fácil. Incluso sin librerías

Esta es seguramente la conclusión más importante que he sacado, algo que por otra parte ya me imaginaba. En mi caso, comencé primero buscando un poco alguna librería / framework / engine de desarrollo de juegos que me facilitara la vida. La idea es que fuera una librería sencillita y enfocada al 2D, nada de polígonos ni historias. La primera que vi fue Rokon, que tenía buena pinta y encajaba en lo que buscaba, pero el autor recomendaba no usarla (imagino que acabó cansado de responder emails de gente haciéndole preguntas). Como el objetivo era complicarse la vida lo menos posible y hacer el juego rápido, la descarté.

Entonces miré libgdx, que es una librería multiplataforma. Eso es una ventaja evidente, pero a la vez para este caso también es una desventaja, porque el objetivo con el que empecé era aprender algo de Android. Cuando me di cuenta de esto, y llevándome eso a descartar sin apenas mirarlas otras librerías con muy buena pinta como AndEngine, pensé: "¿Y si lo hago directamente usando las librerías nativas de Android?".

Buscando por Internet encontré este buen tutorial de introducción de JavaCodeGeeks. Y sólo mirándolo por encima ya vi que Android de serie te da enormes facilidades para manejar gráficos, sonidos y eventos táctiles. Por otra parte, para el juego que nos ocupa no iba a necesitar ningún tipo de aceleración gráfica OpenGL ni otras mandangas de optimizaciones. Así que decidido: no usaría ninguna librería, haría la mía propia basada en la librería estándar de Android.

Gráficos en pantallas con distintas resoluciones

Esto ha sido seguramente lo que más quebraderos de cabeza me ha dado. Y lo cierto es que si lo entiendes bien y no te metes en líos, tampoco es algo que tenga por qué darte problemas. En Android a priori no sabes cuál es el tamaño de la pantalla, ni tampoco sus proporciones (screen ratio), y tienes que intentar que en todas ellas el juego se vea lo mejor posible.

Esto implica redimensionamiento de tres elementos: los gráficos, las posiciones en los que pintas los gráficos y los puntos en los que se detectan los eventos táctiles. De primeras solucioné esto creando una clase (más bien cutre) PointTranslator, con un objeto que le pasaba a todos los demás objetos del juego y al que llamaba cada vez que quería traducir una posición o pintar un bitmap.

Para solucionar el problema de las proporciones de pantalla puse unas franjas negras en la parte que sobrara de la pantalla. Otra solución hubiera sido alargar el bitmap, pero prefería no distorsionar las imágenes. Mi resolución estaba clara, como utilizaba directamente los gráficos del ZX Spectrum, la suya sería la resolución que iba a usar: 256x192 (con proporción 3:4).

Cuando ya tenía algo que pintaba los gráficos y detectaba las pulsaciones en su sitio, me di cuenta de otro problema: según el móvil en el que cargabas los bitmaps, ¡el propio bitmap podía tener un tamaño diferente al real!. Por lo que vi, esto dependía de otro parámetro: la densidad. Esto afecta sobre todo a la carga de sprites. Una de las típicas técnicas en los juegos es meter todos los gráficos de un personaje en un solo fichero. Al dibujar uno de ellos, se dibuja sólo la parte del gráfico que corresponda. Al no tener el bitmap el tamaño que se suponía iba a tener, esto se desmadraba. Ale, otra chapuza a meter al "soluciones todo-en-uno" PointTranslator.

Otro problema que tuve con esto fue el del redondeo. Normalmente los bitmaps se cargaban en su tamaño o en un tamaño múltiplo. Pero, ¡ay!, no siempre es así. Concretamente, el Nexus 7 carga los bitmaps en una escala extraña. Esto hace que en bitmaps con muchos gráficos, el redondeo fuera importante y no se cargaran bien. Concretamente, el problema era muy evidente en las fuentes bitmap que usaba para escribir los textos. Vuelvo a tocar (¡cómo no!) ese maravilloso PointTranslator para que use coma flotante para estas cosas y listo.

Lo cierto es que estos dos últimos problemas: carga de bitmaps y redondeo no tienen por qué existir. Los cuento porque creo que puede ser interesante saberlo, pero la verdad es que desde el principio fue por una metedura de pata mía. Como todo el proyecto lo he ido haciendo sobre la marcha y sin documentarme debidamente, ya que lo más importante era ir avanzando y obtener cosas funcionando lo más rápido posible (doctor, ¿me habré hecho "ágil"?), cuando probé a meter el primer gráfico lo hice en la carpeta "res\drawable-mdpi". En mi ignorancia, pensaba que estas carpetas ldpi, mdpi, hdpi servirían para cargar gráficos más o menos grandes según la resolución de tu dispositivo, y que si sólo encontraba un gráfico en una carpeta cargaría ese y ya está. Craso error. Lo primero es que no es eso lo que significan esas carpetas, no funcionan según la resolución de pantalla (en cuanto a número de pixels), sino en cuanto a la densidad, es decir, los puntos por pulgada del dispositivo. Es decir, el objetivo de usar esto es, por ejemplo, que se vea más o menos igual de grande (en cuanto a tamaño físico) un gráfico cargado en un tablet que cargado en un móvil con resolución alta o en otro con resolución baja. En definitiva, nada que a priori nos interese ni lo más mínimo cuando estamos haciendo un juego. Para más información, tenéis el artículo oficial sobre el tema (un poco ladrillete, pero es que esto es así...). ¿La solución a esto?. Muy fácil, una de estas:

  • Meter los gráficos en una carpeta drawable-nodpi
  • Si queremos cargar diferentes gráficos según la resolución de pantalla, usar carpetas de recursos drawable que dependan del tamaño en píxeles: small, normal, large, xlarge
  • Meter los gráficos como assets en lugar de como resources. Esto, además, nos permite componer de forma dinámica el nombre del bitmap a cargar, o de su carpeta

Esto último es por lo que me he decantado yo, ya que quiero cargar distintos gráficos según la configuración del juego: versión ZX Spectrum, o nueva versión con gráficos HD... ¡pronto en sus kioskos!.

De hecho, esto último me ocasiona un nuevo problema: los gráficos del juego tendrán distintos tamaños, posiciones y hasta resoluciones diferentes según su configuración. Esto me ha llevado a hacer una refactorización, eliminando alguna chapucilla y mejorando el diseño de las clases para facilitar esto. Y sí, tuve que tomar la difícil decisión de eliminar mi clase-bombero... es decir... el PointTranslator ha muerto (¡viva el PointTranslator!).

Por lo pronto, en lugar de redimensionar todos los puntos sobre la marcha dentro del propio juego, ahora lo que hago es pintar todo en un buffer intermedio, que tiene el tamaño exacto de la resolución del juego. Al terminar de dibujar todo, se pinta redimensionado en el buffer de pantalla. Para encapsular todo esto he creado una clase Camera. Cada vez que el controlador del juego quiere pedir a los objetos que se dibujen, llama a la cámara para que devuelva el Canvas (la clase estándar Android donde se pintan cosas) bien configurado. Al terminar todos de dibujar, vuelve a llamarle para que lo plasme. De esta forma, toda la complejidad del proceso se queda en las clases genéricas de mi librería, y las clases específicas del juego se despreocupan totalmente de los problemas de resolución, ellas trabajan siempre con las dimensiones que marque el juego y ya está.

Todavía me he encontrado con un problema, que ha sido a la hora de traducir las posiciones de los eventos táctiles. Para estas cosas, Android tiene una clase, MotionEvent, que la verdad es que me gusta bastante tal cual está y por tanto no tenía intención de crear otra nueva para lo mismo. Pues bien, resulta que la clase MotionEvent no permite reescalar ni modificar sus posiciones. Bueno, a partir de la versión 11 del API sí, pero quiero que el juego funcione en versiones de Android más antiguas. Lo solucioné creando mi propia clase GameMotionEvent, que utiliza el patrón de diseño delegate para encapsular la clase anterior, proporcionando un interfaz igual y llamando en cada método al equivalente a la anterior, haciendo las pertinentes traducciones de puntos cuando hagan falta a través de la clase Camera.

El bucle principal: con cuatro cosillas lo haces, ¡pero cuidado!

Como bien sabrás si has hecho un juego alguna vez, el bucle principal (el game loop) supone la estructura fundamental de cualquier juego. Es un bucle "infinito" de tres pasos: procesar entrada, actualizar estado de los objetos, dibujarlos (aunque en realidad lo de procesar la entrada no tiene por qué ir estrictamente en ese orden y se puede hacer más bien en forma de eventos). Y hacerlo además de forma que cada ciclo se haga en el mismo tiempo, gestionando condiciones como que si tardamos más tiempo de lo que deberíamos en hacer un ciclo, nos podamos saltar pasos de dibujar para que todo vaya lo más suave posible, y si tardamos menos, esperemos un ratito hasta que quede cuadrado. En realidad todo esto está muy bien explicado en el tutorial que enlacé antes, especialmente en un capítulo en el que se da un bucle básico y en otro posterior donde se mejora la implementación. Como digo en el título, hacer un bucle principal es muy sencillo teniendo en cuenta cuatro cosas que son muy conocidas y que este tutorial cuenta muy bien. Pero ojo, ¡es muy importante tenerlas en cuenta!.

Lo que no me gusta tanto del tutorial es el diseño de clases que se da en su implementación, ya que me parece bastante "sucio", haciendo que la clase principal herede directamente de Thread y obligando además al que la use a extender directamente esta misma clase para poder hacer una implementación para un juego concreto. Así que decidí cambiar este diseño y hacer uno más genérico, con una clase limpia GameController que se pueda invocar fácilmente desde el Activity y que use el thread de forma interna. Incorporé las clases Camera y GameMotionEvent que he contado en el punto anterior, para el escalado de los gráficos. Y para permitir la implementación concreta de los objetos creé primero un interface básico GameEntity, con lo mínimo que se necesita para pintar un objeto y que reaccione a eventos. Luego creé otro extendido Scenario, que me pareció interesante para facilitar la creación de "partes" del juego completamente diferenciadas entre sí.

Este es el diseño que quedó:



Continuará...

Y hasta aquí por hoy mis historias programando el juego en Android. Haré un capítulo más, en el que contaré otros refinamientos que he hecho en el diseño, sobre todo para poder tener un sistema sencillo de componentes gráficos y otras cosas como animaciones y efectos. En breve aquí mismito.


West Bank: Crónica RetroMadrid 2013

Antes que nada, os presento al gran campeón del concurso, y ganador de la exclusiva camiseta de West Bank, con una impresionante puntuación de 196,900 puntos... ¡ARQUILLOS!

Arquillos, campeón del concurso West Bank

VTC con la camiseta de Ardent Monkey
También estuvo presente VTC, el segundo clasificado, con una puntuación de 144,910 puntos. VTC por su tenacidad y también gran puntuación, ganó un improvisado segundo premio, una camiseta de Ardent Monkey Games. Como anécdota, comentar que VTC hizo esta gran puntuación sin pasar de la fase 1, ya que no se había dado cuenta de que se podía mover de unas puertas a otras para pasar de fase (error nuestro, en realidad, ya que sólo se explica en la página del Play Store pero no dentro del juego). De hecho, el propio Arquillos nos comentó que para conseguir su máxima puntuación decidió no pasar de fase adrede y se quedó en la segunda, para conseguir ahí el mayor número posible de puntos.
VTC: "¡Así es más divertido!"

La experiencia ha sido muy gratificante, mucha gente pasó por el stand y nos comentaba que le había gustado mucho la conversión y que el juego seguía siendo un vicio a pesar de los años transcurridos. También hemos recibido mensajes del mismo estilo por otros medios, como Twitter, email o el propio Google Play. Incluso gente comentándonos que sus hijos y sobrinos pequeños (¡7 años!) estaban viciándose con el juego. ¿Los clásicos nunca mueren?.


"Foto de familia": los dos primeros clasificados, y Adr y yo haciendo el ganso

Por otra parte, tuvimos un visitante especialmente ilustre en el stand... ¡¡¡Álvaro Mateos, el creador del juego original!!!. Muy majete, y algo sorprendido por todo lo que estábamos montando, me estuvo enseñando la versión que hizo para iPhone (también hay otra para Windows Phone) y que está muy muy bien, con lo cual entre él y nosotros tenemos bastante cubiertos la mayor parte de dispositivos móviles. Añado que una de las preguntas que más nos hizo la gente en el stand fue si íbamos a hacer versión para iPhone. No, no vamos a hacer versión para iPhone, ya está hecha, es esta versión hecha por el propio Álvaro, está disponible en el Apple Store, y el interfaz es muy muy similar a la nuestra (tiene cosas de su propia cosecha, como la carga del juego en cassete). Más información en su web.

Álvaro y yo (y una luz al fondo para que no se vea nada,
¡ya le daré lo suyo al fotógrafo!)

La verdad es que no nos podemos quejar nada de la acogida del juego, en una sola semana desde su presentación lleva ya alrededor de 250 descargas, y ahora mismo la han puntuado en el Play Store 13 personas y todas le han puesto un 5 (la máxima puntuación). El concurso también ha sido un éxito, al principio me cortaba para no hacer puntuaciones demasiado altas y copar yo el top, y ahora ya ni estoy entre los diez primeros... ¡algo que pienso remediar los próximos días, cagontó!


Stand de Ardent Monkey
en RetroMadrid
Por otra parte, muchas publicaciones "retro" se han hecho eco del remake, ¡muchas gracias a todos!:

Tabla de puntuaciones al acabar el
concurso. ¡Impresionante!
Aparte de esto, la RetroMadrid en sí estuvo genial, hacía años que no estaba y me lo pasé realmente bien, muy bien la organización y muy buena calidad en general en el resto de expositores, con mucha presencia de máquinas arcade y "bartop" (a las que miro con deseo aunque al final me contuve y no llegué a comprar ninguna), y muchos imancitos, llaverillos, posters y demás coñas que tanto nos gustan a los retro-frikis. Muy buena la experiencia de compatir expositor con los amigos del CAAD, y genial haber conocido al gran Andrés Samudio (y muy buena su charla, intentando no caer en tópicos).

¿Y ahora?. Nuestro próximo reto es hacer que el juego sea atractivo para las nuevas generaciones, es decir, para la gente que no jugó ni conoció el juego original, ni tampoco le atrae especialmente la estética retro. Creo firmemente que la dinámica del juego es perfectamente válida para el público general, y vamos a intentar demostrarlo.

Para eso, estamos preparando una versión con nuevos gráficos hechos de cero y nuevos sonidos y músicas. Bueno, y con ayudas para que quede clarito cómo moverse entre las puertas, ¡sigh!.

Permaneced atentos al Play Store, cualquier día de estos puede aparecer una actualización del juego con la que podréis sentiros seguros para enseñársela a vuestros amigos, hermanos, padres, abuelos, hijos, sobrinos... y hasta a vuestr@s churris, sin que os miren con cara rara, en plan "que ya tienes una edad... ¡CRECE!".

CONCURSO West Bank RetroMadrid

Saca la mayor puntuación en el remake de West Bank para Android, ¡y gana una estupenda camiseta!.

¡¡¡YA puedes empezar a participar, dale caña!!!

La camiseta se recogerá en la RetroMadrid este mismo Sábado. ¿A qué estás esperando?. ¡No dejes ni uno vivo!




Más información sobre el proyecto y su desarrollo aquí.

Proyecto: West Bank Android

En las últimas entradas, todas muy retro, he ido dejando pistas de que tenía un proyecto en marcha. Pues bien, hoy toca desvelarlo.

Durante estos últimos meses he estado programando... ¡¡¡un remake del WEST BANK para Android!!!.

El juego original

Corría el año 1986. La compañía española pionera por excelencia, Dinamic, estaba empezando a expandirse. Los hermanos Ruiz habían decidido no publicar sólo sus propios juegos, sino promocionar también juegos programados por otras personas. Los tiempos eran muy distintos a los actuales. Triunfaban los ordenadores de 8 bits (que normalmente se usaban como el equivalente a las consolas actuales), como el ZX Spectrum, el Amstrad y el Commodore, pero no existía prácticamente una industria del videojuego en España para ellos. Los juegos los hacía, normalmente, un adolescente en su casa, él solo o con un grupete de amigos.

Los hermanos Ruiz habían demostrado desde el principio una gran habilidad para publicitar sus juegos. Ese mismo año habían tomado la que probablemente fue su decisión más importante: encargar al gran Alfonso Azpiri que les hiciera las portadas. Gracias a esto, estoy seguro de que a mucha gente le sonará la estupenda portada del juego incluso aunque no llegara a jugarlo en su día. [Azpiri sigue en activo y en buena forma, actualmente y junto a Forges está publicando una original y divertida línea de adaptaciones al comic de libros de terror que os recomiendo, Horreibols and terrifics books].

Rocky fue el primer  juego cuya portada hizo Azpiri. Y a su vez, también fue el primer juego que publicó Dinamic hecho por un programador externo: Álvaro Mateos. Pocos meses después, programado por el mismo Álvaro y con portada del mismo Azpiri, aparecía el juego que nos ocupa: West Bank.

Al ser la programación tan artesanal, era bastante habitual que para inspirarse el programador se basara en una máquina recreativa (o directamente la copiara), ya que ellas sí que tenían una poderosa industria, con compañías grandes detrás como Sega y Nintendo. En este caso, el juego es un clon de la recreativa de Sega Bank Panic, aunque debo decir que las sensaciones al jugar uno y otro, dentro de sus parecidos, son bastante distintas. Además, el West Bank incorporaba cosas de su propia cosecha, como los duelos de final de fase.

El juego (tanto la recreativa como el que nos ocupa) era más simple que el mecanismo de un chupete. En resumen, tienes tres puertas que se van abriendo, si el personaje que aparece detrás te apunta con una pistola le disparas, si no lo hace le dejas tranquilico y te dejará una bolsa con dinero. Cuando haya dinero en las 12 puertas del banco, se pasa a la siguiente fase. Es un juego que prácticamente ya estaba anticuado cuando salió en su día, no olvidemos que para entonces ya habían salido virguerías como el Knight Lore, el Great Escape, el Cobra, el Batman o el Three Weeks in Paradise, todos ellos infinitamente superiores técnicamente.

¿Entonces?, ¿cuál es la gracia de esto?. Muy sencillo. A pesar de lo dicho antes, el juego triunfó porque... ¡¡¡es un juego DIVERTIDÍSIMO!!! 

El equipo: Ardent Monkey Games

Ahora damos un salto al presente, o sea, "ventimuchos" años después. Probablemente no conocéis a Muriel (@jdmuriel), pero creedme si os digo que si tuviera tiempo libre para hacer un 1% de las ideas que se le ocurren continuamente... el mundo se acabaría. Normalmente busca ideas para hacernos ricos, que yo siempre le chafo, pero un buen día se le ocurre otra cosa: "¿Sabes qué juego estaría muy bien para móviles?. El West Bank".

No es una idea que vaya a hacer a nadie precisamente rico, pero hay algo que es indudable: es un juego perfecto para interfaz táctil. No tienes que hacer una conversión chunga con una de esas crucetas dentro del juego que tanto se están usando. Cuando quieras disparar a un tipo, le das con el dedo. Simple.

Además, es un gran juego para partidas "a ratos". Para echar una partidilla mientras vas en el metro o esperas al pesado de tu amigo el tardón.

Por otra parte, llevaba ya tiempo con ganas de hacer algo en Android. La programación para móviles, todavía aunque cada vez menos, es lo que siempre me hubiera gustado que existiera cuando era estudiante. No entiendo cómo a día de hoy los aspirantes a informáticos no hacen programas o juegos en Android. Con el tiempo que le dedicaba yo a alguna basurilla de esas que hacía con el BASIC del Spectrum cuando tenía 13 años, podría haber hecho perfectamente juegos en el móvil, y más aún, encima se moverían con suavidad y serían perfectamente jugables. Incluso se puede conseguir algo de dinerillo si te lo curras bien. Ni te digo ya en la universidad. En fin, todo esto ya lo expliqué en mi entrada de presentación del blog, programar ahora es para nenazas.

El caso es que al final, a pesar de mis dudas por eso de que yo tampoco tengo casi tiempo libre, me convenció.

Por último necesitábamos un grafista. Aunque inicialmente usaríamos los gráficos originales del Spectrum, la idea es que también hubiera otros gráficos nuevos. Y además necesitaríamos dibujos o diseños para otro tipo de cosas, como por ejemplo... el propio logo del equipo.

Por suerte convencimos también a mi hermano, el gran Adr, que es un dibujante acojonante. Aquí por ejemplo podéis ver una serie de tiras cómicas que hizo hace tiempo (y que estaría bien que algún día continuara, la verdad): Operación Dragón... bueno, va, os pongo aquí un par de ejemplos, que mola:



Así, el equipo estaba formado. Tras arduas deliberaciones, decidimos llamarnos Ardent Monkey Games.


El remake

Me complace anunciaros que el remake ya está listo y está disponible en el Google Play Store, completamente gratis.




Los gráficos son estos que veis aquí al lado. ¿Ein?, diréis, ¡pero si esos son los de Spectrum!. Pues sí, la versión disponible actualmente es un calco del juego de Spectrum, con sus mismos gráficos y sonidos.

Las diferencias son: el interfaz táctil, que la puedes jugar directamente con el móvil, y que tiene una tabla de puntuaciones global en un servidor, que comparten todos los jugadores, y con la cual los piques están asegurados. Ya sé que esto hace que el juego sea sobre todo apto para el mundillo retro, pero en poco tiempo saldrá otra versión en la que permitiremos seleccionar el "skin" original o la versión con los nuevos gráficos y sonidos, con lo que el juego será más atractivo para el gran público que no ha visto un Spectrum en su vida.

En resumen, las similitudes con el caso del West Bank original son muchas... es una copia descarada de un juego anterior... lo han hecho unos chalaos en su casa (aunque ya no demasiado adolescentes [ejem])... y lo más importante de todo... ¡¡¡sigue siendo DIVERTÍDISIMO!!!


P.D.: En pocos días os cuento más, que tenemos una sorpresita preparada para la RetroMadrid de la semana que viene...

P.D. 2: Desde aquí, me gustaría también agradecer su amabilidad a Álvaro Mateos, ya que le comentamos nuestra idea de hacer un remake y nos dio sus bendiciones. ¡Álvaro, eres grande!