miércoles, 12 de noviembre de 2014

Cuarta Aproximación a Onironauta

En esta cuarta aproximación se realizaron detalles que hacen al juego, y no solo a la estética, pero en comparación con el resto del trabajo fueron simples problemas a resolver.

En tanto a los backgrounds se incorporaron los siguientes ocho:








Se le agregó una animación de salto al mismo sprite del personaje:


Mostrando las imágenes nuevas con el "image_index" solo cuando no hay un "cuad" 36 pixels por delante del objeto player utilizando la función "place_metting" ("place_meeting(x+36, y +81, cuad)").

Se incorporó un "Score Keeper" el cual tiene como objetivo llevar cuenta del puntaje del jugador. Cada letra ingresada en la palabra tiene un puntaje. Utilizando el sistema de puntuaciones del Scrabble logramos darle un nuevo objetivo, superar tu "score" previo.

Además se validó para que cuando el personaje choque con la "pared" izquierda de la pantalla, las teclas se deshabiliten, te avise que perdiste y te ofrezca reiniciar el juego.

Usándo al Score Keeper como base, se generó un sistema de niveles el cual va aumentando la velocidad de movimiento de los "cuad", y aumenta la cantidad de letras que pueden tener las palabras.

Ya no se pueden repetir palabras.

Y como detalles extras, para permitirle al jugador comprender qué está ocurriendo se agregaron:
-Letras que auto-rellenan la primer palabra, dándole a entender al jugador principiante que tiene que escribir para avanzar.
-Y se le agregaron imágenes al sprite del objeto "cuad" para que las letras se tachen cuando se ingresa una palabra incorrecta o una ya utilizada. Quedando así:



Link para descargar el juego:

Link de descarga del proyecto (Hay que importar el proyecto desde el Gamemaker):

Tercera Aproximación a Onironauta

Esta tercera aproximación, no tiene mucho de programación, más bien tiene muchas incorporaciones en base a lo audiovisual.

Entendiendo que el juego ya hace casi todo lo que plantéa, falta la carga visual y sonora. Se le incorporó un sprite para el personaje:

Se creó un objeto "player" el cual tiene como "sprite" la imagen de arriba, y que al igual que nuestro objeto "cuad" tiene su "image_index" e "image_speed" setteadas en 0 desde su create. El objeto es instanciado desde el "create event" del objeto "palabra_actual" dejando a éste como el controlador casi monopólico de la información.

Hubieron muchos problemas con la caminata, ya que pretendía hacer la animación de caminata con cada una de las teclas. Pero si apretabas otra tecla durante la animación, esta se cortaba y el personaje no avanzaba lo que debía, quedándo desfazado con los "cuad" sobre los que camina. Terminé creando dos variables extra: "movement" y "pj_steps".

La variable "movement" crece con cada tecla presionada en 36, y cuando la palabra es aceptada en 72 (para que camine sobre el espacio vacío entre palabras, en la próxima aproximación se le incorporó una animación de salto).

La variable "pj_steps" cuenta la cantidad de pasos dados por el personaje. Setteé un alarm que checkee cada 1 step (unidad mínima de tiempo en gamemaker) si "pj_steps" es menor a "movement". Si lo es el personaje avanza cierta cantidad de "x" cambiando su "image_index" por el siguiente, logrando que quede nuevamente en la primera imagen cuando llegue al próximo cuadrado. Visualmente se ve un simple paso.
Lo bueno de este sistema es que la animación de caminata termina totalmente ajena a la presión de teclas, simplemente avanza lo que las teclas indican, pero sin perder su ritmo. Si muchas teclas son presionadas, el personaje seguirá avanzando hasta "pj_steps" alcance al "movement" establecido.

Por último, para que estas variables no se vayan de rango, cuando ambas valen lo mismo, ambas se van a cero nuevamente.

