Обнаружение столкновения SAT не удается - PullRequest
0 голосов
/ 23 апреля 2020

Я пытаюсь реализовать обнаружение коллизий SAT в моем клоне flappybird, используя DirectX Tk. Все компилируется и работает без ошибок, но просто не работает должным образом. Я пытаюсь настроить его так, чтобы каждая труба в паре проверялась отдельно, а каждая пара проверялась одинаково (с большим количеством циклов for). Трубы работают в массиве из 6 труб. (Когда вы покидаете экран слева, он сбрасывается вправо). Трубы - это каждый прямоугольник, а птица - пятиугольник. Вот код:

Vector2* Bird::getPipePoints(Vector2* points, int index, int top)
{
    Pipe* pipe = pipes[index];

    //upper pipe
    if (top == 0)
    {
        points[0] = Vector2(pipe->getX(), 0);
        points[1] = Vector2(pipe->getX() + pipe->getW(), 0);
        points[2] = Vector2(pipe->getX() + pipe->getW(), pipe->getGapH() - pipe->getGapSize() / 2);
        points[3] = Vector2(pipe->getX(), pipe->getGapH() - pipe->getGapSize() / 2);
    }
    else if (top == 1)
    {
        points[0] = Vector2(pipe->getX(), pipe->getGapH() + pipe->getGapSize() / 2);
        points[1] = Vector2(pipe->getX() + pipe->getW(), pipe->getGapH() + pipe->getGapSize() / 2);
        points[2] = Vector2(pipe->getX() + pipe->getW(), screenHeight);
        points[3] = Vector2(pipe->getX(), screenHeight);
    }

    return points;
}

Vector2* Bird::getBirdPoints(Vector2* points)
{
    points[0] = Vector2(36+screenPos.x,0+screenPos.y);
    points[1] = Vector2(68+screenPos.x, 0+screenPos.y);
    points[2] = Vector2(100+screenPos.x, 44+screenPos.y);
    points[3] = Vector2(57+screenPos.x, 70+screenPos.y);
    points[4] = Vector2(0+screenPos.x, 32+screenPos.y);

    return points;
}

bool Bird::collisionDetection(Vector2* birdPoints, Vector2* pipePoints)
{
    Vector2* axes = new Vector2[9];

    //create array of axes for bird
    for (int i = 0; i < 5; i++)
    {
        Vector2 p1 = birdPoints[i];
        Vector2 p2 = birdPoints[i + 1 == 5 ? 0 : i + 1];

        Vector2 edge = p1 - p2;//Vector2(p1.x - p2.x, p1.y - p2.y);

        Vector2 normal = Vector2(-edge.y, edge.x);

        axes[i] = normal;
    }

    //create array of axes for pipe
    for (int i = 0; i < 4; i++)
    {
        Vector2 p1 = pipePoints[i];
        Vector2 p2 = pipePoints[i + 1 == 5 ? 0 : i + 1];

        Vector2 edge = p1 - p2;//Vector2(p1.x - p2.x, p1.y - p2.y);

        Vector2 normal = Vector2(-edge.y, edge.x);

        axes[i] = normal;
    }

    //loop through every axis
    for (int i = 0; i < 9; i++)
    {
        double minBird = axes[0].Dot(birdPoints[0]);
        double maxBird = minBird;

        double minPipe = axes[0].Dot(pipePoints[0]);
        double maxPipe = minPipe;

        //projects every bird vertex to get min and max
        for (int j = 1; j < 5; j++)
        {
            double p = axes[i].Dot(birdPoints[j]);
            if (p < minBird) {
                minBird = p;
            }
            else if (p > maxBird) {
                maxBird = p;
            }
        }

        //projects every pipe vertex to get min and max
        for (int j = 1; j < 4; j++)
        {
            double p = axes[i].Dot(pipePoints[j]);
            if (p < minPipe) {
                minPipe = p;
            }
            else if (p > maxPipe) {
                maxPipe = p;
            }
        }

        //check overlap
        if ((minBird < maxPipe && minBird > minPipe)
                            ||
            (minPipe < maxBird && minPipe > minBird)) 
        {
            continue;
        }
        else 
        {//if no everlap, no collsion 
            delete[] axes;
            return false;
        }

    }
    delete[] axes;

    //There is collision
    return true;
}

И код, который вызывает функцию из функции обновления:

//check each pipe
    for (int i = 0; i < 6; i++)
    {
        //check both upper and lower pipe   
        for (int j = 0; j < 1; j++)
        {
            Vector2 pipePointsArr[4];
            Vector2* pipePoints = getPipePoints(pipePointsArr, i, j);

            if (collisionDetection(birdPoints, pipePoints))
            {
                OutputDebugStringA("DEAD");
                dead = true;
            }
        }
    }

Если вам нужны какие-либо разъяснения, пожалуйста, спросите. Заранее спасибо.

...