Students Save 30%! Learn & create with unlimited courses & creative assets Students Save 30%! Save Now
Advertisement
  1. Game Development
  2. From Scratch
Gamedevelopment

Crear juego de Match-3 en Construct 2: detección de coincidencias

by
Difficulty:BeginnerLength:LongLanguages:
This post is part of a series called Make a Match-3 Game in Construct 2.
Make a Match-3 Game in Construct 2: Animations and Block Swapping
Make a Match-3 Game in Construct 2: Points, Matching, and Gravity

Spanish (Español) translation by Elías Nicolás (you can also view the original English article)

Hasta ahora, esta serie ha cubierto los aspectos básicos de la configuración de un juego de Match-3 y la implementación de los elementos iniciales del juego, como el intercambio de bloques. En este tutorial, vamos a construir sobre todo eso, y comenzar a detectar cuando el jugador ha hecho una coincidencia.


Demostración final del juego

Aquí hay una demostración del juego al que estamos trabajando a lo largo de esta serie:




1. Detectar una coincidencia

Por ahora, solo implementaremos una versión básica del sistema de coincidencia, centrándonos en encontrar cuándo existen coincidencias y destruyendo bloques coincidentes. En artículos posteriores continuaremos desarrollando y avanzando el sistema.

Sugerencia: debe leer cómo funciona una función recursiva, si aún no lo sabe; esencialmente, es una función que se llama a sí misma. Las funciones recursivas pueden funcionar de manera similar a los bucles, pero dado que también pueden tomar y devolver variables, tienen muchos más usos que los bucles.

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

  • El sistema de coincidencias iterará a través de cada instancia del objeto Block.
  • Para cada bloque Block, pasará el color y la posición del bloque que está mirando en una función recursiva, que mirará el vecino horizontal o vertical, y determinará si son del mismo color.
  • Si se encuentra una coincidencia, volverá a llamar a la función con la posición y el color del nuevo bloque, en lugar de la 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 acaba de ver como Matched con la variable de instancia IsMatched 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á cada bloque que esté marcado como una coincidencia.

Primero, necesitamos un evento que pueda iterar a través de cada Block. La forma en que construí el sistema, en realidad recorre los bloques dos veces: una para verificar las coincidencias verticales y una para verificar las coincidencias horizontales. Dependiendo de qué control está haciendo, utilizará una función diferente para buscar realmente la coincidencia.

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

Ahora, hagamos el evento que iterará a través de los bloques:

Tu código debería verse así:

Match3_Part3_FindMatches

En este caso, iteramos a través de cada bloque y los enviamos a CheckMatchesX o CheckMatchesY, las funciones que verificarán si el Block vecino es coincidencia.

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

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

Después de enviar cada bloque a una de las funciones y la función termina ejecutándose, comprueba NumMatchesFound para ver si encontró tres o más bloques coincidentes, y luego etiqueta los bloques como Matched si lo hizo.

Finalmente, cada Bloque que esté marcado como Matched se destruye después de que pase 1 segundo. Esta declaración de espera wait está ahí para permitir que el juego cambie las imágenes de los bloques a la imagen que indica que coinciden, y para darle al jugador un momento para notar este cambio.

(Si bien puedes eliminar la declaración de espera wait sin afectar negativamente el juego, hace que la coincidencia sea más fácil de entender para el jugador, y ralentiza el juego lo suficiente para que el jugador pueda realizar un seguimiento de lo que está sucediendo).


2. Las dos funciones de verificación

Luego tenemos que hacer las funciones CheckMatchesX y CheckMatchesY. Estas funciones funcionarán de manera similar a los iteradores anteriores, en el sentido de que habrá una versión para verificar las coincidencias horizontales, CheckMatchesX, y una para las coincidencias verticales, CheckMatchesY.

Cheques horizontales

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

Tu código debería verse así:

Match3_Part3_CheckMatchesX

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 que pasamos.
  • Si es así, aumenta NumMatchesFound por uno, y pasa el Bloque recién encontrado a la función 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, comprueba si encontró suficientes bloques coincidentes para crear un grupo y etiqueta los bloques como si fueran iguales.

Verificaciones verticales

Ahora, hagamos otra versión de esta función que hará lo mismo para las coincidencias verticales. Esta va a ser nuestra función CheckMatchesY. Puede copiar la función original y hacer todos los cambios apropiados, o simplemente compilarla de nuevo desde cero; en cualquier caso, así es como debe verse su función cuando esté terminada:

