ES KAsi UN blog

Blog de Unkasoft, donde hablamos de programación de juegos para móviles, advergaming, marketing móvil, la industria de los videojuegos, metodologías ágiles y todos aquellos temas que nos preocupan en nuestro día a día

30 marzo 2006

El proceso de construcción

Hace ya varios años, leí un artículo en Joel on Software que hablaba de las compilaciones diarias. En aquellos tiempos me sonó a chino, cuando pensaba que la compilación de un programa no era más que seleccionar la opción "Project - Build" de mi IDE.
Sin embargo, con el tiempo me he ido dando cuenta de que no tiene nada que ver la "compilación del programa" con la "construcción del producto", aunque los dos deberían hacerse con un único paso.
Compilar un programa no es más que transformar código fuente en código ejecutable, y eso es un trabajo repetitivo y mecánico (aunque bastante complejo) resuelto por el compilador, que para eso se inventó.
Sin embargo, contruir un producto supone mucho más. Por ejemplo, en nuestro caso, para construir El Cuarto Sello tenemos las siguientes tareas:
  1. Compilar el motor abstracto de Battlewizard.
  2. Compilar la implementación específica para el móvil que queremos utilizar: MIDP 2.0, nokia, etc. (Por cierto, tenemos pendiente hablar en detalle de Battlewizard y de su arquitectura).
  3. Incrementar la versión actual y crear el archivo de manifest
  4. Empaquetar todo eso en un archivo JAR.
  5. Compilar el código fuente del juego, utilizando los recursos (gráficos, sonido, cadenas de textos, etc) específicos para el dispositivo e idiomas destino.
  6. Lanzar las pruebas unitarias de todo el código (con JUnit y J2MEUnit)
  7. Ofuscar todo (con ProGuard o RetroGuard, dependiendo del caso).
  8. Optimizar y comprimir el bytecode (con librerías específicas para ello)
  9. Crear el archivo JAD, indicando el tamaño del archivo JAR, nombre del MIDlet, etc.
Casi nada.
Por otro lado tenemos la construcción de Battlewizard, que tiene sus propios pasos, bastante distintos, sobre todo porque Battlewizard tiene una aplicación de escritorio con su propio instalador, generación del archivo ejecutable, etc.
No sé si me dejo algo, pero más o menos nos hacemos a la idea.

Todos estos pasos que hemos descrito forman el proceso de construcción de nuestro producto, sin embargo, nos falta algo importante: automatizarlo. Pues sí, la gracia de todo esto está en que el proceso de construcción sea:
¿Y porqué todo esto? Pues muy sencillo: porque cuando más automaticemos nuestro proceso de construcción, más preparados estaremos para sacar nuevas versiones, en un solo paso, y asegurándonos que son realmente nuevas, y no "medio nuevas".

Otro beneficio es que, construyendo completamente el producto y de forma periodica, conseguimos detectar código erróneo muy pronto. Supongamos que una de nuestras librerías lleva sin modificarse meses, y cuando vamos a compilarla y lanzar sus pruebas unitarias, falla por todos los lados. Si todos los días o semanas hubieramos compilado y probado esa librería (junto con el resto del producto), ese error lo habríamos detectado muy pronto, pocas horas o días después de que alguien lo hubiera cometido, y sería mucho más sencillo corregirlo.

Y por último, haciendo construcciones automáticas conseguimos que cualquier persona, incluso aunque sólo lleve unos días en el equipo, sea capaz de generar el producto. El proceso ya se encargará de obtener los ficheros de donde sea, de hacer las copias necesarias, modificar nosequé librerías, etc. pero de cara al usuario, todo se hace en un sencillo paso.

Bueno, mañana hablaremos de la famosa "integración continua" que recomiendan las metodologías ágiles como eXtreme Programming.

Mientras tanto, podéis leer más sobre el tema en estos artículos que no tienen desperdicio:

Etiquetas:


24 marzo 2006

El tamaño no importa

Esta semana nos ha tocado ir de conferencias: el martes en los Tech Days de Sun y ayer en la presentación de un nuevo producto para la gestión de la configuración.
El caso es que, mientras los distintos ponentes contaban sus historias, presentaban sus productos y demás, yo me iba dando cuenta de lo difícil y distinto que es programar juegos para móviles. Que si bases de datos relacionales, que si frameworks de mapeado R/O, arquitecturas basadas en servicios web, AJAX, OpenGL... y mientras tanto nosotros pegándonos con los desplazamientos de bits, o haciendo malabarismos para evitar esos dichosos arrays de 3 dimensiones que hacen que el heap explote.
Y es que, como bien decía Joel, aunque todos los programadores nos dediquemos a programar, los mundos en los que nos movemos son radicalmente distintos.

