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

Cómo detectar cuando un objeto ha sido rodeado por un gesto

by
Read Time:12 minsLanguages:

Spanish (Español) translation by Luis Chiabrera (you can also view the original English article)

Nunca eres demasiado viejo para un juego de Spot the Difference. Recuerdo jugarlo de niño, ¡y ahora encuentro que mi esposa todavía juega ocasionalmente! En este tutorial, veremos cómo detectar cuándo se ha dibujado un anillo alrededor de un objeto, con un algoritmo que se podría usar con el mouse, el lápiz óptico o la entrada de la pantalla táctil.


Nota: Aunque las demostraciones y el código fuente de este tutorial utilizan Flash y AS3, debería poder usar las mismas técnicas y conceptos en casi cualquier entorno de desarrollo de juegos.


Vista previa del resultado final

Echemos un vistazo al resultado final en el que trabajaremos. La pantalla está dividida en dos imágenes, que son casi idénticas pero no del todo. Intenta detectar las seis diferencias y encierra en un círculo las de la imagen de la izquierda. ¡Buena suerte!

Nota: ¡No tienes que dibujar un círculo perfecto! Solo necesitas dibujar un anillo aproximado o un bucle alrededor de cada diferencia.

¿No tienes flash? Echa un vistazo a esta demostración de vídeo:


Paso 1: El movimiento circular

Usaremos algunos cálculos vectoriales en el algoritmo. Como siempre, es bueno entender las matemáticas subyacentes antes de aplicarlas, así que aquí hay un breve repaso de las matemáticas vectoriales.

Vector definitionVector definitionVector definition

La imagen de arriba muestra el vector A desglosado en sus componentes horizontal y vertical (Ax y Ay, respectivamente).

Ahora veamos la operación del producto punto, ilustrada en la siguiente imagen. Primero, verá la operación del producto de puntos entre los vectores A y B.

Vector mathVector mathVector math

Para encontrar el ángulo intercalado entre los dos vectores, podemos hacer uso de este producto de puntos.

| A | y | B | denota las magnitudes de los vectores A y B, así dados | A | y | B | y A punto B, lo que queda desconocido es theta. Con un poco de álgebra (como se muestra en la imagen), se produce la ecuación final, que podemos usar para encontrar theta.

Para obtener más información sobre el producto vector dot, consulte la siguiente página de Wolfram.

La otra operación útil es el producto cruzado. Echa un vistazo a la operación a continuación:

Cross vector

Esta operación es útil para encontrar si el ángulo intercalado es hacia la derecha o hacia la izquierda con respecto a un vector específico.

Déjame elaborar más. Para el caso del diagrama anterior, la rotación de A a B es en el sentido de las agujas del reloj, por lo que A es B negativo. La rotación de B a A es en sentido contrario a las agujas del reloj, por lo que B en A es positivo. Tenga en cuenta que esta operación es sensible a la secuencia. Una cruz B producirá un resultado diferente de B cruz A.

Eso no es todo. Sucede que en el espacio de coordenadas de muchas plataformas de desarrollo de juegos, el eje y se invierte (y aumenta a medida que avanzamos hacia abajo). Por lo tanto, nuestro análisis se invierte, y A cruz B será positivo mientras que B cruz A es negativo.

Eso es suficiente revisión. Vayamos a nuestro algoritmo.


Paso 2: Interacción en círculos

Los jugadores deberán rodear el detalle correcto en la imagen. Ahora, ¿cómo hacemos eso? Antes de responder a esta pregunta, debemos calcular el ángulo entre dos vectores. Como recordará ahora, podemos usar el producto punto para esto, así que implementaremos esa ecuación aquí.

Aquí hay una demostración para ilustrar lo que estamos haciendo. Arrastre cualquiera de las flechas para ver los comentarios.

Vamos a ver cómo funciona esto. En el código a continuación, simplemente he inicializado los vectores y un temporizador, y puse algunas flechas interactivas en la pantalla.

Cada 50 milisegundos, la siguiente función se ejecuta y se usa para actualizar la retroalimentación gráfica y de texto:

Notará que la magnitud para v1 y v2 son 1 unidad en este escenario (verifique las líneas 52 y 53 resaltadas arriba), por lo que omití la necesidad de calcular la magnitud de los vectores por ahora.

Si desea ver el código fuente completo, consulte Demo1.as en la descarga de la fuente.


Paso 3: Detectar un círculo completo

Ok, ahora que hemos entendido la idea básica, ahora la usaremos para verificar si el jugador circuló un punto con éxito.

Calculate the angles

Espero que el diagrama habla por sí mismo. El inicio de la interacción es cuando se presiona el botón del mouse, y el final de la interacción es cuando se suelta el botón del mouse.

En cada intervalo (de, por ejemplo, 0,01 segundos) durante la interacción, calcularemos el ángulo intercalado entre los vectores actuales y anteriores. Estos vectores se construyen desde la ubicación del marcador (donde está la diferencia) a la ubicación del mouse en esa instancia. Sume todos estos ángulos (t1, t2, t3 en este caso) y si el ángulo formado es de 360 grados al final de la interacción, entonces el jugador ha dibujado un círculo.

Por supuesto, puede ajustar la definición de un círculo completo para que sea de 300-340 grados, dando espacio a los errores del jugador al realizar el gesto del mouse.

