Unlimited WordPress themes, graphics, videos & courses! Unlimited asset downloads! From $16.50/m
Advertisement
  1. Game Development
  2. From Scratch
Gamedevelopment

Hacer un juego de Match-3 en Construct 2: Movimiento de Bloques

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: More Swapping, Points, and Matching
Make a Match-3 Game in Construct 2: Eliminating Pre-Made Matches

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

En la parte anterior de esta serie, hicimos algunos pequeños pero importantes cambios en muchos de los sistemas que creamos para nuestro juego de Match-3. Con estas mejoras implementadas, ahora vamos a volver a ponernos en marcha e implementar uno de los dos últimos sistemas principales para el juego: el sistema de Movimiento de Bloques.

Este tutorial le llevará a través de todo el desarrollo del sistema que permite que los bloques se eleven a la parte superior de la pantalla, y también cubrirá la creación de todos los sistemas más pequeños que necesitaremos implementar para soportar el sistema de movimiento. Aunque los temas que abarco en este tutorial no son demasiado complejos, hay mucho por recorrer, así que vamos a llegar a él.


Demostración final del juego

Aquí está una demostración del juego que estamos trabajando hacia a través de esta serie:




1. Movimiento de bloques hacia arriba

Antes de empezar a mover los bloques, tenemos que hacer un pequeño cambio a los eventos que generan los bloques. Vaya al evento System> On Start of Layout y cambie el bucle Y for para ir de 0 a 3, en lugar de 0 a 7 como lo hizo originalmente.

El evento debería tener el siguiente aspecto:

ModifiedStartingBlockSpawn

La razón por la que hicimos este cambio es porque queremos que el juego comience con menos bloques en la pantalla, de modo que no termine tan rápido cuando añadamos un Game Over en el próximo tutorial.

A continuación, crearemos una variable que representará la velocidad de los bloques:

Ahora crearemos el evento que realmente mueve los bloques:

El evento debería tener este aspecto:

Match3_Part6_BlockMovementEvent1

Si ejecuta el juego después de agregar este evento, lo primero que debe ver es que los bloques se caigan, debido a la gravedad que implementamos en un tutorial anterior. Después de eso, los bloques deben subir lentamente hasta que estén en su posición original, y luego caer de nuevo. Esto se repetirá infinitamente siempre y cuando no haga nada a los bloques.

Esto sucede porque los bloques se están moviendo más allá del punto donde la gravedad se supone para golpear con el pie, y están descubriendo que no hay bloques debajo de ellos, haciendo que todos caen. Si bien esto es un problema, no es el primero que quiero mirar.


2. Arreglando el Intercambio

Ejecutar el juego, e intentar hacer un intercambio de cualquier tipo. Cuando hagas esto, deberías ver que los bloques empiezan a atascarse uno detrás de otro, quedando atascados en posiciones que no están alineadas con la cuadrícula, y generalmente se comportan mal. Hay dos razones para este problema.

La primera cuestión es que, a pesar de que estamos moviendo los bloques en sí, no estamos moviendo los objetos LeftBlock, RightBlock, TopBlock y BottomBlock con ellos, lo que significa que los bloques que usas para detectar swaps no se mueven con la rejilla del bloque Son sólo sentarse en la posición que se establecen en la primera vez que recoger un bloque.

Por lo tanto, cuando intenta hacer un intercambio, los bloques se están poniendo fuera de lugar porque los bloques de detección de intercambio no se han ajustado en absoluto a la cuadrícula. (Ésta es también la razón de la segunda edición que estamos teniendo, que es que no estamos modificando las posiciones que almacenamos en la matriz de BlockPositions tampoco.)

El GIF a continuación demuestra este problema:

UnmovingSwapBlocks

Como se puede ver en el GIF, los bloques de detección de intercambio no se mueven, aunque los bloques sí lo son.

Para solucionar ambos problemas, agregaremos algunas acciones más al evento que acabamos de crear:

El Evento ahora debe verse así:

Match3_Part6_BlockMovementEvent2

Las primeras cuatro acciones que acabamos de agregar ajustan las posiciones de los objetos LeftBlock, TopBlock, RightBlock y BottomBlock para que permanezcan en línea con la cuadrícula de bloques. Los segundos dos eventos ajustan los valores de Y que hemos almacenado en la matriz BlockPositions para que también permanezcan en línea con la cuadrícula de bloques.

Si vuelves a probar el juego en este punto, el intercambio debería ser en su mayoría arreglado.