Os voy a contar un caso nuestro, que ya ha comentado Jaime por encima: nuestros juegos son bastante grandes, sobre todo teniendo en cuenta las capacidades de algunos móviles que soportamos. Por poneros en situación, El Cuarto Sello tiene 12 niveles y 9 tipos distintos de enemigos. Esto lo pone al nivel de muchos juegos de PC, pero metido en un móvil con 500 KB de memoria. Esto nos obliga a exprimir al máximo la memoria del teléfono, y como decía Jaime, hay muchas cosas que están en el heap cuando no estaba previsto que estuvieran.

Si te dedicas a programar aplicaciones de escritorio o servidor, seguramente no te habrás parado a pensar si estás desperdiciando espacio en la memoria. Te bastará con que no haya memory leaks y que el consumo de memoria no se dispare, pero da un poco igual si es posible ahorrar algunos KB, o si tenemos más cosas en el heap de las estrictamente necesarias.
Sin embargo, en nuestro caso sí que importa, y mucho.

Una de las cosas que teníamos en memoria y nos estorbaba eran las instrucciones ejecutables (bytecodes) de algunos métodos. Tenemos mucho código de preproceso, que se encarga de crear imágenes en memoria, leer datos de disco, ordenar listas, descomprimir datos, etc. y todo ese código sólo se ejecuta una vez, en el arranque del juego, por lo que nos lo queríamos quitar de encima una vez que se había ejecutado.
Pero... ¿cómo? Java (y mucho menos J2ME) no ofrece mecanismos para descargar de memoria cierta parte del código... bueno, no hay mecanismos directos, aunque no está todo perdido.

La solución que usamos pasaba por juntar todo ese código "de usar y tirar" en una única clase. Cuando se crea la primera instancia de esa clase, se meterá en el heap todos los bytecodes, y cuando se libere el último objeto de esa clase (y el recolector de basura entre en acción) todos esos bytecodes desaparecerán del heap. Sencillo, y lo mejor de todo es que funciona. Sacando gráficas de consumo de memoria de la aplicación (como la imagen de más arriba), se puede ver un par de descensos bruscos en el consumo de memoria. Se trata del momento justo en el que liberamos la última instancia de la clase de carga y forzamos la llamada al recolector.

Y es que, como se suele decir, el tamaño no importa, ¡¡excepto si programas juegos para móviles!!

Etiquetas: ,


23 marzo 2006

Circulo vicioso

Una vez más el problema de la memoria del HEAP y del tamaño del paquete JAR (J2ME) con los recursos. Uno de los mayores problema que tenemos cada día con los teléfonos móviles más pequeños es que no nos vale comprimir al máximo los archivos que se instalan, porque aunque eliminemos la problemática del límite de tamaño de instalación, nos chocamos con el límite de memoria RAM (heap) disponible.

El verdadero problema con la memoria en los teléfonos móviles es que nunca dispones de lo que esperas. Te dicen que tienes n KB para usar de heap, pero nunca cuentas con que tus imágenes comprimidas (PNG…) se tienen que descomprimir y ocupan como un bitmap, que tu archivo JAR se descomprime también, que tus clases java se tienen que cargar en memoria y claro, cuando ejecutas, te comes mucha más memoria de la esperada.

Al final, la solución es cuestión de equilibrio. Si bajas el tamaño del paquete JAR comprimiendo al máximo, y no controlas el contenido, al descomprimirse te encontrarás con una limitación de HEAP. Lo mejor es pensarlo desde el principio, con todos los recursos y el orden en que los vas a manejar en memoria y a destruirlos.

Voy a enumerar una serie de reglas, creo que importantes, que usamos a la hora de evaluar el HEAP que estamos usando con los recursos y que nos están dando buenos resultados:

1 Nunca pienses en el tope de memoria de HEAP especificado por el fabricante. Siempre tendrás menos en el móvil, ya sea por bugs del firmware o por usos internos de la implementación del fabricante.


2Tus imágenes preparadas para pintar ocuparán en memoria siempre la formula:

