C++ Magnitude(Normalize)似乎不正确

Joh*_*own 1 c++ normalize normals magnitude

我正在做一个2D坦克炮塔游戏,你在屏幕中间旋转坦克,点击你的左按钮然后一个小弹丸移动到那个位置.

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

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

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

这是我将我想要的和当前位置标准化的代码:

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);
Run Code Online (Sandbox Code Playgroud)

当前位置与我的laserTexture中间相关,这是屏幕中间的固定旋转点.

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

数学不是我的强项,所以当谈到编程这类东西时,我比其他人做的更挣扎,所以它需要我更长时间/我会想出一些不太优雅的解决方案.

我的最终目标是获得标准化的位置,然后当点击鼠标左键时,坦克炮塔将会发射,并且射弹将移动到所需的位置.

所以澄清一下:

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

谢谢

小智 5

ad 1.)"我的量级函数是否正确?"

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

result = (sqrt(x*vec2.x)+(y*vec2.y));
Run Code Online (Sandbox Code Playgroud)

result = sqrt(x*vec2.x)+(y*vec2.y);
Run Code Online (Sandbox Code Playgroud)

result = sqrt(x*vec2.x) + (y*vec2.y);
Run Code Online (Sandbox Code Playgroud)

但你可能想写这个:

result = sqrt((x*vec2.x)+(y*vec2.y));
Run Code Online (Sandbox Code Playgroud)

编辑:

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

result = sqrt(vec2.x*vec2.x + vec2.y*vec2.y);
Run Code Online (Sandbox Code Playgroud)

那是因为OP只想计算vec2的大小,所以没有必要使用this.xthis.y.出于这个原因,我建议将您的方法更改为静态:

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

或仅使用实例值:

float vector2D::magnitude()//<! Vector magnitude
{
    return sqrt((x*x)+(y*y));
}
Run Code Online (Sandbox Code Playgroud)

在这个第二种情况下,你需要使用这样的magnitude()方法:

(desiredPos - currentPos).magnitude();
Run Code Online (Sandbox Code Playgroud)

附加说明:

  • 这种方法的结果是幅度而不是标准化(任何事物),但可用于标准化给定的矢量.
  • 这一结果是等于之间的距离desiredPoscurrentPos.
  • 如果除以(desiredPos - currentPos)幅度值,你将得到归一化矢量,它是从方向currentPosdesiredPos.
  • 很明显,但如果desiredPos并且currentPos相等,幅度为零,则无法对矢量进行标准化.
  • 由于上述原因,我会重命名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.
}
Run Code Online (Sandbox Code Playgroud)

然而,仍有一个问题.它是以下几行:

currentPos.x = laserTexture.getSize().x/2.0f;
currentPos.y = laserTexture.getSize().y/2.0f;
Run Code Online (Sandbox Code Playgroud)

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

currentPos.x = laserTexture.getSize().x/2.0f + laserPos.x;
currentPos.y = laserTexture.getSize().y/2.0f + laserPos.y;
Run Code Online (Sandbox Code Playgroud)

这里laserPos是你的激光当前所在位置.