© Stelios Kourakis 2005

< indice de programación

Práctica: Puzzle

Vamos a aprender a usar el ratón en una forma muy útil - arrastrando elementos.


Bajar archivo de inicio

 

Bajar resultado final

 

Esta práctica contiene los cuatro clips de las piezas del puzzle, un clip de enhorabuena y un botón de mezclar.


 

Montaje

Montamos la pelicula con la siguente manera:

Arrastre con el ratón

Examinamos dos diferentes maneras a arrastrar clips:

Programando a mano

Las coordenadas del ratón se dan a partir de las propiedades

_root._xmouse
_root._ymouse

Así, podemos hacer que un clip siga el cursor, si en cada fotograma posicionamos el _x, _y del clip a la posición del cursor. Ahora bien, no queremos que el clip siga el cursor siempre, solo si el usuario ha clicado encima suyo y todavia no ha soltado el botón.

Vamos a declarar una variable booleana seArrastra. A esta se le asigna el valor true si el usuario clica encima del clip, y false si suelta el botón. Luego, en cada fotograma, el clip mira si seArrastra es true, y en este caso solamente, se coloca a la posicióndel cursor.

Probamos (aqui uso un hombro (pieza1 en mi ejemplo) como clip de prueba):

pieza1.seArrastra = false;
pieza1.onPress = empiezaArrastre;
pieza1.onRelease = terminaArrastre;
pieza1.onEnterFrame = arrastra; function empiezaArrastre(){ this.seArrastra = true; } function terminaArrastre(){ this.seArrastra = false; } function arrastra(){ if (this.seArrastra == true){ this._x = _root._xmouse; this._y = _root._ymouse; } }

El único inconveniente en este método, es que da igual de donde lo pillas, el clip siempre se centra al cursor. Incluso si clicamos en la esquina, el clip directamente se coloca centrado al cursor. Aqui tendriamos que calcular la distancia original a mano y luego hacer cálculos... pero ActionScript nos ofrece una alternativa excelente: las funciones startDrag y stopDrag.

 

Usando startDrag

Los movie clips llevan ya una funcionalidad que nos permite arrastrarles con un mínimo de esfuerzo! Existe la función startDrag, que se puede usar en tres modalidades:

clip.startDrag();
clip.startDrag(centradoAlCursor);
clip.startDrag(centradoAlCursor, limX1, limY1, limX2, limY2).

En la primera forma, empezamos el arrastre manteniendo la distancia original entre el cursor y el centro del clip.

En la segunda forma, podemos especificar si queremos centrar el clip al cursor (true) o si queremos mantener la distancia original (false).

En la tercera forma, podemos además delimitar el arrastre en un rectangulo de la escena caracterizado desde las coordenadas de su esquina izquierda superior (limX1, limY1) y derecha inferior (limX2, limY2).

Una vez iniciado el arrastre con la startDrag, el clip se queda arrastrandose hasta terminar el arrastre con stopDrag:

clip.stopDrag();

Solamente un clip se puede arrastrar con startDrag a la vez!

 

Pensamiento

Ahora sabemos que es facil arrastrar clips por la escena, vamos a ponernos pues al tema del puzzle. Examinamos que harán los elementos que tenemos:

Cada pieza tiene que poder averiguar si ha sido soltada cerca de su posición correcta. Así, tendriamos que guardar la posición inicial antes de mezclar por primera vez. Podemos introducir las variables inicioX y inicioY para guardar las coordenadas. Luego, cuando se suelta el clip, calculamos la distancia entre la nueva posicion y la posición correcta, y si está en menos de 20 pixeles en ambos ejes, podemos considerar que está correctamente colocada.

A Programar!

Declaramos las dos variables que vamos a necesitar:

piezasTotales = 4;
piezasEnSitio = 0;

 

El arrastre

Empezamos por las cuatro piezas. Como que las cuatro tendrán exactamente el mismo comportamiento, usamos un bucle for para asignar todas a la vez.

for (i=1;i<=piezasTotales;i++){
_root["pieza"+i].inicioX = _root["pieza"+i]._x;
_root["pieza"+i].inicioY = _root["pieza"+i]._y;
_root["pieza"+i].onPress = iniciarArrastre;
_root["pieza"+i].onRelease = terminarArrastre;
}