Imagen (KB) = (ANCHO (pixels) x ALTO (pixels) x COLORES (bytes)) / 1024

Para una imagen de 64 x 64 en una pantalla de 65.535 colores (16 bits = 2 bytes) tendremos = (64 x 64 x 2) / 1024 = 8 KB de HEAP.

Intenta optimizar los tamaños siempre que puedas de cara a tu memoria de HEAP y el número de colores de cara al tamaño de tu archivo JAR.


3El código de tus clases podrían tener que vivir en el HEAP. Recuerda que el uso de una clase necesita de su bytecode en algún sitio, y ese sitio seguramente sea tu querido HEAP. Piensa que las clases descomprimidas irán usando el HEAP cuando las vayas usando. Una buena solución puede ser tener una clase con métodos de un solo uso como cargas y preparaciones, y cuando se finalice de usar, poner todos sus objetos a null para que, en algunos móviles, te saque su código del HEAP por no estar en uso.


4Si crees que tu archivo JAR no puede descomprimirse en tu HEAP, estás muy equivocado. Algunos móviles descomprimirán tu archivo JAR en tu HEAP y si has comprimido a tope, te encontrarás con poco HEAP disponible. Intenta equilibrar el contenido de tu JAR con el HEAP que necesitas. Si no lo equilibras, entrarás en el círculo vicioso entre HEAP y JAR. Otra opción es implementarte un pequeño descompresor para tus recursos (no clases, ni imágenes o sonidos comprimidos) que permita mantenerlos comprimidos. Equilibrar es básico.


5La mayoría de los recursos y clases tienen cabeceras que ocupan espacio de HEAP y de JAR. Cuantos menos archivos de clases y recursos tengas, menos espacio ocuparás. Cuidado con meter todo en una clase o una imagen, cuando los uses podrá desbordar tu HEAP si son muy grandes. Equilibra el número de clases y recursos con su uso en memoria. No es fácil porque hay que analizar la lógica de tu juego para hacer una correcta división, pero te facilitará entrar en móviles pequeños.


6Adapta la disposición de tus gráficos dentro de las imágenes. No ocupa lo mismo en memoria una imagen más vertical que horizontal o cuadrada. Desde hace mucho tiempo se sabe que la forma de crear las imágenes con tus gráficos puede consumir más o menos memoria de HEAP. A veces, poner en vertical los frames de tus sprites puede que mejoren tu uso de memoria. Experimenta hasta encontrar la mejor combinación y únelo a tu equilibrio entre el número las imágenes de recursos.


7Usa herramientas de optimización de imágenes como PNGOUT, herramientas de optimización de archivos JAR como JARG (Java Archive Grinder) o KZIP. Con esto conseguirás mejorar el tamaño de tu archivo JAR, pero recuerda equilibrarlo con tu espacio de HEAP. El uso de ofuscadores es obligatorio tanto para reducir el tamaño del JAR como el espacio ocupado por el Bytecode en el HEAP. Algunos ofuscadores optimizan más que otros, pero también algunos móviles no aceptan bien grandes clases con ciertos tipos de ofuscado, usa el ofuscador más adecuado en cada caso si puedes.


8 La precarga de imágenes y sonidos puede acelerar la ejecución de tus juegos, pero también puede limitar el tamaño de tu lógica dentro del HEAP. Equilibra tus recursos cacheados en memoria con la lógica de tu juego. Aunque no todos los recursos estén cacheados, puedes hacer algunos efectos durante el juego para que el jugador no se de cuenta de los momentos de carga y preparación. Carga y descarga recursos en memoria de HEAP y usa trucos durante el juego para que el jugador no se de cuenta. Cargar desde el archivo JAR es lento y tener las imágenes preparadas para pintar es caro de cara al HEAP; una buena idea consiste en tener algunos archivos de imágenes (PNG, …) en arrays en memoria como si tuvieras una cache y cuando los necesites, prepararlos como imagen bitmap y pintarlos. Esto es mucho más rápido que ir directamente al jar a buscarlos y son recursos que ocupan poco en el HEAP al estar comprimidos en su formato original (PNG, …). Lo mismo puedes hacer con algunos recursos de audio.


