查找从单元格内的点到该单元格边界的距离 - 沿矢量移动时

问题描述

我正在尝试计算我的对象在移动到另一个单元格之前将在给定单元格内移动多长时间。

这对我来说才是真正重要的,但我也需要知道交叉点是什么(但如果我知道与起点的距离那就微不足道了)。

我的一些游戏规则是:

  • 每个单元格可能有不同的移动成本
  • 整个单元的移动成本完全相同
  • 我将物体从 A 点直线移动到 B 点
  • 我知道起始对象的位置及其方向(作为向量)
  • 单元格在行上有边框,这些行是数字网络上的全整数。

我到底需要什么:

  • 如果它继续朝所述方向前进,那么该单位将在何处耗尽移动点。

所以对于每个单元格我需要计算:

  • 从单元格内的点到该单元格边界的距离 - 沿方向向量移动时。

我想我跳过了一些三角学课,或者我太困了,但我找不到任何简单的解决方案来解决这个问题,既不快速又肮脏的解决方法

enter image description here

解决方法

我做了一些函数,它满足了我的需要。我不确定它是否会完全健壮(我特别害怕一些浮动舍入会导致将点放在 边界上 - 在该边界的错误一侧并导致 0 距离)。 它也打印了很多并分配了很多,但我计划缩短它,改进它并在未来更新这个答案。我想分享一些效果很好的东西 - 以防有人遇到类似问题/或者我不会很快更新它。

Vector2D cellCross(Vector2D startPoint,Vector2D direction)
{
    printf("start point [x:%f|y:%f]\n",startPoint.x,startPoint.y);
    printf("direction [x:%f|y:%f]\n",direction.x,direction.y);
    if (!direction.isNormalized())
    {
        printf("in cellCross() : direction vector must be normalized!\n");
        throw "bad arg";
    }

    //cell center is like Vector2D(x,y) from my image
    Vector2D cellCenter (floor(startPoint.x)+0.5,floor(startPoint.y)+0.5);
    printf("cell center [x:%f|y:%f]\n",cellCenter.x,cellCenter.y);
    //relative point is like Vector2D(m,n) from my image
    Vector2D relativePoint ( startPoint.x-cellCenter.x,startPoint.y-cellCenter.y );
    printf("relative point [x:%f|y:%f]\n",relativePoint.x,relativePoint.y);
    Vector2D targetCorner;
    if (direction.x>0)
        targetCorner.x=0.5;
    else
        targetCorner.x=-0.5;
    if (direction.y>0)
        targetCorner.y=0.5;
    else
        targetCorner.y=-0.5;
    printf("target corner [x:%f|y:%f]\n",targetCorner.x,targetCorner.y);

    double x_diff = targetCorner.x - relativePoint.x;
    double y_diff = targetCorner.y - relativePoint.y;
    printf("x_diff : %f\n",x_diff);
    printf("y_diff : %f\n",y_diff);

    Vector2D crossPoint;

    if (fabs(x_diff*direction.x) > fabs(y_diff*direction.y))
    { // we will cross at (targetCorner.x,[unknown]y)
        crossPoint.x = targetCorner.x;
        crossPoint.y = relativePoint.y + (direction.y * (x_diff/direction.x) );
    }
    else
    { // we will cross at ([unknown]x,targetCorner.y)
        crossPoint.y = targetCorner.y;
        crossPoint.x = relativePoint.x + (direction.x * (y_diff/direction.y) );
    }
    crossPoint.x+=cellCenter.x;
    crossPoint.y+=cellCenter.y;
    printf("cross point [x:%f|y:%f]\n",crossPoint.x,crossPoint.y);
    printf("distance : %f\n",startPoint.distanceTo(crossPoint) );
    return crossPoint;
}

展示一个示例 - 用于:

Vector2D startPoint (2.0,0.5);
Vector2D direction = Vector2D(10,-30).normalized();
Vector2D endingPoint = cellCross(startPoint,direction);

它打印了:

start point [x:2.000000|y:0.500000]
direction [x:0.316228|y:-0.948683]
cell center [x:2.500000|y:0.500000]
relative point [x:-0.500000|y:0.000000]
target corner [x:0.500000|y:-0.500000]
x_diff : 1.000000
y_diff : -0.500000
cross point [x:2.166667|y:0.000000]
distance : 0.527046

对于我和我的计算器来说,这看起来是大致正确的结果。

我可以将与函数结果的距离乘以该图块的移动成本,然后重复计算下一个图块,直到我的单位移动点为负数。通过向同一方向移动 last_tile_movement_cost * motion_points 来快速校正应该将其放置在它应该降落的位置。