Haz un juego de Match 3 en Construct 2 Block Movement

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

Este tutorial lo llevará a través del desarrollo completo del sistema que permite que los bloques lleguen 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 respaldar el sistema de movimiento. Si bien los temas que abarco en este tutorial no son demasiado complejos, hay mucho que repasar, así que vamos a hacerlo..


Demostración final del juego

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




1. Moviendo bloques hacia arriba

Antes de comenzar a mover los bloques, debemos hacer un pequeño cambio en los eventos que generan los Bloques. Ve a la Sistema> Al inicio del diseño evento y cambiar la Y para bucle para ir desde 0 a 3, en lugar de desde 0 a 7 como lo hizo originalmente.

El evento ahora debería verse así:


La razón por la que hicimos este cambio es porque queremos que el juego comience con menos bloques en la pantalla, para que no termine tan rápido cuando agregamos un Juego terminado en el siguiente tutorial..

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

Variable global: Nombre = Tipo de velocidad actual = Valor de número = 0.2

Ahora crearemos el evento que realmente mueve los bloques:

Evento: Condición: Sistema> Cada X segundos de intervalo (segundos) = CurrentSpeed ​​Action: Bloque> Mover en ángulo Ángulo = -90 Distancia = 1

El evento debería verse así:


Si ejecutas el juego después de agregar este evento, lo primero que debes ver es que los bloques se caen, 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 nuevamente. Esto se repetirá infinitamente mientras no le hagas nada a los Bloques..

Esto sucede porque los Bloques se están moviendo más allá del punto donde se supone que la gravedad debe activarse, y están descubriendo que no hay bloques debajo de ellos, lo que hace que todos caigan. Si bien este es un problema, no es el primero que quiero ver.


2. Arreglo de cambio

Ejecuta el juego y trata de hacer un intercambio de cualquier tipo. Cuando haces esto, debes ver que los bloques comienzan a atascarse uno detrás del otro, quedando atascados en posiciones que no están alineadas con la cuadrícula y, en general, se portan mal. Hay dos razones para este problema.

El primer problema es que, aunque estamos moviendo los Bloques en sí mismos, no estamos moviendo los Bloques. Bloqueo izquierdo, Bloqueo a la derecha, TopBlock, y BottomBlock objetos con ellos, lo que significa que los bloques que utiliza para detectar intercambios no se mueven con la cuadrícula de bloques, simplemente están sentados en la posición en la que están configurados la primera vez que levanta un bloque.

Entonces, cuando intenta hacer un intercambio, los bloques se ponen fuera de lugar porque los bloques de detección de cambios no se han ajustado en absoluto a la cuadrícula. (Esta es también la razón del segundo problema que tenemos, que es que no estamos modificando las posiciones que almacenamos en el BlockPositions matriz tampoco.)

El siguiente GIF demuestra este problema:


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

Para resolver estos dos problemas, agregaremos algunas acciones más al evento que acabamos de crear:

Acción: Bloqueo inferior> Mover en ángulo Ángulo = -90 Distancia = 1 Acción: Bloqueo izquierdo> Mover en ángulo Ángulo = -90 Distancia = 1 Acción: Bloqueo a la derecha> Mover en ángulo Ángulo = -90 Distancia = 1 Acción: Bloqueo superior> Mover en ángulo = -90 Distancia = 1 Acción: BlockPositions> Establecer en XY X = 0 Y = 1 Valor = BlockPositions.At (0,1) - 1 Acción: BlockPositions> Establecer en XY X = 1 Y = 1 Value = BlockPositions.At ( 1,1) - 1

El evento ahora debería verse así:


Las primeras cuatro acciones que acabamos de añadir ajustan las posiciones de la Bloqueo izquierdo, TopBlock, Bloqueo a la derecha, y BottomBlock Objetos para que se mantengan en línea con la cuadrícula de bloques. Los segundos dos eventos ajustan los valores Y que hemos almacenado en el BlockPositions matriz para que también se mantengan en línea con la cuadrícula de bloque.

Si vuelves a probar el juego en este punto, el intercambio debería ser mayormente fijo.

En este punto, todavía hay otro problema con el que tenemos que lidiar para que el intercambio funcione correctamente. Ejecute el juego e intente hacer un intercambio a la baja con cualquiera de los bloques en la fila inferior, mientras que esa fila está parcialmente debajo del área inferior del campo de juego:

Haga el intercambio mientras los Bloques estén detrás del borde, como los resaltados en la imagen de arriba.

