3er paso: Interacción entre objetos (V)

Créase o no, estamos en la recta final del proyecto. Si seguiste este tutorial paso a paso ¡te felicito!… requiere de cierta disciplina y paciencia a la que no estamos acostumbrados en estos tiempos que corren.

Desde ya aprovecho nuevamente a pedir disculpas por la redacción, hecha contrarreloj —como casi siempre me pasa—, y con más voluntad que destreza.

Lo que resta hacer no es mucho, pero no es tan simple. A medida que los proyectos crecen se necesita mayor concentración y reflexión sobre lo que estamos haciendo… no recomiendo nunca "poner bloques y ver que pasa" (salvo que estemos investigando sobre sus posibilidades).

Integrando bloques

Focalizando la cuestión, debemos integrar una serie de bloques a los ya existentes. Te recuerdo cual es nuestro objetivo puntual:

Nuestro objetivo puntual será que cuando Murci "choque" con el árbol… [1] emita un sonido (mitad de dolor, mitad de asombro), [2] dé media vuelta sobre sus pasos —es una forma de decir—, y [3] reflexione para sí durante unos segundos.   En cuanto al árbol… ni enterado de que algo pasó.

Análisis previo

SÓLO SI

Probablemente el punto más importante a destacar es que la conjunción de bloques propuestos se va a accionar bajo una determinada condición: SÓLO SI MURCI ESTÁ TOCANDO EL ÁRBOL.

Quizás te suene conocido este SÓLO SI… hablamos de ello en el opúsculo intitulado "Volando hasta el fin".

Cuando introdujimos dentro del programa el bloque [rebotar si está tocando un borde] aclaramos que el mismo se ejecutaba (como parece obvio) SÓLO SI el objeto se ponía en contacto con los límites del escenario… si no era así no producía efecto alguno.

Y aunque no lo mencionamos, la idea de interacción ya se hallaba presente, pero en este caso entre un objeto y el escenario.

similar

También mencionamos que [rebotar si está tocando un borde] era un bloque que daba una solución simple a un problema, y que fue introducido en el lenguaje a los fines de facilitar al programador novato el lograr un objetivo. A modo de curiosidad, te dejo como sería implementar un comportamiento PARECIDO si no tuviésemos el bendito bloque (es hora de mirar a la derecha de tu pantalla). No es la única manera.

SENSORES

Terminada la aclaración, volvamos un poco con la idea del uso de sensores. Si bien la mayoría de las veces Murci no estará tocando un borde ni tocando al árbol, eso es algo que podemos conjeturar nosotros que vemos como es su evolución por el escenario. Pero recordemos que los únicos "sentidos" que le proporcionamos a Murci sólo le permitirán conocer cuando está tocando un borde o cuando está tocando el árbol. Por lo tanto, deberá estar permanentemente sensando esas condiciones, tal como haríamos nosotros con nuestras manos si nos moviésemos por un lugar desconocido en la más completa oscuridad. (LEELO DE NUEVO)

infinito

Es la necesidad de este "sensado continuo" la que justificó la colocación del bloque de rebote dentro del bucle en el script ya conocido (y que te volvemos a mostrar aquí a la izquierda)… la secuencia hace que Murci se mueva 10 pasos, gire aleatoriamente, cambie el disfraz y pruebe si se dá el contacto con el borde, y así por siempre.

No sé si ya se te prendió la lamparita en tu cabeza pero, como conclusión de todo esto último que hablamos, podríamos formularnos una pregunta:

¿Y si además de sensar el contacto con el borde también hacemos que haga algo similar pero con el árbol? (what?).

Pensándolo como instrucciones de programa, quiero decir: que Murci se mueva 10 pasos, que luego gire, luego cambie su disfraz, luego controle si está tocando un borde, y luego controle si entró en contacto con el árbol…, y así por siempre.

Con esta idea en mente vamos a tratar de llegar a una primera solución.

Sensando 2 cosas en un mismo script

solución 1

Vamos a intentar ahora integrar el conjunto de bloques que propusimos en la página anterior (para la interacción con el árbol, are you remember?) con toda nuestra programación previa.

Del análisis realizado recientemente surgió la idea de agregar la nueva condición de sensado también dentro del bucle del script principal de nuestro proyecto. El resultado es lo que podés ver a tu izquierda.

