2D Tower Defense - Пуля врагу

14

Я пытаюсь найти хорошее решение для пули, чтобы поразить врага. В игре 2D Tower Defense, башня должна стрелять пулями и поражать врага гарантированно.

Я попробовал это решение - http://blog.wolfire.com/2009/07/linear-algebra-for-game-developers-part-1/

Упомянутая ссылка вычитает происхождение пули, а также противника (векторное вычитание). Я попробовал это, но пуля просто преследует врага.

float diffX = enemy.position.x - position.x;
float diffY = enemy.position.y - position.y;

velocity.x = diffX;
velocity.y = diffY;

position.add(velocity.x * deltaTime, velocity.y * deltaTime);

Я знаком с векторами, но не уверен, какие шаги (операции векторной математики) нужно сделать, чтобы это решение работало.

Tashu
источник
Связанный: gamedev.stackexchange.com/questions/1885/…
bummzack

Ответы:

11

Ваши рассуждения были идеальными: используйте вектор, чтобы перейти от моей позиции к моей цели. Это цель вектора ; ты просто забыл скорость !

Скорость - это вектор: скорость и направление. Однако, если вы забудете нормализовать разностный вектор и умножить его на скорость пули (скаляр), вы в основном говорите, что если вы находитесь близко к цели (вектор разности мал), пуля замедляется ; в то время как если вы далеко, скорость пули больше.

Это основная проблема: вам нужно рассчитать как направление, так и величину вектора.

FXIII
источник
Спасибо за помощь. Я попытался использовать скаляр после вычисления разностного вектора, похоже, он работал, но выглядит не очень хорошо. Я пытался увидеть, вычисляю ли я вектор разности, нормализую, а затем вычисляю скорость. Это выглядит лучше прямо сейчас. Да, я думаю, что мне понадобятся самонаводящиеся ракеты в этой игре чуть позже. Еще раз спасибо.
Ташу
1
Этот ответ не имеет никакого смысла для кого-либо еще?
BlueRaja - Дэнни Пфлюгофт
@Fxlll: Хорошо, я думаю, что вижу, что ты пытаешься сказать. В начале / конце есть много пуха, не связанного с ответом, и меня также смутил ваш английский (который, я понимаю, вероятно, не ваша вина) . Я отправил предложение по редактированию, чтобы очистить этот ответ.
BlueRaja - Дэнни Пфлюгофт
@BlueRaja - Дэнни Пфлюгофт, спасибо за ваши усилия!
FxIII
7

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

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

Вот псевдокод для квадратного уравнения:

Vector totarget =  target.position - tower.position;

float a = Vector.Dot(target.velocity, target.velocity) - (bullet.velocity * bullet.velocity);
float b = 2 * Vector.Dot(target.velocity, totarget);
float c = Vector.Dot(totarget, totarget);

float p = -b / (2 * a);
float q = (float)Math.Sqrt((b * b) - 4 * a * c) / (2 * a);

float t1 = p - q;
float t2 = p + q;
float t;

if (t1 > t2 && t2 > 0)
{
    t = t2;
}
else
{
    t = t1;
}

Vector aimSpot = target.position + target.velocity * t;
Vector bulletPath = aimSpot - tower.position;
float timeToImpact = bulletPath.Length() / bullet.speed;//speed must be in units per second
Стив Н
источник
Спасибо за псевдокод, я проверю его, чтобы увидеть, как работает квадратное уравнение в этой ситуации. Еще раз спасибо.
Ташу
Проблема в том, что пользователь может двигаться в направлении пули, и прямо перед попаданием он может уйти от следа пули. В этом случае, будет ли это решение достаточно хорошим?
Мартин.
Нет, как указано в первом предложении. Это не для всех игр, но для игры, в которой цели движутся только с постоянной скоростью. Постоянная скорость означает как направление, так и скорость. Например, игра-стиль Defense Grid может использовать этот подход.
Стив Х
3

Вам нужно «предсказать» положение объектов к тому времени, когда пуля достигнет его. Вы можете сделать это, используя скорость объекта / скорость (надеюсь, что это константа;)) и его вектор направления.

Я не уверен, какая точная формула у меня в голове, но я думаю, что это примерно так:

NewPosition = OldPosition + (Speed ​​* DirectionVector);

Если у вас есть заданный путь, вам нужно будет пересчитать, когда объект меняет направление. Используйте эту NewPosition в качестве вектора врага, и пуля должна поразить объект без «эффекта самонаведения». Самонаведение происходит из-за того, что вражеский объект переместился с момента вычисления первоначального вектора, он может догнать только, когда объект движется в одном направлении достаточно долго.

Надеюсь это поможет :)

сойка
источник
3
Или вы можете обмануть и автоматически нажать, а затем использовать движущийся спрайт в качестве визуальной обратной связи. Или просто выстрелите в 50000 миль в час.
Джонатан Коннелл
1

Вы можете избежать использования квадратного корня и степени 2.

var distX:Float = target.x - x;
var distY:Float = target.y - y;
_velX = distX / timeTravel;
_velY = distY / timeTravel;

// Take out if you want a nice slow down as approaches effect.  
timeTravel -= 1.0; // make sure u have a positive timeTravel.
x += _velX;
y += _velY;

if (distX < 0)
    distX = -distX;

if (distY < 0)
    distY = -distY;

if (_velX < 0)
    _velX = -_velX;

if (_velY < 0)
    _velY = -_velY;

// Should both snap @ the same time.
if (distX < _velX)
x = target.x; // snap & see what happens.

if (distY < _velY)
y = target.y; // snap & see what happens.

// TODO: call your onHitTarget here ...
// Hopefully this shall provide 10x the performance 
// of using Math.sqrt and all the extra multiplications.

Это все написано по памяти. Кстати, используйте элементы, которые работают - тестируйте их построчно, если вы новичок в этом. Число с плавающей точкой в ​​AS3.

Крис
источник