Jump to content
UnitySpain
Whiter

Mover un selector entre bloques colocados irregularmente

Recommended Posts

Buenas tardes, mi problema es el siguiente.

Estoy intentando encontrar la forma de mover un selector utilizando teclas (WASD) entre bloques colocados de forma irregular.

image.png

La idea es que si pulsas W, vaya al más cercano hacia arriba, al pulsar D al mas cercano hacia la derecha y así con el resto de teclas.
He mirado que se pueden crear grids, pero no he visto como utilizarlas con bloques separados.


Gracias de antemano.

Share this post


Link to post
Share on other sites

Hay muchas maneras de solventar este "puzzle". Unas más complejas y otras más sencillas.

De entrada, esto es una matriz fija o pueden haber más columnas/filas?

Puede haber más de un objeto alrededor a distinta altura? Es decir, hay solo una posibilidad de objeto para los dos ejes o más de una?

 

Share this post


Link to post
Share on other sites
21 minutes ago, iRobb said:

Hay muchas maneras de solventar este "puzzle". Unas más complejas y otras más sencillas.

De entrada, esto es una matriz fija o pueden haber más columnas/filas?

Puede haber más de un objeto alrededor a distinta altura? Es decir, hay solo una posibilidad de objeto para los dos ejes o más de una?

 

La idea es usarlo para un tower defense, por lo que dependiendo del mapa habrá más o menos columnas y filas, y colocadas de forma diferente.
El juego es en 2D, por lo que todos estarían a la misma altura.

Share this post


Link to post
Share on other sites

Para sumar otra forma a lo que comentaron, podría ser simplemente crear esas conexiones midiendo las distancias entre todos los puntos, luego determinando si pertenecen a der, izq arriba o abajo, y finalmente quien tenga la menor distancia dentro de uno de estos grupos gana el lugar (esto para un item, hay que hacerlo para todos).

Untitled.jpg

Las zonas las determinas mediante ángulos, si el ángulo signado entre Vector2.right y el punto de interés (naranja en la figura) ) fuera de α entonces:

  • -45 < α  < 45 --> R
  • 45  < α  < 135 --> W
  • 135 < α  < 180 o -180 < α  < -135 ---> A
  • -45 < α  < -135 --> S

Una vez que sabés a que zona pertenece tomás al menos distante. Podés optimizar un poco el tema del orden en el que hacés las cosas pero la idea es esa.

Share this post


Link to post
Share on other sites

He probado a hacerlo, pero no funciona del todo bien. El código es el siguiente:

 

Primero meto en un array todos los bloques de la escena:

allTiles = GameObject.FindGameObjectsWithTag("A");

 

Luego, con un for los clasifico en 4 listas comparando sus posiciones x e y con el selector.

for (int t = 0; t < allTiles.Length; t++)
        {
            if (allTiles[t].transform.position.x > transform.position.x)
            {
                rightTiles.Add(allTiles[t]);
            }
            if (allTiles[t].transform.position.x < transform.position.x)
            {
                leftTiles.Add(allTiles[t]);
            }
            if (allTiles[t].transform.position.y > transform.position.y)
            {
                upTiles.Add(allTiles[t]);
            }
            if (allTiles[t].transform.position.y < transform.position.y)
            {
                downTiles.Add(allTiles[t]);
            }
        }

Por ultimo, busco el tile mas cercano de cada una de las listas para meterlo en una variable.
 

