Определить, будут ли объекты сталкиваться в двухмерном пространстве - PullRequest
1 голос
/ 19 марта 2012

Я пытался создать ИИ для игры астероидов, но застрял.Все остальное в игре настроено (то есть астероиды, созданные и движущиеся в случайных направлениях, обнаружение столкновений, корабль и пули). ИИ проходит через каждые 150 мс и может только сказать кораблю, что он должен повернуть налево, повернуть направо, двигаться вверх и стрелять.

Вот фрагмент моего кода, который я использую до сих пор:

                // Convert points to positive
                float asteroid_x = Math.Abs(asteroid.X);
                float asteroid_y = Math.Abs(asteroid.Y);

                float ship_x = Math.Abs(ship.X);
                float ship_y = Math.Abs(ship.Y);

                // Calculate difference in X and Y using positive values
                float dx = asteroid_x - ship_x;
                float dy = asteroid_y - ship_y;

                // Get velocities of asteroid
                float vx = asteroid.VX;
                float vy = asteroid.VY;

Используя эти переменные (dx, dy, vx, vy) мне нужно вычислить, если астероидсобирается ударить корабль.Я пытался использовать тригонометрию, но она продолжает думать, что ударит, когда это не так.Уравнения, которые я пытался использовать:

            float equation1a = (dy / vy) - (dx / vx);
            float equation1 = ((dy / dx) - (vy / vx));

Я тогда пытался использовать оператор IF, чтобы определить, ударит он или нет, но я не уверен, как это сделать.об этом правильно.После этого заявления IF я хочу пойти в AI, чтобы либо повернуть и выстрелить в астероид, либо уклониться от него.

Спасибо за любую помощь.

РЕДАКТИРОВАТЬ: значения X и Y для корабляили астероид также может быть отрицательным, с началом корабля в начале (0,0).

РЕДАКТИРОВАТЬ2: Немного дальше со всем этим и придумайте это:

// Determine if asteroid will collide
int turns_ahead = 100;
bool collision = false;
int least_turns = 500;
for (int i = 0; i < turns_ahead; i++)
{
    PointF asteroid_pos_next = NextPosition(new PointF(asteroid.X, asteroid.Y), new PointF(asteroid.VX, asteroid.VY), i);

    if (asteroid.CollidesWith(asteroid_pos_next.X, asteroid_pos_next.Y, ship.R))
    {
        collision = true;
    }
}

И с помощью этой функции определяется следующая позиция:

    // -----------------------------------------------------------------
    // Function to find position of object in X turns (turns_ahead)
    // -----------------------------------------------------------------
    private static PointF NextPosition(PointF current_pos, PointF velocity, int turns_ahead)
    {
        float next_x_pos = current_pos.X + (velocity.X * turns_ahead);

        float next_y_pos = current_pos.Y + (velocity.Y * turns_ahead);

        // IFs to deal with screen wrap-around
        if (next_x_pos < -Form1.maxX)
        {
            next_x_pos = Form1.maxX;
            if (next_y_pos < 0)
                next_y_pos += Form1.maxY;
            else
                next_y_pos -= Form1.maxY;
        }
        else if (next_x_pos > Form1.maxX)
        {
            next_x_pos = -Form1.maxX;
            if (next_y_pos < 0)
                next_y_pos += Form1.maxY;
            else
                next_y_pos -= Form1.maxY;
        }

        if (next_y_pos < -Form1.maxY)
        {
            next_y_pos = Form1.maxY;
            if (next_x_pos < 0)
                next_x_pos += Form1.maxX;
            else
                next_x_pos -= Form1.maxX;
        }
        else if (next_y_pos > Form1.maxY)
        {
            next_y_pos = -Form1.maxY;
            if (next_x_pos < 0)
                next_x_pos += Form1.maxX;
            else
                next_x_pos -= Form1.maxX;
        }

        PointF next_pos = new PointF(next_x_pos, next_y_pos);

        return next_pos;
    }

the collidesWith является функцией класса астероидов и используется где-то еще, чтобы обнаружить попадание пули / корабля в астероид.Я не уверен, правильна ли моя следующая функция положения, как будто астероид оборачивается вокруг значения X / Y, кажется, застревает в значении maxX / maxY?

Ответы [ 3 ]

0 голосов
/ 19 марта 2012

Учтите следующее: в любой момент у вас есть положение астероида и корабля и их скорости.Затем, в момент времени t (интервалы 150 мс), положение астероида будет

asteroid_x + asteroid.vx * t
asteroid_y + asteroid.vy * t

, а положение корабля будет

ship_x + ship.vx * t
ship_y + ship.vy * t

Таким образом, вы можете просто пройти черезt (от 0 до 100) и проверьте, находятся ли в любое время астероид и корабль на некотором расстоянии (например, от суммы их радиусов) друг от друга - что означает столкновение.

ps расстояние определяется как

sqrt( (asteroid_x - ship_x)^2 + (astroid_y - ship_y)^2 )

Предлагаю вам также прочитать подробнее об обнаружении столкновений в целом

0 голосов
/ 19 марта 2012

Представьте движения ваших объектов в 3 измерениях, где третье - время; они в конечном итоге столкнутся, если эти линии в 3D подойдут достаточно близко друг к другу (меньше, чем сумма их радиусов, если предположить, что оба объекта являются окружностями).

Эти две трехмерные линии могут быть определены точкой (x, y, 0) и вектором направления (vx, vy, 1); затем вы можете применить известную геометрию, чтобы найти ближайшее расстояние между двумя «косыми» 3D линиями; Я не знаю это случайно, но вот статья , которая дает

D = | c · (a × b) | / | a × b |

, где строчные переменные - это векторы, c - это разница между позициями, а a и b - два вектора направления.

Обратите внимание, что это приведет к ложному положительному результату, если объекты столкнулись бы в прошлом на своих текущих траекториях; Я не знаю, как это исправить, но даже если вы оставите это, вероятно, не сильно помешает вашему ИИ. Возможно, есть способ проверить «определенно раздвигаться», или, возможно, знак числителя в этой формуле имеет смысл.

0 голосов
/ 19 марта 2012

Здесь недостаточно контекста, нужно увидеть больше кода.Концепция очень очень высокого уровня, над которой я бы работал, состоит из двух этапов: 1. перемещение объекта астероида (по другому потоку от пользователя / ИИ, перемещающего корабль), 2. проверка положения астероида по сравнению сположение кораблей (для столкновения) на каждом движении (обработчик событий).Кроме того - вы упомянули «собираешься ударить», пытаетесь ли вы предсказать столкновение до того, как оно произойдет?Если это так, вам нужно будет принять во внимание предыдущие / самые последние движения астероида и корабля, чтобы «прогнозировать» их будущие движения.

...