9Tu teléfono dispone de una memoria persistente y en caso de J2ME puedes grabar datos en sus Record Store. En algunos casos, si tus recursos y lógica no caben por la limitación de archivo JAR, puedes intentar meter la lógica en el JAR y que al iniciar el juego, el propio juego se descargue los recursos que le falten y los guarde en Record Store. Usamos teléfonos móviles y se pueden conectar a la red, debemos usar estas capacidades para mejorar nuestros juegos. Poco a poco los jugadores irán asimilando que las aplicaciones móviles necesitan conectarse a la red para actualizarse. La creación y acceso a varios Record Store puede ser lenta, pero el acceso y grabación de registros de un Record Store es bastante rápida. Organiza tus contenidos de tal manera que puedas leerlos sin que el usuario note retrasos durante el juego. Podrás crear juegos bastante impactantes en teléfonos limitados. Recuerda que también hay límites para los Record Store de una MIDlet.


10Equilibrio y diseño. Todo es cuestión de equilibrio y depende de cómo diseñemos nuestro videojuego. Si somos capaces de diseñarlo basándonos en el equilibrio entre JAR y HEAP, conseguiremos meter una gran cantidad de contenidos y crearemos pantallas y niveles muy completos para el jugador. Cuando vayas a hacer un videojuego para el móvil, piensa siempre en este equilibrio para evitarte dolores de cabeza posteriores. Esta regla también vale para otras plataformas porque al final a más capacidad, más contenidos metemos y siempre necesitamos un equilibrio.

Etiquetas: ,


17 marzo 2006

Aquí empezamos la casa por el tejado

...y estamos orgullosos!!

Cómo no...empezaré por el principio, creo que era mi segundo día cuando JM comenzó a explicarme nuestra metodología, empezando por XP llegamos a las pruebas unitarias..

eh??? ¿qué son las pruebas unitarias? (uff que vergüenza reconocer que no las conocía).

A pesar de que es una práctica altamente recomendable y condición sine qua non con el software de calidad, por las empresas por las que he pasado no conocíamos ni el termino.
Después de explicarme su sentido(a grosso modo "las pruebas unitarias prueban que cada modulo de código funcione correctamente por separado", lo vi todo clarísimo (os recomiendo leerlos el artículo de Jm sobre este tema), a partir de ahora siempre usaría pruebas unitarias, hasta que JM siguió explicando y de nuevo consiguió darle la vuelta a mi "claridad"...
ahora decía que hiciera las pruebas unitarias antes que el código!!!,

Pero éste está loco!!! ¿qué empiece la casa por el tejado?..."sí hombre y ahora me dirá que primero programe y luego diseñe" :).


Quería que probase métodos que no existían, clases que no existían...en fin loco!! jejeje, puede parecer una locura pero tiene mucho sentido, esta técnica se conoce como TDD(Test Driven Development), si haces las pruebas primero te estás anticipando a posibles fallos, las pruebas te harán modelar tu diseño de la clase, del método, tendrás una visión muy clara del comportamiento que esperas que tenga un método, clase, etc..
si queréis más información sobre esto nos perdáis el articulo completo de JM.

Etiquetas: ,


15 marzo 2006

Cómo nos organizamos

En Unkasoft tenemos el desarrollo dividido en dos partes bien distintas:

- Por un lado tenemos una división de herramientas en la que trabajamos en un producto llamado Battlewizard. Ya hablaremos con más calma sobre Battlewizard (que os acabaremos aburriendo), pero como adelanto diremos que se trata de un sistema para desarrollar juegos para teléfonos móviles, evitando el infierno de la portabilidad a dispositivos de distintos fabricantes, tamaños de pantalla, capacidades, etc.

- Por otro lado está la división de juegos, donde usamos Battlewizard y su API de J2ME para desarrollar los juegos que sacamos al mercado (Uno en fase de pruebas, otros dos en programación y uno más en fase de diseño). Esto nos permite que, con un único código fuente, podamos sacar juegos en un abanico muy amplio de teléfonos (que al final es una de las cosas que más miran las operadoras). Esto no es nada normal en el mundo del desarrollo para móviles, incluso hay estudios de desarrollo (como GameLoft) que tienen varias copias del código fuente, dependiendo de las peculiaridades de cada dispositivo, y cada copia del fuente tiene su responsable. En estudios pequeños como el nuestro, no nos podemos permitir esos lujos, y creemos que no es la mejor manera de abordar el problema de la fragmentación.