Si hizo esto correctamente, debería ver que no pasó nada y los bloques no se intercambiaron. Si esperó demasiado tiempo, es posible que los bloques se hayan intercambiado porque se habían movido nuevamente por encima del borde del campo de juego, por lo que si esto sucediera, intente nuevamente una vez que caigan y debería ver este problema.

Este problema es bastante simple de resolver y de entender. Si observa el código de los intercambios a la baja, debe encontrar el Evento que agregamos en el tutorial anterior que evita que el jugador realice intercambios a la baja que hagan que el Bloque caiga de la parte inferior del campo de juego. Dado que esta declaración impide que el jugador realice swaps a la baja cuando el BottomBlock el objeto es más bajo que la posición Y inicial del bloque, evita que los bloques se intercambien una vez que hayan caído y solo le permite hacer intercambios nuevamente una vez que hayan pasado de nuevo su posición original.

Para arreglar esta declaración vamos a hacer un pequeño cambio a la condición:

Condición: Bloqueo de fondo> Comparar Comparación de Y = Coordenada Y menor o igual = SPAWNY + ((Block.Width + 2) / 2)

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


Esta modificación significa que un intercambio a la baja solo puede ocurrir mientras el BottomBlock el objeto está a lo más medio bloque por debajo de la posición Y en el que comienzan los bloques. Esto también significa que, una vez que empecemos a generar nuevas filas de bloques y empujándolos en la pantalla desde la parte inferior, esos bloques solo podrán ser intercambiados De esta manera una vez 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 sean utilizables al mismo tiempo, y que no se pueda intercambiar un bloque hasta que al menos la mitad sea visible. Nuevamente, esto también ayudará cuando integramos el sistema que genera nuevas filas de bloques. Para hacer esto, agregaremos una nueva condición a cada uno de los tres eventos de intercambio restantes.

Las condiciones que agregamos serán exactamente las mismas que las que acabamos de modificar en el BottomBlock evento, excepto que se hará referencia a la TopBlock, Bloqueo a la derecha, y Bloqueo izquierdo objetos en lugar de BottomBlock objeto, dependiendo de qué evento se encuentra en.

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

Condición: TopBlock> Comparar Comparación de Y = Coordenada Y menor o igual = SPAWNY + ((Block.Width + 2) / 2)

La nueva condición para el Bloqueo izquierdo El evento debe ser:

Condición: Bloqueo izquierdo> Comparar Comparación de Y = Coordenada Y menor o igual = SPAWNY + ((Block.Width + 2) / 2)

La nueva condición para el Bloqueo a la derecha El evento debe ser:

Condición: Bloqueo a la derecha> Comparar Comparación de Y = Coordenada Y menor o igual = SPAWNY + ((Block.Width + 2) / 2)

Tu todo En la gota DragDrop El evento ahora debería verse así:


Con estas nuevas condiciones en su lugar, hemos arreglado 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. Engendrando más bloques

Ahora que los bloques avanzan a una velocidad constante, debemos hacer que las nuevas filas de bloques se generen en el momento correcto y permitir que el jugador continúe jugando todo el tiempo que quiera. Vamos a usar una función para generar las nuevas filas de bloques, y vamos a usar un evento que detecte cuando los bloques están en línea con SPAWNY para activar esa función.

Así que primero, hagamos la función en sí..

Evento: Condición: Función> En función Nombre = "SpawnNewBlocks" Condición: Sistema> Para Nombre = "X" Iniciar índice = 0 Fin de índice = 7 Acción: Sistema> Crear objeto Objeto = Bloquear capa = 1 X = SPAWNX + (loopIndex ( "X")) * (Block.Width + 2) Y = SPAWNY + (Block.Width + 2) Acción: Bloque> Valor establecido Instancia Variable = Color Valor = piso (Aleatorio (1,7)) Acción: Sistema> Agregar a Variable = NumBlocks Valor = 1

Tu nuevo evento debería verse así:


Cuando se utiliza, esta función creará una fila de bloques debajo de la fila inferior de bloques en el campo de juego. Sin embargo, tal como está ahora, en realidad no usamos esta función en ningún momento, así que hagamos el Evento que hace eso:

Evento: Condición: Sistema> Cada X segundos Intervalo (segundos) = CurrentSpeed ​​Condición: Bloque> Comparar Y Comparación = Igual a Y = SPAWNY Condición: Invertir: Bloquear> Está arrastrando Acción: Función> Función de llamada Nombre = "SpawnNewBlocks"