Y implementamos las dos funciones del arrastre:

function iniciarArrastre(){
this.startDrag();
}
function terminarArrastre(){
this.stopDrag() ;

distanciaX = this.inicioX - this._x;
distanciaY = this.inicioY - this._y;

if (Math.abs(distanciaX) < 10 && Math.abs(distanciaY) < 10){
this._x = this.inicioX;
this._y = this.inicioY;
}
}

En terminarArrastre primero paramos el arrastre. Luego, comprobamos si el clip ha sido colocado a 20 pixeles de la posición correcta, indicada por (inicioX, inicioY). ¿Cómo lo hacemos? Calculamos la distancia en cada eje, y miramos si ambas están entre -10 y 10 pixeles de la posición indicada.

La función Math.abs(numero) devuelve el valor absoluto del parametro numero, o sea el numero siempre en positivo. Hay mas funciones matemáticas que veremos mas adelante - los curiosos, mirad en la ayuda bajo Math.

De momento los clips se arrastran bien, y si los dejamos cerca de su lugar inicial vuelven a su sitio. Ahora seguimos con la funcionalidad de mezclar.

 

La mezcla

El botón mezclar tiene que poner las imagenes en posiciones aleatorias de la pantalla. Las dimensiones de nuestra escena son de 550x400 píxeles. Para que no queden fuera de la escena, vamos a generar coordenadas aleatorias hasta 50 pixeles ménos del limite en cada dirección.

Para generar numeros aleatorios en Flash, se usa la función Math.random(). Esta devuelve un numero decimal entre 0 y 1. Multiplicando por n, tenemos un número aleatorio entre 0 y n. Mirad al final de la página para mas información sobre numeros aleatorios.

botonMezclar.onRelease = mezclar;

function mezclar(){
for (i=1;i<=piezasTotales;i++){
_root["pieza"+i]._x = Math.random()*500;
_root["pieza"+i]._y = Math.random()*350;
_root["pieza"+i]._alpha = 60;
}
}

Esta función la podemos llamar al principio, después de asignar la funcionalidad de las piezas (después del for). Así empiezan en posiciones aleatorias!

mezclar();

 

Control de las piezas colocadas

De momento, no pasa nada si colocamos una pieza en su sitio. Lo que queremos es no moverla más si ya se ha colocado correctamente, y avisar al usuario cuando esté completado el juego por el clip bienHecho.

Una manera intuitiva para controlar si un clip está bien colocado es usar su valor de transparencia. Si todavia no está colocado, tendrá su _alpha a 60, si está colocado a 100. Así,

Cambiamos las dos funciones del arrastre (los cambios en negrita):

function iniciarArrastre(){
if (this._alpha < 100){
this.startDrag();
}
} function terminarArrastre(){
this.stopDrag() ;

distanciaX = this.inicioX - this._x;
distanciaY = this.inicioY - this._y;

if (Math.abs(distanciaX) < 10 && Math.abs(distanciaY) < 10){
this._x = this.inicioX;
this._y = this.inicioY;
this._alpha = 100;

_root.piezasEnSitio++;
if (_root.piezasEnSitio == _root.piezasTotales){
_root.bienHecho._visible = true;
}

}
}

Y finalmente, cambiamos la función mezclar, para que haga desaparecer el clip bienHecho, y que reinicie el valor de piezasEnSitio a 0.

function mezclar(){
for (i=1;i<=piezasTotales;i++){
_root["pieza"+i]._x = Math.random()*500;
_root["pieza"+i]._y = Math.random()*350;
_root["pieza"+i]._alpha = 60;

_root.bienHecho._visible = false;
_root.piezasEnSitio = 0;

}
}

Comprobamos el resultado.

 

Extensiones - Comentarios

Numeros aleatorios

La generación de numeros aleatorios en Flash usando Math.random() es interesante, y ofrece un montón de posibilidades. Vamos a examinarla en detalle:

En el caso que queremos un número entero, y no un número decimal, podemos usar estas funciones:

 

El objeto Math

El objeto Math nos ofrece una serie de constantes y funciones matemáticas muy útiles. Una selección de muestra incluye:

 

< indice de programación