Esto respecto a la programación.
Después tenemos el departamento de QA, donde probamos tanto Battlewizard como los juegos finales, para todos los dispositivos que soportamos.
Esto es una auténtica jungla, porque pensad lo que supone probar el mismo juego en unos 30 teléfonos distintos (nuestro objetivo es llegar a los 200 terminales soportados). Y si no, que se lo digan a Jorge, que a veces le vemos con un móvil en cada mano, probando a la vez dos versiones de El Cuarto Sello :)

Etiquetas:


14 marzo 2006

Unkasoft es otro mundo

Aunque pueda sonar a propaganda barata y panfleto cutre, os puedo asegurar que trabajar en Unkasoft es otro mundo.
Hasta hace más o menos un año, mi experiencia en el mundo del desarrollo me decía que en España no era posible hacer buen software, que nos preocupamos más en compararnos con los demás, que en mirar nuestro código y hacer lo posible para que el equipo mejore (el equipo, menuda palabra más rara).
Después de haber trabajado en unas cuantas empresas del sector, te das cuenta de lo difícil que está el panorama: mucha charcutera que trata a la gente pero que al ganado, mucha consultoría de traje caro, mucho desarrollo de alta tecnología (que luego no es tan "alta") y poco corazón y cerebro... en general, un desastre, hasta tal punto que te preguntas ¿me voy a jubilar yo en este mundo?

En las entrevistas con Jaime ya empecé a notar un "algo" distinto, tanto desde el punto de vista técnico (me sorprendieron mucho las preguntas), como humano (¡se preocupaba por los empleados!). Me fui con una idea en la cabeza: esta gente sabe de lo que habla. Estaba harto de entrevistas en las que al final era yo (el candidato) el que acababa entrevistando a la entrevistadora, y me iba con la misma decepción de siempre: otra empresa que lo único que le importa es la experiencia que tienes con la herramientas/lenguaje X.

Después de un tiempo en Unkasoft me he dado cuenta de que aquellos "good smells" que sentí en la entrevista era muy ciertos, y que era posible trabajar con metodologías ágiles y al estilo Joel, sin tener que dedicar todos tus esfuerzos en convencer a los jefes de que este es el camino. Y para más inri, en el mundo de los videojuegos (que siempre me ha resultado de lo más enigmático) y en un mercado emergente y con tanto potencial como el de los móviles.

En definitiva: que trabajar en Unkasoft es otro mundo, y esa es la suerte que tenemos los que estamos en esta pequeña start-up.

Desde este blog os iremos contando nuestro día a día, nuestros problemas (a montones), fracasos (que seguro que tendremos) y nuestros éxitos (espero que más que fracasos :)
Hablaremos de metodologías ágiles, de programación de juegos, de móviles, de J2ME, y también algo de nuestros propios productos.

Por cierto, me llamo JM y son uno de los programadores de Unkasoft.

Etiquetas:


Cosas que aprendí

7 meses ya....en los cuales he aprendido más de lo que esperaba y menos de lo que debería, esto es así y es lo que me gusta, estar siempre con nuevos retos, esto es Unkasoft.

Empezando por el principio siempre recuerdo cuando hice la entrevista:

entrevistador:¿Conoces Xp?
flopez: claro!!(por dios!!) como no!! y windows 2000, Linux....
entrevistador: extreme programming..... :))

Por entonces había pasado por empresas donde la metodología era "sacar las cosas para ayer y como fuese", cuando te explican XP(extreme programming) te quedas sorprendido, ¿Pair programming?? dos personas en un equipo y trabajando juntas...uy más de un jefe pondría el grito en el cielo: !!!esos están jugando!!!! :)) pero XP no es solo eso, unos de sus preceptos:
"La gente es el principal factor de éxito de un proyecto software" también haría que más de uno se tirase de los pelos y dijese: "¿la gente?, la gente es prescindible", como comprenderéis esto ya me hizo desear entrar aquí, pero hay más... recuerdo cuando estaba trabajando haciendo herramientas web con .Net que solía pensar: uff hacer juegos...una oportunidad para llegar a ese mundo es imposible...eso si es chungo, hacer juegos...siempre he pensado que todo se puede aprender con un buen maestro e internet, y en esas estoy...

Mi trabajo casi al 100% esta en BattleWizard, nuestra plataforma para hacernos la vida más fácil a la hora de hacer juegos, y trabajando en ella es donde más he aprendido y donde más la he cagado en cuanto a desarrollo se refiere, (que se lo digan a JM :) él es mi "yoda", el que me enseña el camino a la fuerza, jejeje).