Tu nuevo evento debería verse así:


El evento que acabamos de crear verifica la posición Y de los bloques cada vez que se mueven. Si encuentra algún bloque que esté en línea con SPAWNY, dispara el SpawnNewBlocks () Funciona como hemos comentado anteriormente. También verifica para asegurarse de que el bloque que encuentra no sea el que está arrastrando 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 eso, todo funciona a la perfección, y se generan nuevos bloques cuando son necesarios..

Esto sucede porque, cuando el juego comienza por primera vez, procesa el código de gravedad. antes de El código que genera nuevas filas de bloques. Para solucionar esto, vamos a hacer un pequeño ajuste en el código que genera el grupo inicial de bloques para que se generen debajo del punto donde se necesitaría una nueva fila. Esto le permite evitar la ejecución del 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. Cambia la acción a esto:

Acción: Sistema> Crear objeto Objeto = Bloque de capa = 1 X = SPAWNX + (loopIndex ("X")) * (Block.Width + 2) Y = SPAWNY - (loopIndex ("Y")) * (Block.Width + 2) + 5

El evento ahora debería verse así:


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


4. Un poco de animación.

En este punto, nuestros Bloques se están moviendo, y estamos creando nuevas filas. Además de eso, recuerda que antes evitamos que el jugador usara cualquier bloque hasta que al menos la mitad del bloque esté visible. Si bien esta es una buena característica, es posible que el jugador no entienda por qué no se puede usar un bloqueo inmediatamente cuando se hace visible, incluso si no hay mucho de eso en ese momento..

Debido a este problema potencial de la interfaz de usuario, vamos a hacer que cada bloque use el sprite de bloque gris (al comienzo de los cuadros de animación del bloque) cuando esté en este estado inutilizable. Esto dejará en claro al jugador cuando un bloque sea utilizable, y nos dará la oportunidad de usar finalmente 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:


El evento que creamos también incluirá una segunda condición que verifica que el bloque que está mirando no se esté arrastrando. Esta condición nos permite asegurarnos de que cuando el jugador arrastra un bloque por debajo del punto donde los bloques se vuelven utilizables, no cambiará su imagen para que sea gris y mantendrá el color que se supone que debe ser..

Para hacer que esta animación funcione, primero necesitamos agregar un nuevo evento:

Evento: Condición: Bloque> Comparar Comparación de Y = Mayor que Y = SPAWNY + ((Block.Width + 2) / 2) Condición: Invertir: Bloquear> Está arrastrando la acción: Bloquear> Establecer marco Número de cuadro = 0

El nuevo evento debería verse así:


Ahora deberías poder probar tu juego y verás que los bloques están usando la imagen gris cuando están por debajo del punto en que se pueden usar..


5. Habilitar y deshabilitar Arrastrar / Soltar

Si ejecuta el juego ahora, notará que aunque los bloques no pueden intercambiarse entre sí cuando están en gris, los bloques grises aún pueden ser arrastrados y manipulados. Esto se debe a que nunca inhabilitamos las capacidades de arrastrar y soltar del bloque cuando evitamos que el jugador intercambie 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 desactiva el arrastre cuando el Bloque está por debajo del punto en el que se puede utilizar..

Agregue esta acción al evento que creamos anteriormente:

Acción: Bloque (DragDrop)> Establecer estado habilitado = Deshabilitado

También vamos a agregar una declaración Else para este Evento que permite que se vuelva a arrastrar el bloque una vez que esté por encima del punto en que el bloque se vuelve utilizable:

Evento: Condición: Else Acción: Bloque (DragDrop)> Establecer estado habilitado = Habilitado

Con estos dos cambios, el Evento debería verse así:


Si prueba el juego en este punto, los bloques ya no deberían poder usarse cuando están en gris, y deberían funcionar de la misma manera que siempre lo están cuando no están..


6. Cambios de velocidad

Lo último que quiero cubrir en este artículo es el sistema que nos permitirá cambiar la velocidad del juego a lo largo del tiempo. Específicamente, este es el sistema que hará que los bloques se muevan más rápido a medida que el jugador elimina más de ellos..

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

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

Variable global: SPEEDMOD Tipo = Número Valor inicial = 0.8 Constante = Sí Variable global: PointsForSpeedUp Tipo = Número Valor inicial = 400 Constante = No Variable global: PointsBetweenSpeedUps Tipo = Número Valor inicial = 400 Constante = No Variable global: POINTSFORSPEEDUPMOD Type = Número inicial valor = 1.4 Constante = Sí

