Haz un juego de Match 3 en Construct 2 Match Detection

Hasta ahora, esta serie ha cubierto los conceptos básicos de configurar un juego de Match-3 e implementar los elementos de juego iniciales, como el intercambio de bloques. En este tutorial, vamos a desarrollar todo eso y comenzar a detectar cuándo el jugador ha hecho una coincidencia..


Demostración final del juego

Aquí está una demostración del juego en el que estamos trabajando a lo largo de esta serie:




1. Detectar un partido

Por ahora, solo vamos a implementar una versión básica del sistema de emparejamiento, centrándonos en encontrar cuándo existen emparejamientos y destruir bloques emparejados. En artículos posteriores seguiremos desarrollando y avanzando el sistema..

Propina: Debes leer cómo funciona una función recursiva, si aún no lo sabes; Básicamente, es una función que se llama a sí misma. Las funciones recursivas pueden funcionar de manera similar a los bucles, pero como también pueden admitir y devolver variables, tienen muchos más usos que los bucles..

Al igual que con el tutorial anterior, primero quiero discutir cómo funcionará el sistema y luego intentar construirlo.

  • El sistema de emparejamiento se repetirá a través de cada instancia del Bloquear objeto.
  • Para cada Bloquear, pasará el color y la posición del bloque que está viendo en una función recursiva, que observará el vecino horizontal o vertical, y determinará si son del mismo color.
  • Si se encuentra una coincidencia, llamará a la función nuevamente con la posición y el color del nuevo bloque, en lugar del original..
  • Esto continuará hasta que no encuentre ninguna coincidencia. En ese punto, comprobará cuántas coincidencias encontró.
  • Si encuentra tres o más coincidencias, marca todos los bloques que simplemente vio como Emparejado con el Ismatched variable de instancia que hicimos en uno de los tutoriales anteriores; de lo contrario, no hace nada.
  • Finalmente, una vez que se hayan verificado todos los bloques, la función destruirá todos los bloques marcados como coincidentes.

Primero, necesitamos un evento que pueda iterar a través de cada Bloquear. La forma en que construí el sistema, en realidad itera a través de los bloques dos veces: una vez para verificar coincidencias verticales, y una vez para verificar coincidencias horizontales. Dependiendo de la verificación que haga, utilizará una función diferente para buscar la coincidencia..

Lo primero que tenemos que hacer es hacer un Variable global para realizar un seguimiento de cuántos bloques coincidentes hemos encontrado en una iteración determinada:

Nombre de variable global: "NumMatchesFound" Type = Number Value = 0

Ahora, hagamos el Evento que recorrerá los bloques:

Evento: Función> Nombre de la función: Subvento "FindMatches": Sistema> Para cada objeto: Acción de bloque: Sistema> Establecer valor NumMatchesFound = 1 Acción: Función> Nombre de la función de llamada: "CheckMatchesX" Parámetro 0: Block.X Parámetro 1 : Bloque.Y Parámetro 2: Sub-Evento Bloque.Color: Sistema> Comparar Variable NumMatchesFound> = 3 Acción: Bloque> Establecer Boolean IsMatched = Verdadero Sub-Evento: Sistema> Para cada objeto: Bloquear acción: Sistema> Establecer valor NumMatchesFound = 1 Acción: Función> Nombre de la función de llamada: "CheckMatchesY" Parámetro 0: Block.X Parámetro 1: Block.Y Parámetro 2: Block.Color Sub-Evento: System> Compare Variable NumMatchesFound> = 3 Action: Block> Set Boolean IsMatched = True Sub-Event: Block> Es el conjunto de variables de instancia Boolean System> Wait Second = 0.1 Block> Destroy

Tu código debería verse así:


En este caso, recorremos cada bloque y los enviamos a CheckMatchesX o CheckMatchesY, Las funciones que verifican si el Bloque vecino es una coincidencia..

Para enviar el bloque a la función, pasamos las funciones a tres parámetros diferentes:

  • Parámetro 0 es la posición X del bloque
  • Parámetro 1 es la posición Y del bloque
  • Parámetro 2 es el color.

Después de que cada bloque se envía a una de las funciones y la función termina de ejecutarse, se comprueba NumMatchesFound para ver si encontró tres o más Bloques coincidentes, y luego etiqueta los Bloques como Emparejado si lo hiciera.

Finalmente, cada Bloque que está marcado como siendo Emparejado se destruye después de .1 segundos pasa. Esta Espere La declaración está ahí para permitir que el juego cambie las imágenes de los Bloques a la imagen que indica que están emparejadas, y le da al jugador un momento para notar este cambio..

(Mientras que usted podría quitar el Espere sin afectar negativamente el juego, hace que el juego sea más fácil de entender y ralentiza el juego lo suficiente como para que el jugador pueda realizar un seguimiento de lo que está pasando.)


2. Las dos funciones de verificación

A continuación tenemos que hacer el CheckMatchesX y CheckMatchesY funciones Estas funciones funcionarán de manera similar a los iteradores anteriores, ya que habrá una versión para verificar coincidencias horizontales, CheckMatchesX, y uno para cerillas verticales, CheckMatchesY.