for (int i = 0; i < rightTiles.Count; i++)
            if (rightTiles[i].transform.position.x < minval)
            {
                if (rightTiles[i].transform.position.y < transform.position.y + 1 && rightTiles[i].transform.position.y > transform.position.y - 1)
                {
                    minval = rightTiles[i].transform.position.x;
                    lowestIndex = i;
                }

            }

        if(lowestIndex == -1)
        {
            minval = 1000000;
            //Más a la izquierda de todas. (Menor valor y de la lista izquierda)
            for (int i = 0; i < leftTiles.Count; i++)
                if (leftTiles[i].transform.position.x < minval)
                {
                    if (leftTiles[i].transform.position.y < transform.position.y + 1 && leftTiles[i].transform.position.y > transform.position.y - 1)
                    {
                        minval = leftTiles[i].transform.position.x;
                        lowestIndex = i;
                    }

                }

                rightTile = leftTiles[lowestIndex];
        }
        else rightTile = rightTiles[lowestIndex];
        
        
        
        minval = 1000000;
        lowestIndex = -1;

        for (int i = 0; i < leftTiles.Count; i++)
            if (leftTiles[i].transform.position.x < minval)
            {
                if (leftTiles[i].transform.position.y < transform.position.y + 1 && leftTiles[i].transform.position.y > transform.position.y - 1)
                {
                    minval = leftTiles[i].transform.position.x;
                    lowestIndex = i;
                }

            }

        if (lowestIndex == -1)
        {
            minval = -1000000;
            //Más a la derecha de todas. (Mayor valor y de la lista derecha)
            for (int i = 0; i < rightTiles.Count; i++)
                if (rightTiles[i].transform.position.x > minval)
                {
                    if (rightTiles[i].transform.position.y < transform.position.y + 1 && rightTiles[i].transform.position.y > transform.position.y - 1)
                    {
                        minval = rightTiles[i].transform.position.x;
                        lowestIndex = i;
                    }

                }

            leftTile = rightTiles[lowestIndex];
        }
        else leftTile = leftTiles[lowestIndex];

        
        
        minval = 1000000;
        lowestIndex = -1;

        for (int i = 0; i < upTiles.Count; i++)
            if (upTiles[i].transform.position.y < minval)
            {
                if (upTiles[i].transform.position.x < transform.position.x + 1 && upTiles[i].transform.position.x > transform.position.x - 1)
                {
                    minval = upTiles[i].transform.position.y;
                    lowestIndex = i;
                }

            }

        if (lowestIndex == -1)
        {
            minval = 1000000;
            //Más a la derecha de todas. (Mayor valor y de la lista derecha)
            for (int i = 0; i < downTiles.Count; i++)
                if (downTiles[i].transform.position.y < minval)
                {
                    if (downTiles[i].transform.position.x < transform.position.x + 1 && downTiles[i].transform.position.x > transform.position.x - 1)
                    {
                        minval = downTiles[i].transform.position.y;
                        lowestIndex = i;
                    }

                }

            upTile = downTiles[lowestIndex];
        }
        else upTile = upTiles[lowestIndex];
        #endregion
        #region DownTiles
        minval = 1000000;
        lowestIndex = -1;

        for (int i = 0; i < downTiles.Count; i++)
            if (downTiles[i].transform.position.y < minval)
            {
                if (downTiles[i].transform.position.x < transform.position.x + 1 && downTiles[i].transform.position.x > transform.position.x - 1)
                {
                    minval = downTiles[i].transform.position.y;
                    lowestIndex = i;
                }

            }

        if (lowestIndex == -1)
        {
            minval = -1000000;

            for (int i = 0; i < upTiles.Count; i++)
                if (upTiles[i].transform.position.y > minval)
                {
                    if (upTiles[i].transform.position.x < transform.position.x + 1 && upTiles[i].transform.position.x > transform.position.x - 1)
                    {
                        minval = upTiles[i].transform.position.y;
                        lowestIndex = i;
                    }

                }

            downTile = upTiles[lowestIndex];
        }
        else downTile = downTiles[lowestIndex];

Lo que hago es primero ver cual dentro de la lista tiene el valor mas pequeño en caso de arriba y derecha y el mas grande en caso de abajo e izquierda.
Luego, para que no coja un bloque que esta a la derecha pero muy arriba, le pongo que este como máximo una unidad por arriba o por abajo del eje contrario.

Y por ultimo, al pulsar WASD la posición se cambiara por la posición del bloque.
 

if (Input.GetKeyDown(KeyCode.W))
        {
            transform.position = upTile.transform.position;
            ClasifyTiles();
        }
        else if (Input.GetKeyDown(KeyCode.S))
        {
            transform.position = downTile.transform.position;
            ClasifyTiles();
        }
        else if (Input.GetKeyDown(KeyCode.D))
        {
            transform.position = rightTile.transform.position;
            ClasifyTiles();
        }
        else if (Input.GetKeyDown(KeyCode.A))
        {
            transform.position = leftTile.transform.position;
            ClasifyTiles();
        }

 

 

Al iniciar, y hacer el primer calculo, parece ir sin problemas.
Pero según vas moviéndote, empieza a dar errores de out of range, saltar a bloques que no debería saltar, o en vez de saltar al mas cercano, saltar al mas lejano.

 

 

He estado dándole muchas vueltas al código pero no he conseguido arreglarlo, agradecería la ayuda.

Share this post


Link to post
Share on other sites

×