Crear juego de "Busca las parejas" en Flash (1/2)

  Compatibilidad del artículo: ActionScript 3.0.   

Este AS necesita para funcionar importar la clase carta (Crear juego de "Busca las parejas" en Flash (2/2), la clase carta).

En este artículo se explica como hacer un juego en flash de tipo encuentra las parejas. En principio puede haber muchas formas de hacerlo, nosotros tampoco somos expertos en hacer juegos Flash, pero siempre se pueden ver códigos útiles.

El ejemplo utiliza como imágenes, una baraja de cartas, que se puede descargar aquí, aunque el código permite utilizar cualquier tipo de imagen, siempre que se nombren de forma 1, 2, 3, ....

La parte de diseño, tiene un campo de texto (txtCampos) para introducir el número de parejas que queremos, otro para el texto estático "Puntuación" (txtPunt1), otro para mostrar la puntuación (txtPunt2) y un botón para comenzar (btnComienzo).

Pasamos a explicar el código paso a paso:

  1. Se importa la Clase Carta, en este caso se encontraría en la misma carpeta que nuestro fuente.

    import Carta;

  2. Se definen los valores de la aplicación, el número máximo de imágenes, el número de imágenes por línea (para que no se salga de pantalla) y las posiciones iniciales de las cartas y sus correspondientes incrementos (si tuviesemos imagenes mayores, habría que definir valores mayores).

    // VARIABLES A DEFINIR
    const NUMCARTASMAX:int = 48;         // Número máximo de parejas de elementos
    const NUMCARTASMAXLINEA:int = 15;     // Número máximo de cartas por línea
    const POSINICIALX:int = 25;         // Posición inicial horizontal de las cartas
    const POSINICIALY:int = 100;         // Posición inicial vertical de las cartas
    const INCREMENTOX:int = 50;         // Incremento de la posición horizontal de las cartas
    const INCREMENTOY:int = 75;         // Incremento de la posición vertical de las cartas

  3. Se inicializan las variables globales y establece el listener del timer gtEspera a 1 segundo (1000 milisegundos).

    // Inicializaciones

    var gaoCartas:Array = new Array();
    var giPos:int = new int(-1);
    var giPosUltima:int = new int(-1);
    var giPuntuacion:int = new int(0);

    var gtEspera:Timer = new Timer(1000);
    gtEspera.addEventListener(TimerEvent.TIMER, cerrar_cartas);

  4. Se crea el "listener" del botón de comienzo.

    btnComienzo.buttonMode=true;
    btnComienzo.addEventListener(MouseEvent.CLICK, fl_onClick);

  5. Se crea la función del listener "fl_onClick".
    1. Se inicializan variables.

      var aiPosCartas:Array = new Array();
          
      var iPosX:int = POSINICIALX;
      var iPosY:int = POSINICIALY;
          
      var iCont:int=0;

    2. Se inicia la variable del número de cartas "iNumCartas", con el valor del campo de texto txtCampos, comprobando que no pase el máximo establecido, posteriormente, multiplica su valor por 2 (se deben crear parejas).

      var iNumCartas:int = 0;
          
      if (int(txtCampos.text) > NUMCARTASMAX)
          iNumCartas = NUMCARTASMAX;
      else
          iNumCartas = int(txtCampos.text);
          
      txtCampos.text = String(iNumCartas);

      iNumCartas *= 2;

    3. Se eliminan las posibles instancias a "carta" que se hayan podido crear anteriormente y se inicializan valores.

      // Eliminamos las "cartas" creadas anteriormente
          
          for (iCont=0; iCont < gaoCartas.length; iCont++)
              removeChild(gaoCartas[iCont].mvCarta);
          
          gaoCartas = new Array();
          
          giPosUltima = -1;
          giPuntuacion = 0;
          
          txtPunt2.replaceText(0, 100, String(giPuntuacion));

    4. Se inicializa el array de cartas (por parejas) y se desordena con la función Desordenar Array aleatoriamente en ActionScript.

      // Iniciamos el array de "cartas"
          
      var iNum:int = 0;

      for (iCont=0; iCont < iNumCartas; iCont++)
      {
          
          if (iCont % 2 == 0)
              iNum ++;
          
          aiPosCartas[iCont] = iNum;
      }

      // Lo desordenamos

      aiPosCartas = aDesordenar(aiPosCartas);

    5. Bucle donde se crean las "cartas", se añaden con addChild (sino, no se verían), se les crea un Listener de click (para cada una) pasando como parámetro la posición dentro del array global, la función se pasa mediante otra función de "transición" para poder enviar el parámetro (Pasar parámetros a la función dentro del addEventListener) y se establece "useWeakReference" a true, para que al ser eliminada la carta, se elimine el listener. Posteriormente se posiciona la "carta" y se incrementan las variables de posición.

      // Se "pintan" las cartas
      for (iCont=0; iCont < iNumCartas; iCont++)
      {
          
          gaoCartas[iCont] = new Carta(aiPosCartas[iCont]);
          
          addChild(gaoCartas[iCont].mvCarta);
          
          gaoCartas[iCont].mvCarta.addEventListener(MouseEvent.CLICK, EventoTransicion(mvCarta_onClick, iCont), false, 0, true);
          
          // Se establecen las coordenadas
          gaoCartas[iCont].mvCarta.x = iPosX;
          gaoCartas[iCont].mvCarta.y = iPosY;
          
          // Se incrementan las coordenadas
          
          if ((iCont + 1) % NUMCARTASMAXLINEA == 0)
          {
              iPosY += INCREMENTOY;
              iPosX = POSINICIALX;
          }
          else
          {
              iPosX += INCREMENTOX;
          }
          
      }

  6. Se crea la función del Listener de carta (mvCarta_onClick).
    1. Se comprueba que no se esté mostrando ya una pareja de cartas con el el evento timer, que no se haya pulsado la misma carta 2 veces, o que la carta clicada esté bloqueada (por haber encontrado ya su pareja). En cualquier caso, saldría de la función.

      if (gtEspera.running)
          return;

      if ((iPos == giPosUltima) || (gaoCartas[iPos].bBloqueado))
          return;

    2. Muestra la carta con la función "Carta_muestra" de la clase carta.

      gaoCartas[iPos].Carta_muestra();

    3. Si "giPosUltima" viene definida, es que ya hay una "carta" seleccionada.

      if (giPosUltima > -1)
      {
          
          // Seleccionada una pareja

      1. Si el valor de la anterior y la actual es el mismo, se ha encontrado la pareja, se "bloquean", se inicializa la variable de ultima carta, se incrementa el contador de puntos y se muestra.

        if (gaoCartas[giPosUltima].iValorCarta == gaoCartas[iPos].iValorCarta)
        {
            // PAREJA ENCONTRADA !!!
            gaoCartas[iPos].bBloqueado = true;
            gaoCartas[giPosUltima].bBloqueado = true;
            giPosUltima = -1;
            giPuntuacion += 10;
            
            txtPunt2.replaceText(0, 100, String(giPuntuacion));
        }

      2. En caso contrario, no se ha encontrado la pareja, guarda la posición de la carta y activa el timer para que ejecute en 1 segundo "cerrar_cartas".

        else
        {
            // PAREJA ERRONEA
            giPos = iPos;
            gtEspera.start();
        }

    4. Si giPosUltima no viene definida, se guarda su posición en "giPosUltima".

      else
      {
          giPosUltima = iPos;
      }

  7. Se llama a la función cerrar_cartas que es llamada al segundo de seleccionar una pareja errónea. Cierra ambas cartas con la función "Carta_oculta" de la clase carta, le resta uno a la puntuación, inicia la variable giPosUltima y muestra su valor. Por último, para el listener.

    function cerrar_cartas(evento:TimerEvent):void
    {
        
        gaoCartas[giPos].Carta_oculta();
        gaoCartas[giPosUltima].Carta_oculta();
        
        giPuntuacion--;
        giPosUltima = -1;
        
        txtPunt2.replaceText(0, 100, String(giPuntuacion));
        
        gtEspera.stop();
    }

  8. Se crea la función de desordenar matrices (Desordenar Array aleatoriamente en ActionScript).
  9. Se crea la función para pasar parámetros dentro de los eventos (Pasar parámetros a la función dentro del addEventListener).


ActionScript:
// Copyright © McAnam.com
// http://www.mcanam.com/articulos/Flash.php?id=4

import Carta;

// VARIABLES A DEFINIR
const NUMCARTASMAX:int = 48;         // Número máximo de parejas de elementos
const NUMCARTASMAXLINEA:int = 15;     // Número máximo de cartas por línea
const POSINICIALX:int = 25;         // Posición inicial horizontal de las cartas
const POSINICIALY:int = 100;         // Posición inicial vertical de las cartas
const INCREMENTOX:int = 50;         // Incremento de la posición horizontal de las cartas
const INCREMENTOY:int = 75;         // Incremento de la posición vertical de las cartas

// Inicializaciones

var gaoCartas:Array = new Array();
var giPos:int = new int(-1);
var giPosUltima:int = new int(-1);
var giPuntuacion:int = new int(0);

var gtEspera:Timer = new Timer(1000);
gtEspera.addEventListener(TimerEvent.TIMER, cerrar_cartas);

btnComienzo.buttonMode=true;
btnComienzo.addEventListener(MouseEvent.CLICK, fl_onClick);

function fl_onClick(evt:MouseEvent):void {
    
    var aiPosCartas:Array = new Array();
    
    var iPosX:int = POSINICIALX;
    var iPosY:int = POSINICIALY;
    
    var iCont:int=0;
    var iNumCartas:int = 0;
    
    if (int(txtCampos.text) > NUMCARTASMAX)
        iNumCartas = NUMCARTASMAX;
    else
        iNumCartas = int(txtCampos.text);
        
    txtCampos.text = String(iNumCartas);
    
    iNumCartas *= 2;
    
    // Eliminamos las "cartas" creadas anteriormente
    
    for (iCont=0; iCont < gaoCartas.length; iCont++)
        removeChild(gaoCartas[iCont].mvCarta);
    
    gaoCartas = new Array();
    
    giPosUltima = -1;
    giPuntuacion = 0;
    
    txtPunt2.replaceText(0, 100, String(giPuntuacion));
    
    // Iniciamos el array de "cartas"
    
    var iNum:int = 0;
    
    for (iCont=0; iCont < iNumCartas; iCont++)
    {
        
        if (iCont % 2 == 0)
            iNum ++;
        
        aiPosCartas[iCont] = iNum;
    }
    
    // Lo desordenamos
    
    aiPosCartas = aDesordenar(aiPosCartas);
    
    // Se "pintan" las cartas
    for (iCont=0; iCont < iNumCartas; iCont++)
    {
        
        gaoCartas[iCont] = new Carta(aiPosCartas[iCont]);
        
        addChild(gaoCartas[iCont].mvCarta);
        
        gaoCartas[iCont].mvCarta.addEventListener(MouseEvent.CLICK, EventoTransicion(mvCarta_onClick, iCont), false, 0, true);
        
        // Se establecen las coordenadas
        gaoCartas[iCont].mvCarta.x = iPosX;
        gaoCartas[iCont].mvCarta.y = iPosY;
        
        // Se incrementan las coordenadas
        
        if ((iCont + 1) % NUMCARTASMAXLINEA == 0)
        {
            iPosY += INCREMENTOY;
            iPosX = POSINICIALX;
        }
        else
        {
            iPosX += INCREMENTOX;
        }
        
    }
    
    
}

function mvCarta_onClick(evt:MouseEvent, iPos:int):void
{
    
    if (gtEspera.running)
        return;
    
    if ((iPos == giPosUltima) || (gaoCartas[iPos].bBloqueado))
        return;
    
    gaoCartas[iPos].Carta_muestra();
    
    if (giPosUltima > -1)
    {
        
        // Seleccionada una pareja
        
        if (gaoCartas[giPosUltima].iValorCarta == gaoCartas[iPos].iValorCarta)
        {
            // PAREJA ENCONTRADA !!!
            gaoCartas[iPos].bBloqueado = true;
            gaoCartas[giPosUltima].bBloqueado = true;
            giPosUltima = -1;
            giPuntuacion += 10;
            
            txtPunt2.replaceText(0, 100, String(giPuntuacion));
        }
        else
        {
            // PAREJA ERRONEA
            giPos = iPos;
            gtEspera.start();
        }
        
    }
    else
    {
        giPosUltima = iPos;
    }
    
}

function cerrar_cartas(evento:TimerEvent):void
{
    
    gaoCartas[giPos].Carta_oculta();
    gaoCartas[giPosUltima].Carta_oculta();
    
    giPuntuacion--;
    giPosUltima = -1;
    
    txtPunt2.replaceText(0, 100, String(giPuntuacion));
    
    gtEspera.stop();
}

// Copyright © McAnam.com
// http://www.mcanam.com/articulos/Flash.php?id=4

function aDesordenar(aMatriz):Array {
    
    var iAleatorio:int = 0;
    var Temp;
    
    for (var iCont:int=0; iCont < aMatriz.length; iCont++)
    {
        
        iAleatorio = Math.round(Math.random()*(aMatriz.length-1));
        
        Temp = aMatriz[iCont];
        
        aMatriz[iCont] = aMatriz[iAleatorio];
        aMatriz[iAleatorio] = Temp;
        
    }
    
    return(aMatriz);
    
}

// Copyright © McAnam.com
// http://www.mcanam.com/articulos/Flash.php?id=3

function EventoTransicion(funcion:Function, ... args):Function{
    
    return function(evento:Event):void{
        funcion.apply(funcion, new Array(evento).concat(args));
    }

}


Ejemplo:

Links relacionados:
Crear juego de "Busca las parejas" en Flash (2/2), la clase carta
Reproducir música con flash (indefinidamente)
Desordenar Array aleatoriamente en ActionScript
Pasar parámetros a la función dentro del addEventListener


Para cualquier duda, consulta, sugerencia, opinión, colaboración, etc; no dude en ponerse en contacto con nosotros

Copyright © 2002-2017 [McAnam]. Reservados todos los derechos.
www.mcanam.com