Стрельба на опережениеМатериал из Blitz Et CeteraПрактически во всех играх механизм ведения огня компьютерным противником одинаков - нацелиться прямо на игрока и выстрелить. Соответственно, от снаряда легко увернуться, просто шагнув в сторону. Немного сложнее увернуться от ракет (т. к. нужно отбежать от места взрыва) и от огня (например, пехотинцев в Unreal) со случайным отклонением от цели. Моментальный выстрел (когда сразу просчитывается вся траектория полета снаряда и определяется объект столкновения) не рассматриваем - здесь хорошо подходит именно простой вариант (с небольшими вариациями типа задержки перед началом стрельбы (пулеметчик из Doom2), низкой частотой огня (сержант из Doom) и уменьшенной точностью). Линейное движениеПусть даны координаты пушки (x0, y0) и координаты объекта (x, y). Рассмотрим задачу для двумерного пространства: снаряд стартует в центре пушки и его скорость - константа (v0), а объект движется с постоянной скоростью (v) под углом a от оси X. Необходимо найти угол a0, при котором снаряд, выпущенный из пушки, попадет точно в центр объекта. Координаты объекта в момент времени t будут равны (x0 + t vx, y0 + t vy), где vx = cos(a), vy = sin(a). Следует учесть, что снаряд вылетает не из центра пушки, а из дула, которое находится на некотором расстоянии от нее. До этой точки снаряд долетел бы, преодолев некоторое расстояние r. Таким образом, под каким бы углом пушка бы не выстрелила, в момент времени t снаряд будет от нее на расстоянии vt + r. Выразив расстояние через координаты, получаем уравнение: В итоге, после возведения в квадрат (т. к. t > 0, v > 0 и r > 0, то знак учитывать не нужно), раскрытия скобок и приведения подобных, получим квадратное уравнение (Δx = x - x0, Δy = y - y0): Если дискриминант этого уравнения меньше нуля, значит решения не существует (при этом целесообразно будет просто нацелить пушку на объект с помощью функции ATan2). В ином случае, если больший из корней положителен, то пушка стреляет в направлении точки, в которой должна произойти встреча снаряда и объекта. Вы можете улучшить алгоритм, просчитав вариант, когда оба корня положительны (тогда оптимальным будет выбор меньшего корня - снаряд попадет раньше). Решение для трехмерного варианта выводится аналогичным образом - попытайтесь его найти. Задачи, где учитывается ускорение и скорость вращения, гораздо сложнее, т. к. из-за усложнения формулы для движения объекта, приходится решать уравнения четвертой степени. Устранение зависимости от FPSХотя напрямую этот раздел темы не касается, все же будет полезно его разобрать. Часто бывает так, что старые игры и демошки на одних компьютерах тормозят, на других - идут нормально, на третьих - быстрят. Это происходит из-за того, что в этих программах за один цикл действия происходит фиксированная трансформация мира (например, движение на один пиксел, поворот камеры на 1 градус и т. д.). Поэтому, чем больше / меньше от задуманного в программе циклов (и больше / меньше кадров в секунду она выдает), тем быстрее / медленнее идет процесс. Чтобы этого избежать, фиксируют кол-во кадров в секунду (а если скорость низкая - рендеринг некоторых может быть пропущен) или вводят зависимость внутренних процессов от времени. Недостаток первого - ограниченный FPS (можно сделать его завышенным, делая по нескольку циклов на рендеринг), второго - искажение процессов, вызванное изменением FPS (перемещения становятся более округлыми или резкими и скачкообразными, чего можно, впрочем, избежать, задав верхнюю границу периода времени на рендеринг). Остановимся на втором варианте. Все довольно просто - во все процессы, которые должны зависеть от времени, добавляется множитель dt#, который равен протяженности предыдущего цикла в миллисекундах. Это поворот игрока, движение игрока и снарядов. Поворот башен (кроме вращающихся автоматически) не требует регулировки. СамообучениеСоздания самообучающейся системы - задача, основной этап решения которой ориентирован на поиск подходящей модели. В данном случае, требуется найти оптимальный угол для стрельбы, основываясь на опыте предыдущих. Входные параметры - координаты, направление движения игрока, скорость, координаты снарядов. Алгоритм должен стремиться попасть в игрока - оптимальным будет вариант, когда снаряд попадет в центр. Но для этого снаряд должен долететь до цели т. е. расстояния от пушки до игрока и до снаряда должны сравняться. В этом случае можно заключить, насколько удачен был выстрел и, на основе этого опыта, алгоритм должен сделать вывод. А вывод таков - "если бы пушка выстрелила в направлении текущей позиции игрока этим снарядом, то результат был бы оптимален". Соответственно, компьютер учитывает поправку к выстрелу для данного расстояния и, когда игрок будет на таком же расстоянии, как в прошлый раз, нужно будет выстрелить, отклонившись от прямого направления на игрока на сохраненный угол. Для хранения соответствий "расстояние - поправка" создадим массив и зададим шаг, на который будут различаться соседние расстояния в массиве. Расстояние для записи поправки можно взять как в момент встречи (так в приведенном коде), так и в момент выстрела (придется запоминать и включить переменную в тип снаряда) - разница невелика. В программе есть доп. алгоритмы стрельбы - в заданном направлении, вращаясь и стрельба веером. Graphics3D 800,600
Автор: Матвей Меркулов (E-mail: MattMerkulov |