Controles horizontales

Primero, construyamos la función de verificación horizontal:

Evento: Función> En función Nombre: Subevento "CheckMatchesX": Condición: Bloque> Comparar XX = Función.Param (0) + (Block.Width + 2) Condición: Bloque> Comparar YY = Función.Param (1) Condición : Bloque> Comparar variable de instancia Color = Función. Parámetros (2) Acción: Sistema> Agregar a Variable = NumBlocks Valor = 1 Acción: Función> Nombre de la función de llamada: "CheckMatchesX" Parámetro 0: Función.Param (0) + (Bloque. Ancho + 2) Parámetro 1: Function.Param (1) Parámetro 2: Function.Param (2) Sub-Evento: System> Compare Variable NumMatchesFound> = 3 Action: Block> Set Boolean IsMatched = True

Tu código debería verse así:


Entonces, ¿qué está haciendo esta función?

  • Primero, prueba para ver si existe un bloque vecino a la izquierda del bloque que pasamos.
  • Una vez que la función confirma que hay un Bloque en la ubicación vecina, verifica si es del mismo color que el Bloque al que pasamos.
  • Si es así, aumenta. NumMatchesFound por uno, y pasa el Bloque recién encontrado a la función tal como lo hizo para el original.
  • Esto continúa hasta que encuentra un Bloque que no es del mismo color que el original. En ese punto, verifica si encontró suficientes bloques coincidentes para crear un grupo, y etiqueta los bloques como coincidencias si lo hiciera.

Controles verticales

Ahora, hagamos otra versión de esta función que haga lo mismo para las coincidencias verticales. Esta va a ser nuestra CheckMatchesY función. Puede copiar la función original y hacer todos los cambios apropiados, o simplemente compilarla nuevamente desde cero; en cualquier caso, aquí es cómo debe verse su función cuando se termina:

Evento: Función> Activado Nombre de la función: Subevento "CheckMatchesY": Condición: Bloque> Comparar XX = Función.Param (0) Condición: Bloque> Comparar YY = Función.Param (1) + (Block.Width + 2) Condición : Bloque> Comparar variable de instancia Color = Función. Parámetros (2) Acción: Sistema> Agregar a Variable = NumBlocks Valor = 1 Acción: Función> Nombre de la función de llamada: "CheckMatchesY" Parámetro 0: Función.Param (0) Parámetro 1: Función .Param (1) + (Block.Width + 2) Parámetro 2: Function.Param (2) Sub-Evento: Sistema> Comparar Variable NumMatchesFound> = 3 Action: Block> Set Boolean IsMatched = True

Tu código debería verse así:



3. En realidad buscando cheques

Finalmente, necesitamos llamar al FindMatches función. Ve a la SwapBlocks Función y agregar un nuevo sub-evento al final de la función:

Evento: Función> Subevento: Acción: Función> Nombre de la función de llamada: "FindMatches"

Notarás que este sub-evento en realidad no tiene ninguna condición. Si nunca ha realizado un subevento como este antes, simplemente cree un subevento con cualquier condición, ya que requiere que usted presente una condición al crear un subevento y luego elimine la condición, pero deje la sub-evento. De esta manera, te aseguras de que el sub-evento siempre se ejecute.

Tu SwapBlocks El evento ahora debería verse así:

Si ejecuta el juego en este punto, verá que los bloques se destruyen cuando se producen las coincidencias. Sin embargo, también notarás que cualquier partido que esté allí cuando comience el juego no desaparecerá hasta que hagas un intercambio de algún tipo. Esto es porque nunca llamamos al FindMatches Funciona despues de crear la cuadrícula de bloques..

La razón por la que no hemos agregado este código es porque en la versión final habrá otra función que evita que las coincidencias se generen automáticamente de esta manera, por lo que realmente no hay razón para preocuparse por este problema. (Pero no dude en llamar al FindMatches funciona antes, si lo desea.)


4. Consolidando los cheques

En este punto, tenemos un sistema de concordancia bastante fuerte, pero el problema es que nuestro código es redundante. Actualmente, tenemos dos funciones diferentes que verifican si hay un vecino que coincida, y la única diferencia entre ellos es que uno verifica verticalmente y el otro verifica horizontalmente.

Dado que la versión gratuita de Construct 2 limita la cantidad de eventos que podemos tener, esto definitivamente es un desperdicio. Para resolver esto, vamos a hacer una nueva versión de la función que puede hacer ambas comprobaciones..

Si observa la función, verá que la única diferencia entre las dos versiones es que se agrega una Block.Width + 2 a la posición x del Bloque, y el otro lo agrega a la posición y del Bock. Entonces, el obstáculo que tenemos que superar para hacer de esta una función única, es darle a la función una forma de agregar Block.Width + 2 a solo X, o solo Y, sin usando una Si Declaración o múltiples funciones, ya que requieren más eventos para ser ejecutados..

