Calcule la distancia entre puntos en la matriz conectados en todas las direcciones
– UnityAssets3Free
hola , me llamo Camilo y aqui os traigo
esta unity pregunta
Estoy tratando de hacer un juego en línea donde quiero simular un mundo conectado en todas las direcciones, como «PAC-MAN». Cuando el jugador cruza los límites del mapa, estará en el otro lado de la cuadrícula.
Hasta ahora todo bien, logré construir un servidor que contiene una matriz de 10×10 (adjunte algunos imágenes como referencia), y utilizando alguna aritmética modular calcula y envía al cliente las piezas correspondientes del mapa según la posición del jugador.
Entonces, asumiendo «view_distance = 2» por ejemplo, el servidor envía las piezas correspondientes según la posición del jugador:
Creo que hice mi punto, ahora enfrentemos mi problema.
Cuando el cliente obtiene la lista de mosaicos para renderizar desde el servidor, necesita calcular la distancia al jugador (vector unitario) para cada mosaico con el fin de instanciar en el lugar correcto. Cada mosaico instanciado tiene un script que vuelve a calcular la distancia al jugador cada vez que se mueve para que se destruya a sí mismo cuando esté más lejos que la «distancia_vista».
Entonces, por ejemplo, si el cliente está en la posición (9,5), el vector unitario del mosaico (7,7) sería (-2,2)
El cliente dispone de la siguiente información:
- La baldosa en la que está parado:
Globals.PlayerInfo.PlayerPosition
- La longitud del mapa:
Globals.MAP_LENGHT
(en este caso son 10) - La distancia de visualización:
Globals.DATA_DISTANCE
(en este caso son 2)
¿Cómo calcular el vector unitario? Hice la siguiente función pero no parece funcionar. ¿Me estoy olvidando de algo?
public static Position GetPlayerDistance(Position position)
var unitVector = new Position() X = position.X, Y = position.Y ;
if (position.Y > Math.Truncate(Globals.PlayerInfo.PlayerPosition.Y) + Globals.DATA_DISTANCE)
unitVector.Y = position.Y - Globals.MAP_LENGHT;
if (position.X > Math.Truncate(Globals.PlayerInfo.PlayerPosition.X) + Globals.DATA_DISTANCE)
unitVector.X = position.X - Globals.MAP_LENGHT;
unitVector.X -= (float)Math.Truncate(Globals.PlayerInfo.PlayerPosition.X);
unitVector.Y -= (float)Math.Truncate(Globals.PlayerInfo.PlayerPosition.Y);
return unitVector;
1 respuesta 1
Tú mismo lo dices, la grilla es connected in all directions
. Entonces, dado que su cuadrícula es «infinita», cada posición existe un número «infinito» de veces. Lo que estás buscando no es una distancia entre dos puntos, sino la más pequeña de varias posibilidades.
Pero no te preocupes 😉 Basta con marcar una vez en cada dirección (arriba, abajo, izquierda, derecha) y elegir la menor de las distancias resultantes en esas direcciones, ya que cualquier otra será mayor de todos modos.
Solo como un ejemplo de lo que estoy hablando. digamos
- el jugador esta en
1,1
(rojo) - el enemigo esta en
8,2
(azul)
entonces, si queremos obtener la distancia mínima en el eje X, solo verifique en ambas direcciones, izquierda y derecha.
En este caso, encontrar la siguiente posición a la izquierda es trivial: es la posición real del jugador. x = 1
.
Ahora que hacemos bien? → Simplemente extendemos virtualmente la cuadrícula (gris claro) y asignamos la posición del jugador a donde haría estar en esta grilla extendida → x = 11
(Luz roja).
Aquí una imagen para que se vea mejor.
En el código, esto podría verse como, por ejemplo
public static Position GetPlayerDistance(Position position)
// Get values local to not go through the accessors all the time
Position playerPos = Globals.PlayerInfo.PlayerPosition;
int playerX = (int)playerPos.X;
int playerY = (int)playerPos.Y;
int ownX = (int)position.X;
int ownY = (int)position.Y;
// On the X axis gather the next actual or virtual player position
// where virtual means as if the grid was extended
// Per default assume the positions are equal
var nextXLeft = ownX;
var nextXRight = ownX;
// Is the player actually left of us?
if(playerX < ownX)
// Then trivial: the next left position is the actual one
nextXLeft = playerX;
// The next right position is a virtual one so we pretend
// to extend the grid by the length and "copy" the player there
nextXRight = Globals.MAP_LENGHT + playerX;
// Or is the player actually right of us?
else if (playerX > ownX)
// Just the other way round
// this time the next position to the left is virtual
nextXLeft = -Globals.MAP_LENGHT + playerX;
// The next right position is the actual one
nextXRight = playerX;
// Now we calculate the directed distances in both directions
var distanceLeft = nextXLeft - ownX;
var distanceRight = nextXRight - ownX;
// use the Absolute only for comparing which is shorter
var distanceX = Mathf.Abs(distanceRight) < Mathf.Abs(distanceLeft) ? distanceRight : distanceLeft;
// And finally we want the smallest of both possible distances
var distanceX = Mathf.Min(distanceLeft, distanceRight);
// Repeat the same for the Y axis
var nextYDown = ownY;
var nextYUp = ownY;
if(playerY < ownY)
nextYDown = playerY;
nextYUp = Globals.MAP_LENGHT + playerY;
else if (playerY > ownY)
nextYDown = -Globals.MAP_LENGHT + playerY;
nextYUp = playerY;
var distanceDown = nextYDown - ownY;
var distanceUp = nextYUp - ownY;
var distanceY = Mathf.Abs(distanceUp) < Mathf.Abs(distanceDown) ? distanceUp : distanceDown;
// Now you have a directed distance vector for both axis with the
// minimal absolute distance from the player
return new Position() X = distanceX, Y = distanceY ;
Aquí hay una pequeña vista previa de cómo funciona ahora
Como nota al margen: ya existe Vector2Int
es posible que desee utilizar en lugar de su habitual Position
nota: si aun no se resuelve tu pregunta por favor dejar un comentario y pronto lo podremos de nuevo , muchas gracias
eso es todo,espero que te halla servido