Tu código debería verse así:

Match3_Part3_CheckMatchesY

3. Realmente buscando cheques

Finalmente, necesitamos llamar realmente a la función FindMatches. Vaya a la función SwapBlocks y agregue un nuevo sub-evento al final de la función:

Notarás que este sub-evento en realidad no tiene ninguna condición. Si nunca has hecho un sub-evento como este antes, simplemente haz un sub-evento con cualquier condición, ya que requiere que des una condición al hacer un sub-evento, y luego borra la condición, pero deja el sub-evento. De esta forma, asegúrate de que el sub-evento siempre se ejecute.

Su evento SwapBlocks ahora debería verse así:

Match3_Part3_SwapBlocks

Si ejecuta el juego en este punto, verá que los bloques se destruyen cuando ocurren las coincidencias. También notarás que cualquier partida que esté allí cuando comience el juego no desaparecerá hasta que realices un intercambio de algún tipo. Esto es porque nunca llamamos a la función FindMatches después de que creamos la grilla 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 evitará que las coincidencias se generen automáticamente de esta manera, por lo que realmente no hay motivo para preocuparse por este problema. (Pero no dude en llamar a la función FindMatches antes, si lo desea).


4. Consolidar los cheques

En este punto, tenemos un sistema de correspondencia bastante sólido, 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 comprueba 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 verificaciones.

Si miras la función, verás que la única diferencia entre las dos versiones es que uno agrega Block.Width + 2 a la posición x del bloque, y el otro lo agrega a la posición y de Bock. Entonces, el obstáculo que tenemos que superar para hacer de esto una función única, es darle a la función una forma de agregar Block.Width + 2 a solo X, o solo a Y, sin usar una instrucción If o múltiples funciones, ya que esas requieren más Eventos para ser ejecutados.

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

  1. Eliminar el evento CheckMatchesY.
  2. Cambie el nombre del evento CheckMatchesX a, simplemente, CheckMatches.
  3. En la llamada de función para CheckMatchesX en el evento FindMatches:
    1. Modifique la llamada de función para CheckMatches en lugar de CheckMatchesX.
    2. Agregar el Parameter 3.
      1. Value = 1.
    3. Agregar el Parameter 4.
      1. Value = 0.
  4. En la llamada de función para CheckMatchesY en el evento FindMatches:
    1. Modifique la llamada de función para CheckMatches en lugar de CheckMatchesY.
    2. Agregar el Parameter 3.
      1. Value = 0.
    3. Agregar el Parameter 4.
      1. Value = 1.

Como explicaré pronto, estos parámetros adicionales le indicarán a CheckMatches si está realizando una verificación horizontal o una verificación vertical. Cuando enviamos en 1 para el Parameter 3, y en 0 para el Parameter 4, es una verificación horizontal, y cuando enviamos en 0 para el Parameter 3, y 1 para el Parameter 4, es una verificación vertical.

Ahora, regrese a la función CheckMatches y modifique las condiciones y acciones para que se vean así:

Este es el aspecto que tendrán ahora los códigos FindMatches y CheckMatches:

Match3_Part3_ModifiedCheckMatches

¿Como funciona esto?

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

Bueno, cada vez que llamas a CheckMatches estás enviando dos parámetros más, y en lugar de agregar Block.Width + 2 a la posición x o a y, agrega (Block.Width + 2) * Function.Param(3) a la posición x, y (Block.Width + 2) * Function.Param(4) a la posición y.

Como uno de esos dos parámetros siempre será 1, y el otro siempre será 0, esto significa que la posición x o la posición y será modificada, ¡nunca las dos!

Por ejemplo, si pasamos en 1 para el Parameter 3, y en 0 para el Parameter 4, entonces agrega (Block.Width + 2) * 1, que simplemente es Block.Width + 2, a la posición x, y (Block.Width + 2) * 0, que 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 comprobará la coincidencia. Digamos que en este ejemplo, el bloque original está en (200, 200) y los bloques tienen un ancho de 40. Por lo tanto, si queremos obtener la posición del bloque vertical vecino, las fórmulas funcionarían 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 funcionarí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 ejecuta el juego ahora, debería ver que el sistema de coincidencia sigue funcionando de la manera original, 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í. Mira la demostración en su forma actual.

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

Si desea tener 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. ¡Intenta mirar la función Block > Is Overlapping at Offset para obtener inspiración!

Advertisement
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.