计算在所有方向连接的矩阵中点之间的距离
Calculate distance between points in matrix connected in all directions
我正在尝试制作一款在线游戏,我想在其中模拟一个四通八达的世界,就像“吃豆人”一样。当玩家越过地图的边界时,他会在网格的另一边。
到目前为止一切顺利,我设法构建了一个包含 10x10 矩阵的服务器(我附加了一些 images 作为参考),并使用一些模块化算法计算并发送给客户端给定玩家位置的相应地图图块。
所以假设“view_distance = 2”,例如服务器根据玩家的位置发送相应的瓷砖:
Player position (4,4)
Player position (9,5)
Player position (0,0)
我想我已经表达了我的观点,现在让我们面对我的问题。
当客户端从服务器获取要渲染的图块列表时,它需要计算每个图块到玩家的距离(单位向量),以便它可以在正确的位置进行实例化。每个实例化的图块都有一个脚本,每次玩家移动时都会重新计算与玩家的距离,因此当它比“view_distance”更远时会自行销毁。
例如,如果我的客户端位于 (9,5) 位置,则图块 (7,7) 的单位向量将为 (-2,2)
客户有以下信息:
- 他所在的方块:
Globals.PlayerInfo.PlayerPosition
- 地图的长度:
Globals.MAP_LENGHT
(在本例中为 10)
- 视距:
Globals.DATA_DISTANCE
(本例中为 2)
如何计算单位向量?我做了以下功能,但它似乎不起作用。我错过了什么吗?
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;
}
你自己说吧,格子是connected in all directions
。因此,由于您的网格是“无限”的,因此每个位置都存在“无限”的次数。你要找的不是两点之间的一个距离,而是多种可能性中最小的一个。
不过不用担心 ;) 每个方向(上、下、左、右)检查一次并选择这些方向上的最小结果距离就足够了,因为无论如何其他方向都会更远.
我所说的只是一个例子。
让我们说
- 玩家在
1,1
(红色)
- 敌人在
8,2
(蓝色)
因此,如果我们想获得 X 轴上的最小距离,我们只需检查左右两个方向即可。
在这种情况下,找到左边的下一个位置很简单:它是实际玩家位置 x = 1
。
现在我们向右怎么办? → 我们只是虚拟地扩展网格(浅灰色)并将玩家位置映射到它 将 在扩展网格中的位置 → x = 11
(浅红色)。
这里有一张图片可以更好地形象化
在代码中,这可能类似于
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 };
}
下面是它现在如何工作的一些可视化效果
附带说明:您可能想要使用 Vector2Int
而不是自定义 Position
我正在尝试制作一款在线游戏,我想在其中模拟一个四通八达的世界,就像“吃豆人”一样。当玩家越过地图的边界时,他会在网格的另一边。
到目前为止一切顺利,我设法构建了一个包含 10x10 矩阵的服务器(我附加了一些 images 作为参考),并使用一些模块化算法计算并发送给客户端给定玩家位置的相应地图图块。
所以假设“view_distance = 2”,例如服务器根据玩家的位置发送相应的瓷砖:
Player position (4,4)
Player position (9,5)
Player position (0,0)
我想我已经表达了我的观点,现在让我们面对我的问题。
当客户端从服务器获取要渲染的图块列表时,它需要计算每个图块到玩家的距离(单位向量),以便它可以在正确的位置进行实例化。每个实例化的图块都有一个脚本,每次玩家移动时都会重新计算与玩家的距离,因此当它比“view_distance”更远时会自行销毁。
例如,如果我的客户端位于 (9,5) 位置,则图块 (7,7) 的单位向量将为 (-2,2)
客户有以下信息:
- 他所在的方块:
Globals.PlayerInfo.PlayerPosition
- 地图的长度:
Globals.MAP_LENGHT
(在本例中为 10) - 视距:
Globals.DATA_DISTANCE
(本例中为 2)
如何计算单位向量?我做了以下功能,但它似乎不起作用。我错过了什么吗?
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;
}
你自己说吧,格子是connected in all directions
。因此,由于您的网格是“无限”的,因此每个位置都存在“无限”的次数。你要找的不是两点之间的一个距离,而是多种可能性中最小的一个。
不过不用担心 ;) 每个方向(上、下、左、右)检查一次并选择这些方向上的最小结果距离就足够了,因为无论如何其他方向都会更远.
我所说的只是一个例子。 让我们说
- 玩家在
1,1
(红色) - 敌人在
8,2
(蓝色)
因此,如果我们想获得 X 轴上的最小距离,我们只需检查左右两个方向即可。
在这种情况下,找到左边的下一个位置很简单:它是实际玩家位置 x = 1
。
现在我们向右怎么办? → 我们只是虚拟地扩展网格(浅灰色)并将玩家位置映射到它 将 在扩展网格中的位置 → x = 11
(浅红色)。
这里有一张图片可以更好地形象化
在代码中,这可能类似于
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 };
}
下面是它现在如何工作的一些可视化效果
附带说明:您可能想要使用 Vector2Int
而不是自定义 Position