Я пишу простую защиту башни и немного застрял там, где моя башня должна стрелять по врагу.
С этим кодом:
void Bullet::move(int x, int y, int speed)
{
Punkt delta = {(x + speed) - this->x, (y + speed) - this->y};
if (abs(delta.x) > 1 && abs(delta.y) > 1)
{
this->x += delta.x / this->speed;
this->y += delta.y / this->speed;
}
else
{
this->dead = true;
}
}
Где аргументы метода — целевая позиция и скорость. Он должен перемещать пулю вдоль вектора, пока не достигнет цели, но вектор меняется, потому что цель движется. Пока пуля заканчивается вот так (черный — это башня, синий — это пуля, а красный — враг)
И я знаю, что проблема в том, что моя пуля нацелена на что-то, что уже перемещено, поэтому мой вопрос — как улучшить этот код, чтобы он работал правильно? Я не знаю, как обернуть голову вокруг векторов и баллистики, поэтому заранее благодарю за простоту.
Разумное решение этой проблемы, которое я видел ранее, заключается в следующем:
Таким образом, если вы достаточно умны со своей математикой, это будет хорошо выглядеть. Но в остальном игра все равно будет работать правильно.
Этот подход также более надежен, если враги могут изменять скорость (например, они замедляются из-за особой местности или башни с эффектом области) после того, как вы обстреляете их.
Если вы стреляете в движущуюся цель, вам нужно прицелиться в то место, где она будет находиться за то время, которое требуется для пули, чтобы достичь ее, тогда у вас есть две известные позиции, чтобы вы знали вектор.
Хорошо, я немного заглянул на форумы gamedev и нашел решение (которое мне даже удалось понять). Все дело в правильном расчете (как все говорили, было необходимо преобразовать в float). Вот код для ленивых:
float dx = x - this->x;
float dy = y - this->y;
float dx2, dy2;
float distance;
float vx, vy;
distance = sqrt(dx * dx + dy * dy);
dx2 = dx / distance;
dy2 = dy / distance;
vx = dx2 * this->speed;
vy = dy2 * this->speed;
if (distance > 10) // 10 is hitbox size
{
this->x += vx; // still float, its converted to int when applying to surface
this->y += vy;
}
else
{
this->dead = true;
}