Aquí hay una demostración de esta idea. Arrastra un gesto circular alrededor del marcador rojo en el medio. Puede mover la posición del marcador rojo usando las teclas W, A, S, D.


Paso 4: La Implementación

Examinemos la implementación de la demo. Veremos los cálculos importantes aquí.

Verifique el código resaltado a continuación y cópielo con la ecuación matemática en el Paso 1. Notará que el valor para arccos a veces produce Not a Number (NaN) si salta la línea 92. Además, constants_value a veces excede de 1 debido a imprecisiones de redondeo, por lo que necesitamos devolverlo manualmente a un máximo de 1. Cualquier número de entrada para arccos más de 1 producirá un NaN.

La fuente completa para esto se puede encontrar en Demo2.as


Paso 5: El defecto

Un problema que puede ver es que mientras dibuje un círculo grande que encierre el lienzo, el marcador se considerará en un círculo. No necesito saber dónde está el marcador.

Bueno, para contrarrestar este problema, podemos verificar la proximidad del movimiento circular. Si el círculo se dibuja dentro de los límites de un cierto rango (cuyo valor está bajo su control), solo entonces se considera un éxito.

Echa un vistazo al código de abajo. Si alguna vez el usuario supera MIN_DIST (con un valor de 60 en este caso), entonces se considera una suposición aleatoria.

De nuevo, trata de rodear el marcador. Si crees que el MIN_DIST es un poco implacable, siempre se puede ajustar para adaptarse a la imagen.


Paso 6: Diferentes formas

¿Qué pasa si la "diferencia" no es un círculo exacto? Algunos pueden ser rectangulares, triangulares o cualquier otra forma.
En estos casos, en lugar de utilizar un solo marcador, podemos colocar algunos:

Circling multiple cirlceCircling multiple cirlceCircling multiple cirlce

En el diagrama de arriba, se muestran dos cursores de ratón en la parte superior. Comenzando con el cursor situado más a la derecha, realizaremos un movimiento circular en el sentido de las agujas del reloj hacia el otro extremo de la izquierda. Tenga en cuenta que la ruta rodea los tres marcadores.

También he dibujado los ángulos transcurridos por este camino en cada uno de los marcadores (guiones claros a guiones oscuros). Si los tres ángulos son más de 360 grados (o el valor que elija), solo entonces lo contamos como un círculo.

Pero eso no es suficiente. ¿Recuerdas la falla en el paso 4? Bueno, lo mismo ocurre aquí: tendremos que verificar la proximidad. En lugar de requerir que el gesto no exceda un radio determinado de un marcador específico, solo verificaremos si el cursor del mouse se acercó a todos los marcadores para al menos una breve instancia. Usaré pseudocódigo para explicar esta idea:


Paso 7: Demo para la Idea

Aquí, estamos usando tres puntos para representar un triángulo.

Trate de rodear alrededor:

  • un punto
  • dos puntos
  • tres puntos

... en la imagen de abajo. Tenga en cuenta que el gesto solo tiene éxito si contiene los tres puntos.

Veamos el código de esta demo. He resaltado las líneas clave para la idea a continuación; El script completo está en Demo4.as.


Paso 8: Dibujando los círculos

El mejor método para dibujar realmente la línea que traza dependerá de su plataforma de desarrollo, por lo que solo describiré el método que usaríamos en Flash aquí.

Actionscript drawing APIActionscript drawing APIActionscript drawing API

Hay dos formas de dibujar líneas en AS3, como se indica en la imagen de arriba.

El primer enfoque es bastante simple: use moveTo () para mover la posición de dibujo a coordinar (10, 20). Luego dibuja una línea para conectar (10, 20) a (80, 70) usando lineTo ().

El segundo enfoque es almacenar todos los detalles en dos matrices, commands [] y coords [] (con las coordenadas almacenadas en pares (x, y) dentro de coords []) y luego dibujar todos los detalles gráficos en el lienzo usando drawPath () en un sola Disparo. He optado por el segundo enfoque en mi demo.

Compruébelo: intente hacer clic y arrastrar el mouse sobre el lienzo para dibujar una línea.

Y aquí está el código AS3 para esta demo. Echa un vistazo a la fuente completa en Drawing1.as.

En Flash, el uso del objeto graphics para dibujar de esta manera utiliza el procesamiento en modo retenido, lo que significa que las propiedades de las líneas individuales se almacenan por separado, a diferencia del procesamiento en modo inmediato, donde solo se almacena la imagen final. (Los mismos conceptos existen en otras plataformas de desarrollo; por ejemplo, en HTML5, dibujar en SVG usa el modo retenido, mientras que dibujar en lienzo usa el modo inmediato).

Si hay muchas líneas en la pantalla, entonces almacenarlas y volver a renderizarlas todas por separado puede hacer que su juego sea lento y lento. La solución dependerá de su plataforma: en Flash, puede usar BitmapData.draw () para almacenar cada línea en un solo mapa de bits una vez que se haya dibujado.


Paso 9: Nivel de muestra

Aquí he creado una demostración para el nivel de muestra de un juego Spot the Difference. ¡Echale un vistazo! La fuente completa está en Sample2.as de la descarga de la fuente.

Conclusión

Gracias por leer este artículo; Espero que te haya dado una idea para construir tu propio juego. Deje algunos comentarios si hay algún problema con el código y le responderé lo antes posible.

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.