Los fondos tienen sus complicaciones. La idea del juego es que los fondos cambien dependiendo las palabras que fueron ingresadas. Recién a esta altura me di cuenta de que el gamemaker tiene sus marcados caprichos con los "backgrounds".

Como primera limitación, solo puede tener ocho backgrounds cargados, como segunda limitación, tiene bastantes problemas para cambiarlos en tiempo real por otro que no esté cargado entre esos ocho.

Esto no sería problema todavía porque solo contábamos con los siguientes cinco fondos:






Pero como el juego debe contar con muchos fondos, ya que es parte de la gracia del mismo, tenía que encontrar alguna solución para este tema.

Realmente, experimenté bastante con todas las funciones que dispone el gamemaker para los backgrounds (Backgrounds YoYo), pero no pude hacerlo funcionar como yo realmente quería. La única solución que encontré para que lograr que los fondos cambiaran fue con la función "background_replace", la cual te cambia un fondo de los ocho posibles por alguna imagen que esté en la carpeta del juego. Horrible solución, engorrosa, fea, y la verdad pobre. Pero por ahora fue lo único que encontré para hacerlo cambiar.

Por otra parte, el tamaño del room fue cambiado de 800x600 a 1600x600, dejándo la visualización centrada en los primeros 800x600. Visualmente se aprecia exactamente lo mismo. Pero resulta que cuando se generan los "cuad" nuevos, si se está muy cerca de la "pared" derecha, los "cuad" que excedan el room no van a formarse nunca. 800 pixels extra parece un tamaño excesivo para la solución de este problema, pero los backgrounds de por sí fueron moldeados a ese tamaño, y para evitar problemas me pareció conveniente dejarlos de igual medida. Para agregarle gracia, me ayudó a solucionar un problema en la próxima aproximación.

En tanto al sonido, tuve la necesidad de querer escuchar al juego con algo de fondo, para no sentirlo tan vacío. Y por alguna razón la música de "Lavender Town" (pokemon) vino a mi mente. En 8-bits no me convencía para la estética del juego, ya que no pegaba mucho con los dibujos a mano, por lo cual busqué un cover en piano, y terminé probando con el siguiente. Se lo mostré al resto del grupo y les convenció bastante, por más que le daba un tono excesivamente "creepy" el cual nadie se esperaba en primer momento.

Una vez bajadas tantas tazas de café en esa hermosa noche, solo quedan detalles para terminar el juego.

Les dejo el link al juego:

Segunda Aproximación a Onironauta

Como el tema de la interacción ya estaba resuelto, ahora solo restaba afrontar la realidad, y ponerme a ver cómo hacer para que mi pantalla tenga "cosas" y darle un poco de alegría, un poquito al menos.

Creé un sprite muy bello, lo llamé "cuadrado" (super original).

Cada cuadrado fue creado con el editor de sprites del gamemaker, el cual fue muy simple y efectivo. Cada uno mide 36x36 pixels, y van cambiando según lo que el usuario ingresa.

Como primerísima instancia, tenía que crear un objeto, para luego instanciarlo en el room. Lo denominé "cuad", le puse como sprite al que ven arriba, y en su "create event" le puse "image_index = 0", e "image_speed = 0", para que su imagen al ser creado sea el espacio vacío y que no vaya cambiando, ya que estos sprites funcionan a modo de gif. De no haberle puesto el speed en cero iría cambiando por sí solo con la velocidad predeterminada.

Una vez creado el objeto "cuad", tenía que encontrar la manera de hacerlo aparecer por código en el room, ya que se necesitan crear X cantidad de estos por partida. Para lo mismo, tuve que usar la función "instance_create" del gamemaker. Esta función te deja crear una instancia de un objeto en una "x" y una "y" determinada. Para no hacer el código muy pesado, decidí modularlo, creando una función llamada "generar".

