нормали — С ++ Величина (нормализовать) не кажется правильной

Я играю в небольшую 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);

Текущее положение привязано к середине моей лазерной текстуры, которая является фиксированной точкой поворота в середине экрана.

Мое желаемое местоположение — щелчок мышью, который возвращает положение в X и Y (Это работает).

Математика не моя сильная сторона, поэтому, когда дело доходит до программирования такого рода вещей, я борюсь больше, чем другие люди, так что это занимает намного больше времени / я просто придумаю какое-то не очень элегантное решение.

Моя конечная цель состоит в том, чтобы получить нормализованное местоположение, а затем, когда будет нажата левая кнопка мыши, турель-танк выстрелит, и снаряд получит перемещение в нужное место.

Итак, чтобы уточнить:

  • Является ли моя функция величины правильной?
  • Правильно ли я нормализую желаемые и текущие позиции?

Спасибо

1

Решение

объявление 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.x а также 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) на величину, вы получите нормализованный вектор, который является направлением от currentPos в desiredPos,
  • Это очевидно, но если 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.
}

Однако есть все еще подвох. Это следующие строки:

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;

где laserPos это позиция, где находится ваш лазер.

5

Другие решения

Норма вектора — это квадратный корень из суммы квадратов его координат. Ваш метод должен быть:

float vector2D::magnitude(vector2D vec2)
{
return sqrt(vec2.x * vec2.x + vec2.y * vec2.y);
}
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;

Чтобы избежать подобных проблем, во-первых: не бойтесь пробела, а во-вторых: не используйте слишком много скобок.

1

зачем вам нужна величина? вам нужно направление, которое является углом (градусы или радианы). поскольку у вас уже есть базовая позиция танка и желаемое место, где вы щелкнули мышью, из этого вам нужно будет рассчитать, под каким углом находятся эти точки. немного пифагора и тригонометрия, вы можете определить угол, повернуть танк на этот угол, запустить снаряд в том же направлении.

0
По вопросам рекламы [email protected]