c# - 如何使跟随 Ai 在基于环形 2D 网格的地图上工作
问题描述
我在 2D 矩阵中有一些环绕的 NPC,我必须让它们使用环形地图跟随敌方派系 NPC。
我尝试了几种解决方案,但它们都给了我奇怪的行为,只对网格的某个值x
或y
值起作用,然后而不是跟随它们返回一个图块。
这就是我现在要决定走哪条路:
public Position GetNextStepTowards(Position origin, Position target)
{
Position nextStep = new Position(0, 0);
float dx = MathF.Abs(target.X - origin.X);
float dy = MathF.Abs(target.Y - origin.Y);
if (dx > mapXSize / 2) nextStep.X = -1;
else if (dx < mapXSize / 2) nextStep.X = 1;
if (dy > mapYSize / 2) nextStep.Y = 1;
else if (dy < mapYSize / 2) nextStep.Y = -1;
return nextStep;
}
一个职位是:
public struct Position
{
public int X { get; set; }
public int Y { get; set; }
public Position(int x, int y)
{
this.X = x;
this.Y = y;
}
}
NPC 只能移动一个单元格(Moore's),因此移动向量应该只能是 和 之间的-1
值1
。
提前感谢您的帮助!
解决方案
如果我们考虑X轴,有两种情况,如下图所示:
在第一种情况下(顶部),目标位于原点的右侧。在这种情况下,向右移动是直接的,向左移动是环形的。
在第二种情况下(底部),目标位于原点的左侧。在这种情况下,向左移动是直接的,向右移动是环形的。
所以代码需要检查原点和目标的相对位置,然后适当的计算左右距离。较小的距离决定了 deltaX 的方向和大小。相同的逻辑适用于 deltaY。
然后如果 deltaX 和 deltaY 具有相同的大小,我们沿着对角线移动。否则,我们将朝着具有较大增量的方向移动。
private int ComputeDelta(int src, int dst, int mapSize)
{
int increasing, decreasing;
if (dst >= src)
{
increasing = dst - src; // increasing direction is direct
decreasing = (mapSize + src) - dst; // decreasing direction is toroidal
}
else
{
increasing = (mapSize + dst) - src; // increasing direction is toroidal
decreasing = src - dst; // decreasing direction is direct
}
if (increasing <= decreasing) { return increasing; }
else { return -decreasing; }
}
public Position GetNextStepTowards(Position origin, Position target)
{
Position nextStep = new Position(0, 0);
// compute the distances
int dx = ComputeDelta(origin.X, target.X, mapXSize);
int dy = ComputeDelta(origin.Y, target.Y, mapYSize);
// keep the dominant distance, and clear the other distance
// keep both if they're equal
if (dx*dx > dy*dy) { dy = 0; }
else if (dx*dx < dy*dy) { dx = 0; }
// normalize the distances so they are -1, 0, or 1
nextStep.X = dx.CompareTo(0);
nextStep.Y = dy.CompareTo(0);
return nextStep;
}
推荐阅读
- javascript - 如何获得失败 api 的响应
- r - 随着时间的推移计算具有起源和演变的数值特征
- postgresql - 如何使用子查询在 PostgreSQL 中创建唯一索引?
- bash - fold:使用参数运行脚本时列数无效
- amazon-web-services - 如何使用 Terraform 附加或删除安全组的入口/出口规则?
- node.js - 静音控制台文本输入
- javascript - 在另一个网站上填写我在我的网站上输入的表格
- android - 如何根据android中的firebase身份验证状态执行条件导航
- docker - 如何将在同一端口上侦听的堆栈的多个实例部署到 Docker Swarm(在反向代理之后)?
- xamarin - 如何将 Linux 库添加到我的 Xamarin 项目