La función "instance_create" devuelve un valor almacenable en una variable, el cual contiene la dirección en memoria de la instancia creada, permitiéndote modificar a la variable en la cual almacenaste dicho valor como si fuera la instancia misma. Por lo cuál cree un "array" global llamado "cuads[]" el cual contiene en cada uno de sus elementos los "cuad" instanciados.

Hice que la función generar reciba como parametro una la "x" inicial del primer cuadrado en la cadena de "cuad". Y la llamo por primera vez en el "create event" de "palabra_actual", con una "x" de 100. Entonces, como la primera palabra era siempre de tres letras, apenas se comienza el juego, aparecen en el x 100 tres cuadrados vacíos indicándole al jugador la cantidad de letras que debe ingresar.

Modifiqué los eventos "key press" de cada una de las letras, para que además de agregar la letra correspondiente a "palabra" cambien el "image_index" del "cuad[cantidad_letras]" por el número de imagen del sprite que contiene la letra precionada. De esta manera, el jugador aprieta una letra y tiene una respuesta inmediata en pantalla, sin necesidad de carteles de alerta o cosas feas.

Cuando una palabra es aceptada, el evento "key_press" de "enter" tiene una llamada a la función "generar" con la "x" actual del último "cuad" de la palabra ("generar(cuads[letra_actual - 1].x + 36)") sumándole un 36 pixels para que deje un espacio entre palabra y palabra.
La variable "letra_actual" fue creada con el propósito de poder retener la última letra de la palabra, habiendo cargado la cantidad de letras de la próxima palabra en "cantidad_letras".

Por último, ya logrando que esto genere espacios infinitos para palabras, necesitaba que cumpla su función de "sidescroller", o sea que se vaya desplazando hacia la izquierda y vayan desapareciendo.

Acá vino una complicación, porque cada vez que generaba una palabra nueva, volvía a cargar "cuads[]" desde el elemento 0, perdiendo acceso a las instancias anteriores. Viendo un par de tutoriales, recordé la existencia de los objetos padre e hijos. Entonces, lo único que tuve que hacer fue crear un objeto "cuad_father" el cual se mueve hacia la izquierda, haciendo que Todas las instancias habidas y por haber de "cuad" se desplacen en ese mismo sentido y velocidad.

Por otra parte, hice que los cuads que desaparecieran de pantalla, sean destruidos, para no mantener en memoria instancias sin uso que puedan hacer "crashear" el juego en algún punto avanzado del mismo por falta de recursos.

Como agregado, el diccionario fue ampliado a diez mil palabras, incorporándole todas las presentes en esta lista de las palabras más frecuentes brindado por la Real Academia Española:
http://corpus.rae.es/frec/10000_formas.TXT

Les dejo el juego con lo explicado hasta recién:
Descargar

Primera Aproximación con Gamemaker

Como primera instancia, como no tenía idea de como manejar Gamemaker, decidí encarar la interacción con el juego, más que la parte visual, por lo cual me tiré de lleno sobre los objetos, el room y los scripts.

Como primera instancia, sabía que al usuario se le tenía que dar una cierta cantidad de letras. En base a éstas, el jugador debía ingresar una palabra que ocupe ni más ni menos esa cantidad y luego corroborar si lo que ingresó era una palabra válida y no sólo un par de caracteres sueltos.
Empecé por crear un objeto, el cual denominé "palabra_actual", en cuyo "create event" definí las variables necesarias ("cantidad_letras" y "palabra").

La variable "cantidad_letras" cargada en principio con un tres, que me pareció el mínimo indispensable para cada una de las palabras, indica la cantidad de letras que debe tener la palabra. Una vez aceptada la palabra ingresada se debe cargar esta variable con un número aleatorio entre 3 y 7 (me pareció que para probarlo, siete era suficiente).

La variable netamente "string" "palabra" está destinada a contener la palabra, valga la redundancia, que el jugador está construyendo. Una vez que la palabra tiene la cantidad de letras que "cantidad_letras" indica, el usuario puede probar si es aceptada, y continuar con el juego.