En este punto, todavía hay un otro tema que necesitamos tratar de hacer el intercambio de trabajo correctamente. Ejecutar el juego e intentar hacer un intercambio hacia abajo con cualquiera de los bloques en la fila inferior, mientras que la fila está parcialmente por debajo de la zona inferior del campo de juego:

Match3_Part6_BlocksBehindField
Haga el intercambio mientras que los bloques están detrás de la frontera, como los destacados en la imagen de arriba.

Si lo hizo correctamente, debería ver que no sucedió nada y los bloques no se intercambiaron. Si esperó demasiado tiempo, los bloques pueden haber cambiado porque se habían movido por encima de la frontera del campo de juego de nuevo, por lo que si esto sucedió, vuelva a intentarlo una vez que se caigan y debería ver este problema ocurrir.

Esta cuestión es bastante simple de resolver y de entender. Si observa el código de los intercambios descendentes, debe encontrar el evento que agregamos en el tutorial anterior, lo que evita que el jugador realice intercambios descendentes que causen que el bloque caiga en la parte inferior del campo de juego. Dado que esta instrucción impide que el jugador realice intercambios descendentes cuando el objeto BottomBlock es inferior a la posición Y inicial del bloque, impide que los bloques se intercambien una vez que hayan caído y sólo le permita hacer intercambios de nuevo una vez que hayan pasado de su posición original de nuevo.

Para corregir esta declaracion vamos a hacer un pequeño cambio a la condición:

La condición ahora debería verse así:

Match3_Part6_ModifiedBottomSwap

Esta modificación significa que un intercambio hacia abajo sólo puede ocurrir mientras el objeto BottomBlock es como máximo un medio bloque por debajo de la posición Y en la que los bloques comienzan. Esto también significa que, una vez que comencemos a generar nuevas filas de bloques y empujándolos a la pantalla desde La parte inferior, estos bloques sólo podrán ser intercambiados de esta manera una vez que al menos la mitad del bloque es visible.

También vamos a poner una restricción similar en todos nuestros eventos de intercambio para asegurarnos de que todos ellos se conviertan en utilizables al mismo tiempo y que un bloque no pueda ser intercambiado en absoluto hasta que al menos la mitad sea visible. De nuevo, esto también ayudará cuando integremos el sistema que genera nuevas filas de bloques. Para ello, agregaremos una nueva condición a cada uno de los otros tres eventos de intercambio.

Las condiciones que agregamos serán exactamente iguales a las que acabamos de modificar en el evento BottomBlock, excepto que harán referencia a los objetos TopBlock, RightBlock y LeftBlock en lugar del objeto BottomBlock, dependiendo del evento en el que se encuentre.

La nueva condición para el evento TopBlock debe ser:

La nueva condición para el evento LeftBlock debe ser:

La nueva condición para el evento RightBlock debería ser:

Todo el evento de On DragDrop drop debería verse así:

Match3_Part6_ModifiedDragDropEvent

Con estas nuevas condiciones, hemos fijado nuestra mecánica de intercambio y hemos comenzado a preparar los sistemas existentes para el siguiente sistema que estamos agregando: el que generará nuevas filas de bloques.


3. Generar más bloques

Ahora que tenemos los bloques moviéndonos a una velocidad constante, necesitamos hacer que las nuevas filas de bloques aparezcan en el momento correcto, y permitir que el jugador continúe jugando por el tiempo que quieran. Vamos a utilizar una función para generar las nuevas filas de bloques, y vamos a utilizar un evento que detecta cuando los bloques están en línea con SPAWNY para activar esa función.

Así que primero, hagamos la función misma.

Tu nuevo Evento debería tener este aspecto:

Match3_Part6_SpawnNewBlocks

Cuando se utiliza, esta función creará una fila de bloques debajo de la fila inferior de bloques en el campo de juego. En este momento, sin embargo, en realidad no utilizamos esta función en ningún momento, así que hagamos el Evento que hace eso:

Tu nuevo Evento debería tener este aspecto:

Match3_Part6_CallSpawnNewBlocks

El Evento que acabamos de crear comprueba la posición Y de los bloques cada vez que se mueven. Si encuentra los bloques que están en línea con SPAWNY, activa la función SpawnNewBlocks() como discutimos anteriormente. También comprueba para asegurarse de que el bloque que encuentra no es el que es arrastrado por el jugador.