Mi solución para esto no es muy compleja, pero será más fácil de entender si podemos verlo en conjunto, así que lo implementaremos y explicaré cómo funciona una vez que podamos verlo todo en acción..

  1. Eliminar el CheckMatchesY evento.
  2. Renombrar CheckMatchesX evento a, simplemente, CheckMatches.
  3. En la llamada de función para CheckMatchesX bajo la FindMatches evento:
    1. Modificar la llamada de función para que sea para CheckMatches en lugar de CheckMatchesX.
    2. Añadir Parámetro 3.
      1. Valor = 1.
    3. Añadir Parámetro 4.
      1. Valor = 0.
  4. En la llamada de función para CheckMatchesY bajo la FindMatches evento:
    1. Modificar la llamada de función para que sea para CheckMatches en lugar de CheckMatchesY.
    2. Añadir Parámetro 3.
      1. Valor = 0.
    3. Añadir Parámetro 4.
      1. Valor = 1.

Como explicaré pronto, estos parámetros añadidos dirán CheckMatches Si se está haciendo una verificación horizontal o una verificación vertical. Cuando enviamos 1 para Parámetro 3, y 0 para Parámetro 4, Es una verificación horizontal, y cuando enviamos 0 para Parámetro 3, y 1 para Parámetro 4, es un cheque vertical.

Ahora, vuelve a la CheckMatches Funciona, y modifica las condiciones y acciones para lucir así:

Evento: Función> En función Nombre: Subventanas "CheckMatches": Condición: Bloque> Comparar XX = Función.Param (0) + ((Block.Width + 2) * Function.Param (3)) Condición: Bloque> Comparar YY = Function.Param (1) + ((Block.Width + 2) * Function.Param (4)) Condición: Bloque> Comparar variable de instancia Color = Function.Param (2) Action: Block> Set Boolean IsMatched = True Action : Función> Nombre de la función de llamada: "CheckMatches" Parámetro 0: Function.Param (0) + ((Block.Width + 2) * Function.Param (3)) Parámetro 1: Function.Param (1) + ((Block. Ancho + 2) * Función. Parámetro (4)) Parámetro 2: Función. Parámetro (2) Parámetro 3: Función. Parámetro (3) Parámetro 4: Función. Parámetros (Sub) Evento: Sistema> Comparar variables NumMatchesFound> = 3 Acción: Bloquear> Establecer Booleano IsMatched = Verdadero

Esto es lo que tu FindMatches y CheckMatches El código ahora debería verse como:


Como funciona esto?

Entonces, ¿qué está haciendo esta nueva versión de la función??

Bueno, cuando llames CheckMatches ahora está enviando dos parámetros más, y en lugar de agregar Block.Width + 2 a la posición xo a la posición y, se agrega (Block.Width + 2) * Function.Param (3) a la posición x, y (Block.Width + 2) * Function.Param (4) a la posición y.

Dado que uno de esos dos parámetros siempre será 1, y el otro siempre será 0, esto significa que se modificarán la posición x o la posición y, nunca ambas!

Por ejemplo, si pasamos en 1 para Parámetro 3, y 0 para Parámetro 4, entonces agrega (Block.Width + 2) * 1, que es simplemente Block.Width + 2, a la posición x, y (Block.Width + 2) * 0, cual es 0, a la posición y.

Aquí hay un ejemplo rápido para mostrar lo que quiero decir y cómo calcula la posición del bloque donde se verificará la coincidencia. Digamos que en este ejemplo el Bloque original está en (200, 200), y los bloques tienen un ancho de 40. Entonces, si queremos obtener la posición del Bloque vertical vecino, las fórmulas funcionarán así:

  • X = 200 + ((Block.Width + 2) * 0) = 200 + (40 + 2) * 0 = 200 + 0 = 200
  • Y = 200 + ((Block.Width + 2) * 1) = 200 + (40 + 2) * 1 = 200 + 42 = 242

Si quisiéramos obtener la posición del Bloque horizontal vecino, las fórmulas se resolverían así:

  • X = 200 + ((Block.Width + 2) * 1) = 200 + (40 + 2) * 1 = 200 + 42 = 242
  • Y = 200 + ((Block.Width + 2) * 0) = 200 + (40 + 2) * 0 = 200 + 0 = 200

Si ejecutas el juego ahora, deberías ver que el sistema de partidos sigue funcionando como lo hizo originalmente, pero desde nuestro punto de vista, en realidad es un sistema mejor..


Conclusión

En este punto, nuestra función de detección de coincidencias aún está incompleta, pero ya hemos hecho mucho en este tutorial y creo que es importante dejar que todo esto se hunda antes de agregar algo más. Con eso en mente, voy a terminar este artículo aquí. Echa un vistazo a la demostración en su forma actual.

En el siguiente artículo agregaremos un sistema de puntos, mejoraremos el sistema de emparejamiento y agregaremos "gravedad" para que los Bloques caigan cuando se eliminen los Bloques debajo de ellos..

Si desea obtener una ventaja en el próximo artículo, tómese un tiempo para considerar cómo detectaría cuando haya un espacio vacío debajo de un Bloque. Trata de mirar el Bloquear> Se superpone en la compensación función para la inspiración!