Voy a pecar de ser reiterativo: a diferencia de las acciones de mover, girar, cambiar el disfraz y la espera "forzada" de 0.1 seg —que se ejecutan siempre—, las dos condiciones de sensado ejecutan su acción SÓLO SI… es decir, sólo algunas veces.

Hasta que copies, chiste incluido (¿lo viste?, ¿lo entendiste?), la solución propuesta en tu programa, no tengo mucho más para decir: por lo tanto abrí tu proyecto si lo tenías cerrado y cambiá tu script principal. Yo te espero.

Supongo que ya lo probaste. Congratulations! Ya conseguiste hacer funcionar tu primera interacción entre objetos. Y Murci ya no podrá decir que su vida es monótona (aunque se haya vuelto algo accidentada).

Luego de superada la emoción, corresponde que TODOS observemos el resultado de nuestro proyecto y analicemos si la animación tiene un funcionamiento que nos conforme, o hay algo para corregir. Date un tiempo para hacerlo, que después seguimos.

Una mirada crítica

Aquí ya entramos en el terreno de lo opinable. Estarán quienes ya consideren los objetivos cumplidos, y quienes encuentren cosas para corregir: yo estoy entre estos últimos.

Particularmente me "molestan" 2 cosas: una que ocurre siempre, y otra que ocurre raras veces, pero ocurre.

Lo que siempre ocurre es que cuando Murci piensa para sí "¡huy, no lo escuché...!" por 2 segundos también se "congela" su movimiento por esa cantidad de tiempo.

Lo que a veces ocurre es que después de "haberse dado cuenta" de que chocó con el árbol vuelve nuevamente sobre sus pasos, chocando así otra vez… entiendo que sea distraído ¡pero no tanto!

Ambos comportamientos son explicables y solucionables. Empecemos por el segundo.

¿Tan distraído? 

Antes que nada no te preocupes si esta explicación no te resulta evidente: lleva algún tiempo desarrollar la capacidad de analizar primero porque pasa lo que pasa, y ver después como dar con una solución (a veces requiere plantear un nuevo acercamiento).

Murci chocó contra el árbol: ciertas veces lo que pasa es que después de volver al principio del bucle y de ser ejecutadas las 2 primeras instrucciones —que son [mover(10)pasos] y la del giro aleatorio— puede pasar que ¡Murci siga tocando el árbol!… y por lo tanto volverá a "gritar", a girar 180º, y a "pensar". Es decir, no consigue alejarse lo suficiente para dejar de tocar al árbol.

La solución rápida que se puede proponer es agregar un nuevo bloque [mover(20)pasos], esta vez a continuación del bloque [girar(180)grados]: el efecto conseguido es el de apartar a Murci del árbol lo suficiente como para terminar con el contacto, y de esa manera poder seguir con su vuelo.

NOTA: cuando se usa una solución de este tipo hay que probar "cuantos pasos" serán necesarios para eliminar el efecto de repetición no deseado. A mí me funcionó con 20 pasos.

¿Y cuando "se congela" qué hago?

Dá para algún chascarrillo, pero estoy apurado. Si recordás algo puntualizado en la página anterior, la opción "cronometrada" del bloque pensar retrasa  la ejecución de la instrucción siguiente… como es la opción que usamos en nuestro programa ya podemos ver la razón por la cual Murci  se "paraliza" por 2 segundos antes de seguir.

Este delay  no existiría si usásemos la opción simple del bloque, pero debemos descartarla como solución porque aparecería un nuevo problema: Murci no pararía de "pensar" (pobre, nadie quiere eso).

¿Cómo solucionar nuestro problema sin dejar de cumplir los objetivos?

Pensemos. Ya descubrimos cuál bloque origina el congelamiento de Murci, pero en principio no podemos descartarlo y reemplazarlo por otro. ¡Parece que estamos en un callejón sin salida!

Pero no. Ya se me ocurrió una manera de poder usar el bloque de diálogo sin que afecte el vuelo de nuestro amigo. ¿Magia?   
NO… usando programación multi-hilo. Pero la explicación la dejamos para la página final (¡ y si esto no es crear suspenso…!)

 

Última actualización: Mayo 2, 2012