Si prueba su juego en este punto, funcionará, pero debería notar un problema extraño. En el momento en que comiences el juego, tus bloques caerán como si no hubiera bloques debajo de ellos, pero después de ese punto todo funciona perfectamente, y nuevos bloques se generan cuando son necesarios.

Esto sucede porque, cuando el juego comienza por primera vez, procesa el código de gravedad antes del código que genera nuevas filas de bloques. Para corregir esto vamos a hacer un pequeño ajuste al código que genera el grupo inicial de bloques para que se generen por debajo del punto donde una nueva fila sería necesario. Esto le permite evitar ejecutar el código de gravedad inmediatamente, y le permite crear la nueva fila de bloques una vez que los bloques existentes están en la ubicación correcta.

Vaya al Evento que genera el grupo inicial de bloques y modifique la Acción que realmente crea el bloque. Cambie la Acción a esto:

El Evento ahora debe verse así:

Match3_Part6_ModifiedInitialBlockSpawn

Esta modificación significa que los bloques generarán cinco píxeles por debajo de SPAWNY. Esto significa que los bloques realmente tendrán que subir cinco veces antes de que aparezca una nueva fila, y resuelve nuestro problema.


4. Un poco de animación

En este punto nuestros bloques se están moviendo, y tenemos nuevas filas que se están creando. Además de eso, recuerde que antes impedimos al jugador usar cualquier bloque hasta que al menos la mitad del bloque sea visible. Si bien esto es una buena característica, el jugador puede no entender por qué un bloque no puede ser utilizado inmediatamente cuando se hace visible, aunque no mucho de lo que es visible en ese momento.

Debido a este potencial problema de interfaz de usuario, vamos a hacer que cada bloque utilice el sprite de bloque gris (al principio de los cuadros de animación del bloque) cuando se encuentre en este estado inutilizable. Esto le dejará claro al jugador cuando un bloque se convierte en utilizable, y nos dará la oportunidad de finalmente usar nuestra última imagen de bloque.

Puede ver un ejemplo de cómo se verá cuando los Bloques pasen de estar inactivos a activos en el GIF a continuación:

BlockColorChange

El Evento que creamos también incluirá una segunda Condición que comprueba que el bloque que está viendo no está siendo arrastrado. Esta condición nos permite asegurar que cuando el jugador arrastra un bloque por debajo del punto donde los bloques se vuelven utilizables, no cambiará su imagen para que quede gris, y permanecerá el color que se supone que es.

Para que esta animación funcione, primero tenemos que añadir un nuevo Evento:

El nuevo evento debería tener este aspecto:

InactiveBlockAnimation

Ahora deberías ser capaz de probar tu juego y deberías ver que los bloques están usando la imagen gris cuando están por debajo del punto en que se vuelven utilizables.


5. Activar y desactivar arrastrar / soltar

Si ejecuta el juego ahora, notará que aunque los bloques no se pueden intercambiar entre sí cuando están en gris, los bloques grises pueden arrastrarse y manipularse. Esto se debe a que nunca desactivamos las capacidades de arrastrar / soltar del bloque cuando impedimos al jugador intercambiar con ellos.

Para evitar que los bloques grises se puedan mover, modificaremos el Evento que creamos en la sección anterior. Primero agregaremos una nueva acción que apaga el arrastrar cuando el bloque está por debajo del punto en que se convierte en utilizable.

Agregue esta Acción al Evento que creamos anteriormente:

También vamos a añadir una declaración Else para este Evento que permite que el bloque sea arrastrado de nuevo una vez que está por encima del punto en que el bloque se convierte en utilizable:

Con estos dos cambios, el Evento debería tener este aspecto:

Match3_Part6_ModifiedInactive

Si prueba el juego en este punto, los bloques ya no se pueden utilizar cuando son grises, y deben funcionar de la misma manera que siempre tienen cuando no lo son.


6. Cambios de velocidad

La última cosa que quiero cubrir en este artículo es el sistema que nos permitirá cambiar la velocidad del juego con el tiempo. Específicamente, este es el sistema que hará que los bloques se muevan más rápido, ya que el jugador elimina más de ellos.

El sistema que vamos a crear es relativamente simple: cada vez que el jugador obtiene un cierto número de puntos, la velocidad del juego aumentará basado en un modificador que vamos a crear, y el número de puntos que el jugador necesita para obtener El siguiente aumento de velocidad cambiará en función de un segundo modificador.

Antes de que podamos empezar a realizar los eventos para este sistema, crearemos un par de variables globales para manejar las nuevas funciones para nosotros:

Sus nuevas variables deberían tener este aspecto:

Match3_Part6_GlobalVariables

Ahora que tenemos las variables en su lugar, voy a explicar lo que cada uno hace.

  • SPEEDMOD es la variable que multiplicaremos la velocidad para modificarla cada vez que el jugador alcance el número de puntos que necesitan para provocar un aumento de velocidad.
  • PointsForSpeedUp es el número de puntos que el jugador necesita para alcanzar la siguiente velocidad.
  • PointsBetweenSpeedUps representa cuánto aumentará la variable PointsForSpeedUp cuando el jugador obtiene una aceleración, para ajustarla de modo que la próxima velocidad aumente aún más puntos. En este momento es 400, como PointsForSpeedUp, pero cuando el jugador realmente obtiene una aceleración se multiplicará por POINTSFORSPEEDUPMOD antes de que se agregue a PointsForSpeedUp.
  • Por último, POINTSFORSPEEDUPMOD es la variable que vamos a utilizar para modificar el número de puntos que el jugador necesita para llegar a aumentar su velocidad otra vez más allá de la que más recientemente tuvo.

Junto con la configuración de las variables, también tenemos que crear un nuevo objeto sprite que actuará como la alerta para el jugador cuando la velocidad aumenta.

Vaya a Layout 1 y siga estos pasos para crear el nuevo sprite:

  1. Inserte un nuevo objeto Sprite en el Layout 1.
  2. Con el Editor de animación, abra la imagen SpeedIncImage.png.
    1. Establezca el nombre en SpeedIncreaseIndicator.
    2. Establezca Layer a Game Field.
    3. Establezca la Position en 188, 329.
    4. Establezca Initial visibility a Invisible.
      1. Agregue un comportamiento Fade al Sprite.
      2. Establecer Active at Start a No.
      3. Ajuste el Fade out time a 2.5.
      4. Establecer Destroy a No.

Su diseño debería verse así:

Match3_Part6_SpeedLayout

Ahora vamos a crear el evento que cambia la velocidad:

Su evento debe tener este aspecto:

Match3_Part6_CheckForSpeedUp

Cuando se llama a esta función, comprueba si el jugador ha anotado suficientes puntos para garantizar un aumento de velocidad. Si tienen, entonces:

  • Activa el sprite que le dice al jugador que la velocidad ha aumentado haciéndolo visible y comenzando el Fade
  • Aumenta la velocidad multiplicándola por el modificador
  • Determina el número de puntos necesarios antes de la siguiente aceleración, y
  • Agrega ese valor al número total de puntos que el jugador necesitará tener antes de que la velocidad aumente de nuevo.

Con esta función completa, sólo tenemos que asegurarnos de que se llama. Vaya a la función GivePoints() y agregue esta Acción al final del evento principal y el sub-evento:

La función GivePoints() debería tener el siguiente aspecto:

Match3_Part6_ModifiedGivePoints

Con ese evento completo, debería ser capaz de probar su juego y ver la aceleración del sistema en acción.

Sugerencia: Mientras jugaba con él más, descubrí que estos valores se sentían un poco apagados, así que le sugiero que tome algún tiempo para experimentar con el sistema, y encontrar los valores que se sienten más cómodos con.


Conclusion

Hemos cubierto muchos temas diferentes en este artículo, pero todo lo que tratamos estaba relacionado directa o indirectamente con conseguir que el sistema de movimiento funcionara de la manera que queríamos. Mientras que tomó un cierto tiempo, y nos requirió hacer más sistemas que podríamos haber anticipado al principio, la recompensa valió la pena y terminamos para arriba con un sistema muy fuerte en el extremo.

Debido a lo mucho que ya hemos cubierto, creo que este es un buen lugar para terminar este artículo. El próximo artículo debe ser el tutorial final de esta serie y vamos a cubrir un montón de temas más pequeños dentro de él, pero lo más importante que estamos cubriendo es definitivamente la eliminación de los partidos pre-hechos.

Si desea empezar a tratar de averiguar cómo vamos a eliminarlos, eche un vistazo a cómo detectar los partidos para empezar. El sistema que creamos será muy similar a ese sistema, excepto que utilizará las coincidencias que encuentre de una manera diferente. Comienza a pensar en ello y verás lo que puedes imaginar, y te veré aquí la próxima vez para el último gran tutorial de la serie.

Advertisement
Advertisement
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.