Tus nuevas variables deberían verse así:


Ahora que tenemos las variables establecidas, explicaré lo que hace cada una.

  • SPEEDMOD Es la variable por la que multiplicaremos la velocidad para modificarla cada vez que el jugador alcance la cantidad de puntos que necesita para causar un aumento de velocidad..
  • PointsForSpeedUp es el número de puntos que el jugador necesita para alcanzar la siguiente velocidad.
  • Puntos entre intervalos de velocidad representa cuanto PointsForSpeedUp La variable aumentará cuando el jugador obtenga una velocidad, para ajustarla de modo que la próxima velocidad tome aún más puntos. En este momento es de 400, como PointsForSpeedUp, pero cuando el jugador realmente consigue una aceleración se multiplicará por PUNTOS PARA PODER antes de agregarse a PointsForSpeedUp.
  • Finalmente, PUNTOS PARA PODER es la variable que usaremos para modificar la cantidad de puntos que el jugador necesita para aumentar su velocidad otra vez después de la que obtuvo recientemente..

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

Ir Diseño 1 y sigue estos pasos para crear el nuevo sprite:

  1. Insertar un nuevo Duende objeto en Diseño 1.
  2. Con el editor de animaciones, abre la imagen. SpeedIncImage.png.
    1. Selecciona el Nombre a SpeedIncreaseIndicator.
    2. Selecciona el Capa a Campo de juego.
    3. Selecciona el Posición a 188, 329.
    4. Conjunto Visibilidad inicial a Invisible.
      1. Agrega un Descolorarse Comportamiento al Sprite.
      2. Conjunto Activo al inicio a No.
      3. Selecciona el Desaparecer el tiempo a 2.5.
      4. Conjunto Destruir a No.

Tu diseño ahora debería verse así:


Ahora vamos a crear el evento que cambia la velocidad:

Evento: Condición: Función> En función Nombre = "CheckForSpeedUp" Condición: Sistema> Comparar variable Variable = Puntuación Comparación = Mayor o igual Valor = PuntosForSpeedUp Acción: SpeedIncreaseIndicator> Establecer visibilidad visible = Visible Acción: SpeedIncreaseIndicator> Iniciar fundido Acción Sistema> Establecer valor Variable = Valor CurrentSpeed ​​= CurrentSpeed ​​* SPEEDMOD Action System> Establecer valor Variable = PointsBetweenSpeedUp Value = PointsBetweenSpeedUp * POINTSFORSPEEDUPMOD Action: System> Add to Variable = PointsForSpeedUp Value = PointsBetweenSpeedUp

Su evento debe verse así:


Cuando se llama a esta función, verifica 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 al hacerla visible y comenzar el desvanecimiento.
  • aumenta la velocidad multiplicándola por el modificador
  • determina la cantidad de puntos necesarios antes de la próxima aceleración, y
  • agrega ese valor al número total de puntos que el jugador necesitará tener antes de que la velocidad aumente nuevamente.

Con esta función completa, solo tenemos que asegurarnos de que se llame. Ve a la GivePoints () Funciona y agrega esta acción al final del evento principal y el sub-evento:

Acción: Función> Nombre de la función de llamada = "CheckForSpeedUp"

los GivePoints () La función ahora debería verse así:


Con ese Evento completo, deberías poder probar tu juego y ver el sistema de aceleración en acción.

Propina: A medida que jugué más, descubrí que estos valores se sentían un poco más bajos, por lo que te sugiero que te tomes un tiempo para experimentar con el sistema y encuentres los valores con los que te sientas más cómodo..


Conclusión

Hemos cubierto muchos temas diferentes en este artículo, pero todo lo que tratamos estaba directa o indirectamente relacionado con hacer que el sistema de movimiento funcionara como queríamos. Si bien tomó algún tiempo y nos exigió hacer más sistemas de los que habíamos anticipado al principio, la recompensa valió la pena y al final terminamos con un sistema muy sólido..

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

Si quieres comenzar a tratar de descubrir cómo los eliminaremos, observa cómo detectamos las coincidencias, para empezar. El sistema que creamos será muy similar a ese sistema, excepto que utilizará las coincidencias que encuentre de una manera diferente. Empiece a pensar en ello y vea qué puede hacer, y la veré aquí la próxima vez para el último tutorial principal de la serie..