MetaCard y Revolution: Herramientas de autor multiplataforma para multimedia | ||
---|---|---|
Anterior | Capítulo 4. Objetos y controles básicos | Siguiente |
A la hora de incluir representaciones visuales estáticas donde sea necesario un grado de libertad a la hora de crearlas o que no incremente el uso de recursos de la aplicación, es posible hacer uso de los gráficos vectoriales.
Veamos algunos ejemplos de subtipos de un gráfico, en concreto el primero y el cuarto siguiendo el orden de aparición en la barra de "Menu Bar":
El Graphic tool (polygon) se puede utilizar para realizar objetos cerrados o no. Es como la herramienta de "polilínea" que tienen otras aplicaciones, puesto que pueden quedar abiertos los dos extremos.
La Figura 4-14 muestra cómo se puede realizar una gráfica a partir de una serie de datos numéricos. Estos pueden ser el resultado de un cálculo previo, aquí los he fijado estáticos en un campo de texto. La aplicación consste en ...
Acuérdese de desactivar la propiedad Relative to topLeft del gráfico "grafic". El código de la tarjeta es el siguiente
on mouseUp sort lines of me ascending by item 1 of each put trunc((the height of this card - 120) / \ (the first item of last line of me - the first item of first line of me) ) \ into separacioY put (the first item of first line of me) into minValor put fld "copiaValors" into me sort lines of me ascending by item 2 of each put trunc((the width of this card - 120) / the number of lines of me ) \ into separacioX put empty into fld "coordXY" repeat with i = 1 to the number of lines of me put 60 + (separacioX * (i - 1)),\ ((the height of this card - 60) - \ (separacioY * (the first item of line i of me - minValor))) &\ return \ after fld "coordXY" end repeat send "mouseUp" to graphic "grafic" end mouseUp
El Graphic tool (oval) permite la creación de círculos y, si está activa la propiedad Filled, de circunferencias y arcos. Veamos un ejemplo puede servir para empezar una aplicación o para entretener a nuestro usuario mientras hacemos alguna otra cosa. Al estilo de cuando empieza una secuencia de cine, vamos a mostrar una cuenta descendente y sobre esta una circunferencia que se abre y se cierra. Al finalizar la cuenta, empezaría el verdadero intercambio de información con el usuario.
La tarjeta en cuestión consta únicamente de dos objetos que examinaremos enseguida, de momento su misión es incializar: el valor inicial de la cuenta atrás y enviar un mensaje de que "empiece el espectáculo". Cuando haya terminado, ya la avisarán para que cambie a otra tarjeta. Aquí el código de "ir a otra tarjeta" se ha hecho lo más sencillo posible para no desviarnos demasiado del manejo de gráficos. Pero observe que se puede hacer cualquier cosa, desde hacer sonar un archivo de audio hasta elegir a qué tarjeta se va, no tiene por qué ser la siguiente.
# #La tarjeta # on openCard put "5" into fld "num"; send "mouseUp" to grc "circul" end openCard on continuar go to next card end continuar
El gráfico tiene como misión hacer un ciclo completo, esto es, ir cerrándose dejando ver lo que hay debajo (que es la cuenta) y se realimenta así mismo reenviándose el mensaje. Mientras MetaCard puede ejecutar otro código "en paralelo". Terminado el ciclo, envía un mensaje al campo de texto para que este decremente la cuenta y ya decidirá aquel qué sigue.
# # Gráfico "circul" # on mouseUp set startAngle of me to 90 set arcAngle of me to 360 send "paso" to me end mouseUp on paso # put "Ara " & arcAngle of me set arcAngle of me to arcAngle of me - 20 if arcAngle of me = 0 then send "decrNum" to fld "num" else send "paso" to me in 10 millisecond end if end paso
Quien controla cuando acaba esto es el campo de texto, así que puede tomar más o menos tiempo y el mecanismo sigue siendo válido. La labor de este control es decrementar la cuenta, mostrarla, señalar al gráfico que haga su trabajo y, cuando sea el momento, decirle entonces a la tarjeta que la cuenta ha terminado y que esta decida cómo, cuándo y a qué tarjeta pasar. El usuario sólo verá un cambio que asumirá como el siguiente contenido.
# # Campo de texto "num" # on decrNum # put "text = " & the text of me if the text of me <> 0 then put the text of me - 1 into me send "mouseUp" to graphic "circul" else send "continuar" to this card end if end decrNum
Si quiere decorar un poco más la presentación, puede aprovechar que la pila es la primera en poder entrar en acción para tomar algunas medidas de caracter estético como las siguientes.
# # Pila # on preOpenStack set the backdrop to black move me to the screenLoc # set the decorations to none set the width of me to 256 set the height of me to 256 go to card "Inici" end preOpenStack
Se puede aprovechar un objeto de tipo gráfico para realizar sencillas animaciones por que sus valores se pueden generar en tiempo de ejecución, pero para el caso que nos ocupa, se ha realizado de forma estática sin pérdida de generalidad en la exposición.
El caso expuesto ilustra cómo se puede plantear el movimiento de un objeto que recorre el contorno de un texto en pantalla. Se puede ver una ilustración del mismo en la Figura 4-16. Reaprovechamos así lo aprendido en el primer tutorial de MetaCard
#button "Pren" on mouseUp set the loc of graphic "xispes" to the first line of the points of graphic "camiMetxa" show graphic "xispes" move the graphic "xispes" to the points of graphic "camiMetxa" in 6 seconds hide graphic "xispes" end mouseUp
A partir de este caso sencillo se puede plantear la construcción de un efecto de "mecha" sobre el mismo texto. Se deja a la consideración del lector añadir los elementos decorativos (imágines y seguramente sonido) que permitan similar una mecha. El caso, visto de forma simplificada, de querer simular una mecha que se va consumiendo conforme se deplaza el objeto animado obliga a recurrir a un bucle como el que se ha utilizado en el segundo de los tutoriales sobre MetaCard. Puesto que ahora es necesario realizar acciones conforme se realiza el moviento principal.
#button "Pren2" on mouseUp show graphic "metxa" set the points of graphic "metxa" to the the points of graphic "camiMetxa" set the loc of graphic "xispes" to the first line of the points of graphic "camiMetxa" show graphic "xispes" repeat with i = 1 to the number of lines in the points of graphic "camiMetxa" move graphic "xispes" to line (i+1) of the points of graphic "camiMetxa" set the points of graphic "metxa" to \ line i to (the number of lines of the points of graphic "camiMetxa") of \ the points of graphic "camiMetxa" end repeat hide graphic "metxa" hide graphic "xispes" end mouseUp
Para ilustrar lo que está pasando se ha dejado comentada una posible modificación relativa al tiempo que hay que emplear en cada moviento para que el lector pueda comprobar de modo experimental que es lo que está pasando en cada iteracción del bucle y que se muestra en la Figura 4-17.
Aviso |
Descriure este "rellontge" |
Aviso |
I este atre "rellontge" |
La pila inicializa una propiedad importante en este caso, debido a la variabilidad que estamos introduciendo en el contenido de la ventana: alwaysBuffer. La tarjeta permite parar y reiniciar el proceso. Finalmente, el código que nos trae a este caso es el del objeto gráfico.
# En la pila # on openCard set the alwaysBuffer of this stack to true end openCard local idMensatge, numId # # La tarjeta local varAux on mouseUp quinBoto if quinBoto = 1 then set the startAngle of graphic "segons" to 90 set the arcAngle of graphic "segons" to 360 else send "paraLo" to graphic "segons" end if end mouseUp # # Gráfico "segons" # on mouseUp send "pasaElTemps" to me in 1 millisecond end mouseUp on pasaElTemps set the arcAngle of me to (the arcAngle of me - 1) if the arcAngle of me <> 0 then delete first line of idMensatge send "pasaElTemps" to me in 1 second #round(60/1000) milliseconds put the result & return after idMensatge end if end pasaElTemps on paraLo repeat with numId = the number of lines of idMensatge down to 1 cancel line numId of idMensatge end repeat end paraLo
Vamos a desarrollar un comecocos, bueno sólo una de las piezas del juego : el protagonista. Es un ejercicio para introducir las posibilidades de emplear gráficos vectoriales frente a mapas de bits. Primero que nada deberíamos planificar nuestras acciones, nuestros objetivos y diseñar nuestros modelos para que la implementación no sea un mar de dudas. El objetivo final es algo parecido a la Figura 4-20. Aquí hay que considerar que hay resolver:
Un escenario por donde habrán elementos estáticos que determinarán las opciones de moverse de las piezas móbiles.
Estas piezas móviles tienen un comportamiento propio, esto es se mueven cambiando de posición y algunas de sus características morfológicas.
Existirán puntos de colisión que impedirán el movimiento y otros que no lo harán pero que influyen en la puntuación final.
Figura 4-20. Apariencia de una pantalla típica del juego del Comecocos (del trabajo de Rafael Salguero y Jose V. Sebastiá).
Para realizar un juego de tablero o de casillas, lo cómodo es crear un tablero de forma dinámica sobre el que se disponen en cada una de sus casillas un elemento. Si este es de naturaleza estática, estará asignado de forma fija en todo momento. Si es móvil, hay que actualizar en cada instante la posible variación de los mismos.
La creación del tablero la abordaremos en la la sección de nombre Generación y uso dinámico de multiples objetos en Capítulo 6. Hecho esto, sólo restará asignar un valor a cada casilla de libre o ocupado. Esto resuelve que un objeto se pueda mover (en una de las cuatro direcciones posibles) o no.
Sólo puede haber un caso de "colisión" entre objetos móbiles, que resuelven las reglas del juego, para decidir quién pasa a ocupar la nueva posición y en cuyo caso se ha de determinar la modificación de la puntuación. Ahora cabe distinguir que entre los objetos dinámicos, los que pueden aparecer en algún lugar de la ruta recorrible, existiran comportamientos fijos y variables: los fijos son los que permiten recoger útiles (puntos, vidas, energía, ...) y los variables son los oponentes que tendrán un comportamiento más o menos inteligente, hudizo, atrevido, ...
Dejemos algo para los ejercicios y centrémonos en una cosa: las posibilidades de un gráfico cuyas propiedades permiten alterar su apariencia de forma dinámica. Hecho para uno establecermos las bases para los otros. El protagonista de nuestra aventura es el más complejo y vamos a encararlo aquí. Lo vamos a realizar en tres etapas utilizando sólo gráficos vectoriales:
Para ello en primera intancia (Figura 4-21a) crearemos un objeto gráfico de tipo oval, lo rellenamos y le asignamos un color (Figura 4-21b).
Después se puede incluir (Figura 4-21) la característica boca y ponerle un ojo. Ya sólo falta que la boca se abra y cierre de una manera rápida o lenta, pero a voluntad del programador y que se puedaprogramar .
Casi está terminado, queda rellenar el ojo de color y agrupar los dos elementos bajo un mismo nombre. El código hará el resto.
El código que impulsa a este elemento está compuesto, por una parte por el movimiento de la boca y por otro por el del conjunto. Preparemos un par de botones para poner el marcha ("Mou-lo") al "monstruito" y para pararlo ("Para'l"). Si llevamos todo el código relativo a la animación al objeto podremos después clonarlo para hacer un pequeño ejército y el conteo de las puntuaciones que las centralice otra parte del juego. Concentrémos en mover al bicho en horizontal y después ya le dejo para que piense cómo le da la vuelta. En tres pasos:
Los dos botones que hemos creado enviaran un mensaje al grupo para iniciar el movimiento y para pararlo (bueno, de paso lo llevo a una posición conocida de antemano para que esté listo para la siguiente prueba), nada más. El primer paso es ver cómo hacemos para que se mueva la boca. Recordará que hemos creado un gráfico y le hecho una "boca" utilizando las propiedades de startAngle y arcAngle. Con estas vamos a jugar ahora.
# # Botón "Mou-lo" # on mouseUp send "mouTe" to group "comecocos" end mouseUp # # Botón "Para'l" # on mouseUp send "paraT" to group "comecocos" end mouseUp # # Grupo "comecocos" # on mouTe send "mouTe" to graphic "cara" in 250 milliseconds end mouTe on paraT send "paraT" to graphic "cara" set the loc of me to 102,144 end parat
Ahora es todo cuestión del gráfico "cara", si tiene la boca abierta que la cierre y si no que la abra. De paso, que se recuerde a sí mismo que tiene que seguir haciéndolo. Los valores numéricos están puestos a mi gusto.
local idMensatge on paraT cancel idMensatge end parat on mouTe if the arcAngle of me = 358 then set the arcAngle of me to 317 else set the arcAngle of me to 358 send mouTe to me in 250 milliseconds put the result into idMensatge end mouTe
Si ya funciona esto, sólo queda que avance. Es decir, que todo el grupo se deplace en un sentido y que siga así hasta que se le de la orden de parar. Esto implica que el grupo también ha de reenviarse un mensaje para acordarse de que está moviéndose. Incluiré también una prueba de que no "tropieza" para ilustrar el control de colisiones.
local idMensatge on paraT cancel idMensatge send "paraT" to graphic "cara" set the loc of me to 102,144 end parat on mouTe send "mouTe" to graphic "cara" in 250 milliseconds send "menejat" to me in 500 milliseconds end mouTe on menejat if not (the first item of the loc of me > the width of this card-(the width of me / 2)) then move me rel 10,0 send "menejat" to me in 500 milliseconds put the result into idMensatge end if end menejat
Nota: Dependiendo de los tiempos en que se programen los eventos y la de veces que se pulsen los botones podemos tener problemas con este código. El problema radica en que sólo se almancena el último mensaje en uno y otro lado, así que sólo podemos cancelar el mismo número de eventos pendientes.
La solución, como ya habrá imaginado puede venir (aunque hay otras maneras) de guardar cada identificador en una línea de la variable que los guarda, consumiendo (borrando) el primero antes de reenviarse el mensaje. A la hora de parar el movimiento hay que "cancelar", uno por uno, todos los identificadores almacenados.
local idMensatge on paraT repeat with i = 1 to the number of lines of idMensatge cancel line i of idMensatge end repeat end parat on mouTe if the arcAngle of graphic "cara" = 358 then set the arcAngle of graphic "cara" to 317 else set the arcAngle of graphic "cara" to 358 send mouTe to me in 250 milliseconds put the result & return after idMensatge end mouTe
En la implementación final del juego, como en casi todos los de "tablero", habría que diseñar un tablero con dos columnas y dos filas más de las visibles: los bordes del tablero. Estas, siempre puestas a un valor de "obstáculo", facilitarían la comprobación de que el movimiento que se va a intentar no lleva a un posición que no se puede ocupar; algo similar a lo que hemos implementado.