1

我正在做一个小型 2D 坦克炮塔游戏,您可以在屏幕中间旋转坦克,单击左键,然后一个小弹丸移动到该位置。

我目前处于我拥有当前位置和所需位置的位置,我现在需要做的是获取这两个点的大小,它应该返回 1 或 0。

这是我的 C++ VectorClass 幅度函数:

float vector2D::magnitude(vector2D vec2)//<! Vector magnitude
{
    float result;
    result = (sqrt(x*vec2.x)+(y*vec2.y));
    return result;
}

这是我标准化所需位置和当前位置的代码:

currentPos.x = laserTexture.getSize().x/2.0f;
currentPos.y = laserTexture.getSize().y/2.0f;
desiredPos.x = sf::Mouse::getPosition().x;
desiredPos.y = sf::Mouse::getPosition().y;
normalisedLocation = magnitude(desiredPos - currentPos);

当前位置绑定到我的laserTexture的中间,这是屏幕中间的一个固定旋转点。

我想要的位置是鼠标单击,它返回 X 和 Y 中的位置(这有效)。

数学不是我的强项,所以在编写这类东西时,我比其他人更努力,所以我需要更长的时间/我只会想出一些不太优雅的解决方案。

我的最终目标是获得标准化位置,然后单击鼠标左键时,坦克炮塔将开火,弹丸将移动到所需位置。

所以澄清一下:

  • 我的幅度函数正确吗?
  • 我是否正确地规范了我想要的和当前的位置?

谢谢

4

4 回答 4

5

广告 1.) “我的幅度函数正确吗?”

不,您的maginutude()方法几乎没有错误。你的:

result = (sqrt(x*vec2.x)+(y*vec2.y));

result = sqrt(x*vec2.x)+(y*vec2.y);

result = sqrt(x*vec2.x) + (y*vec2.y);

但你可能想写这个:

result = sqrt((x*vec2.x)+(y*vec2.y));

编辑:

我最初写的sqrt(x*vec2.x+y*vec2.y)是正确的,但事实并非如此,正确的是:

result = sqrt(vec2.x*vec2.x + vec2.y*vec2.y);

那是因为 OP 只想计算 vec2 的大小,不需要使用this.xand this.y。出于这个原因,我会进一步建议将您的方法更改为静态:

static float vector2D::magnitude(vector2D vec2)//<! Vector magnitude
{
    return sqrt((vec2.x*vec2.x)+(vec2.y*vec2.y));
}

或仅使用实例值:

float vector2D::magnitude()//<! Vector magnitude
{
    return sqrt((x*x)+(y*y));
}

在这种情况下,第二种情况,您需要使用如下magnitude()方法:

(desiredPos - currentPos).magnitude();

进一步说明:

  • 这种方法的结果是幅度而不是归一化(任何东西),但可用于对给定向量进行归一化。
  • 这个结果等于 和 之间的desiredPos距离currentPos
  • 如果除以(desiredPos - currentPos)幅度值,您将得到归一化向量,即方向 from currentPosto desiredPos
  • 很明显,但如果desiredPoscurrentPos相等,则幅度为零,您无法对向量进行归一化。
  • 由于上述原因,我将重命名normalisedLocation变量。它的距离,如上所述。

广告 2。)“我是否正确地规范了我想要的和当前的位置?”

我不确定如何理解这个问题,因为您没有对示例代码中的任何内容进行规范化。无论如何,看看这个:

// This is from your code:
currentPos.x = laserTexture.getSize().x/2.0f;
currentPos.y = laserTexture.getSize().y/2.0f;
desiredPos.x = sf::Mouse::getPosition().x;
desiredPos.y = sf::Mouse::getPosition().y;

// Store direction to desired position. Currently length of this vector is
// distance between the two points.
vector2D dirToDesiredPos = (desiredPos - currentPos);

// Calculate distance between the two points.
float dirToDesiredPosDist = magnitude(desiredPos - currentPos);

// Detect whether the distance is zero. Problem is, you cannot compare float
// with zero (computer is not accurate enough) so we compare it with a delta
// value. It should be some small number, for example 0.01f.
// (Note that in this case we don't need to compare it with negative value -
// which would be -0.01f, because distance is always positive or zero.)
if(dirToDesiredPosDist < FLOAT_DELTA)
{
    // User clicked on the tank, we cannot shoot!!!
}
else
{
    // Following two lines do actuall normalization - direction of this vector
    // is unchanged, but it's length is currently 1.
    dirToDesiredPos.x /= dirToDesiredPosDist;
    dirToDesiredPos.y /= dirToDesiredPosDist;

    // Now dirToDesiredPos can be used to calculate to move your bullet to the
    // desired location.
}

但是,仍然有一个问题。它是以下几行:

currentPos.x = laserTexture.getSize().x/2.0f;
currentPos.y = laserTexture.getSize().y/2.0f;

有了这个,你可以计算激光纹理的中心,但是只有当激光在 [0, 0] 位置渲染时,这个位置才是正确的。否则,您需要像这样更新它:

currentPos.x = laserTexture.getSize().x/2.0f + laserPos.x;
currentPos.y = laserTexture.getSize().y/2.0f + laserPos.y;

wherelaserPos是您的激光器当前所在的位置。

于 2014-05-27T11:59:43.537 回答
1

向量的范数是其坐标的平方和的平方根。你的方法应该是:

float vector2D::magnitude(vector2D vec2)
{
    return sqrt(vec2.x * vec2.x + vec2.y * vec2.y);
}
于 2014-05-27T12:04:35.577 回答
1

你的向量的大小,即它的长度,将是

float vector2D::magnitude() const
{
    return sqrt(x*x + y*y);
}

(它是边 x 和 y 的直角三角形的斜边。)

要对向量进行归一化,即得到一个方向相同但长度为 1 的向量,请将其坐标除以其大小:

vector2D vector2D::normalise() const 
{
    float length = magnitude();
    // Do something suitable to handle the case where the length is close to 0 here...
    return vector2D(x / length, y / length);
}

你的最后一行是

normalisedDirection = (desiredPos - currentPos).normalise();

或者,更详细

vector2D direction = desiredPos - currentPos;
normalisedDirection = location.normalise();

(我重命名了一个变量以澄清我们正在计算一个方向,而不是一个位置。)

或者,您可以使用免费功能:

float magnitude(vector2D v)
{
    return sqrt(v.x * v.x + v.y * v.y);
}

vector2D normalise(vector2D v)
{
   float length = magnitude(v);
   v.x /= length;
   v.y /= length;
   return v;
}

// ...

normalisedDirection = normalise(desiredPos - currentPos);

旁注:
您的函数中有一个错字,使其更加不正确:

(sqrt(x*vec2.x)+(y*vec2.y));

看起来很像

sqrt((x*vec2.x)+(y*vec2.y));

因为末尾有两个括号,但实际上是

sqrt(x * vec2.x) + y * vec2.y;

为了避免这类问题,第一:不要害怕空格键,第二:不要使用过多的括号。

于 2014-05-27T12:29:11.240 回答
0

为什么需要幅度?您需要方向,它是一个角度(度数或弧度)。因为您已经有了坦克的基本位置,以及单击鼠标的所需位置,因此您需要计算这些点的角度。用一点毕达哥拉斯和三角函数,你可以计算出角度,将你的坦克旋转到那个角度,在同一个方向发射你的射弹。

于 2014-05-27T12:13:56.317 回答