He aprendido muchísimo de arquitectura, pero muchísimo!! sobre todo a saber utilizarla, a entender para que se necesita y lo necesaria que es,por no hablar de la programación orientada a objetos, la verdad....hasta ahora no estaba usando ni el 10% de su potencial... pero no todo lo que uno aprende es a nivel técnico, quizá la cosa que más me ha costado aprender es en realidad una cura de humildad, hasta ahora en donde había estado trabajando siempre había destacado(o eso pensaba yo), y siempre había querido destacar, aquí estoy rodeado de autenticas maquinas, y no es peloteo, de gente de la que siempre tienes algo que aprender, aquí todos tienen algo que aportar y que decir, la mayoría de las ocasiones si quieres aprender solo tienes que escuchar, otras es mejor no oír(sobre todo en cine que yayo no tiene ni idea :)).

También he aprendido que jugar en red los viernes es tremendamente divertido :)

Etiquetas:


13 marzo 2006

Qué facil es comenzar un videojuego y qué difícil resulta terminarlo

Qué facil es comenzar un videojuego ! y qué difícil resulta terminarlo. Después de otro día de desarrollo y organización dentro de los proyectos de Unkasoft, me doy cuenta de las lágrimas que hay que derramar para cerrar un videojuego con un mínimo de calidad. Desde hace tres años, estamos enfrascados en un proyecto para hacer videojuegos y herramientas para hacer nuestros videojuegos. Son videojuegos "simples" porque son para teléfonos móviles, pero son nuevos, impactantes y de calidad y eso supone innovar y luchar a unas cotas muy altas. En los últimos meses hemos estado desarrollando nuestro primer videojuego, El Cuarto Sello, un "Action-RPG" que tiene que revolucionar los juegos para móviles por su calidad y su cantidad de contenidos. Tres meses de probar los motores y la tecnología desarrollada en el último año, probado nuestros guiones y diseños y adaptando los contenidos originales a pantallas de 128 x 128.
Si existe un infierno, ese es el de hacer videojuegos para teléfonos móviles, donde todo es distinto entre cada teléfono. Da igual que sean de la misma marca e inclusive entre modelos iguales, cada firmware es un mundo y luchar en tantos mundos es complejo.
Nuestra intención original era romper con una nueva tecnología, una nueva metodología de desarrollo basada en las metodologías ágiles pero adaptándolas al desarrollo de videojuegos para móviles y en parte estamos teniendo éxito. Funcionamos igual en todos los móviles que tenemos para probar. Da igual que tengamos poca memoria o capacidad, tenemos los mismos gráficos y contenidos (adaptando los tamaños gráficos) para todo el videojuego. Da igual que tengas un pequeño teléfono de 128x128 que un SmartPhone de 300x200, jugarás al mismo juego, pero siempre hay un coste que pagar: mucha calidad en teléfonos pequeños supone una calidad media en teléfonos grandes.
Nuestro gran enemigo, el tiempo, no nos quita ojo y estamos obligados a avanzar para sacar nuestro primer juego. Estamos a punto de acabarlo y estamos, más que otra cosa, un poco cansados. El sueño de sacar videojuegos al mercado, es eso, un sueño, porque es muy fácil comenzar y muy difícil terminar, pero gracias al esfuerzo del equipo hemos comenazado a presentarlo a los distribuidores, y esperamos en no demasiado tiempo poder ofrecerlo al público de varios países para que puedan disfrutar de nuestro primer "niño".
Queremos cambiar tantas cosas, pero ya no hay tiempo, es el momento de comercializar y hemos de reservar nuestros cambios para otros juegos y sobre todo, hemos de empujar lo que hemos aprendido para el siguiente título. Es el momento de cerrar un proyecto que parecía inacabable y comenzar otro, y aunque nos parezca que no está todavía terminado, debemos pensar en el quilibrio y tomar la decisión de finalizar y dejar las mejoras para el siguiente.
De nuevo empezaremos el siguiente juego con muchas ganas y nos olvidaremos de las lágrimas que nos tocará derramar dentro de unos meses para terminarlo. Pase lo que pase, tengo ganas de empezar con el siguiente, hacer videojuegos debería clasificarse como un estilo de vida, sólo apto para "pirados algo masocas".

Etiquetas: ,


This page is powered by Blogger. Isn't yours?