Para lograr que esto funcione, primero necesitaba informarle al jugador cuántas letras debía ingresar, pero como no quise meterme de ninguna manera en la parte gráfica, me manejé puramente con los "show_message" que vendrían a ser los carteles de alerta que puede manejar el juego. A través de estos escribía el contenido que me permitía checkear que todo funcionara correctamente.

Una vez que el usuario supiera qué tenía que hacer, le tenía que dar las herramientas para que pudiera cargar la palabra, por lo que empezó mi primera batalla por entender los caprichos del gamemaker. Mi idea era usar el evento "key press" con "any key" y adentro del mismo ir haciendo las validaciones necesarias para detectar qué tecla estaba presionando, y en base al ascii de cada una de las letras ir cargando "palabra". Pero me di cuenta de que las validaciones terminaban siendo engorrosas de maneras innecesarias. Por lo cual terminé haciendo un evento "key press" para cada una de las letras, otra para el enter (para permitirle probar cuando creía que la palabra estaba correcta), borrar, y otro para el tilde.

Borrar, funciona con la tecla "backspace", quita el último caracter de "palabra", y deja de funcionar cuando "palabra" tiene 0 caracteres.

Al agregar el tilde, tuve que agregar una variable extra llamada "acento", esta es una booleana, la cual se pone en true cuando la tecla del tilde es precionada, y se pone en false con la próxima vocal presionada. El código de las vocales está diferenciado para cuando "acento" es verdadera o falsa, logrando agregar la vocal con o sin tilde.

Al apretar cada una de estas teclas, exceptuando la del tilde, se genera un cartel de alerta, permitiéndole al usuario visualizar qué está agregando. 

Por último le puse una validación a cada letra para que no le deje ingresar más letras en "palabra" cuando su "length" sea igual a "cantidad_letras".

Una vez que el jugador puede cargar su palabra, necesitaba corroborar de alguna manera que lo que ingresó sea correcto. Para esto, decidí usar un archivo agregado, para poder ir modificándolo sin tener que entrar en el juego, y que cada uno pueda cambiarlo si quiere, con las palabras que son "válidas". El juego, toma la palabra y leyendo las que el archivo "diccionario.txt" contiene, compara. Si encuentra una similar, le dice al usuario que está bien, limpia "palabra", genera un número aleatorio entre 3 y 7 para "cantidad_letras" y repite el proceso. En caso contrario, el usuario puede seguir probando hasta darle a una palabra incorporada.

Como prueba, el juego solo tenía al rededor de diez palabras, era simplemente para probar el sistema comunicativo.

Por último, para dejar esto funcional, creé un room al cual le dí las medidas de ochocientos por seiscientos y tiré adentro el objeto "palabra_actual"

Les dejo el programa para que lo vean:

Onironauta

Onironauta, es un videojuego, de código abierto, de sidescrolling que implica destreza mental y de "tippeo". Usa como plataforma el Gamemaker: Studio 1.3. El juego sigue en etapa de desarrollo (fines de 2014) por parte de Francisco Tamburri, Carolina German y Jazmín Chalkho con las devoluciones, recomendaciones y críticas de la Cátedra de Artes Multimediales (de la carrera Artes Multimediales, IUNA).

Onironauta, trata de un personaje que inmerso en sus sueños debe ir construyendo palabras para no despertarse. Las palabras que piensa modifican su ambiente, haciendo que los fondos del juego se alteren constantemente. La idea conseguir la mayor cantidad de puntos escribiendo palabras válidas, sin faltas ortográficas, sin repetición de las mismas, antes de chocar contra la pared y despertar.

Este blog tiene la intención de ir contando cómo fue el desarrollo del juego, cómo fue avanzando, con qué errores y complicaciones se fue topando. Pero ciertos inconvenientes de tiempo las primeras entradas se realizarán el mismo día de la entrega, tratando de no dejar detalles de lado.